OXYGENHUB
# 25103dddd993 oxygen-vscode / test / oxy.test.mjs
5.7 KiB · last changed Milestone 0.4: history graph webview with per-change actions, file history diffs between versions, inline blame aligned to unsaved edits with a Myers line diff 1 month ago source blame history raw
bed495a9 Andy McCall ↶ 1
// The process wrapper against the real oxy binary on a scratch repository.
2
// Runs with `npm test`; needs oxy on PATH, at ~/.local/bin/oxy, or in OXY_BIN.
3
4
import { test } from "node:test";
5
import assert from "node:assert/strict";
6
import { mkdtempSync, writeFileSync, mkdirSync } from "node:fs";
7
import { tmpdir } from "node:os";
8
import { join } from "node:path";
9
import { Oxy, findBinary } from "../out/oxy.mjs";
10
11
const binary = process.env.OXY_BIN ?? findBinary(undefined);
12
const oxy = new Oxy(binary);
13
14
test("root, status, cat, log and commit round trip", async () => {
15
  const dir = mkdtempSync(join(tmpdir(), "oxy-vscode-"));
16
  const home = join(dir, "home");
17
  mkdirSync(home);
18
  process.env.OXY_HOME = home;
19
  await oxy.check(dir, ["init", "repo"]);
20
  const root = join(dir, "repo");
21
  await oxy.check(root, ["identity", "create", "--name", "Test", "--email", "[email protected]"]);
22
23
  const version = await oxy.version();
24
  assert.equal(version.protocol, 1);
25
  assert.equal(await oxy.root(dir), null, "outside a repository");
26
  const info = await oxy.root(root);
27
  assert.equal(info?.bookmark, "main");
28
  assert.ok(info?.root.endsWith("repo"));
29
30
  writeFileSync(join(root, "a.txt"), "one\n");
31
  let status = await oxy.status(root);
32
  assert.deepEqual(status.paths, [{ path: "a.txt", status: "Added" }]);
33
  assert.equal(status.clean, false);
34
  await oxy.commit(root, "first");
35
  status = await oxy.status(root);
36
  assert.equal(status.clean, true);
37
38
  writeFileSync(join(root, "a.txt"), "one\ntwo\n");
39
  assert.equal((await oxy.cat(root, "a.txt")).toString(), "one\n", "the base version");
40
  const log = await oxy.log(root, 10);
41
  assert.equal(log.changes.filter((c) => !c.working_copy).length, 1);
42
  assert.equal(log.changes.find((c) => !c.working_copy)?.signature?.status, "unsigned");
43
  assert.ok((await oxy.prompt(root)).includes("main"));
44
  const bookmarks = await oxy.bookmarks(root);
45
  assert.deepEqual(bookmarks.map((b) => [b.name, b.current]), [["main", true]]);
46
  await assert.rejects(oxy.cat(root, "missing.txt"), /not in that state/);
35d56b58 Andy McCall ↶ 47
5779e5c7 Andy McCall ↶ 48
  // Amend folds the edit into the single head.
49
  await oxy.amend(root, "first, amended");
50
  assert.equal((await oxy.status(root)).clean, true);
51
  assert.ok((await oxy.log(root, 10)).changes.some((c) => c.message === "first, amended"));
52
53
  // Hunks: commit only b.txt's, leave a.txt's edit, then discard it.
54
  writeFileSync(join(root, "a.txt"), "one\ntwo\nthree\n");
35d56b58 Andy McCall ↶ 55
  writeFileSync(join(root, "b.txt"), "b\n");
56
  const hunks = await oxy.hunks(root);
57
  assert.ok(hunks.length >= 2, JSON.stringify(hunks));
58
  const bHunk = hunks.find((h) => h.path === "b.txt");
59
  await oxy.commitHunks(root, "b only", [bHunk.index]);
60
  status = await oxy.status(root);
61
  assert.deepEqual(status.paths.map((p) => p.path), ["a.txt"], "a.txt stays uncommitted");
5779e5c7 Andy McCall ↶ 62
  assert.equal((await oxy.cat(root, "b.txt")).toString(), "b\n", "committed with its content");
35d56b58 Andy McCall ↶ 63
  await oxy.discard(root, ["a.txt"]);
64
  assert.equal((await oxy.status(root)).clean, true);
5779e5c7 Andy McCall ↶ 65
66
  // The operation log, and undo of the last operation (the commit).
35d56b58 Andy McCall ↶ 67
  const ops = await oxy.opLog(root);
68
  assert.ok(ops[0].current && ops.length > 3);
69
  assert.match(await oxy.undo(root), /Undone/);
5779e5c7 Andy McCall ↶ 70
  status = await oxy.status(root);
71
  assert.ok(status.paths.some((p) => p.path === "b.txt"), "the commit is undone; b.txt is uncommitted work again");
bed495a9 Andy McCall ↶ 72
});
c8f95589 Andy McCall ↶ 73
74
test("bookmarks, remotes and sync against a local origin", async () => {
75
  const dir = mkdtempSync(join(tmpdir(), "oxy-vscode-sync-"));
76
  const home = join(dir, "home");
77
  mkdirSync(home);
78
  process.env.OXY_HOME = home;
79
  await oxy.check(dir, ["init", "origin"]);
80
  await oxy.clone(dir, join(dir, "origin"), join(dir, "work"));
81
  const root = join(dir, "work");
82
  writeFileSync(join(root, "a.txt"), "a\n");
83
  await oxy.commit(root, "a");
84
  const remotes = await oxy.remotes(root);
85
  assert.equal(remotes[0].name, "origin");
86
  let push = await oxy.push(root);
87
  assert.equal(push[0].ok, true);
88
  let bookmarks = await oxy.bookmarks(root);
89
  assert.deepEqual(bookmarks.map((b) => [b.name, b.current, b.ahead, b.behind]), [["main", true, 0, 0]]);
90
91
  await oxy.bookmarkCreate(root, "feature");
92
  await oxy.bookmarkSwitch(root, "feature");
93
  writeFileSync(join(root, "a.txt"), "a\nfeature\n");
94
  await oxy.commit(root, "feature work");
95
  bookmarks = await oxy.bookmarks(root);
96
  assert.equal(bookmarks.find((b) => b.current)?.name, "feature");
97
  await oxy.bookmarkSwitch(root, "main");
98
  assert.equal((await oxy.cat(root, "a.txt")).toString(), "a\n");
99
  writeFileSync(join(root, "b.txt"), "b\n");
100
  await assert.rejects(oxy.bookmarkSwitch(root, "feature"), /has changes/);
101
  await oxy.commit(root, "b on main");
102
  assert.match(await oxy.merge(root, "feature"), /Merged/);
103
  assert.equal((await oxy.cat(root, "a.txt")).toString(), "a\nfeature\n");
104
  push = await oxy.push(root, "origin", "feature");
105
  assert.equal(push[0].ok, true);
106
  push = await oxy.push(root);
107
  assert.equal(push[0].ok, true);
108
  const fetch = await oxy.fetch(root);
109
  assert.equal(fetch.remote, "origin");
110
  const pull = await oxy.pull(root);
111
  assert.equal(pull.changed, false);
112
  await oxy.bookmarkDelete(root, "feature");
113
  bookmarks = await oxy.bookmarks(root);
114
  assert.deepEqual(bookmarks.map((b) => b.name), ["main"]);
ab81294a Andy McCall ↶ 115
116
  // Blame, show, diff text, and file history.
117
  const blame = await oxy.blame(root, "a.txt");
118
  assert.deepEqual(blame.map((l) => l.line), [1, 2]);
119
  assert.notEqual(blame[0].hash, blame[1].hash, "two changes introduced the two lines");
120
  const show = await oxy.show(root, `#${blame[1].hash.slice(0, 12)}`);
121
  assert.equal(show.message, "feature work");
122
  assert.deepEqual(show.files.map((f) => f.path), ["a.txt"]);
123
  assert.match(await oxy.diffText(root, `#${blame[1].hash.slice(0, 12)}`), /\+feature/);
124
  const history = await oxy.log(root, 50, "a.txt");
125
  assert.equal(history.changes.filter((c) => !c.working_copy).length, 2);
c8f95589 Andy McCall ↶ 126
});
127