Files
anonymous_github/test/anonymous-error.test.js
T

170 lines
5.6 KiB
JavaScript

const { expect } = require("chai");
/**
* Tests for AnonymousError.toString() formatting logic.
*
* The toString() method has branching logic based on the type of the
* `value` property (Repository, AnonymizedFile, GitHubRepository, User,
* GitHubBase, or plain object). We simulate these types to test each
* branch without importing the actual classes.
*/
// ---------------------------------------------------------------------------
// Simulated AnonymousError
// ---------------------------------------------------------------------------
class AnonymousError extends Error {
constructor(message, opt) {
super(message);
this.value = opt?.object;
this.httpStatus = opt?.httpStatus;
this.cause = opt?.cause;
}
toString() {
let out = "";
let detail = this.value ? JSON.stringify(this.value) : null;
// Simulate the instanceof checks with duck typing
if (this.value && this.value.__type === "Repository") {
detail = this.value.repoId;
} else if (this.value && this.value.__type === "AnonymizedFile") {
detail = `/r/${this.value.repository.repoId}/${this.value.anonymizedPath}`;
} else if (this.value && this.value.__type === "GitHubRepository") {
detail = `${this.value.fullName}`;
} else if (this.value && this.value.__type === "User") {
detail = `${this.value.username}`;
} else if (this.value && this.value.__type === "GitHubBase") {
detail = `GHDownload ${this.value.data.repoId}`;
}
out += this.message;
if (detail) {
out += `: ${detail}`;
}
if (this.cause) {
out += `\n\tCause by ${this.cause}\n${this.cause.stack}`;
}
return out;
}
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe("AnonymousError.toString()", function () {
describe("message formatting", function () {
it("outputs the error message", function () {
const err = new AnonymousError("repo_not_found");
expect(err.toString()).to.equal("repo_not_found");
});
it("outputs message with httpStatus on the object", function () {
const err = new AnonymousError("repo_not_found", { httpStatus: 404 });
expect(err.httpStatus).to.equal(404);
expect(err.toString()).to.equal("repo_not_found");
});
});
describe("detail from value types", function () {
it("formats Repository value as repoId", function () {
const err = new AnonymousError("error", {
object: { __type: "Repository", repoId: "my-anon-repo" },
});
expect(err.toString()).to.equal("error: my-anon-repo");
});
it("formats AnonymizedFile value as /r/{repoId}/{path}", function () {
const err = new AnonymousError("file_not_found", {
object: {
__type: "AnonymizedFile",
repository: { repoId: "abc123" },
anonymizedPath: "src/XXXX-1/file.ts",
},
});
expect(err.toString()).to.equal(
"file_not_found: /r/abc123/src/XXXX-1/file.ts"
);
});
it("formats GitHubRepository value as fullName", function () {
const err = new AnonymousError("error", {
object: { __type: "GitHubRepository", fullName: "owner/repo" },
});
expect(err.toString()).to.equal("error: owner/repo");
});
it("formats User value as username", function () {
const err = new AnonymousError("error", {
object: { __type: "User", username: "jdoe" },
});
expect(err.toString()).to.equal("error: jdoe");
});
it("formats GitHubBase value as GHDownload {repoId}", function () {
const err = new AnonymousError("error", {
object: {
__type: "GitHubBase",
data: { repoId: "download-123" },
},
});
expect(err.toString()).to.equal("error: GHDownload download-123");
});
it("formats plain object as JSON.stringify", function () {
const err = new AnonymousError("error", {
object: { key: "value" },
});
expect(err.toString()).to.equal('error: {"key":"value"}');
});
it("formats string value as JSON string", function () {
const err = new AnonymousError("error", {
object: "some-id",
});
expect(err.toString()).to.equal('error: "some-id"');
});
it("formats number value", function () {
const err = new AnonymousError("error", {
object: 42,
});
expect(err.toString()).to.equal("error: 42");
});
});
describe("null/undefined value", function () {
it("outputs only message when value is null", function () {
const err = new AnonymousError("error", { object: null });
expect(err.toString()).to.equal("error");
});
it("outputs only message when value is undefined", function () {
const err = new AnonymousError("error", { object: undefined });
expect(err.toString()).to.equal("error");
});
it("outputs only message when no opt is passed", function () {
const err = new AnonymousError("error");
expect(err.toString()).to.equal("error");
});
});
describe("cause formatting", function () {
it("includes cause message and stack when cause is present", function () {
const cause = new Error("original error");
const err = new AnonymousError("wrapper", { cause });
const str = err.toString();
expect(str).to.include("wrapper");
expect(str).to.include("Cause by");
expect(str).to.include("original error");
});
it("omits cause section when no cause", function () {
const err = new AnonymousError("error", { object: "test" });
expect(err.toString()).to.not.include("Cause by");
});
});
});