Skip to content

Commit d46268b

Browse files
chore: Replace mock-fs with memfs/unionfs for fs mocking (#6470)
--------- Co-authored-by: sap-cloud-sdk-bot[bot] <274190970+sap-cloud-sdk-bot[bot]@users.noreply.github.com>
1 parent f7cfa64 commit d46268b

45 files changed

Lines changed: 900 additions & 541 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.licensee.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"licenses": {
3-
"spdx": ["CC-BY-3.0"],
3+
"spdx": ["CC-BY-3.0", "CC-BY-4.0"],
44
"blueOak": "bronze"
55
},
66
"corrections": true,

build-packages/changesets-fixed-version-bump/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
"semver": "^7.7.4"
2121
},
2222
"devDependencies": {
23+
"@sap-cloud-sdk/test-util-build-internal": "*",
2324
"@vercel/ncc": "^0.38.4",
2425
"depcheck": "^1.4.7",
2526
"eslint": "^9.39.2",
27+
"memfs": "^4.57.1",
2628
"prettier": "^3.8.1",
2729
"typescript": "~5.9.3"
2830
}

build-packages/changesets-fixed-version-bump/util.spec.ts

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
import { resolve } from 'node:path';
2-
import mock from 'mock-fs';
2+
import { readFileSync } from 'node:fs';
3+
import { vol } from 'memfs';
4+
import { jest, describe, afterEach, it } from '@jest/globals';
5+
import { mockFsWithMemfs } from '@sap-cloud-sdk/test-util-build-internal';
36
import { getNextVersion } from './util.js';
47

8+
mockFsWithMemfs(jest);
9+
10+
const changesetConfig = readFileSync(
11+
resolve('..', '.changeset', 'config.json'),
12+
'utf8'
13+
);
14+
515
describe('getNextVersion', () => {
616
afterEach(() => {
7-
mock.restore();
17+
vol.reset();
818
});
919
const sharedMock = {
1020
'package.json':
@@ -17,13 +27,16 @@ describe('getNextVersion', () => {
1727
};
1828

1929
it('should make a patch update', async () => {
20-
mock({
21-
...sharedMock,
22-
'.changeset': {
23-
'config.json': mock.load(resolve('..', '.changeset', 'config.json')),
24-
'alex.md': '---\n' + "'@sap-cloud-sdk/connectivity': patch\n" + '---'
25-
}
26-
});
30+
vol.fromNestedJSON(
31+
{
32+
...sharedMock,
33+
'.changeset': {
34+
'config.json': changesetConfig,
35+
'alex.md': '---\n' + "'@sap-cloud-sdk/connectivity': patch\n" + '---'
36+
}
37+
},
38+
process.cwd()
39+
);
2740

2841
expect(await getNextVersion()).toEqual({
2942
version: '1.2.4',
@@ -32,14 +45,17 @@ describe('getNextVersion', () => {
3245
});
3346

3447
it('should make a minor update', async () => {
35-
mock({
36-
...sharedMock,
37-
'.changeset': {
38-
'config.json': mock.load(resolve('..', '.changeset', 'config.json')),
39-
'alex.md': '---\n' + "'@sap-cloud-sdk/connectivity': patch\n" + '---',
40-
'bob.md': '---\n' + "'@sap-cloud-sdk/connectivity': minor\n" + '---'
41-
}
42-
});
48+
vol.fromNestedJSON(
49+
{
50+
...sharedMock,
51+
'.changeset': {
52+
'config.json': changesetConfig,
53+
'alex.md': '---\n' + "'@sap-cloud-sdk/connectivity': patch\n" + '---',
54+
'bob.md': '---\n' + "'@sap-cloud-sdk/connectivity': minor\n" + '---'
55+
}
56+
},
57+
process.cwd()
58+
);
4359

4460
expect(await getNextVersion()).toEqual({
4561
version: '1.3.0',
@@ -48,14 +64,17 @@ describe('getNextVersion', () => {
4864
});
4965

5066
it('should make a major update', async () => {
51-
mock({
52-
...sharedMock,
53-
'.changeset': {
54-
'config.json': mock.load(resolve('..', '.changeset', 'config.json')),
55-
'alex.md': '---\n' + "'@sap-cloud-sdk/connectivity': major\n" + '---',
56-
'bob.md': '---\n' + "'@sap-cloud-sdk/connectivity': minor\n" + '---'
57-
}
58-
});
67+
vol.fromNestedJSON(
68+
{
69+
...sharedMock,
70+
'.changeset': {
71+
'config.json': changesetConfig,
72+
'alex.md': '---\n' + "'@sap-cloud-sdk/connectivity': major\n" + '---',
73+
'bob.md': '---\n' + "'@sap-cloud-sdk/connectivity': minor\n" + '---'
74+
}
75+
},
76+
process.cwd()
77+
);
5978

6079
expect(await getNextVersion()).toEqual({
6180
version: '2.0.0',
@@ -64,12 +83,13 @@ describe('getNextVersion', () => {
6483
});
6584

6685
it('should throw an error, when no changesets exist', async () => {
67-
mock({
68-
...sharedMock,
69-
'.changeset': {
70-
'config.json': mock.load(resolve('..', '.changeset', 'config.json'))
71-
}
72-
});
86+
vol.fromNestedJSON(
87+
{
88+
...sharedMock,
89+
'.changeset': { 'config.json': changesetConfig }
90+
},
91+
process.cwd()
92+
);
7393

7494
await expect(getNextVersion()).rejects.toThrow(
7595
'Invalid new version -- the current version: 1.2.3 and the release type: none."'

build-packages/check-pr/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@
1313
"lint": "eslint --ignore-pattern '!index.ts' && prettier --check **/*.ts",
1414
"lint:fix": "eslint --ignore-pattern '!index.ts' --fix --quiet && prettier --write **/*.ts",
1515
"check:dependencies": "depcheck --skip-missing=true .",
16-
"all": "yarn && yarn run lint && yarn run compile"
16+
"all": "yarn && yarn lint && yarn compile"
1717
},
1818
"dependencies": {
1919
"@actions/core": "^3.0.0",
2020
"@actions/github": "^9.0.0"
2121
},
2222
"devDependencies": {
23+
"@sap-cloud-sdk/test-util-build-internal": "*",
2324
"@vercel/ncc": "^0.38.4",
2425
"depcheck": "^1.4.7",
2526
"eslint": "^9.39.2",
26-
"mock-fs": "^5.5.0",
27+
"memfs": "^4.57.1",
2728
"prettier": "^3.8.1",
2829
"typescript": "~5.9.3"
2930
}

build-packages/check-pr/validators.spec.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import mock from 'mock-fs';
21
import { jest } from '@jest/globals';
2+
import { vol } from 'memfs';
3+
import { mockFsWithMemfs } from '@sap-cloud-sdk/test-util-build-internal';
4+
5+
mockFsWithMemfs(jest);
36

47
jest.unstable_mockModule('@actions/core', () => ({
58
error: jest.fn(),
@@ -21,19 +24,20 @@ with multiple lines`;
2124

2225
describe('check-pr', () => {
2326
beforeEach(() => {
24-
mock({
25-
'.github': {
26-
'PULL_REQUEST_TEMPLATE.md': prTemplate
27+
vol.fromNestedJSON(
28+
{
29+
'.github': { 'PULL_REQUEST_TEMPLATE.md': prTemplate },
30+
'my-changeset.md': '[Fixed Issue] Something is fixed.'
2731
},
28-
'my-changeset.md': '[Fixed Issue] Something is fixed.'
29-
});
32+
process.cwd()
33+
);
3034

3135
getInput.mockReturnValue('my-changeset.md');
3236
process.exitCode = 0;
3337
});
3438

3539
afterEach(() => {
36-
mock.restore();
40+
vol.reset();
3741
setFailed.mockClear();
3842
});
3943

build-packages/check-public-api/check-public-api.spec.ts

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,9 @@
11
import path from 'path';
22
import { describe, jest, beforeEach } from '@jest/globals';
33
import { vol } from 'memfs';
4+
import { mockFsWithMemfs } from '@sap-cloud-sdk/test-util-build-internal';
45

5-
jest.unstable_mockModule('fs', () =>
6-
import('memfs').then(m => ({
7-
...m.fs,
8-
default: m.fs
9-
}))
10-
);
11-
jest.unstable_mockModule('fs/promises', () =>
12-
import('memfs').then(m => ({
13-
...m.fs.promises,
14-
default: m.fs.promises
15-
}))
16-
);
17-
jest.unstable_mockModule('node:fs', () =>
18-
import('memfs').then(m => ({
19-
...m.fs,
20-
default: m.fs
21-
}))
22-
);
23-
jest.unstable_mockModule('node:fs/promises', () =>
24-
import('memfs').then(m => ({
25-
...m.fs.promises,
26-
default: m.fs.promises
27-
}))
28-
);
6+
mockFsWithMemfs(jest);
297

308
const actionsCoreMock = {
319
error: jest.fn(),

build-packages/check-public-api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"glob": "^13.0.6"
2424
},
2525
"devDependencies": {
26+
"@sap-cloud-sdk/test-util-build-internal": "*",
2627
"@vercel/ncc": "^0.38.4",
2728
"depcheck": "^1.4.7",
2829
"eslint": "^9.39.2",

build-packages/test-utils/index.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { jest } from '@jest/globals';
2+
3+
/**
4+
* Mock all `fs` module variants with pure memfs using `jest.unstable_mockModule` (ESM).
5+
* Must be called before any dynamic `import()` of modules that use `fs`.
6+
* @internal
7+
*/
8+
export function mockFsWithMemfs(j: typeof jest): void {
9+
j.unstable_mockModule('fs', () =>
10+
import('memfs').then(m => ({
11+
...m.fs,
12+
default: m.fs,
13+
__esModule: true
14+
}))
15+
);
16+
j.unstable_mockModule('fs/promises', () =>
17+
import('memfs').then(m => ({
18+
...m.fs.promises,
19+
default: m.fs.promises,
20+
__esModule: true
21+
}))
22+
);
23+
j.unstable_mockModule('node:fs', () =>
24+
import('memfs').then(m => ({
25+
...m.fs,
26+
default: m.fs,
27+
__esModule: true
28+
}))
29+
);
30+
j.unstable_mockModule('node:fs/promises', () =>
31+
import('memfs').then(m => ({
32+
...m.fs.promises,
33+
default: m.fs.promises,
34+
__esModule: true
35+
}))
36+
);
37+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "@sap-cloud-sdk/test-util-build-internal",
3+
"version": "4.6.0",
4+
"description": "Shared test utilities for SAP Cloud SDK packages",
5+
"private": true,
6+
"type": "module",
7+
"publishConfig": {
8+
"access": "restricted"
9+
},
10+
"license": "Apache-2.0",
11+
"main": "./lib/index.js",
12+
"scripts": {
13+
"compile": "tsc -p tsconfig.json",
14+
"lint": "eslint --ignore-pattern '!index.ts' && prettier --check **/*.ts",
15+
"lint:fix": "eslint --ignore-pattern '!index.ts' --fix --quiet && prettier --write **/*.ts",
16+
"check:dependencies": "depcheck .",
17+
"all": "yarn && yarn lint && yarn compile"
18+
},
19+
"dependencies": {
20+
"@jest/globals": "^30.3.0",
21+
"memfs": "^4.57.1"
22+
},
23+
"devDependencies": {
24+
"depcheck": "^1.4.7",
25+
"eslint": "^9.39.2",
26+
"prettier": "^3.8.1",
27+
"typescript": "~5.9.3"
28+
}
29+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2022",
4+
"module": "Node16",
5+
"esModuleInterop": true,
6+
"forceConsistentCasingInFileNames": true,
7+
"strict": true,
8+
"skipLibCheck": true,
9+
"isolatedModules": true,
10+
"rootDir": ".",
11+
"outDir": "./lib",
12+
"tsBuildInfoFile": "./lib/.tsbuildinfo"
13+
},
14+
"include": ["*.ts"],
15+
"exclude": []
16+
}

0 commit comments

Comments
 (0)