import { describe, expect, it } from 'vitest'; import { diffRefs, refsToState, removedRefs } from '../src/refs.js'; import { checkRequestKey, latestCheckKey, parseSpec, repoKey, } from '../src/spec.js'; describe('diffRefs', () => { it('reports a new ref with no previous object id', () => { expect(diffRefs({}, [{ name: 'refs/heads/main', sha: 'aa' }])).toEqual([ { name: 'refs/heads/main', sha: 'aa', previousSha: null }, ]); }); it('reports a ref that moved', () => { const previous = { 'refs/heads/main': 'aa' }; expect( diffRefs(previous, [{ name: 'refs/heads/main', sha: 'bb' }]), ).toEqual([{ name: 'refs/heads/main', sha: 'bb', previousSha: 'aa' }]); }); it('reports nothing when every ref is where it was', () => { const refs = [ { name: 'refs/heads/main', sha: 'aa' }, { name: 'refs/heads/topic', sha: 'bb' }, ]; expect(diffRefs(refsToState(refs), refs)).toEqual([]); }); it('ignores a ref that disappeared', () => { const previous = { 'refs/heads/main': 'aa', 'refs/heads/gone': 'bb' }; expect( diffRefs(previous, [{ name: 'refs/heads/main', sha: 'aa' }]), ).toEqual([]); }); }); describe('parseSpec', () => { it('splits a handle from a repository name', () => { expect(parseSpec('alice.example.com/my-project')).toEqual({ authority: 'alice.example.com', repoName: 'my-project', }); }); it('keeps a DID whole', () => { expect(parseSpec('did:plc:abc123/my-project')).toEqual({ authority: 'did:plc:abc123', repoName: 'my-project', }); }); it('rejects a spec with no repository name', () => { expect(() => parseSpec('alice.example.com')).toThrow(/expected/); expect(() => parseSpec('alice.example.com/')).toThrow(/expected/); expect(() => parseSpec('/my-project')).toThrow(/expected/); }); }); describe('repoKey', () => { it('keys a repository by DID and name', () => { expect(repoKey('did:plc:abc', 'proj')).toBe('did:plc:abc/proj'); }); }); describe('removedRefs', () => { it('names the refs the last look saw that are not there now', () => { expect( removedRefs({ 'refs/heads/main': 'a', 'refs/heads/fix': 'b' }, [ { name: 'refs/heads/main', sha: 'a' }, ]), ).toEqual(['refs/heads/fix']); }); it('names none where every ref is still held', () => { expect( removedRefs({ 'refs/heads/main': 'a' }, [ { name: 'refs/heads/main', sha: 'c' }, ]), ).toEqual([]); }); }); describe('latestCheckKey', () => { // The account page derives the same key in @pdsjs/core to find a check. If // these disagree, a published check never resolves, so both assert this. it('keeps the colons a DID and a record key both allow', () => { expect(latestCheckKey('did:plc:abc', 'proj', 'refs/heads/main')).toBe( 'did:plc:abc:proj:refs_heads_main', ); }); it('replaces every character a record key forbids', () => { expect(latestCheckKey('did:plc:abc', 'proj', 'refs/heads/a b/c')).toBe( 'did:plc:abc:proj:refs_heads_a_b_c', ); }); it('separates two refs of one repository', () => { const main = latestCheckKey('did:plc:abc', 'proj', 'refs/heads/main'); const topic = latestCheckKey('did:plc:abc', 'proj', 'refs/heads/topic'); expect(main).not.toBe(topic); }); it('separates same-named repositories owned by different accounts', () => { const mine = latestCheckKey('did:plc:abc', 'proj', 'refs/heads/main'); const yours = latestCheckKey('did:plc:xyz', 'proj', 'refs/heads/main'); expect(mine).not.toBe(yours); }); }); describe('checkRequestKey', () => { // The account page derives the same key in @pdsjs/core to write a request. // If these disagree, asking twice leaves two records and the daemon runs // twice, so both assert this. it('names the repository and the ref, and nothing else', () => { expect(checkRequestKey('proj', 'refs/heads/main')).toBe( 'proj:refs_heads_main', ); }); it('replaces every character a record key forbids', () => { expect(checkRequestKey('proj', 'refs/heads/a b/c')).toBe( 'proj:refs_heads_a_b_c', ); }); it('separates two refs of one repository', () => { expect(checkRequestKey('proj', 'refs/heads/main')).not.toBe( checkRequestKey('proj', 'refs/heads/topic'), ); }); });