CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /**
* Unit tests for src/lib/import-verify.ts.
*
* We stub the `../db` module with `mock.module` so we never touch Neon.
* The fake `db.select(...)` chain returns whatever the per-test closure
* decides — either undefined (repo not found) or a plausible row whose
* on-disk path points somewhere that doesn't exist.
*
* Bun 1.3's `bun test` shares a single module registry across every test
* file in a run and `mock.restore()` does NOT un-mock `mock.module(...)`
* registrations. To avoid leaking our stub into other test files, we use a
* defensive fake: `_nextRow` defaults to `undefined` (so any library code
* that does `select().from().where().limit(1)` sees an empty result and
* falls through to its DB-unavailable branch), and we reset the row back
* to `undefined` in `afterAll`.
*/
import { describe, it, expect, mock, afterAll } from "bun:test";
// Per-test mutable row — each test assigns its own value before calling
// verifyMigration. The chained Drizzle-style select builder ends in
// `.limit(1)` which we return as an array containing (or omitting) this row.
let _nextRow: { repoName: string; ownerName: string | null } | undefined;
// Minimal Drizzle `db.select(...).from(...).leftJoin(...).where(...).limit(1)`
// chain. Every step returns `this` except `.limit()` which resolves the
// fake row as a 1-element (or 0-element) array.
const _chain: any = {
from: () => _chain,
leftJoin: () => _chain,
innerJoin: () => _chain,
rightJoin: () => _chain,
where: () => _chain,
orderBy: () => _chain,
groupBy: () => _chain,
limit: async () => (_nextRow ? [_nextRow] : []),
};
// Mock `../db` at module scope so the dynamic import of ../lib/import-verify
// below picks up the stub instead of the real Neon-backed proxy.
const _fakeDb = {
db: { select: () => _chain, insert: () => _chain, update: () => _chain, delete: () => _chain },
getDb: () => ({ select: () => _chain, insert: () => _chain, update: () => _chain, delete: () => _chain }),
};
mock.module("../db", () => _fakeDb);
// Reset the fake row after our tests finish so any later test file whose
// code happens to run `db.select()...limit(1)` sees an empty result (and
// falls through to its real null/empty branch) rather than inheriting the
// half-built row from our "git dir missing" test.
afterAll(() => {
_nextRow = undefined;
});
// Point GIT_REPOS_PATH at a directory that definitely doesn't contain
// any of the fake repos we'll reference, so `clonable` checks fail.
process.env.GIT_REPOS_PATH = "/tmp/gluecron-import-verify-does-not-exist";
describe("verifyMigration", () => {
it("returns clonable:false and issue when repo not found in DB", async () => {
_nextRow = undefined;
const { verifyMigration } = await import("../lib/import-verify");
const r = await verifyMigration(999);
expect(r.repoId).toBe(999);
expect(r.clonable).toBe(false);
expect(r.hasDefaultBranch).toBe(false);
expect(r.commitCount).toBe(0);
expect(r.issues).toContain("repo not found");
});
it("returns clonable:false with issue when git dir is missing", async () => {
_nextRow = { repoName: "ghost", ownerName: "nobody" };
const { verifyMigration } = await import("../lib/import-verify");
const r = await verifyMigration(42);
expect(r.repoId).toBe(42);
expect(r.clonable).toBe(false);
// At least one of the sentinel-file issues should be present.
const hasMissing = r.issues.some(
(s) =>
s.includes("missing HEAD") ||
s.includes("missing config") ||
s.includes("missing objects")
);
expect(hasMissing).toBe(true);
// The git shell-outs against a non-existent path should also fail
// and contribute to issues, but we don't assert the exact wording
// (it varies across git versions).
expect(r.hasDefaultBranch).toBe(false);
expect(r.commitCount).toBe(0);
});
});
|