|
| 1 | +import assert from 'node:assert/strict'; |
| 2 | +import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs'; |
| 3 | +import { tmpdir } from 'node:os'; |
| 4 | +import { join } from 'node:path'; |
| 5 | +import { test } from 'node:test'; |
| 6 | + |
| 7 | +import { linkDesktop, linkDesktopChangesets } from './link-desktop-changesets.mjs'; |
| 8 | + |
| 9 | +const cliOnly = '---\n"@pymodel/pythinker-code": minor\n---\n\nAdd panel tabs.\n'; |
| 10 | + |
| 11 | +void test('adds the desktop package at the CLI bump level', () => { |
| 12 | + assert.equal( |
| 13 | + linkDesktop(cliOnly), |
| 14 | + '---\n"@pymodel/pythinker-code": minor\n"@pymodel/pythinker-desktop": minor\n---\n\nAdd panel tabs.\n', |
| 15 | + ); |
| 16 | +}); |
| 17 | + |
| 18 | +void test('leaves a changeset that already names desktop alone', () => { |
| 19 | + const both = '---\n"@pymodel/pythinker-desktop": patch\n"@pymodel/pythinker-code": patch\n---\n\nx\n'; |
| 20 | + assert.equal(linkDesktop(both), null); |
| 21 | + assert.equal(linkDesktop(linkDesktop(cliOnly)), null); |
| 22 | +}); |
| 23 | + |
| 24 | +void test('accepts quoted bump values and does not duplicate the desktop entry', () => { |
| 25 | + const quoted = '---\n"@pymodel/pythinker-code": "minor"\n---\n\nx\n'; |
| 26 | + assert.equal(linkDesktop(quoted), '---\n"@pymodel/pythinker-code": "minor"\n"@pymodel/pythinker-desktop": minor\n---\n\nx\n'); |
| 27 | + assert.equal(linkDesktop(linkDesktop(quoted)), null); |
| 28 | + assert.equal(linkDesktop("---\n'@pymodel/pythinker-desktop': 'patch'\n\"@pymodel/pythinker-code\": 'patch'\n---\n\nx\n"), null); |
| 29 | +}); |
| 30 | + |
| 31 | +void test('reuses the CLI entry indentation', () => { |
| 32 | + assert.equal( |
| 33 | + linkDesktop('---\n "@pymodel/pythinker-code": patch\n---\n\nx\n'), |
| 34 | + '---\n "@pymodel/pythinker-code": patch\n "@pymodel/pythinker-desktop": patch\n---\n\nx\n', |
| 35 | + ); |
| 36 | +}); |
| 37 | + |
| 38 | +void test('ignores changesets that do not name the CLI', () => { |
| 39 | + assert.equal(linkDesktop('---\n"@pymodel/klient": patch\n---\n\nx\n'), null); |
| 40 | + assert.equal(linkDesktop('no frontmatter\n'), null); |
| 41 | +}); |
| 42 | + |
| 43 | +void test('keeps other packages and the prose intact', () => { |
| 44 | + const source = '---\n"@pymodel/klient": patch\n"@pymodel/pythinker-code": patch\n---\n\nBody mentions "@pymodel/pythinker-desktop": major but that is prose.\n'; |
| 45 | + const next = linkDesktop(source); |
| 46 | + assert.equal( |
| 47 | + next, |
| 48 | + '---\n"@pymodel/klient": patch\n"@pymodel/pythinker-code": patch\n"@pymodel/pythinker-desktop": patch\n---\n\nBody mentions "@pymodel/pythinker-desktop": major but that is prose.\n', |
| 49 | + ); |
| 50 | +}); |
| 51 | + |
| 52 | +void test('rewrites only the changesets that need it and is idempotent', () => { |
| 53 | + const dir = mkdtempSync(join(tmpdir(), 'changesets-')); |
| 54 | + writeFileSync(join(dir, 'README.md'), '---\n"@pymodel/pythinker-code": patch\n---\n'); |
| 55 | + writeFileSync(join(dir, 'config.json'), '{}'); |
| 56 | + writeFileSync(join(dir, 'a.md'), cliOnly); |
| 57 | + writeFileSync(join(dir, 'b.md'), '---\n"@pymodel/klient": patch\n---\n\nx\n'); |
| 58 | + assert.deepEqual(linkDesktopChangesets(dir), ['a.md']); |
| 59 | + assert.match(readFileSync(join(dir, 'a.md'), 'utf8'), /pythinker-desktop": minor/u); |
| 60 | + assert.deepEqual(linkDesktopChangesets(dir), []); |
| 61 | + assert.equal(readFileSync(join(dir, 'README.md'), 'utf8'), '---\n"@pymodel/pythinker-code": patch\n---\n'); |
| 62 | +}); |
0 commit comments