@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
256 lines • 11.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const file_1 = require("../vo/file");
// Mock dependencies
jest.mock('../vo/filemeta');
jest.mock('../vo/fileinfo');
// Mock the factory functions
jest.mock('../vo/fileinfo', () => ({
...jest.requireActual('../vo/fileinfo'),
newFileInfo: jest.fn(),
}));
jest.mock('../vo/filemeta', () => ({
...jest.requireActual('../vo/filemeta'),
newFileMeta: jest.fn(),
}));
describe('File Value Object', () => {
let mockFile;
let mockFileMeta;
let mockFs;
let file;
beforeEach(() => {
mockFile = {
close: jest.fn(),
read: jest.fn(),
readAt: jest.fn(),
seek: jest.fn(),
write: jest.fn(),
writeAt: jest.fn(),
name: jest.fn().mockReturnValue('/test/file.txt'),
readdir: jest.fn(),
readdirnames: jest.fn(),
stat: jest.fn(),
sync: jest.fn(),
truncate: jest.fn(),
writeString: jest.fn(),
};
mockFileMeta = {
fileName: jest.fn().mockReturnValue('/test/file.txt'),
relativeFilename: jest.fn().mockReturnValue('/file.txt'),
component: jest.fn().mockReturnValue('content'),
root: jest.fn().mockReturnValue('/test'),
};
mockFs = {
name: jest.fn().mockReturnValue('MockFs'),
stat: jest.fn(),
};
file = new file_1.File(mockFile, mockFileMeta, mockFs);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('constructor', () => {
it('should initialize with file, metadata, and filesystem', () => {
expect(file.file).toBe(mockFile);
expect(file.fileMeta).toBe(mockFileMeta);
expect(file.fs).toBe(mockFs);
expect(file._isDir).toBe(false);
});
it('should initialize as directory when specified', () => {
const dirFile = new file_1.File(mockFile, mockFileMeta, mockFs, true);
expect(dirFile._isDir).toBe(true);
});
it('should handle null file (no-op file)', () => {
const nopFile = new file_1.File(null, mockFileMeta, mockFs);
expect(nopFile.file).toBeNull();
});
});
describe('isNop', () => {
it('should return false for regular file', () => {
expect(file.isNop()).toBe(false);
});
it('should return true for null file', () => {
const nopFile = new file_1.File(null, mockFileMeta, mockFs);
expect(nopFile.isNop()).toBe(true);
});
});
describe('meta', () => {
it('should return file metadata', () => {
const result = file.meta();
expect(result).toBe(mockFileMeta);
});
});
describe('close', () => {
it('should close underlying file', async () => {
await file.close();
expect(mockFile.close).toHaveBeenCalledTimes(1);
});
it('should handle no-op file close', async () => {
const nopFile = new file_1.File(null, mockFileMeta, mockFs);
await expect(nopFile.close()).resolves.toBeUndefined();
});
});
describe('readDir', () => {
it('should read directory entries when file is directory', async () => {
const dirFile = new file_1.File(mockFile, mockFileMeta, mockFs, true);
const mockFileInfos = [
{ name: () => 'file1.txt', isDir: () => false },
{ name: () => 'file2.txt', isDir: () => false },
];
const mockWrappedFileInfos = [
{ fileName: () => 'file1.txt', setMeta: jest.fn() },
{ fileName: () => 'file2.txt', setMeta: jest.fn() },
];
const mockNewFileMeta = {
merge: jest.fn(),
};
mockFile.readdir.mockResolvedValue(mockFileInfos);
const { newFileInfo } = require('../vo/fileinfo');
const { newFileMeta } = require('../vo/filemeta');
newFileMeta.mockReturnValue(mockNewFileMeta);
newFileInfo
.mockReturnValueOnce(mockWrappedFileInfos[0])
.mockReturnValueOnce(mockWrappedFileInfos[1]);
const result = await dirFile.readDir(2);
expect(mockFile.readdir).toHaveBeenCalledWith(2);
expect(newFileInfo).toHaveBeenCalledTimes(2);
expect(mockNewFileMeta.merge).toHaveBeenCalledTimes(2);
expect(result).toEqual(mockWrappedFileInfos);
});
it('should return empty array when not a directory', async () => {
const result = await file.readDir(2);
expect(result).toEqual([]);
});
it('should return empty array for no-op file', async () => {
const nopFile = new file_1.File(null, mockFileMeta, mockFs, true);
const result = await nopFile.readDir(2);
expect(result).toEqual([]);
});
});
describe('File interface delegation', () => {
it('should delegate read to underlying file', async () => {
const buffer = new Uint8Array(10);
const expectedResult = { bytesRead: 5, buffer };
mockFile.read.mockResolvedValue(expectedResult);
const result = await file.read(buffer);
expect(mockFile.read).toHaveBeenCalledWith(buffer);
expect(result).toEqual(expectedResult);
});
it('should delegate readAt to underlying file', async () => {
const buffer = new Uint8Array(10);
const expectedResult = { bytesRead: 5, buffer };
mockFile.readAt.mockResolvedValue(expectedResult);
const result = await file.readAt(buffer, 100);
expect(mockFile.readAt).toHaveBeenCalledWith(buffer, 100);
expect(result).toEqual(expectedResult);
});
it('should delegate seek to underlying file', async () => {
mockFile.seek.mockResolvedValue(200);
const result = await file.seek(100, 1);
expect(mockFile.seek).toHaveBeenCalledWith(100, 1);
expect(result).toBe(200);
});
it('should delegate write to underlying file', async () => {
const buffer = new Uint8Array([1, 2, 3]);
const expectedResult = { bytesWritten: 3, buffer };
mockFile.write.mockResolvedValue(expectedResult);
const result = await file.write(buffer);
expect(mockFile.write).toHaveBeenCalledWith(buffer);
expect(result).toEqual(expectedResult);
});
it('should delegate writeAt to underlying file', async () => {
const buffer = new Uint8Array([1, 2, 3]);
const expectedResult = { bytesWritten: 3, buffer };
mockFile.writeAt.mockResolvedValue(expectedResult);
const result = await file.writeAt(buffer, 100);
expect(mockFile.writeAt).toHaveBeenCalledWith(buffer, 100);
expect(result).toEqual(expectedResult);
});
it('should get name from file metadata', () => {
const result = file.name();
expect(mockFileMeta.fileName).toHaveBeenCalled();
expect(result).toBe('file.txt'); // basename of '/test/file.txt'
});
it('should delegate readdir to readDir method', async () => {
const mockFileInfos = [{ name: () => 'test.txt' }];
// Mock the readDir method instead
const readDirSpy = jest.spyOn(file, 'readDir').mockResolvedValue([]);
const result = await file.readdir(10);
expect(readDirSpy).toHaveBeenCalledWith(10);
readDirSpy.mockRestore();
});
it('should delegate readdirnames to underlying file', async () => {
const expectedNames = ['file1.txt', 'file2.txt'];
mockFile.readdirnames.mockResolvedValue(expectedNames);
const result = await file.readdirnames(10);
expect(mockFile.readdirnames).toHaveBeenCalledWith(10);
expect(result).toEqual(expectedNames);
});
it('should delegate stat to underlying file', async () => {
const mockFileInfo = { name: () => 'test.txt' };
mockFile.stat.mockResolvedValue(mockFileInfo);
const result = await file.stat();
expect(mockFile.stat).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockFileInfo);
});
it('should delegate sync to underlying file', async () => {
await file.sync();
expect(mockFile.sync).toHaveBeenCalledTimes(1);
});
it('should delegate truncate to underlying file', async () => {
await file.truncate(100);
expect(mockFile.truncate).toHaveBeenCalledWith(100);
});
it('should delegate writeString to underlying file', async () => {
const expectedResult = { bytesWritten: 11 };
mockFile.writeString.mockResolvedValue(expectedResult);
const result = await file.writeString('Hello World');
expect(mockFile.writeString).toHaveBeenCalledWith('Hello World');
expect(result).toEqual(expectedResult);
});
});
describe('no-op file behavior', () => {
let nopFile;
beforeEach(() => {
nopFile = new file_1.File(null, mockFileMeta, mockFs);
});
it('should throw error for read on no-op file', async () => {
const buffer = new Uint8Array(10);
await expect(nopFile.read(buffer)).rejects.toThrow('File is null');
});
it('should throw error for write on no-op file', async () => {
const buffer = new Uint8Array([1, 2, 3]);
await expect(nopFile.write(buffer)).rejects.toThrow('File is null');
});
it('should handle name for no-op file', () => {
const result = nopFile.name();
expect(result).toBe('file.txt'); // From mockFileMeta.fileName()
expect(mockFileMeta.fileName).toHaveBeenCalled();
});
it('should throw error for stat on no-op file', async () => {
await expect(nopFile.stat()).rejects.toThrow('File is null');
});
});
describe('factory functions', () => {
it('should create File with newFile', () => {
const result = (0, file_1.newFile)(mockFile, '/test/file.txt', mockFs);
expect(result).toBeInstanceOf(file_1.File);
});
it('should create File with newFileWithMeta', () => {
const result = (0, file_1.newFileWithMeta)(mockFile, mockFileMeta, mockFs);
expect(result).toBeInstanceOf(file_1.File);
expect(result.meta()).toBe(mockFileMeta);
});
it('should create directory File with newDirFileWithMeta', () => {
const result = (0, file_1.newDirFileWithMeta)(mockFile, mockFileMeta, mockFs);
expect(result).toBeInstanceOf(file_1.File);
expect(result._isDir).toBe(true);
});
it('should handle null file in factory functions', () => {
const result = (0, file_1.newFileWithMeta)(null, mockFileMeta, mockFs);
expect(result).toBeInstanceOf(file_1.File);
expect(result.isNop()).toBe(true);
});
});
});
//# sourceMappingURL=vo-file.test.js.map