Rsbuild with React
Start building amazing things with Rsbuild.
"`,
7 | );
8 | });
9 |
--------------------------------------------------------------------------------
/tests/ssr/fixtures/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "lib": ["DOM", "ES2020"],
5 | "module": "ESNext",
6 | "jsx": "react-jsx",
7 | "strict": true,
8 | "skipLibCheck": true,
9 | "isolatedModules": true,
10 | "resolveJsonModule": true,
11 | "moduleResolution": "bundler",
12 | "useDefineForClassFields": true
13 | },
14 | "include": ["src"]
15 | }
16 |
--------------------------------------------------------------------------------
/tests/ssr/index.test.ts:
--------------------------------------------------------------------------------
1 | import { dirname, join } from 'node:path';
2 | import { fileURLToPath } from 'node:url';
3 | import { describe, expect, it } from '@rstest/core';
4 | import { runRstestCli } from '../scripts/';
5 |
6 | const __filename = fileURLToPath(import.meta.url);
7 | const __dirname = dirname(__filename);
8 |
9 | describe('test ssr', () => {
10 | it('should run ssr test succeed', async () => {
11 | const { cli } = await runRstestCli({
12 | command: 'rstest',
13 | args: ['run', 'test/index.test.ts'],
14 | options: {
15 | nodeOptions: {
16 | cwd: join(__dirname, 'fixtures'),
17 | },
18 | },
19 | });
20 |
21 | await cli.exec;
22 |
23 | const logs = cli.stdout.split('\n').filter(Boolean);
24 |
25 | expect(cli.exec.process?.exitCode).toBe(0);
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/tests/test-api/__snapshots__/concurrentContext.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Snapshot v1
2 |
3 | exports[`concurrent test 2 1`] = `"hello world"`;
4 |
--------------------------------------------------------------------------------
/tests/test-api/chain.test.ts:
--------------------------------------------------------------------------------
1 | import { dirname } from 'node:path';
2 | import { fileURLToPath } from 'node:url';
3 | import { describe, expect, it } from '@rstest/core';
4 | import { runRstestCli } from '../scripts';
5 |
6 | const __filename = fileURLToPath(import.meta.url);
7 | const __dirname = dirname(__filename);
8 |
9 | describe('Test Chain', () => {
10 | it('chain API enumerable', async () => {
11 | expect(Object.keys(it)).toMatchInlineSnapshot(`
12 | [
13 | "fails",
14 | "concurrent",
15 | "sequential",
16 | "skip",
17 | "todo",
18 | "only",
19 | "runIf",
20 | "skipIf",
21 | "each",
22 | "for",
23 | "extend",
24 | ]
25 | `);
26 | expect(Object.keys(it.only)).toMatchInlineSnapshot(`
27 | [
28 | "fails",
29 | "concurrent",
30 | "sequential",
31 | "skip",
32 | "todo",
33 | "only",
34 | "runIf",
35 | "skipIf",
36 | "each",
37 | "for",
38 | ]
39 | `);
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/tests/test-api/concurrentContext.test.ts:
--------------------------------------------------------------------------------
1 | import { it } from '@rstest/core';
2 |
3 | it.concurrent('concurrent test 1', async ({ expect }) => {
4 | expect.assertions(1);
5 | await new Promise((resolve) => setTimeout(resolve, 200));
6 | expect(1 + 1).toBe(2);
7 | });
8 |
9 | it.concurrent('concurrent test 2', async ({ expect }) => {
10 | expect(1 + 1).toBe(2);
11 | await new Promise((resolve) => setTimeout(resolve, 100));
12 | expect('hello world').toMatchSnapshot();
13 | });
14 | it.concurrent('concurrent test 3', async ({ expect }) => {
15 | expect.assertions(2);
16 | await new Promise((resolve) => setTimeout(resolve, 100));
17 | expect(1 + 1).toBe(2);
18 | expect(1 + 2).toBe(3);
19 | });
20 |
--------------------------------------------------------------------------------
/tests/test-api/concurrentIsolated.test.ts:
--------------------------------------------------------------------------------
1 | import { afterAll, describe, expect, it } from '@rstest/core';
2 | const logs: string[] = [];
3 |
4 | afterAll(() => {
5 | expect(logs).toEqual([
6 | '[log] concurrent test 1',
7 | '[log] concurrent test 2',
8 | '[log] concurrent test 2 - 1',
9 | '[log] concurrent test 1 - 1',
10 | '[log] concurrent test B 1',
11 | '[log] concurrent test B 2',
12 | '[log] concurrent test B 2 - 1',
13 | '[log] concurrent test B 1 - 1',
14 | ]);
15 | });
16 |
17 | describe('suite', () => {
18 | it.concurrent('concurrent test 1', async () => {
19 | logs.push('[log] concurrent test 1');
20 | await new Promise((resolve) => setTimeout(resolve, 200));
21 | logs.push('[log] concurrent test 1 - 1');
22 | });
23 |
24 | it.concurrent('concurrent test 2', async () => {
25 | logs.push('[log] concurrent test 2');
26 | await new Promise((resolve) => setTimeout(resolve, 100));
27 | logs.push('[log] concurrent test 2 - 1');
28 | });
29 | });
30 |
31 | describe('suite B', () => {
32 | it.concurrent('concurrent test B 1', async () => {
33 | logs.push('[log] concurrent test B 1');
34 | await new Promise((resolve) => setTimeout(resolve, 200));
35 | logs.push('[log] concurrent test B 1 - 1');
36 | });
37 |
38 | it.concurrent('concurrent test B 2', async () => {
39 | logs.push('[log] concurrent test B 2');
40 | await new Promise((resolve) => setTimeout(resolve, 100));
41 | logs.push('[log] concurrent test B 2 - 1');
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/tests/test-api/concurrentLimit.test.ts:
--------------------------------------------------------------------------------
1 | import { dirname } from 'node:path';
2 | import { fileURLToPath } from 'node:url';
3 | import { expect, it } from '@rstest/core';
4 | import { runRstestCli } from '../scripts';
5 |
6 | it('should run concurrent cases correctly with limit', async () => {
7 | const __filename = fileURLToPath(import.meta.url);
8 | const __dirname = dirname(__filename);
9 |
10 | const { cli } = await runRstestCli({
11 | command: 'rstest',
12 | args: ['run', 'fixtures/concurrentLimit.test.ts', '--maxConcurrency=4'],
13 | options: {
14 | nodeOptions: {
15 | cwd: __dirname,
16 | },
17 | },
18 | });
19 | await cli.exec;
20 | expect(cli.exec.process?.exitCode).toBe(0);
21 |
22 | const logs = cli.stdout.split('\n').filter(Boolean);
23 |
24 | expect(logs.filter((log) => log.includes('[log]'))).toMatchInlineSnapshot(`
25 | [
26 | "[log] concurrent test 1",
27 | "[log] concurrent test 2",
28 | "[log] concurrent test 3",
29 | "[log] concurrent test 4",
30 | "[log] concurrent test 2 - 1",
31 | "[log] concurrent test 5",
32 | "[log] concurrent test 3 - 1",
33 | "[log] concurrent test 6",
34 | "[log] concurrent test 4 - 1",
35 | "[log] concurrent test 7",
36 | "[log] concurrent test 1 - 1",
37 | "[log] concurrent test 5 - 1",
38 | "[log] concurrent test 6 - 1",
39 | "[log] concurrent test 7 - 1",
40 | ]
41 | `);
42 | });
43 |
--------------------------------------------------------------------------------
/tests/test-api/condition.test.ts:
--------------------------------------------------------------------------------
1 | import { afterAll, describe, expect, it } from '@rstest/core';
2 |
3 | describe('Test Condition (runIf & skipIf)', () => {
4 | const logs: string[] = [];
5 |
6 | afterAll(() => {
7 | expect(logs.length).toBe(1);
8 | });
9 |
10 | it.skipIf(1 + 1 === 2).each([
11 | { a: 1, b: 1, expected: 2 },
12 | { a: 1, b: 2, expected: 3 },
13 | { a: 2, b: 1, expected: 3 },
14 | ])('add($a, $b) -> $expected', ({ a, b, expected }) => {
15 | logs.push('executed');
16 | expect(a + b).toBe(expected);
17 | });
18 |
19 | it.runIf(1 + 1 === 2)('add two numbers correctly', () => {
20 | logs.push('executed');
21 | expect(1 + 1).toBe(2);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/tests/test-api/each.test.ts:
--------------------------------------------------------------------------------
1 | import { afterAll, expect, it } from '@rstest/core';
2 |
3 | const logs: string[] = [];
4 |
5 | afterAll(() => {
6 | expect(logs.length).toBe(6);
7 | });
8 |
9 | it.each([
10 | { a: 1, b: 1, expected: 2 },
11 | { a: 1, b: 2, expected: 3 },
12 | { a: 2, b: 1, expected: 3 },
13 | ])('add($a, $b) -> $expected', ({ a, b, expected }) => {
14 | expect(a + b).toBe(expected);
15 | logs.push('executed');
16 | });
17 |
18 | it.each([
19 | [2, 1, 3],
20 | [2, 2, 4],
21 | [3, 1, 4],
22 | ])('case-%# add(%i, %i) -> %i', (a, b, expected) => {
23 | expect(a + b).toBe(expected);
24 | logs.push('executed');
25 | });
26 |
--------------------------------------------------------------------------------
/tests/test-api/extend.auto.test.ts:
--------------------------------------------------------------------------------
1 | import { afterAll, expect, test } from '@rstest/core';
2 |
3 | const logs: string[] = [];
4 |
5 | afterAll(() => {
6 | // should init on demand
7 | expect(logs.length).toBe(4);
8 | });
9 |
10 | const todos: number[] = [];
11 | const archive: number[] = [];
12 |
13 | const myTest = test.extend<{
14 | todos: number[];
15 | archive: number[];
16 | }>({
17 | todos: [
18 | async (_, use) => {
19 | logs.push('init todos');
20 | todos.push(1, 2, 3);
21 | await use(todos);
22 | // cleanup after each test function
23 | todos.length = 0;
24 | },
25 | {
26 | auto: true,
27 | },
28 | ],
29 | archive: [
30 | async (_, use) => {
31 | logs.push('init archive');
32 | await use(archive);
33 | // cleanup after each test function
34 | archive.length = 0;
35 | },
36 | {
37 | auto: true,
38 | },
39 | ],
40 | });
41 |
42 | myTest('add todo', ({ todos }) => {
43 | expect(todos.length).toBe(3);
44 |
45 | todos.push(4);
46 | expect(todos.length).toBe(4);
47 | });
48 |
49 | myTest('add archive', ({ archive }) => {
50 | expect(archive.length).toBe(0);
51 |
52 | archive.push(1, 2);
53 | expect(archive.length).toBe(2);
54 | });
55 |
--------------------------------------------------------------------------------
/tests/test-api/extend.depends.test.ts:
--------------------------------------------------------------------------------
1 | import { afterAll, expect, test } from '@rstest/core';
2 |
3 | const todos: number[] = [];
4 | const archive: number[] = [];
5 |
6 | const logs: string[] = [];
7 |
8 | afterAll(() => {
9 | expect(logs).toEqual(['clean getList', 'clean archive', 'clean todos']);
10 | });
11 |
12 | const myTest = test.extend<{
13 | todos: number[];
14 | archive: number[];
15 | getList: () => {
16 | todos: number[];
17 | archive: number[];
18 | };
19 | }>({
20 | todos: async (_, use) => {
21 | await new Promise((resolve) => setTimeout(resolve, 10));
22 | todos.push(1, 2, 3);
23 | await use(todos);
24 | logs.push('clean todos');
25 | // cleanup after each test function
26 | todos.length = 0;
27 | },
28 | archive: async (_, use) => {
29 | archive.push(1, 2, 3);
30 | await use(archive);
31 | logs.push('clean archive');
32 | // cleanup after each test function
33 | archive.length = 0;
34 | },
35 | getList: async ({ todos, archive }, use) => {
36 | await use(() => ({ todos, archive }));
37 | logs.push('clean getList');
38 | },
39 | });
40 |
41 | myTest('add todo', ({ getList }) => {
42 | expect(getList()).toEqual({
43 | todos: [1, 2, 3],
44 | archive: [1, 2, 3],
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/tests/test-api/extend.extend.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from '@rstest/core';
2 |
3 | const todos: number[] = [];
4 | const archive: number[] = [];
5 |
6 | const myTest = test.extend<{
7 | todos: number[];
8 | }>({
9 | todos: async (_, use) => {
10 | await new Promise((resolve) => setTimeout(resolve, 10));
11 | todos.push(1, 2, 3);
12 | await use(todos);
13 | // cleanup after each test function
14 | todos.length = 0;
15 | },
16 | });
17 |
18 | const myTest1 = myTest.extend<{
19 | archive: number[];
20 | }>({
21 | archive: async (_, use) => {
22 | archive.push(1, 2, 3);
23 | await use(archive);
24 | // cleanup after each test function
25 | archive.length = 0;
26 | },
27 | });
28 |
29 | myTest1('add todo', ({ todos }) => {
30 | expect(todos.length).toBe(3);
31 |
32 | todos.push(4);
33 | expect(todos.length).toBe(4);
34 | });
35 |
36 | myTest1('add archive', ({ archive }) => {
37 | expect(archive.length).toBe(3);
38 |
39 | archive.push(4, 5);
40 | expect(archive.length).toBe(5);
41 | });
42 |
--------------------------------------------------------------------------------
/tests/test-api/extend.onDemand.test.ts:
--------------------------------------------------------------------------------
1 | import { afterAll, expect, test } from '@rstest/core';
2 |
3 | const logs: string[] = [];
4 |
5 | afterAll(() => {
6 | // should init on demand
7 | expect(logs.length).toBe(3);
8 | });
9 |
10 | const todos: number[] = [];
11 |
12 | const myTest = test.extend<{
13 | todos: number[];
14 | archive: number[];
15 | }>({
16 | todos: async (_, use) => {
17 | logs.push('init todos');
18 | await new Promise((resolve) => setTimeout(resolve, 10));
19 | todos.push(1, 2, 3);
20 | await use(todos);
21 | // cleanup after each test function
22 | todos.length = 0;
23 | },
24 | archive: [],
25 | });
26 |
27 | myTest('add todo 1', ({ todos }) => {
28 | expect(todos.length).toBe(3);
29 |
30 | todos.push(4);
31 | expect(todos.length).toBe(4);
32 | });
33 |
34 | myTest('add todo 2', ({ todos }) => {
35 | expect(todos.length).toBe(3);
36 |
37 | todos.push(4, 5);
38 | expect(todos.length).toBe(5);
39 | });
40 |
41 | myTest.fails('add todo 3 - failed', ({ todos }) => {
42 | expect(todos.length).toBe(3);
43 |
44 | todos.push(4, 5);
45 | expect(todos.length).toBe(6);
46 | });
47 |
48 | myTest('add archive', ({ archive }) => {
49 | expect(archive.length).toBe(0);
50 |
51 | archive.push(1, 2);
52 | expect(archive.length).toBe(2);
53 | });
54 |
--------------------------------------------------------------------------------
/tests/test-api/fixtures/concurrentLimit.test.ts:
--------------------------------------------------------------------------------
1 | import { it } from '@rstest/core';
2 |
3 | it.concurrent('concurrent test 1', async () => {
4 | console.log('[log] concurrent test 1');
5 | await new Promise((resolve) => setTimeout(resolve, 200));
6 | console.log('[log] concurrent test 1 - 1');
7 | });
8 |
9 | it.concurrent('concurrent test 2', async () => {
10 | console.log('[log] concurrent test 2');
11 | await new Promise((resolve) => setTimeout(resolve, 100));
12 | console.log('[log] concurrent test 2 - 1');
13 | });
14 | it.concurrent('concurrent test 3', async () => {
15 | console.log('[log] concurrent test 3');
16 | await new Promise((resolve) => setTimeout(resolve, 100));
17 | console.log('[log] concurrent test 3 - 1');
18 | });
19 |
20 | it.concurrent('concurrent test 4', async () => {
21 | console.log('[log] concurrent test 4');
22 | await new Promise((resolve) => setTimeout(resolve, 100));
23 | console.log('[log] concurrent test 4 - 1');
24 | });
25 |
26 | it.concurrent('concurrent test 5', async () => {
27 | console.log('[log] concurrent test 5');
28 | await new Promise((resolve) => setTimeout(resolve, 100));
29 | console.log('[log] concurrent test 5 - 1');
30 | });
31 |
32 | it.concurrent('concurrent test 6', async () => {
33 | console.log('[log] concurrent test 6');
34 | await new Promise((resolve) => setTimeout(resolve, 100));
35 | console.log('[log] concurrent test 6 - 1');
36 | });
37 |
38 | it.concurrent('concurrent test 7', async () => {
39 | console.log('[log] concurrent test 7');
40 | await new Promise((resolve) => setTimeout(resolve, 100));
41 | console.log('[log] concurrent test 7 - 1');
42 | });
43 |
--------------------------------------------------------------------------------
/tests/test-api/fixtures/error.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, it } from '@rstest/core';
2 |
3 | it('test asymmetricMatcher error', () => {
4 | expect({
5 | text: 'hello world',
6 | }).toEqual({
7 | text: expect.stringMatching('hhh'),
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/tests/test-api/fixtures/moduleNotFound.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, it } from '@rstest/core';
2 |
3 | const expectNotFound = async () => {
4 | try {
5 | // @ts-expect-error
6 | const res = await import('404');
7 | return res;
8 | } catch (err) {
9 | return null;
10 | }
11 | };
12 |
13 | const unexpectNotFound = async () => {
14 | // @ts-expect-error
15 | return import('aaa');
16 | };
17 |
18 | it('test expectNotFound error', async () => {
19 | await expect(expectNotFound()).resolves.toBeNull();
20 | });
21 |
22 | it('test expectNotFound error', async () => {
23 | await expect(unexpectNotFound()).rejects.toThrowError(
24 | /Cannot find module \'aaa\'/,
25 | );
26 | });
27 |
--------------------------------------------------------------------------------
/tests/test-api/fixtures/onlyInSkip.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from '@rstest/core';
2 |
3 | describe.skip('level A', () => {
4 | // biome-ignore lint/suspicious/noFocusedTests: