takt/src/__tests__/repertoire/lock-file.test.ts

168 lines
5.1 KiB
TypeScript

/**
* Tests for .takt-repertoire-lock.yaml generation and parsing.
*
* Covers:
* - extractCommitSha: parse SHA from tarball directory name {owner}-{repo}-{sha}/
* - generateLockFile: produces correct fields (source, ref, commit, imported_at)
* - ref defaults to "HEAD" when not specified
* - parseLockFile: reads .takt-repertoire-lock.yaml content
*/
import { describe, it, expect } from 'vitest';
import {
extractCommitSha,
generateLockFile,
parseLockFile,
} from '../../features/repertoire/lock-file.js';
// ---------------------------------------------------------------------------
// extractCommitSha
// ---------------------------------------------------------------------------
describe('extractCommitSha', () => {
it('should extract SHA from standard tarball directory name', () => {
// Given: tarball directory name in {owner}-{repo}-{sha} format
const dirName = 'nrslib-takt-fullstack-abc1234def5678';
// When: SHA is extracted
const sha = extractCommitSha(dirName);
// Then: last segment (the SHA) is returned
expect(sha).toBe('abc1234def5678');
});
it('should extract SHA when repo name contains hyphens', () => {
// Given: repo name has multiple hyphens
const dirName = 'nrslib-takt-security-facets-deadbeef1234';
// When: SHA is extracted
const sha = extractCommitSha(dirName);
// Then: the last segment is the SHA
expect(sha).toBe('deadbeef1234');
});
it('should extract SHA when owner is a single word', () => {
// Given: simple owner and repo
const dirName = 'owner-repo-0123456789abcdef';
// When: SHA is extracted
const sha = extractCommitSha(dirName);
// Then: last segment is returned
expect(sha).toBe('0123456789abcdef');
});
});
// ---------------------------------------------------------------------------
// generateLockFile
// ---------------------------------------------------------------------------
describe('generateLockFile', () => {
it('should produce lock file with all required fields', () => {
// Given: all parameters provided
const params = {
source: 'github:nrslib/takt-fullstack',
ref: 'v1.2.0',
commitSha: 'abc1234def5678',
importedAt: new Date('2026-02-20T12:00:00Z'),
};
// When: lock file is generated
const lock = generateLockFile(params);
// Then: all fields are present
expect(lock.source).toBe('github:nrslib/takt-fullstack');
expect(lock.ref).toBe('v1.2.0');
expect(lock.commit).toBe('abc1234def5678');
expect(lock.imported_at).toBe('2026-02-20T12:00:00.000Z');
});
it('should default ref to "HEAD" when ref is undefined', () => {
// Given: ref not specified
const params = {
source: 'github:nrslib/takt-security-facets',
ref: undefined,
commitSha: 'deadbeef1234',
importedAt: new Date('2026-01-01T00:00:00Z'),
};
// When: lock file is generated
const lock = generateLockFile(params);
// Then: ref is "HEAD"
expect(lock.ref).toBe('HEAD');
});
it('should record the exact commit SHA from the tarball directory', () => {
// Given: SHA from tarball extraction
const sha = '9f8e7d6c5b4a';
const params = {
source: 'github:someone/dotfiles',
ref: undefined,
commitSha: sha,
importedAt: new Date(),
};
// When: lock file is generated
const lock = generateLockFile(params);
// Then: commit SHA matches
expect(lock.commit).toBe(sha);
});
});
// ---------------------------------------------------------------------------
// parseLockFile
// ---------------------------------------------------------------------------
describe('parseLockFile', () => {
it('should parse a valid .takt-repertoire-lock.yaml string', () => {
// Given: lock file YAML content
const yaml = `source: github:nrslib/takt-fullstack
ref: v1.2.0
commit: abc1234def5678
imported_at: 2026-02-20T12:00:00.000Z
`;
// When: parsed
const lock = parseLockFile(yaml);
// Then: all fields are present
expect(lock.source).toBe('github:nrslib/takt-fullstack');
expect(lock.ref).toBe('v1.2.0');
expect(lock.commit).toBe('abc1234def5678');
expect(lock.imported_at).toBe('2026-02-20T12:00:00.000Z');
});
it('should parse lock file with HEAD ref', () => {
// Given: lock file with HEAD ref (no tag specified at import)
const yaml = `source: github:acme-corp/takt-backend
ref: HEAD
commit: 789abcdef0123
imported_at: 2026-01-15T08:30:00.000Z
`;
// When: parsed
const lock = parseLockFile(yaml);
// Then: ref is "HEAD"
expect(lock.ref).toBe('HEAD');
expect(lock.commit).toBe('789abcdef0123');
});
it('should return empty-valued lock without crashing when yaml is empty string', () => {
// Given: empty yaml (lock file absent - existsSync guard fell through to '')
// yaml.parse('') returns null, which must not cause TypeError
// When: parsed
const lock = parseLockFile('');
// Then: returns defaults without throwing
expect(lock.source).toBe('');
expect(lock.ref).toBe('HEAD');
expect(lock.commit).toBe('');
expect(lock.imported_at).toBe('');
});
});