Skip to content

Commit 4162353

Browse files
authored
refactor(shrinkwrap-extractor): Refactor test fixtures (#1226)
The `shrinkwrap-extractor` tests use real `package-lock.json` samples as fixtures. GitHub Dependabot scans all `package-lock.json` files in the repository and reports vulnerabilities, even though these are: - Test-only data files (never installed or executed) - Part of a private package (`shrinkwrap-extractor`) - Parsed virtually by `@npmcli/arborist.loadVirtual()` without installing packages This creates false-positive security alerts at https://github.com/UI5/cli/security/dependabot. The solution is to rename test fixtures from `package-lock.json` to `package-lock.fixture.json` so Dependabot ignores them. Since `@npmcli/arborist.loadVirtual()` requires a file named exactly `package-lock.json`, we create temporary symlinks during test execution. Symlinks are automatically cleaned up after each test.
1 parent 76fbae6 commit 4162353

File tree

7 files changed

+50
-6
lines changed

7 files changed

+50
-6
lines changed

internal/shrinkwrap-extractor/test/fixture/invalid/invalid-packages/package-lock.json renamed to internal/shrinkwrap-extractor/test/fixture/invalid/invalid-packages/package-lock.fixture.json

File renamed without changes.

internal/shrinkwrap-extractor/test/fixture/invalid/malformed/package-lock.json renamed to internal/shrinkwrap-extractor/test/fixture/invalid/malformed/package-lock.fixture.json

File renamed without changes.

internal/shrinkwrap-extractor/test/fixture/invalid/no-packages/package-lock.json renamed to internal/shrinkwrap-extractor/test/fixture/invalid/no-packages/package-lock.fixture.json

File renamed without changes.

internal/shrinkwrap-extractor/test/fixture/invalid/v2/package-lock.json renamed to internal/shrinkwrap-extractor/test/fixture/invalid/v2/package-lock.fixture.json

File renamed without changes.

internal/shrinkwrap-extractor/test/fixture/project.a/package-lock.json renamed to internal/shrinkwrap-extractor/test/fixture/project.a/package-lock.fixture.json

File renamed without changes.

internal/shrinkwrap-extractor/test/fixture/project.b/package-lock.json renamed to internal/shrinkwrap-extractor/test/fixture/project.b/package-lock.fixture.json

File renamed without changes.

internal/shrinkwrap-extractor/test/lib/convertToShrinkwrap.js

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import path from "node:path";
2-
import {readFile, mkdir, writeFile, unlink} from "node:fs/promises";
2+
import {readFile, mkdir, writeFile, unlink, symlink} from "node:fs/promises";
33
import convertPackageLockToShrinkwrap from "../../lib/convertPackageLockToShrinkwrap.js";
44
import {test} from "node:test";
55
import assert from "node:assert";
@@ -18,10 +18,27 @@ function setupPacoteMock() {
1818
});
1919
}
2020

21+
/**
22+
* Create a temporary symlink from package-lock.fixture.json to package-lock.json
23+
* This is needed because @npmcli/arborist.loadVirtual() expects package-lock.json
24+
*
25+
* @param {string} fixtureDir - Directory containing the fixture file
26+
* @returns {Promise<string>} Path to the created symlink
27+
*/
28+
async function setupFixtureSymlink(fixtureDir) {
29+
const symlinkPath = path.join(fixtureDir, "package-lock.json");
30+
const targetPath = "package-lock.fixture.json";
31+
await symlink(targetPath, symlinkPath);
32+
return symlinkPath;
33+
}
34+
2135
test("Convert package-lock.json to shrinkwrap", async (t) => {
2236
const __dirname = import.meta.dirname;
2337

2438
const cwd = path.join(__dirname, "..", "fixture", "project.a");
39+
const symlinkPath = await setupFixtureSymlink(cwd);
40+
t.after(async () => await unlink(symlinkPath).catch(() => {}));
41+
2542
const targetPackageName = "@ui5/cli";
2643
const shrinkwrapJson = await convertPackageLockToShrinkwrap(cwd, targetPackageName);
2744

@@ -80,6 +97,9 @@ test("Compare generated shrinkwrap with expected result", async (t) => {
8097

8198
// Generate shrinkwrap from fixture
8299
const cwd = path.join(__dirname, "..", "fixture", "project.a");
100+
const symlinkPath = await setupFixtureSymlink(cwd);
101+
t.after(async () => await unlink(symlinkPath).catch(() => {}));
102+
83103
const targetPackageName = "@ui5/cli";
84104
const generatedShrinkwrap = await convertPackageLockToShrinkwrap(cwd, targetPackageName);
85105

@@ -131,6 +151,9 @@ test("Compare generated shrinkwrap with expected result", async (t) => {
131151

132152
// Generate shrinkwrap from fixture
133153
const cwd = path.join(__dirname, "..", "fixture", "project.b");
154+
const symlinkPath = await setupFixtureSymlink(cwd);
155+
t.after(async () => await unlink(symlinkPath).catch(() => {}));
156+
134157
const targetPackageName = "@ui5/cli";
135158

136159
const generatedShrinkwrap = await convertPackageLockToShrinkwrap(cwd, targetPackageName);
@@ -150,6 +173,8 @@ test("Compare generated shrinkwrap with expected result", async (t) => {
150173
test("Error handling - invalid target package name", async (t) => {
151174
const __dirname = import.meta.dirname;
152175
const validCwd = path.join(__dirname, "..", "fixture", "project.a");
176+
const symlinkPath = await setupFixtureSymlink(validCwd);
177+
t.after(async () => await unlink(symlinkPath).catch(() => {}));
153178

154179
await assert.rejects(
155180
convertPackageLockToShrinkwrap(validCwd, null),
@@ -170,6 +195,8 @@ test("Error handling - invalid target package name", async (t) => {
170195
test("Error handling - target package not found", async (t) => {
171196
const __dirname = import.meta.dirname;
172197
const validCwd = path.join(__dirname, "..", "fixture", "project.a");
198+
const symlinkPath = await setupFixtureSymlink(validCwd);
199+
t.after(async () => await unlink(symlinkPath).catch(() => {}));
173200

174201
await assert.rejects(
175202
convertPackageLockToShrinkwrap(validCwd, "non-existent-package"),
@@ -187,28 +214,45 @@ test("Error handling - invalid workspace directory", async (t) => {
187214
test("Error handling - invalid package-lock.json files", async (t) => {
188215
const __dirname = import.meta.dirname;
189216

217+
// Setup symlinks for all invalid fixtures
218+
const malformedDir = path.join(__dirname, "..", "fixture", "invalid", "malformed");
219+
const noPackagesDir = path.join(__dirname, "..", "fixture", "invalid", "no-packages");
220+
const invalidPackagesDir = path.join(__dirname, "..", "fixture", "invalid", "invalid-packages");
221+
const v2Dir = path.join(__dirname, "..", "fixture", "invalid", "v2");
222+
223+
const symlinks = [
224+
await setupFixtureSymlink(malformedDir),
225+
await setupFixtureSymlink(noPackagesDir),
226+
await setupFixtureSymlink(invalidPackagesDir),
227+
await setupFixtureSymlink(v2Dir)
228+
];
229+
230+
// Cleanup all symlinks after test
231+
t.after(async () => {
232+
await Promise.all(symlinks.map((link) => unlink(link).catch(() => {})));
233+
});
234+
190235
// Test malformed JSON
191236
await assert.rejects(
192-
convertPackageLockToShrinkwrap(path.join(__dirname, "..", "fixture", "invalid", "malformed"), "@ui5/cli"),
237+
convertPackageLockToShrinkwrap(malformedDir, "@ui5/cli"),
193238
/Unexpected token/
194239
);
195240

196241
// Test missing packages field
197242
await assert.rejects(
198-
convertPackageLockToShrinkwrap(path.join(__dirname, "..", "fixture", "invalid", "no-packages"), "@ui5/cli"),
243+
convertPackageLockToShrinkwrap(noPackagesDir, "@ui5/cli"),
199244
/Invalid package-lock\.json: missing packages field/
200245
);
201246

202247
// Test invalid packages field
203248
await assert.rejects(
204-
convertPackageLockToShrinkwrap(
205-
path.join(__dirname, "..", "fixture", "invalid", "invalid-packages"), "@ui5/cli"),
249+
convertPackageLockToShrinkwrap(invalidPackagesDir, "@ui5/cli"),
206250
/Invalid package-lock\.json: packages field must be an object/
207251
);
208252

209253
// Test unsupported lockfile version
210254
await assert.rejects(
211-
convertPackageLockToShrinkwrap(path.join(__dirname, "..", "fixture", "invalid", "v2"), "@ui5/cli"),
255+
convertPackageLockToShrinkwrap(v2Dir, "@ui5/cli"),
212256
/Unsupported lockfile version: 2\. Only lockfile version 3 is supported/
213257
);
214258
});

0 commit comments

Comments
 (0)