Skip to content

Commit 8efc79c

Browse files
authored
Merge pull request #541 from pixijs/511-setup-e2e-testing
Setup e2e testing
2 parents 8490ecb + 583caf4 commit 8efc79c

File tree

13 files changed

+10390
-7738
lines changed

13 files changed

+10390
-7738
lines changed

.eslintrc.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ module.exports = {
44
globals: {
55
globalThis: 'readonly',
66
},
7+
ignorePatterns: [
8+
'dist/**/*',
9+
'lib/**/*',
10+
],
711
parserOptions: {
812
project: './tsconfig.eslint.json',
913
ecmaVersion: 2020,

.github/workflows/handle-release-branch-push.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ jobs:
1414
# command: test:types
1515
- name: Lint
1616
command: test:lint
17+
installPlaywright: false
1718
- name: Unit tests
18-
command: test
19+
command: test:unit
20+
installPlaywright: false
21+
- name: E2E tests
22+
command: test:e2e
23+
installPlaywright: true
1924
steps:
2025
- name: Checkout
2126
uses: actions/checkout@v4
@@ -25,6 +30,10 @@ jobs:
2530
- name: Setup
2631
uses: ./.github/actions/setup
2732

33+
- name: Install Playwright browsers
34+
if: ${{ matrix.script.installPlaywright }}
35+
run: npx playwright install
36+
2837
- name: ${{ matrix.script.name }}
2938
run: npm run ${{ matrix.script.command }}
3039

package-lock.json

Lines changed: 10196 additions & 7731 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
"prerelease": "npm run test:lint && npm run build",
4646
"release": "xs bump,publish,git-push",
4747
"test": "tsc --project tsconfig.test.json && vitest run",
48+
"test:e2e": "tsc --project tsconfig.test.json && vitest run e2e",
49+
"test:unit": "tsc --project tsconfig.test.json && vitest run unit",
4850
"test:lint": "xs lint",
4951
"test:watch": "vitest"
5052
},
@@ -66,20 +68,26 @@
6668
"@rollup/plugin-commonjs": "^25.0.8",
6769
"@rollup/plugin-json": "^6.1.0",
6870
"@rollup/plugin-node-resolve": "^15.2.3",
71+
"@testing-library/jest-dom": "^6.4.8",
6972
"@testing-library/react": "^16.0.0",
73+
"@testing-library/user-event": "^14.5.2",
7074
"@types/eslint": "^8.56.10",
7175
"@types/react": "^18.3.2",
7276
"@types/react-reconciler": "0.28.8",
77+
"@vitejs/plugin-react": "^4.3.1",
78+
"@vitest/browser": "^2.0.4",
7379
"canvas": "^2.11.2",
7480
"husky": "^8.0.0",
81+
"jsdom": "^25.0.0",
7582
"pixi.js": "8.2.6",
83+
"playwright": "^1.45.3",
7684
"react": "^18.3.1",
7785
"react-dom": "^18.3.1",
7886
"rollup": "^4.18.0",
7987
"rollup-plugin-esbuild": "^6.1.1",
8088
"rollup-plugin-sourcemaps": "^0.6.3",
8189
"typescript": "^5.4.5",
82-
"vitest": "^1.6.0"
90+
"vitest": "^2.0.0"
8391
},
8492
"peerDependencies": {
8593
"pixi.js": "^8.2.6",

src/hooks/useTick.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function useTick<T>(
3838
{
3939
callback = options.callback;
4040
context = options.context;
41-
isEnabled = options.isEnabled;
41+
isEnabled = options.isEnabled ?? true;
4242
priority = options.priority;
4343
}
4444

src/typedefs/ApplicationProps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface BaseApplicationProps
2020
className?: string
2121

2222
/** @description Child components. */
23-
children: PixiReactChildNode;
23+
children?: PixiReactChildNode;
2424

2525
/** @description The default style to be applied to text nodes. */
2626
defaultTextStyle?: TextStyle | TextStyleOptions,

src/typedefs/UseTickOptions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface UseTickOptions<T>
99
context?: T
1010

1111
/** @description Whether this callback is currently enabled. */
12-
isEnabled: true,
12+
isEnabled?: true,
1313

1414
/** @description The priority of this callback compared to other callbacks on the ticker. */
1515
priority?: number
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import type { ReactNode } from 'react'
2+
import {
3+
describe,
4+
expect,
5+
it,
6+
} from 'vitest';
7+
import {
8+
render,
9+
renderHook,
10+
} from '@testing-library/react'
11+
import { Application as PixiApplication } from 'pixi.js';
12+
13+
import { Application } from '../../../src/components/Application.ts'
14+
import { useApplication } from '../../../src/hooks/useApplication.ts'
15+
16+
describe('useApplication', () =>
17+
{
18+
it('returns the nearest application', async () =>
19+
{
20+
let initApp: PixiApplication | null = null
21+
let testApp: PixiApplication | null = null
22+
23+
const TestComponentWrapper = (props: {
24+
children?: ReactNode,
25+
}) => {
26+
const { children } = props
27+
28+
const handleInit = (app: PixiApplication) => (initApp = app)
29+
30+
return (
31+
<Application onInit={handleInit}>
32+
{children}
33+
</Application>
34+
)
35+
}
36+
37+
const TestComponent = () => {
38+
const { app } = useApplication()
39+
40+
if (app) {
41+
testApp = app
42+
}
43+
44+
return null
45+
}
46+
47+
render(<TestComponent />, {
48+
wrapper: TestComponentWrapper,
49+
})
50+
51+
await new Promise<void>(resolve => {
52+
let intervalID = setInterval(() => {
53+
if (initApp) {
54+
clearInterval(intervalID)
55+
setTimeout(resolve, 10)
56+
}
57+
}, 10)
58+
})
59+
60+
expect(testApp).to.equal(initApp)
61+
})
62+
63+
it('throws when not in a React Pixi tree', () =>
64+
{
65+
expect(() => renderHook(() => useApplication())).to.throw(Error, /no context found/i)
66+
});
67+
});

test/e2e/hooks/useTick.test.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import {
2+
describe,
3+
expect,
4+
it,
5+
vi,
6+
} from 'vitest';
7+
import {
8+
render,
9+
renderHook,
10+
} from '@testing-library/react'
11+
import { Ticker } from 'pixi.js';
12+
13+
import { Application } from '../../../src/components/Application'
14+
import { useTick } from '../../../src/hooks/useTick'
15+
import { wait } from '../../utils/wait'
16+
17+
describe('useTick', () =>
18+
{
19+
describe('with a function', () => {
20+
it('runs the callback', async () => {
21+
const useTickSpy = vi.fn()
22+
23+
const TestComponent = () => {
24+
useTick(useTickSpy)
25+
26+
return null
27+
}
28+
29+
render(<TestComponent />, { wrapper: Application })
30+
31+
await wait(100)
32+
33+
expect(useTickSpy.mock.lastCall?.[0]).to.be.instanceOf(Ticker)
34+
});
35+
})
36+
37+
describe('with an options hash', () => {
38+
it('runs the callback', async () => {
39+
const useTickSpy = vi.fn()
40+
41+
const TestComponent = () => {
42+
useTick({ callback: useTickSpy })
43+
44+
return null
45+
}
46+
47+
render(<TestComponent />, { wrapper: Application })
48+
49+
await wait(100)
50+
51+
expect(useTickSpy.mock.lastCall?.[0]).to.be.instanceOf(Ticker)
52+
});
53+
})
54+
55+
it('throws when not in a React Pixi tree', () =>
56+
{
57+
const result = () => renderHook(() => useTick(() => {}))
58+
59+
expect(result).to.throw(Error, /no context found/i)
60+
});
61+
});

test/utils/wait.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function wait(waitMS: number, rejectOnComplete: boolean = false)
2+
{
3+
return new Promise((resolve, reject) =>
4+
{
5+
setTimeout(rejectOnComplete ? reject : resolve, waitMS);
6+
});
7+
}

tsconfig.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"jsx": "react-jsx",
1313
"lib": [
1414
"DOM",
15-
"ESNext"
15+
"ESNext",
1616
],
1717
"module": "ESNext",
1818
"moduleResolution": "node",
@@ -23,7 +23,13 @@
2323
"skipLibCheck": true,
2424
"sourceMap": true,
2525
"strict": true,
26-
"target": "ESNext"
26+
"target": "ESNext",
27+
"types": [
28+
"@testing-library/jest-dom",
29+
"react",
30+
"vite/client",
31+
"vitest",
32+
],
2733
},
2834
"exclude": [
2935
"dist",

vitest.setup.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { afterEach } from 'vitest';
2+
import '@testing-library/jest-dom/vitest';
3+
import { cleanup } from '@testing-library/react';
4+
5+
afterEach(() =>
6+
{
7+
cleanup();
8+
});

vitest.workspace.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11
import { defineWorkspace } from 'vitest/config';
2+
import react from '@vitejs/plugin-react';
23

34
export default defineWorkspace([
45
{
6+
plugins: [react()],
57
test: {
68
environment: 'jsdom',
79
include: ['test/unit/**/*.test.ts?(x)'],
810
pool: 'forks',
911
},
1012
},
13+
{
14+
plugins: [react()],
15+
test: {
16+
browser: {
17+
enabled: true,
18+
name: 'chromium',
19+
provider: 'playwright',
20+
},
21+
globals: true,
22+
include: ['test/e2e/**/*.test.ts(x)'],
23+
setupFiles: [
24+
'./vitest.setup.ts'
25+
],
26+
},
27+
},
1128
]);

0 commit comments

Comments
 (0)