Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 77 additions & 14 deletions src/test/local-file-system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,88 @@ describe('LocalFileSystem', () => {
let tempDir: string;

beforeEach(async () => {
tempDir = await fs.mkdtemp(path.join(tmpdir(), 'reporter-test-'));
tempDir = await fs.mkdtemp(path.join(tmpdir(), 'lfs-'));
await fs.writeFile(
path.join(tempDir, 'package.json'),
JSON.stringify({name: 'pkg', version: '1.0.0'})
);
});

afterEach(async () => {
await fs.rm(tempDir, {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 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);
});
it('should report false for a missing file and true for an existing file', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be two tests

Copy link
Contributor

@43081j 43081j Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at it, this and the readFile tests were probably organised better before, no?

roughly:

  • fileExists
    • test that it is true for files that exist
    • test that it is false for files that dont exist
  • readFile
    • test that it returns files that exist
    • test that it throws for files that don't exist

same with the listPackageFiles tests, they should have their own block i think

  • listPackageFiles
    • return empty list when no node_modules
    • return list of packages when node_modules exists

and getInstallSize:

  • getInstallSize
    • returns 0 when no modules
    • returns size when modules

const lfs = new LocalFileSystem(tempDir);
expect(await lfs.fileExists('/tsconfig.json')).toBe(false);

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(tempDir);

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(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(tempDir, 'node_modules', 'a', 'node_modules', 'b'),
{
recursive: true
}
);
await fs.writeFile(
path.join(tempDir, 'node_modules', 'a', 'package.json'),
JSON.stringify({name: 'a', version: '1.0.0'})
);
await fs.writeFile(
path.join(
tempDir,
'node_modules',
'a',
'node_modules',
'b',
'package.json'
),
JSON.stringify({name: 'b', version: '1.0.0'})
);

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/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(tempDir);
expect(await lfs.getInstallSize()).toBe(0);

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);
});
});
117 changes: 74 additions & 43 deletions src/test/tarball-file-system.test.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,84 @@
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);
});

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();
});

afterEach(async () => {
await fs.rm(tempDir, {recursive: true, force: 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')
);
});

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 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);
});
});
Loading