Skip to content

Commit a78b4f2

Browse files
authored
Merge pull request finos#1378 from fabiovincenzi/fix/test-shuffle-independence
fix: make tests independent of execution order
2 parents ccb5d1d + 384cc5c commit a78b4f2

16 files changed

Lines changed: 389 additions & 162 deletions

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"build-ui": "vite build",
5454
"check-types": "tsc",
5555
"check-types:server": "tsc --project tsconfig.publish.json --noEmit",
56+
"test-shuffle": "NODE_ENV=test vitest --run --dir ./test --sequence.shuffle",
5657
"test": "cross-env NODE_ENV=test vitest --run --dir ./test",
5758
"test:e2e": "vitest run --config vitest.config.e2e.ts",
5859
"test:e2e:watch": "vitest --config vitest.config.e2e.ts",

src/proxy/index.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,26 @@ export class Proxy {
7171
public async start() {
7272
await this.proxyPreparations();
7373
this.expressApp = await this.createApp();
74-
this.httpServer = http
75-
.createServer(getServerOptions() as any, this.expressApp)
76-
.listen(proxyHttpPort, () => {
74+
await new Promise<void>((resolve, reject) => {
75+
const server = http.createServer(getServerOptions() as any, this.expressApp!);
76+
server.on('error', reject);
77+
server.listen(proxyHttpPort, () => {
7778
console.log(`HTTP Proxy Listening on ${proxyHttpPort}`);
79+
resolve();
7880
});
81+
this.httpServer = server;
82+
});
7983
// Start HTTPS server only if TLS is enabled
8084
if (getTLSEnabled()) {
81-
this.httpsServer = https
82-
.createServer(getServerOptions(), this.expressApp)
83-
.listen(proxyHttpsPort, () => {
85+
await new Promise<void>((resolve, reject) => {
86+
const server = https.createServer(getServerOptions(), this.expressApp!);
87+
server.on('error', reject);
88+
server.listen(proxyHttpsPort, () => {
8489
console.log(`HTTPS Proxy Listening on ${proxyHttpsPort}`);
90+
resolve();
8591
});
92+
this.httpsServer = server;
93+
});
8694
}
8795
}
8896

src/proxy/processors/push-action/clearBareClone.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import { Action, Step } from '../../actions';
2-
import fs from 'node:fs';
2+
import fs from 'node:fs/promises';
33

44
const exec = async (req: any, action: Action): Promise<Action> => {
55
const step = new Step('clearBareClone');
66

77
// Recursively remove the contents of ./.remote and ignore exceptions
8-
fs.rm('./.remote', { recursive: true, force: true }, (err) => {
9-
if (err) {
10-
throw err;
11-
}
12-
console.log(`.remote is deleted!`);
13-
});
8+
await fs.rm('./.remote', { recursive: true, force: true });
9+
console.log(`.remote is deleted!`);
1410

1511
action.addStep(step);
1612
return action;

src/service/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ async function stop(): Promise<void> {
194194
reject(err);
195195
} else {
196196
console.log('Service stopped');
197+
_httpServer = null;
197198
resolve();
198199
}
199200
});

src/service/routes/repo.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,15 @@ const repo = (proxy: any) => {
178178
const repoDetails = await db.createRepo(req.body);
179179
const proxyURL = getProxyURL(req);
180180

181-
// return data on the new repoistory (including it's _id and the proxyUrl)
182-
res.send({ ...repoDetails, proxyURL, message: 'created' });
183-
184181
// restart the proxy if we're proxying a new domain
185182
if (newOrigin) {
186183
console.log('Restarting the proxy to handle an additional host');
187184
await theProxy.stop();
188185
await theProxy.start();
189186
}
187+
188+
// return data on the new repository (including it's _id and the proxyUrl)
189+
res.send({ ...repoDetails, proxyURL, message: 'created' });
190190
} catch (e: any) {
191191
console.error('Repository creation failed due to error: ', e.message ? e.message : e);
192192
console.error(e.stack);

test/1.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ describe('init', () => {
6969

7070
// Example test: use vi.doMock to override the config module
7171
it('should return an array of enabled auth methods when overridden', async () => {
72+
// Clear module cache so vi.doMock takes effect on the fresh import below
73+
vi.resetModules();
7274
// fs must be mocked BEFORE importing the config module
7375
// We also mock existsSync to ensure the file "exists"
7476
vi.doMock('fs', async (importOriginal) => {

test/ConfigLoader.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,17 @@ describe('ConfigLoader', () => {
443443
enabled: true,
444444
};
445445

446+
// Clean up cached clone of the fake repo so the test works regardless of order
447+
const envPaths = (await import('env-paths')).default;
448+
const paths = envPaths('git-proxy', { suffix: '' });
449+
const repoDirName = Buffer.from(source.repository)
450+
.toString('base64')
451+
.replace(/[^a-zA-Z0-9]/g, '_');
452+
const repoDir = path.join(paths.cache, 'git-config-cache', repoDirName);
453+
if (fs.existsSync(repoDir)) {
454+
fs.rmSync(repoDir, { recursive: true });
455+
}
456+
446457
await expect(configLoader.loadFromSource(source)).rejects.toThrow(
447458
/Failed to clone repository/,
448459
);

test/extractRawBody.test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, it, beforeEach, expect, vi, Mock, afterAll } from 'vitest';
1+
import { describe, it, beforeEach, expect, vi, Mock } from 'vitest';
22
import { PassThrough } from 'stream';
33

44
// Tell Vitest to mock dependencies
@@ -21,6 +21,9 @@ describe('extractRawBody middleware', () => {
2121
let next: Mock;
2222

2323
beforeEach(() => {
24+
(rawBody as Mock).mockClear();
25+
(chain.executeChain as Mock).mockClear();
26+
2427
req = new PassThrough();
2528
req.method = 'POST';
2629
req.url = '/proj/foo.git/git-upload-pack';
@@ -35,11 +38,6 @@ describe('extractRawBody middleware', () => {
3538
next = vi.fn();
3639
});
3740

38-
afterAll(() => {
39-
(rawBody as Mock).mockClear();
40-
(chain.executeChain as Mock).mockClear();
41-
});
42-
4341
it('skips non-pack posts', async () => {
4442
req.method = 'GET';
4543
await extractRawBody(req, res, next);

test/preReceive/preReceive.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ describe.skipIf(process.platform === 'win32')('Pre-Receive Hook Execution', () =
2929
});
3030

3131
afterEach(() => {
32-
vi.resetModules();
33-
vi.restoreAllMocks();
32+
vi.clearAllMocks();
3433
});
3534

3635
it('should catch and handle unexpected errors', async () => {

test/processors/getDiff.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ describe('getDiff', () => {
3232
});
3333

3434
it('should get diff between commits', async () => {
35+
// Ensure we have a known state: write initial content, then modify it
36+
await fs.writeFile(path.join(tempDir, 'test.txt'), 'initial content');
37+
await git.add('.');
38+
// Use --allow-empty or amend to handle case where content is already 'initial content'
39+
try {
40+
await git.commit('reset to initial');
41+
} catch {
42+
// no changes to commit - that's fine
43+
}
44+
3545
await fs.writeFile(path.join(tempDir, 'test.txt'), 'modified content');
3646
await git.add('.');
3747
await git.commit('second commit');
@@ -51,6 +61,15 @@ describe('getDiff', () => {
5161
});
5262

5363
it('should get diff between commits with no changes', async () => {
64+
// Create a known two-commit state: initial -> same content commit
65+
await fs.writeFile(path.join(tempDir, 'test-nochange.txt'), 'initial content');
66+
await git.add('.');
67+
await git.commit('base commit for no-change test');
68+
69+
await fs.writeFile(path.join(tempDir, 'test-nochange2.txt'), 'more initial content');
70+
await git.add('.');
71+
await git.commit('second commit for no-change test');
72+
5473
const action = new Action('1234567890', 'push', 'POST', 1234567890, 'test/repo.git');
5574
action.proxyGitPath = __dirname; // Temp dir parent path
5675
action.repoName = 'temp-test-repo';

0 commit comments

Comments
 (0)