Skip to content

Commit 6bd7ec4

Browse files
authored
test: use expect.poll to avoid flaky watching file changes test cases (#1157)
1 parent 515ab45 commit 6bd7ec4

File tree

5 files changed

+49
-72
lines changed

5 files changed

+49
-72
lines changed

tests/integration/cli/build-watch/build.test.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { after } from 'node:test';
44
import { describe, expect, test } from '@rstest/core';
55
import fse from 'fs-extra';
66
import {
7-
awaitFileChanges,
8-
awaitFileExists,
7+
expectFile,
8+
expectFileChanges,
99
rslibBinPath,
1010
runCli,
1111
} from 'test-helper';
@@ -35,7 +35,7 @@ export default defineConfig({
3535
cwd: __dirname,
3636
});
3737

38-
await awaitFileExists(distEsmIndexFile);
38+
await expectFile(distEsmIndexFile);
3939

4040
fse.outputFileSync(
4141
tempConfigFile,
@@ -54,7 +54,7 @@ export default defineConfig({
5454
`,
5555
);
5656

57-
await awaitFileExists(dist1EsmIndexFile);
57+
await expectFile(dist1EsmIndexFile);
5858

5959
process.kill();
6060
});
@@ -111,12 +111,12 @@ export default defineConfig({
111111
shell: true,
112112
},
113113
);
114-
await awaitFileExists(distIndexFile);
114+
await expectFile(distIndexFile);
115115

116116
fse.outputFileSync(srcFooFile, `export const foo = 'foo';`);
117117
fse.outputFileSync(srcFoo2File, `export const foo2 = 'foo2';`);
118-
await awaitFileExists(distFooFile);
119-
await awaitFileExists(distFoo2File);
118+
await expectFile(distFooFile);
119+
await expectFile(distFoo2File);
120120
const content1 = await fse.readFile(distFooFile, 'utf-8');
121121
expect(content1!).toMatchInlineSnapshot(`
122122
"const foo = 'foo';
@@ -135,9 +135,8 @@ export default defineConfig({
135135
fse.removeSync(srcIndexFile);
136136

137137
// change
138-
const wait = await awaitFileChanges(distFooFile, 'foo1');
139138
fse.outputFileSync(srcFooFile, `export const foo = 'foo1';`);
140-
await wait();
139+
await expectFileChanges(distFooFile, content1, 'foo1');
141140
const content3 = await fse.readFile(distFooFile, 'utf-8');
142141
expect(content3!).toMatchInlineSnapshot(`
143142
"const foo = 'foo1';

tests/integration/cli/mf/mf.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';
44
import { startMFDevServer } from '@rslib/core';
55
import { expect, test } from '@rstest/core';
66
import fse from 'fs-extra';
7-
import { awaitFileExists, runCli, runCliSync } from 'test-helper';
7+
import { expectFile, runCli, runCliSync } from 'test-helper';
88

99
const { existsSync } = fse;
1010

@@ -26,7 +26,7 @@ describe('mf-dev', () => {
2626
},
2727
});
2828

29-
await awaitFileExists(distPath);
29+
await expectFile(distPath);
3030

3131
const rspackConfigContent = await fse.readFile(rspackConfigFile, 'utf-8');
3232
expect(rspackConfigContent).toContain(`nodeEnv: 'development'`);
@@ -52,8 +52,8 @@ describe('mf-dev', () => {
5252
cwd: fixturePath,
5353
});
5454

55-
await awaitFileExists(distPath1);
56-
await awaitFileExists(distPath2);
55+
await expectFile(distPath1);
56+
await expectFile(distPath2);
5757

5858
expect(existsSync(distPath1)).toBe(true);
5959
expect(existsSync(distPath2)).toBe(true);

tests/integration/plugins/index.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'node:fs';
22
import { join } from 'node:path';
33
import { expect, test } from '@rstest/core';
4-
import { awaitFileExists, buildAndGetResults, runCli } from 'test-helper';
4+
import { buildAndGetResults, expectFile, runCli } from 'test-helper';
55

66
import { distIndex } from './basic/rslib.config';
77
import { plugin1Path, plugin2Path } from './mf-dev/rslib.config';
@@ -20,8 +20,8 @@ test('should merge plugins correctly', async () => {
2020
cwd: fixturePath,
2121
});
2222

23-
await awaitFileExists(plugin1Path);
24-
await awaitFileExists(plugin2Path);
23+
await expectFile(plugin1Path);
24+
await expectFile(plugin2Path);
2525

2626
const content1 = fs.readFileSync(plugin1Path, 'utf-8');
2727
const content2 = fs.readFileSync(plugin2Path, 'utf-8');

tests/integration/server/index.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { existsSync } from 'node:fs';
22
import { join } from 'node:path';
33
import { describe, expect, test } from '@rstest/core';
44
import fse from 'fs-extra';
5-
import { awaitFileExists, buildAndGetResults, runCli } from 'test-helper';
5+
import { buildAndGetResults, expectFile, runCli } from 'test-helper';
66

77
describe('server config', async () => {
88
test('basic config', async () => {
@@ -31,7 +31,7 @@ describe('server config', async () => {
3131
},
3232
});
3333

34-
await awaitFileExists(doneFile);
34+
await expectFile(doneFile);
3535

3636
const rsbuildConfigContent = await fse.readFile(rsbuildConfigFile, 'utf-8');
3737
expect(rsbuildConfigContent).toContain('open: true');

tests/scripts/helper.ts

Lines changed: 32 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import fs from 'node:fs';
12
import { platform } from 'node:os';
23
import { join } from 'node:path';
4+
import { expect } from '@playwright/test';
35
import fse from 'fs-extra';
46
import { convertPathToPattern, type GlobOptions, glob } from 'tinyglobby';
57

@@ -62,60 +64,36 @@ export const proxyConsole = (
6264
};
6365
};
6466

65-
export const waitFor = async (
66-
fn: () => boolean,
67-
{
68-
maxChecks = 100,
69-
interval = 20,
70-
}: {
71-
maxChecks?: number;
72-
interval?: number;
73-
} = {},
74-
) => {
75-
let checks = 0;
76-
77-
while (checks < maxChecks) {
78-
if (fn()) {
79-
return true;
80-
}
81-
checks++;
82-
await new Promise((resolve) => setTimeout(resolve, interval));
83-
}
84-
85-
return false;
86-
};
87-
88-
export const awaitFileExists = async (dir: string) => {
89-
const result = await waitFor(() => fse.existsSync(dir), {
90-
interval: 50,
91-
maxChecks: 400,
92-
});
93-
if (!result) {
94-
throw new Error(`awaitFileExists failed: ${dir}`);
95-
}
96-
};
97-
98-
export const awaitFileChanges = async (file: string, content: string) => {
99-
const oldContent = await fse.readFile(file, 'utf-8');
100-
return async () => {
101-
const result = await waitFor(
102-
() => {
103-
try {
104-
return (
105-
fse.readFileSync(file, 'utf-8') !== oldContent &&
106-
fse.readFileSync(file, 'utf-8').includes(content)
107-
);
108-
} catch (_e) {
109-
return false;
110-
}
111-
},
112-
{ interval: 50 },
113-
);
67+
/**
68+
* A faster `expect.poll`
69+
*/
70+
export const expectPoll: (fn: () => boolean) => ReturnType<typeof expect.poll> =
71+
(fn) => {
72+
return expect.poll(fn, {
73+
intervals: [20, 30, 40, 50, 60, 70, 80, 90, 100],
74+
});
75+
};
11476

115-
if (!result) {
116-
throw new Error(`awaitFileChanges failed: ${file}`);
77+
/**
78+
* Expect a file to exist
79+
*/
80+
export const expectFile = (dir: string) =>
81+
expectPoll(() => fs.existsSync(dir)).toBeTruthy();
82+
83+
/**
84+
* Expect a file to be changed and contain newContent
85+
*/
86+
export const expectFileChanges = async (
87+
file: string,
88+
oldContent: string,
89+
newContent: string,
90+
) => {
91+
await expectPoll(() => {
92+
try {
93+
const content = fse.readFileSync(file, 'utf-8');
94+
return content !== oldContent && content.includes(newContent);
95+
} catch {
96+
return false;
11797
}
118-
119-
return result;
120-
};
98+
}).toBeTruthy();
12199
};

0 commit comments

Comments
 (0)