Files
mygit/scripts/test/resolve-base-tag.test.js
T
DuckQ1u 93d1b7c3d3
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
first commit
2026-04-22 19:51:20 +07:00

180 lines
6.4 KiB
JavaScript

const {describe, it, before, after} = require('node:test');
const assert = require('node:assert');
const os = require('node:os');
const path = require('node:path');
const fs = require('node:fs');
const {execSync} = require('node:child_process');
const semver = require('semver');
const {resolveBaseTag} = require('../lib/resolve-base-tag');
/**
* Create a temporary git repo with semver tags for testing.
* Returns the repo path. Caller is responsible for cleanup.
*/
function createTestRepo() {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ghost-release-test-'));
execSync([
`cd ${tmpDir}`,
'git init',
'git config user.email "test@test.com"',
'git config user.name "Test"',
// Initial commit + stable tag v6.17.0
'echo "initial" > file.txt',
'git add .',
'git commit -m "initial"',
'git tag v6.17.0',
// Second commit + stable tag v6.17.1
'echo "patch" >> file.txt',
'git add .',
'git commit -m "patch release"',
'git tag v6.17.1',
// Third commit (no tag — simulates post-release development)
'echo "new work" >> file.txt',
'git add .',
'git commit -m "post-release commit"'
].join(' && '));
return tmpDir;
}
describe('resolveBaseTag', () => {
let testRepo;
before(() => {
testRepo = createTestRepo();
});
after(() => {
fs.rmSync(testRepo, {recursive: true, force: true});
});
describe('semver.prerelease detection', () => {
it('returns null for stable versions', () => {
assert.strictEqual(semver.prerelease('6.17.1'), null);
assert.strictEqual(semver.prerelease('6.18.0'), null);
assert.strictEqual(semver.prerelease('5.0.0'), null);
});
it('returns prerelease components for rc versions', () => {
const result = semver.prerelease('6.19.0-rc.0');
assert.deepStrictEqual(result, ['rc', 0]);
});
it('returns prerelease components for alpha versions', () => {
const result = semver.prerelease('7.0.0-alpha.1');
assert.deepStrictEqual(result, ['alpha', 1]);
});
});
describe('stable version path', () => {
it('constructs tag directly from version', () => {
// Stable versions don't hit git — the tag is just v{version}
const {tag, isPrerelease} = resolveBaseTag('6.17.1', '/nonexistent');
assert.strictEqual(tag, 'v6.17.1');
assert.strictEqual(isPrerelease, false);
});
it('works for any stable version format', () => {
const {tag} = resolveBaseTag('5.0.0', '/nonexistent');
assert.strictEqual(tag, 'v5.0.0');
});
});
describe('prerelease version path', () => {
it('resolves to the latest stable tag', () => {
const {tag, isPrerelease} = resolveBaseTag('6.19.0-rc.0', testRepo);
assert.strictEqual(isPrerelease, true);
assert.strictEqual(tag, 'v6.17.1');
});
it('resolved tag is a stable version (no prerelease suffix)', () => {
const {tag} = resolveBaseTag('6.19.0-rc.0', testRepo);
assert.match(tag, /^v\d+\.\d+\.\d+$/);
assert.strictEqual(semver.prerelease(tag.slice(1)), null);
});
it('resolved tag is a valid git ref', () => {
const {tag} = resolveBaseTag('6.19.0-rc.0', testRepo);
const sha = execSync(`cd ${testRepo} && git rev-parse ${tag}`, {encoding: 'utf8'});
assert.ok(sha.trim().length > 0, 'Tag should resolve to a commit SHA');
});
it('git diff succeeds with the resolved tag', () => {
const {tag} = resolveBaseTag('6.19.0-rc.0', testRepo);
const result = execSync(
`cd ${testRepo} && git diff --diff-filter=A --name-only ${tag} HEAD`,
{encoding: 'utf8'}
);
assert.strictEqual(typeof result, 'string');
});
it('git log succeeds with the resolved tag', () => {
const {tag} = resolveBaseTag('6.19.0-rc.0', testRepo);
const result = execSync(
`cd ${testRepo} && git log --oneline ${tag}..HEAD`,
{encoding: 'utf8'}
);
assert.strictEqual(typeof result, 'string');
// Should have at least 1 commit (the post-release commit)
assert.ok(result.trim().length > 0, 'Should find commits after the tag');
});
});
describe('prerelease excludes prerelease tags', () => {
let repoWithPrereleaseTag;
before(() => {
// Create a repo that has both stable and prerelease tags
repoWithPrereleaseTag = fs.mkdtempSync(path.join(os.tmpdir(), 'ghost-release-test-pre-'));
execSync([
`cd ${repoWithPrereleaseTag}`,
'git init',
'git config user.email "test@test.com"',
'git config user.name "Test"',
'echo "initial" > file.txt',
'git add .',
'git commit -m "initial"',
'git tag v6.17.0',
'echo "alpha" >> file.txt',
'git add .',
'git commit -m "alpha work"',
'git tag v7.0.0-alpha.0',
'echo "more" >> file.txt',
'git add .',
'git commit -m "more work"'
].join(' && '));
});
after(() => {
fs.rmSync(repoWithPrereleaseTag, {recursive: true, force: true});
});
it('skips prerelease tags and finds the stable one', () => {
const {tag} = resolveBaseTag('7.0.0-rc.0', repoWithPrereleaseTag);
// Should find v6.17.0 (stable), NOT v7.0.0-alpha.0 (prerelease)
assert.strictEqual(tag, 'v6.17.0');
});
});
describe('semver.inc compatibility', () => {
it('patch of an rc produces the stable release', () => {
assert.strictEqual(semver.inc('6.19.0-rc.0', 'patch'), '6.19.0');
});
it('minor of an rc produces the stable release (not next minor)', () => {
assert.strictEqual(semver.inc('6.19.0-rc.0', 'minor'), '6.19.0');
});
it('prerelease rc of an rc increments the rc number', () => {
assert.strictEqual(semver.inc('6.19.0-rc.0', 'prerelease', 'rc'), '6.19.0-rc.1');
});
});
});