{"id":15391409,"url":"https://github.com/mizdra/inline-fixture-files","last_synced_at":"2025-04-15T23:18:32.761Z","repository":{"id":174382001,"uuid":"648701201","full_name":"mizdra/inline-fixture-files","owner":"mizdra","description":"A utility to write filesystem fixtures inline.","archived":false,"fork":false,"pushed_at":"2025-02-16T15:28:09.000Z","size":671,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-15T23:18:28.335Z","etag":null,"topics":["filesystem","fixtures","nodejs","testing","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mizdra.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mizdra"}},"created_at":"2023-06-02T15:32:58.000Z","updated_at":"2025-03-19T15:30:16.000Z","dependencies_parsed_at":"2023-07-10T18:16:12.515Z","dependency_job_id":"455d7a22-45a4-408a-8e2f-dd096c6ce689","html_url":"https://github.com/mizdra/inline-fixture-files","commit_stats":{"total_commits":150,"total_committers":2,"mean_commits":75.0,"dds":"0.11333333333333329","last_synced_commit":"a0aeef0beeae447fb4b48a3f300a0de816fd8e6c"},"previous_names":["mizdra/inline-fs-fixtures","mizdra/inline-fixture-files"],"tags_count":6,"template":false,"template_full_name":"mizdra/npm-package-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizdra%2Finline-fixture-files","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizdra%2Finline-fixture-files/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizdra%2Finline-fixture-files/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizdra%2Finline-fixture-files/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mizdra","download_url":"https://codeload.github.com/mizdra/inline-fixture-files/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249167592,"owners_count":21223532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filesystem","fixtures","nodejs","testing","typescript"],"created_at":"2024-10-01T15:11:01.703Z","updated_at":"2025-04-15T23:18:32.741Z","avatar_url":"https://github.com/mizdra.png","language":"TypeScript","funding_links":["https://github.com/sponsors/mizdra"],"categories":[],"sub_categories":[],"readme":"# @mizdra/inline-fixture-files\n\nThe utility for writing fixture files inline.\n\n## Installation\n\n```console\n$ npm i -D @mizdra/inline-fixture-files\n```\n\n## Features\n\n- Write fixture files inline\n- Type-safe access to the fixture file path\n- Share fixture files with test cases\n- Flexible fixture creation API\n- Cross-platform support\n- Zero dependencies\n\n## Motivation\n\nWhen writing tests, it is often necessary to create fixture files. A common approach is to create a `fixture/` directory and write the fixture files there.\n\n```console\n$ ls -R fixture\ntest-case-1/src:\nindex.ts\n\ntest-case-2/src:\nindex.ts    math.ts\n```\n\nHowever, this approach leads to the test code and fixture file definitions being far apart. This makes it difficult to understand the test code.\n\n`@mizdra/inline-fixture-files` allows you to define fixture files in your test code. This makes the test code easier to understand.\n\n## API documentation\n\nSee [/docs/api/index.md](/docs/api/index.md).\n\n## Examples\n\n### Example: Basic\n\nYou can use `iff.paths` to get the paths of the generated fixture files.\n\n```ts\n// example/01-basic.test.ts\nimport { randomUUID } from 'node:crypto';\nimport { rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport dedent from 'dedent';\nimport { ESLint } from 'eslint';\nimport { expect, test } from 'vitest';\nimport { defineIFFCreator } from '@mizdra/inline-fixture-files';\n\n// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\nconst fixtureDir = join(tmpdir(), 'your-app-name', process.env['VITEST_POOL_ID']!);\nconst createIFF = defineIFFCreator({ generateRootDir: () =\u003e join(fixtureDir, randomUUID()) });\n\nawait rm(fixtureDir, { recursive: true, force: true });\n\ntest('eslint reports lint errors', async () =\u003e {\n  const iff = await createIFF({\n    '.eslintrc.cjs': `module.exports = { root: true, rules: { semi: 'error' } };`,\n    'src': {\n      'semi.js': dedent`\n          var withSemicolon = 1;\n          var withoutSemicolon = 2\n        `,\n    },\n    // The above can be written in abbreviated form:\n    // 'src/semi.js': dedent`...`,\n  });\n\n  const eslint = new ESLint({ cwd: iff.rootDir, useEslintrc: true });\n  const results = await eslint.lintFiles([iff.paths['src/semi.js']]);\n  const formatter = await eslint.loadFormatter('unix');\n  const resultText = formatter.format(results);\n  expect(resultText).toStrictEqual(dedent`\n    ${iff.paths['src/semi.js']}:2:25: Missing semicolon. [Error/semi]\n\n    1 problem\n  `);\n});\n```\n\n### Example: Share fixture files with test cases\n\n`iff.fork` is an API that changes the root directory while taking over previously created fixture files. It allows fixture files to be shared with test cases.\n\n```ts\n// example/02-share-fixtures-with-test-cases.test.ts\nimport { randomUUID } from 'node:crypto';\nimport { readFile, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport dedent from 'dedent';\nimport { ESLint } from 'eslint';\nimport { describe, expect, it } from 'vitest';\nimport { defineIFFCreator } from '@mizdra/inline-fixture-files';\n\n// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\nconst fixtureDir = join(tmpdir(), 'your-app-name', process.env['VITEST_POOL_ID']!);\nconst createIFF = defineIFFCreator({ generateRootDir: () =\u003e join(fixtureDir, randomUUID()) });\n\nawait rm(fixtureDir, { recursive: true, force: true });\n\ndescribe('eslint', async () =\u003e {\n  // Share `.eslintrc.cjs` between test cases.\n  const baseIFF = await createIFF({\n    '.eslintrc.cjs': `module.exports = { root: true, rules: { semi: 'error' } };`,\n  });\n  it('reports lint errors', async () =\u003e {\n    // The `fork` allows you to change the `rootDir` of fixtures while inheriting the fixtures from `baseIFF`.\n    const iff = await baseIFF.fork({\n      src: {\n        'semi.js': dedent`\n          var withSemicolon = 1;\n          var withoutSemicolon = 2\n        `,\n      },\n    });\n    const eslint = new ESLint({ cwd: iff.rootDir, useEslintrc: true });\n    const results = await eslint.lintFiles([iff.paths['src/semi.js']]);\n    const formatter = await eslint.loadFormatter('unix');\n    const resultText = formatter.format(results);\n    expect(resultText).toStrictEqual(dedent`\n      ${iff.paths['src/semi.js']}:2:25: Missing semicolon. [Error/semi]\n  \n      1 problem\n    `);\n  });\n  it('fix lint errors', async () =\u003e {\n    const iff = await baseIFF.fork({\n      src: {\n        'semi.js': dedent`\n          var withoutSemicolon = 2\n        `,\n      },\n    });\n    const eslint = new ESLint({ cwd: iff.rootDir, useEslintrc: true, fix: true });\n    const results = await eslint.lintFiles([iff.paths['src/semi.js']]);\n\n    expect(await readFile(iff.paths['src/semi.js'], 'utf8')).toMatchInlineSnapshot('\"var withoutSemicolon = 2\"');\n    await ESLint.outputFixes(results);\n    expect(await readFile(iff.paths['src/semi.js'], 'utf8')).toMatchInlineSnapshot('\"var withoutSemicolon = 2;\"');\n  });\n});\n```\n\n### Example: Flexible fixture creation API\n\n`@mizdra/inline-fixture-files` provides a flexible API for creating various variations of files. This allows you to create files with customized encoding, mode, atime, and mtime. It also allows for copying and symlinking.\n\n```ts\nimport { defineIFFCreator } from '@mizdra/inline-fixture-files';\nimport { writeFile, utimes, cp, symlink, mkdir } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst fixtureDir = join(tmpdir(), 'your-app-name', process.env['VITEST_POOL_ID']!);\nconst createIFF = defineIFFCreator({ generateRootDir: () =\u003e join(fixtureDir, randomUUID()) });\n\n// Example: File\nconst iff1 = await createIFF({\n  'buffer.txt': async (path) =\u003e writeFile(path, Buffer.from([0x00, 0x01])),\n  'encoding.txt': async (path) =\u003e writeFile(path, 'text', { encoding: 'utf16le' }),\n  'mode.txt': async (path) =\u003e writeFile(path, 'text', { mode: 0o600 }),\n  'flag.txt': async (path) =\u003e writeFile(path, 'text', { flag: 'wx' }),\n  'utime.txt': async (path) =\u003e {\n    await writeFile(path, 'text');\n    await utimes(0, 0);\n  },\n  'cp.txt': async (path) =\u003e cp('./cp.txt', path, { mode: constants.COPYFILE_FICLONE }),\n  'symlink.txt': async (path) =\u003e symlink('./symlink.txt', path),\n  // NOTE: The flexible file creation API does not automatically create parent directories.\n  // Therefore, you must manually create the parent directories in order to create nested files.\n  'nested/file.txt': async (path) =\u003e {\n    await mkdir(dirname(path));\n    await writeFile(path, 'text', { mode: 0o600 });\n  },\n});\nexpectType\u003c{\n  'buffer.txt'': string;\n  'encoding.txt': string;\n  'mode.txt': string;\n  'flag.txt': string;\n  'utime.txt': string;\n  'cp.txt': string;\n  'symlink.txt': string;\n  'nested': string;\n  'nested/file.txt': string;\n}\u003e(iff1.paths);\n\n// Example: Directory\nconst iff2 = await createIFF({\n  'mode': async (path) =\u003e mkdir(path, { mode: 0o600 }),\n  'cp': async (path) =\u003e cp('./cp', path, { mode: constants.COPYFILE_FICLONE }),\n  'symlink': async (path) =\u003e symlink('./symlink', path),\n  // NOTE: The flexible file creation API does not automatically create parent directories.\n  // Therefore, the recursive option is required to create nested directories.\n  'nested/directory': async (path) =\u003e mkdir(path, { mode: 0x600, recursive: true }),\n}).addFixtures({\n  // Use the add function to add files to the directory created by the flexible file creation API.\n  'mode': {\n    'file1.txt': 'file1',\n  },\n  // If you want to include the paths to the files in the copied directory in `iff2.paths`,\n  // you can use the following hack:\n  'cp': {\n    'file1.txt': null, // If null is passed, the file will not be written, but will be included in paths.\n  },\n});\nexpectType\u003c{\n  'mode': string;\n  'mode/file1.txt': string;\n  'cp': string;\n  'cp/file1.txt': string;\n  'symlink': string;\n  'nested': string;\n  'nested/directory': string;\n}\u003e(iff2.paths);\n```\n\n## Prior art\n\n- [inline-fixtures](https://github.com/GoogleCloudPlatform/inline-fixtures)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizdra%2Finline-fixture-files","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmizdra%2Finline-fixture-files","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizdra%2Finline-fixture-files/lists"}