codemap.test.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { afterEach, describe, expect, test } from 'bun:test';
  2. import {
  3. existsSync,
  4. mkdirSync,
  5. mkdtempSync,
  6. readFileSync,
  7. rmSync,
  8. writeFileSync,
  9. } from 'node:fs';
  10. import os from 'node:os';
  11. import path from 'node:path';
  12. import {
  13. computeFileHash,
  14. computeFolderHash,
  15. loadState,
  16. PatternMatcher,
  17. selectFiles,
  18. } from './codemap.mjs';
  19. const tempDirs: string[] = [];
  20. function createTempDir() {
  21. const dir = mkdtempSync(path.join(os.tmpdir(), 'codemap-'));
  22. tempDirs.push(dir);
  23. return dir;
  24. }
  25. afterEach(() => {
  26. for (const dir of tempDirs.splice(0)) {
  27. rmSync(dir, { force: true, recursive: true });
  28. }
  29. });
  30. describe('PatternMatcher', () => {
  31. test('matches expected paths', () => {
  32. const matcher = new PatternMatcher([
  33. 'node_modules/',
  34. 'dist/',
  35. '*.log',
  36. 'src/**/*.ts',
  37. ]);
  38. expect(matcher.matches('node_modules/foo.js')).toBe(true);
  39. expect(matcher.matches('vendor/node_modules/bar.js')).toBe(true);
  40. expect(matcher.matches('dist/main.js')).toBe(true);
  41. expect(matcher.matches('src/dist/output.js')).toBe(true);
  42. expect(matcher.matches('error.log')).toBe(true);
  43. expect(matcher.matches('logs/access.log')).toBe(true);
  44. expect(matcher.matches('src/index.ts')).toBe(true);
  45. expect(matcher.matches('src/utils/helper.ts')).toBe(true);
  46. expect(matcher.matches('README.md')).toBe(false);
  47. expect(matcher.matches('tests/test.py')).toBe(false);
  48. });
  49. });
  50. describe('hash helpers', () => {
  51. test('computes file hash', () => {
  52. const dir = createTempDir();
  53. const filePath = path.join(dir, 'file.txt');
  54. writeFileSync(filePath, 'test content');
  55. expect(computeFileHash(filePath)).toBe('9473fdd0d880a43c21b7778d34872157');
  56. });
  57. test('computes stable folder hash', () => {
  58. const fileHashes = {
  59. 'src/a.ts': 'hash-a',
  60. 'src/b.ts': 'hash-b',
  61. 'tests/test.ts': 'hash-test',
  62. };
  63. const hash1 = computeFolderHash('src', fileHashes);
  64. const hash2 = computeFolderHash('src', fileHashes);
  65. const hash3 = computeFolderHash('src', {
  66. 'src/a.ts': 'hash-a-modified',
  67. 'src/b.ts': 'hash-b',
  68. });
  69. expect(hash1).toBe(hash2);
  70. expect(hash1).not.toBe(hash3);
  71. });
  72. });
  73. describe('selectFiles', () => {
  74. test('respects include and exclude patterns', () => {
  75. const root = createTempDir();
  76. mkdirSync(path.join(root, 'src'));
  77. mkdirSync(path.join(root, 'node_modules'));
  78. writeFileSync(path.join(root, 'src', 'index.ts'), 'code');
  79. writeFileSync(path.join(root, 'src', 'index.test.ts'), 'test');
  80. writeFileSync(path.join(root, 'node_modules', 'foo.js'), 'dep');
  81. writeFileSync(path.join(root, 'package.json'), '{}');
  82. const selected = selectFiles(
  83. root,
  84. ['src/**/*.ts', 'package.json'],
  85. ['**/*.test.ts', 'node_modules/'],
  86. [],
  87. [],
  88. ).map((filePath) =>
  89. path.relative(root, filePath).replaceAll(path.sep, '/'),
  90. );
  91. expect(selected).toEqual(['package.json', 'src/index.ts']);
  92. });
  93. });
  94. describe('loadState', () => {
  95. test('migrates legacy cartography state', () => {
  96. const root = createTempDir();
  97. const slimDir = path.join(root, '.slim');
  98. mkdirSync(slimDir);
  99. const legacyState = { metadata: { version: '1.0.0' } };
  100. writeFileSync(
  101. path.join(slimDir, 'cartography.json'),
  102. JSON.stringify(legacyState),
  103. );
  104. expect(loadState(root)).toEqual(legacyState);
  105. expect(existsSync(path.join(slimDir, 'cartography.json'))).toBe(false);
  106. expect(
  107. JSON.parse(readFileSync(path.join(slimDir, 'codemap.json'), 'utf8')),
  108. ).toEqual(legacyState);
  109. });
  110. });