98 lines
3.2 KiB
TypeScript
98 lines
3.2 KiB
TypeScript
import path from "node:path";
|
|
import { describe, expect, test } from "vitest";
|
|
|
|
import {
|
|
GitUpdateService,
|
|
UPDATE_REMOTE_URL,
|
|
type CommandResult,
|
|
type CommandRunner,
|
|
} from "../../src/updater/git-update-service.js";
|
|
|
|
function result(stdout = "", code = 0, stderr = ""): CommandResult {
|
|
return { code, stdout, stderr };
|
|
}
|
|
|
|
function fakeRunner(responses: Map<string, CommandResult>): CommandRunner {
|
|
return async (command, args) =>
|
|
responses.get(`${command} ${args.join(" ")}`) ??
|
|
result("", 1, "unexpected command");
|
|
}
|
|
|
|
describe("GitUpdateService", () => {
|
|
test("checks the currently checked-out branch", async () => {
|
|
const root = path.resolve(".");
|
|
const runner = fakeRunner(
|
|
new Map([
|
|
["git branch --show-current", result("feature/demo\n")],
|
|
[
|
|
`git fetch --quiet ${UPDATE_REMOTE_URL} +refs/heads/feature/demo:refs/remotes/xo-updater/feature/demo`,
|
|
result(),
|
|
],
|
|
["git rev-parse HEAD", result("aaa\n")],
|
|
["git rev-parse refs/remotes/xo-updater/feature/demo", result("bbb\n")],
|
|
["git status --porcelain", result()],
|
|
["git merge-base --is-ancestor aaa bbb", result()],
|
|
["git log -1 --format=%s bbb", result("Useful update\n")],
|
|
]),
|
|
);
|
|
|
|
const update = await new GitUpdateService(root, runner).check();
|
|
|
|
expect(update).toMatchObject({
|
|
status: "available",
|
|
branch: "feature/demo",
|
|
currentCommit: "aaa",
|
|
targetCommit: "bbb",
|
|
canApply: true,
|
|
});
|
|
});
|
|
|
|
test("reports an available update but blocks applying over local changes", async () => {
|
|
const root = path.resolve(".");
|
|
const runner = fakeRunner(
|
|
new Map([
|
|
["git branch --show-current", result("main\n")],
|
|
[
|
|
`git fetch --quiet ${UPDATE_REMOTE_URL} +refs/heads/main:refs/remotes/xo-updater/main`,
|
|
result(),
|
|
],
|
|
["git rev-parse HEAD", result("aaa\n")],
|
|
["git rev-parse refs/remotes/xo-updater/main", result("bbb\n")],
|
|
["git status --porcelain", result(" M src/example.ts\n")],
|
|
["git merge-base --is-ancestor aaa bbb", result()],
|
|
["git log -1 --format=%s bbb", result("Update\n")],
|
|
]),
|
|
);
|
|
|
|
const update = await new GitUpdateService(root, runner).check();
|
|
|
|
expect(update).toMatchObject({ status: "available", canApply: false });
|
|
});
|
|
|
|
test("does not replace commits when the local branch is ahead", async () => {
|
|
const root = path.resolve(".");
|
|
const runner = fakeRunner(
|
|
new Map([
|
|
["git branch --show-current", result("main\n")],
|
|
[
|
|
`git fetch --quiet ${UPDATE_REMOTE_URL} +refs/heads/main:refs/remotes/xo-updater/main`,
|
|
result(),
|
|
],
|
|
["git rev-parse HEAD", result("bbb\n")],
|
|
["git rev-parse refs/remotes/xo-updater/main", result("aaa\n")],
|
|
["git status --porcelain", result()],
|
|
["git merge-base --is-ancestor bbb aaa", result("", 1)],
|
|
["git merge-base --is-ancestor aaa bbb", result()],
|
|
]),
|
|
);
|
|
|
|
await expect(
|
|
new GitUpdateService(root, runner).check(),
|
|
).resolves.toMatchObject({
|
|
status: "up-to-date",
|
|
branch: "main",
|
|
currentCommit: "bbb",
|
|
});
|
|
});
|
|
});
|