Files
relicario/extension/src/service-worker/__tests__/mem-fs.test.ts

99 lines
3.9 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { createMemFs } from '../mem-fs';
describe('createMemFs', () => {
it('writeFile/readFile binary roundtrip (Uint8Array)', async () => {
const fs = createMemFs().promises;
const data = new Uint8Array([1, 2, 3, 4]);
await fs.writeFile('/a.bin', data);
const result = await fs.readFile('/a.bin', undefined);
expect(result).toBeInstanceOf(Uint8Array);
expect(Array.from(result as Uint8Array)).toEqual([1, 2, 3, 4]);
});
it('writeFile/readFile utf8 roundtrip via {encoding:"utf8"}', async () => {
const fs = createMemFs().promises;
await fs.writeFile('/hello.txt', 'hello Relicario');
const result = await fs.readFile('/hello.txt', { encoding: 'utf8' });
expect(result).toBe('hello Relicario');
});
it('writeFile/readFile utf8 roundtrip via string encoding arg', async () => {
const fs = createMemFs().promises;
await fs.writeFile('/hello2.txt', 'hola Relicario');
const result = await fs.readFile('/hello2.txt', 'utf8');
expect(result).toBe('hola Relicario');
});
it('writeFile copies a subarray view correctly', async () => {
const fs = createMemFs().promises;
const bigBuf = new Uint8Array([0, 1, 10, 20, 30, 99, 99]);
const view = bigBuf.subarray(2, 5); // [10, 20, 30]
await fs.writeFile('/sub.bin', view);
// Mutate the original buffer — stored copy must be unaffected
bigBuf[2] = 0xff;
bigBuf[3] = 0xff;
bigBuf[4] = 0xff;
const result = await fs.readFile('/sub.bin', undefined);
expect(Array.from(result as Uint8Array)).toEqual([10, 20, 30]);
});
it('readdir returns only immediate children for explicit mkdir dirs', async () => {
const fs = createMemFs().promises;
await fs.mkdir('/mydir');
await fs.writeFile('/mydir/file1.txt', 'a');
await fs.writeFile('/mydir/file2.txt', 'b');
await fs.mkdir('/mydir/subdir');
const entries = await fs.readdir('/mydir');
expect(entries.sort()).toEqual(['file1.txt', 'file2.txt', 'subdir'].sort());
});
it('readdir returns only immediate children for implicit dirs', async () => {
const fs = createMemFs().promises;
// Write a deeply nested file without explicit mkdir
await fs.writeFile('/a/b/c.txt', 'test');
const aEntries = await fs.readdir('/a');
expect(aEntries).toEqual(['b']);
const bEntries = await fs.readdir('/a/b');
expect(bEntries).toEqual(['c.txt']);
});
it('stat: a written file isFile()', async () => {
const fs = createMemFs().promises;
await fs.writeFile('/statfile.txt', 'data');
const st = await fs.stat('/statfile.txt');
expect(st.isFile()).toBe(true);
expect(st.isDirectory()).toBe(false);
expect(st.isSymbolicLink()).toBe(false);
expect(typeof st.size).toBe('number');
expect(typeof st.ino).toBe('number');
expect(typeof st.mode).toBe('number');
});
it('stat: an implicit parent directory isDirectory()', async () => {
const fs = createMemFs().promises;
await fs.writeFile('/c/items/x.enc', new Uint8Array([9]));
const st = await fs.stat('/c/items');
expect(st.isDirectory()).toBe(true);
expect(st.isFile()).toBe(false);
});
it('stat: missing path throws ENOENT', async () => {
const fs = createMemFs().promises;
await expect(fs.stat('/does/not/exist')).rejects.toMatchObject({ code: 'ENOENT' });
});
it('unlink removes a file (subsequent readFile throws ENOENT)', async () => {
const fs = createMemFs().promises;
await fs.writeFile('/todelete.txt', 'bye');
await fs.unlink('/todelete.txt');
await expect(fs.readFile('/todelete.txt', undefined)).rejects.toMatchObject({ code: 'ENOENT' });
});
it('readlink and symlink are functions (regression guard for isomorphic-git bindFs)', () => {
const { promises } = createMemFs();
expect(typeof promises.readlink).toBe('function');
expect(typeof promises.symlink).toBe('function');
});
});