From 1d6d4e3f60e8e2eea9a9d84ac1f9e0f6637382ae Mon Sep 17 00:00:00 2001 From: outslept <135520429+outslept@users.noreply.github.com> Date: Sun, 21 Sep 2025 03:25:53 +0300 Subject: [PATCH 1/3] x --- src/test/tarball-file-system.test.ts | 118 +++++++++++++++++---------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/src/test/tarball-file-system.test.ts b/src/test/tarball-file-system.test.ts index d5f0610..568c5e0 100644 --- a/src/test/tarball-file-system.test.ts +++ b/src/test/tarball-file-system.test.ts @@ -1,53 +1,83 @@ -import {describe, it, expect, beforeEach, afterEach} from 'vitest'; -import {TarballFileSystem} from '../tarball-file-system.js'; -import {detectAndPack} from '../detect-and-pack-node.js'; -import * as fs from 'node:fs/promises'; +import {describe, it, expect, beforeEach, vi} from 'vitest'; import * as path from 'node:path'; -import {tmpdir} from 'node:os'; + +import {TarballFileSystem} from '../tarball-file-system.js'; + +const enc = (s: string) => new TextEncoder().encode(s); +let mockFiles: Array<{name: string; data: Uint8Array}>; +const mockRootDir = 'package'; + +vi.mock('@publint/pack', () => { + return { + unpack: vi.fn(async () => ({ + rootDir: mockRootDir, + files: mockFiles + })) + }; +}); + describe('TarballFileSystem', () => { - let tempDir: string; + beforeEach(() => { + mockFiles = [ + { + name: path.posix.join(mockRootDir, 'package.json'), + data: enc(JSON.stringify({name: 'pkg', version: '1.0.0'})) + }, + { + name: path.posix.join(mockRootDir, 'tsconfig.json'), + data: enc('{}') + }, + { + name: path.posix.join(mockRootDir, 'node_modules/a/package.json'), + data: enc(JSON.stringify({name: 'a', version: '1.0.0'})) + }, + { + name: path.posix.join( + mockRootDir, + 'node_modules/a/node_modules/b/package.json' + ), + data: enc(JSON.stringify({name: 'b', version: '1.0.0'})) + }, + { + name: path.posix.join(mockRootDir, 'node_modules/a/readme.txt'), + data: enc('abc') + } + ]; + }); - beforeEach(async () => { - tempDir = await fs.mkdtemp(path.join(tmpdir(), 'reporter-test-')); + it('should report true for an existing file and false for a missing file', async () => { + const tfs = new TarballFileSystem(new ArrayBuffer(0)); + + expect(await tfs.fileExists('/tsconfig.json')).toBe(true); + expect(await tfs.fileExists('/does-not-exist.json')).toBe(false); }); - afterEach(async () => { - await fs.rm(tempDir, {recursive: true, force: true}); + it('should read /package.json and throw on a non-existent path', async () => { + const tfs = new TarballFileSystem(new ArrayBuffer(0)); + + const text = await tfs.readFile('/package.json'); + expect(JSON.parse(text).name).toBe('pkg'); + + await expect(tfs.readFile('/nope.json')).rejects.toBeTruthy(); }); - describe('fileExists', () => { - it('should return false when file does not exist in tarball', async () => { - // Create a minimal package.json for the tarball - await fs.writeFile( - path.join(tempDir, 'package.json'), - JSON.stringify({ - name: 'test-package', - version: '1.0.0' - }) - ); - - const tarball = await detectAndPack(tempDir, 'npm'); - const fileSystem = new TarballFileSystem(tarball); - const hasConfig = await fileSystem.fileExists('/tsconfig.json'); - expect(hasConfig).toBe(false); - }); - - it('should return true when file exists in tarball', async () => { - // Create a minimal package.json for the tarball - await fs.writeFile( - path.join(tempDir, 'package.json'), - JSON.stringify({ - name: 'test-package', - version: '1.0.0' - }) - ); - - await fs.writeFile(path.join(tempDir, 'tsconfig.json'), '{}'); - const tarball = await detectAndPack(tempDir, 'npm'); - const fileSystem = new TarballFileSystem(tarball); - const hasConfig = await fileSystem.fileExists('/tsconfig.json'); - expect(hasConfig).toBe(true); - }); + it('should list package.json files, including nested ones', async () => { + const tfs = new TarballFileSystem(new ArrayBuffer(0)); + const root = await tfs.getRootDir(); + const files = await tfs.listPackageFiles(); + + expect(files).toContain(path.posix.join(root, 'package.json')); + expect(files).toContain(path.posix.join(root, 'node_modules/a/package.json')); + expect(files).toContain( + path.posix.join(root, 'node_modules/a/node_modules/b/package.json') + ); }); -}); + + it('should compute install size as the sum of file bytes from the unpacked tarball', async () => { + const tfs = new TarballFileSystem(new ArrayBuffer(0)); + const expected = mockFiles.reduce((n, f) => n + f.data.byteLength, 0); + const size = await tfs.getInstallSize(); + expect(size).toBe(expected); + }); +}); \ No newline at end of file From edd8c6123732212c2677d386f2cabaf22fa6a603 Mon Sep 17 00:00:00 2001 From: outslept <135520429+outslept@users.noreply.github.com> Date: Sun, 21 Sep 2025 03:27:37 +0300 Subject: [PATCH 2/3] x --- src/test/local-file-system.test.ts | 80 ++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/src/test/local-file-system.test.ts b/src/test/local-file-system.test.ts index d3a48b7..90dc9a2 100644 --- a/src/test/local-file-system.test.ts +++ b/src/test/local-file-system.test.ts @@ -5,28 +5,78 @@ import * as path from 'node:path'; import {tmpdir} from 'node:os'; describe('LocalFileSystem', () => { - let tempDir: string; + let dir: string; beforeEach(async () => { - tempDir = await fs.mkdtemp(path.join(tmpdir(), 'reporter-test-')); + dir = await fs.mkdtemp(path.join(tmpdir(), 'lfs-')); + await fs.writeFile( + path.join(dir, 'package.json'), + JSON.stringify({name: 'pkg', version: '1.0.0'}) + ); }); afterEach(async () => { - await fs.rm(tempDir, {recursive: true, force: true}); + await fs.rm(dir, {recursive: true, force: true}); }); - describe('fileExists', () => { - it('should return false when tsconfig.json does not exist', async () => { - const fileSystem = new LocalFileSystem(tempDir); - const hasConfig = await fileSystem.fileExists('/tsconfig.json'); - expect(hasConfig).toBe(false); - }); + it('should report false for a missing file and true for an existing file', async () => { + const lfs = new LocalFileSystem(dir); + expect(await lfs.fileExists('/tsconfig.json')).toBe(false); + + await fs.writeFile(path.join(dir, 'tsconfig.json'), '{}'); + expect(await lfs.fileExists('/tsconfig.json')).toBe(true); + }); + + it('should read /package.json and throw on a non-existent path', async () => { + const lfs = new LocalFileSystem(dir); - it('should return true when file exists', async () => { - await fs.writeFile(path.join(tempDir, 'tsconfig.json'), '{}'); - const fileSystem = new LocalFileSystem(tempDir); - const hasConfig = await fileSystem.fileExists('/tsconfig.json'); - expect(hasConfig).toBe(true); + const text = await lfs.readFile('/package.json'); + expect(JSON.parse(text).name).toBe('pkg'); + + await expect(lfs.readFile('/does-not-exist.json')).rejects.toBeTruthy(); + }); + + it('should return an empty list of package files when node_modules is missing', async () => { + const lfs = new LocalFileSystem(dir); + const files = await lfs.listPackageFiles(); + expect(files).toEqual([]); + }); + + it('should list package.json files in node_modules, including nested ones', async () => { + await fs.mkdir(path.join(dir, 'node_modules', 'a', 'node_modules', 'b'), { + recursive: true }); + await fs.writeFile( + path.join(dir, 'node_modules', 'a', 'package.json'), + JSON.stringify({name: 'a', version: '1.0.0'}) + ); + await fs.writeFile( + path.join(dir, 'node_modules', 'a', 'node_modules', 'b', 'package.json'), + JSON.stringify({name: 'b', version: '1.0.0'}) + ); + + const lfs = new LocalFileSystem(dir); + const files = await lfs.listPackageFiles(); + + expect( + files.some((p) => p.endsWith('/node_modules/a/package.json')) + ).toBe(true); + expect( + files.some((p) => + p.endsWith('/node_modules/a/node_modules/b/package.json') + ) + ).toBe(true); + }); + + it('should report 0 install size without node_modules and a positive size when files exist', async () => { + const lfs = new LocalFileSystem(dir); + expect(await lfs.getInstallSize()).toBe(0); + + await fs.mkdir(path.join(dir, 'node_modules', 'x'), {recursive: true}); + await fs.writeFile(path.join(dir, 'node_modules', 'x', 'f1.txt'), 'abc'); + await fs.writeFile(path.join(dir, 'node_modules', 'x', 'f2.txt'), 'X'); + + const size = await lfs.getInstallSize(); + expect(size).toBeGreaterThan(0); }); -}); +}); \ No newline at end of file From 0220a43a81bc145556c0b4bcb40e836df5e886f0 Mon Sep 17 00:00:00 2001 From: outslept <135520429+outslept@users.noreply.github.com> Date: Sun, 21 Sep 2025 03:32:09 +0300 Subject: [PATCH 3/3] x --- src/test/local-file-system.test.ts | 57 +++++++++++++++++----------- src/test/tarball-file-system.test.ts | 7 ++-- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/test/local-file-system.test.ts b/src/test/local-file-system.test.ts index 90dc9a2..aa04fef 100644 --- a/src/test/local-file-system.test.ts +++ b/src/test/local-file-system.test.ts @@ -5,30 +5,30 @@ import * as path from 'node:path'; import {tmpdir} from 'node:os'; describe('LocalFileSystem', () => { - let dir: string; + let tempDir: string; beforeEach(async () => { - dir = await fs.mkdtemp(path.join(tmpdir(), 'lfs-')); + tempDir = await fs.mkdtemp(path.join(tmpdir(), 'lfs-')); await fs.writeFile( - path.join(dir, 'package.json'), + path.join(tempDir, 'package.json'), JSON.stringify({name: 'pkg', version: '1.0.0'}) ); }); afterEach(async () => { - await fs.rm(dir, {recursive: true, force: true}); + await fs.rm(tempDir, {recursive: true, force: true}); }); it('should report false for a missing file and true for an existing file', async () => { - const lfs = new LocalFileSystem(dir); + const lfs = new LocalFileSystem(tempDir); expect(await lfs.fileExists('/tsconfig.json')).toBe(false); - await fs.writeFile(path.join(dir, 'tsconfig.json'), '{}'); + await fs.writeFile(path.join(tempDir, 'tsconfig.json'), '{}'); expect(await lfs.fileExists('/tsconfig.json')).toBe(true); }); it('should read /package.json and throw on a non-existent path', async () => { - const lfs = new LocalFileSystem(dir); + const lfs = new LocalFileSystem(tempDir); const text = await lfs.readFile('/package.json'); expect(JSON.parse(text).name).toBe('pkg'); @@ -37,30 +37,40 @@ describe('LocalFileSystem', () => { }); it('should return an empty list of package files when node_modules is missing', async () => { - const lfs = new LocalFileSystem(dir); + const lfs = new LocalFileSystem(tempDir); const files = await lfs.listPackageFiles(); expect(files).toEqual([]); }); it('should list package.json files in node_modules, including nested ones', async () => { - await fs.mkdir(path.join(dir, 'node_modules', 'a', 'node_modules', 'b'), { - recursive: true - }); + await fs.mkdir( + path.join(tempDir, 'node_modules', 'a', 'node_modules', 'b'), + { + recursive: true + } + ); await fs.writeFile( - path.join(dir, 'node_modules', 'a', 'package.json'), + path.join(tempDir, 'node_modules', 'a', 'package.json'), JSON.stringify({name: 'a', version: '1.0.0'}) ); await fs.writeFile( - path.join(dir, 'node_modules', 'a', 'node_modules', 'b', 'package.json'), + path.join( + tempDir, + 'node_modules', + 'a', + 'node_modules', + 'b', + 'package.json' + ), JSON.stringify({name: 'b', version: '1.0.0'}) ); - const lfs = new LocalFileSystem(dir); + const lfs = new LocalFileSystem(tempDir); const files = await lfs.listPackageFiles(); - expect( - files.some((p) => p.endsWith('/node_modules/a/package.json')) - ).toBe(true); + expect(files.some((p) => p.endsWith('/node_modules/a/package.json'))).toBe( + true + ); expect( files.some((p) => p.endsWith('/node_modules/a/node_modules/b/package.json') @@ -69,14 +79,17 @@ describe('LocalFileSystem', () => { }); it('should report 0 install size without node_modules and a positive size when files exist', async () => { - const lfs = new LocalFileSystem(dir); + const lfs = new LocalFileSystem(tempDir); expect(await lfs.getInstallSize()).toBe(0); - await fs.mkdir(path.join(dir, 'node_modules', 'x'), {recursive: true}); - await fs.writeFile(path.join(dir, 'node_modules', 'x', 'f1.txt'), 'abc'); - await fs.writeFile(path.join(dir, 'node_modules', 'x', 'f2.txt'), 'X'); + await fs.mkdir(path.join(tempDir, 'node_modules', 'x'), {recursive: true}); + await fs.writeFile( + path.join(tempDir, 'node_modules', 'x', 'f1.txt'), + 'abc' + ); + await fs.writeFile(path.join(tempDir, 'node_modules', 'x', 'f2.txt'), 'X'); const size = await lfs.getInstallSize(); expect(size).toBeGreaterThan(0); }); -}); \ No newline at end of file +}); diff --git a/src/test/tarball-file-system.test.ts b/src/test/tarball-file-system.test.ts index 568c5e0..94a8722 100644 --- a/src/test/tarball-file-system.test.ts +++ b/src/test/tarball-file-system.test.ts @@ -16,7 +16,6 @@ vi.mock('@publint/pack', () => { }; }); - describe('TarballFileSystem', () => { beforeEach(() => { mockFiles = [ @@ -68,7 +67,9 @@ describe('TarballFileSystem', () => { const files = await tfs.listPackageFiles(); expect(files).toContain(path.posix.join(root, 'package.json')); - expect(files).toContain(path.posix.join(root, 'node_modules/a/package.json')); + expect(files).toContain( + path.posix.join(root, 'node_modules/a/package.json') + ); expect(files).toContain( path.posix.join(root, 'node_modules/a/node_modules/b/package.json') ); @@ -80,4 +81,4 @@ describe('TarballFileSystem', () => { const size = await tfs.getInstallSize(); expect(size).toBe(expected); }); -}); \ No newline at end of file +});