import { Dirent, readFileSync, readdirSync } from 'fs'; import { basename, dirname, extname, join, parse } from 'path'; /** * Return a boolean indicating that given dirent is a file or not. * * @param dirent The dirent object * @return A boolean indicating that the dirent name matches the text */ export function direntIsFile(dirent: Dirent): boolean { return dirent.isFile(); } /** * Return a boolean indicating that the dirent name includes the text. * * @param text The text to match * @param dirent The dirent object * @return A boolean indicating that the dirent name includes the text */ export function direntFilenameMatchText(text: string, dirent: Dirent): boolean { return parse(dirent.name).name === text; } /** * Read the file and parse its content as json. * * @param path The file path * @return The file content */ export function readJSONFileSync(path: string): any { return JSON.parse(readFileSync(path).toString()); } /** * Read the fixture file. * * @param path The fixture path * @return The fixture content */ export function readFixtureFileSync(path: string): any { if (extname(path) === '.json') { return readJSONFileSync(path); } return readFileSync(path); } /** * Find the file path of a given dirname and basename. * * @param dir The file dirname * @param base The file basename * @param scenario An optional custom scenario for a fixture file * @return File path if found */ export function findFilePathByDirnameAndBasename( dir: string, base: string, scenario?: string ): string { const fullBasename = scenario ? `${base}--${scenario}` : base; const [fixture] = readdirSync(dir, { withFileTypes: true }) .filter(direntIsFile) .filter((dirent) => direntFilenameMatchText(fullBasename, dirent)); if (!fixture) { throw new Error('Fixture not found'); } return join(dir, fixture.name); } /** * Scan the fixture path of a given path, searching also as a folder with an index file. * * @param path The search path * @param scenario An optional custom scenario for a fixture file * @return The fixture path */ export function scanFixturePath(path: string, scenario?: string): string { const folder = dirname(path); const file = basename(path); const pathDirnameFixtureDirectory = join('data', folder); const pathFixtureDirectory = join('data', path); try { const indexFixture = findFilePathByDirnameAndBasename( pathFixtureDirectory, 'index', scenario ); return indexFixture; } catch (error) { const fixture = findFilePathByDirnameAndBasename( pathDirnameFixtureDirectory, file, scenario ); return fixture; } } /** * Read the first file that matches a valid fixture of a given path and scenario. * * @param path The search path * @param scenario An optional custom scenario for a fixture file * @return The file content */ export function readFixturePathSync(path: string, scenario?: string): any { const fixturePath = scanFixturePath(path, scenario); return readFixtureFileSync(fixturePath); } /** * Read a fixture file using the extension when available, or by scanning the whole directory. * * @param path The file path * @param fallbackPath The fallback file path * @param scenario An optional custom scenario for a fixture file * @return The file content. */ export function readFixtureSync( path: string, fallbackPath?: string, scenario?: string ): any { const extension = extname(path); try { return extension ? readFixtureFileSync(path) : readFixturePathSync(path, scenario); } catch (error) { if (fallbackPath) { try { return readFixturePathSync(fallbackPath, scenario); } catch (fallbackError) { console.error( 'You probably forgot to create the fallback fixture file', fallbackPath, fallbackError ); } } else { console.error( 'You probably forgot to create the fixture file.', path, error ); } } }