codemap.test.ts 3.5 KB

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