swarm-ui: test the review try-out form's pure logic
The try-out page's checks and request body get tests under the package's node runner: the repo check, a row's checks in their order, a shared name, and the open-a-PR gate (repo, then each row in order, then a shared name, with no PR number). Also the row a request sends, and the row a loaded rule becomes. Refs #5259
This commit is contained in:
parent
915364c918
commit
36c3f38717
1 changed files with 132 additions and 0 deletions
132
frontend/packages/swarm-ui/test/tryout-types.test.mjs
Normal file
132
frontend/packages/swarm-ui/test/tryout-types.test.mjs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
// The review try-out form's pure logic: the repo and row checks, the gate on
|
||||
// opening a PR from the rows, and the request body each row becomes. Run by
|
||||
// `npm test`, which Node runs with its built-in test runner and type
|
||||
// stripping, so the `.ts` module is imported as it is.
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
import {
|
||||
draftFromRule,
|
||||
draftProblem,
|
||||
duplicateName,
|
||||
hasTypedText,
|
||||
prNumber,
|
||||
repoProblem,
|
||||
rowsProblem,
|
||||
thresholdValue,
|
||||
toBody,
|
||||
} from "../src/pages/review-tryout/TryOutTypes.ts";
|
||||
|
||||
// A row ready to send, with `over` replacing any of its fields.
|
||||
function row(over = {}) {
|
||||
return {
|
||||
key: 0,
|
||||
name: "no-ads",
|
||||
description: "No ads.",
|
||||
polarity: "negative",
|
||||
threshold: "80",
|
||||
...over,
|
||||
};
|
||||
}
|
||||
|
||||
test("a repo is owner/name with forge-safe characters in each part", () => {
|
||||
assert.equal(repoProblem("hyperhive/hyperhive"), null);
|
||||
assert.equal(repoProblem(" o/r.name_x-1 "), null);
|
||||
for (const bad of ["", "o", "o/", "/r", "o/r/x", "o/..", "./r", "o/r s"]) {
|
||||
assert.match(repoProblem(bad), /owner\/name/, bad);
|
||||
}
|
||||
});
|
||||
|
||||
test("a row needs a name, then a description, then a whole 0-100 threshold", () => {
|
||||
assert.equal(draftProblem(row()), null);
|
||||
assert.match(draftProblem(row({ name: " " })), /a name/);
|
||||
assert.match(
|
||||
draftProblem(row({ name: " ", description: "" })),
|
||||
/a name/,
|
||||
"the name is checked first",
|
||||
);
|
||||
assert.match(
|
||||
draftProblem(row({ description: " " })),
|
||||
/no-ads needs a description/,
|
||||
);
|
||||
assert.match(
|
||||
draftProblem(row({ description: "", threshold: "x" })),
|
||||
/description/,
|
||||
"the description is checked before the threshold",
|
||||
);
|
||||
for (const bad of ["", "101", "-1", "1.5", "x"]) {
|
||||
assert.match(draftProblem(row({ threshold: bad })), /threshold/, bad);
|
||||
}
|
||||
assert.equal(draftProblem(row({ threshold: " 100 " })), null);
|
||||
assert.equal(draftProblem(row({ threshold: "0" })), null);
|
||||
});
|
||||
|
||||
test("two rows with one trimmed name are refused", () => {
|
||||
assert.equal(duplicateName([row(), row({ name: "other" })]), null);
|
||||
assert.match(
|
||||
duplicateName([row(), row({ name: " no-ads " })]),
|
||||
/two classifications are named no-ads/,
|
||||
);
|
||||
});
|
||||
|
||||
test("opening a PR is gated by the repo, then each row, then a shared name", () => {
|
||||
const good = [row(), row({ name: "other" })];
|
||||
assert.equal(rowsProblem("o/r", good), null);
|
||||
|
||||
// Each check on its own.
|
||||
assert.match(rowsProblem("", good), /owner\/name/);
|
||||
assert.match(rowsProblem("o/r", [row(), row({ name: "" })]), /a name/);
|
||||
assert.match(rowsProblem("o/r", [row(), row()]), /two classifications/);
|
||||
|
||||
// The order: a bad repo wins over a bad row, and a bad row over a shared
|
||||
// name.
|
||||
assert.match(rowsProblem("o", [row({ name: "" })]), /owner\/name/);
|
||||
assert.match(
|
||||
rowsProblem("o/r", [row(), row({ threshold: "x" }), row()]),
|
||||
/threshold/,
|
||||
);
|
||||
// Rows are checked in their order.
|
||||
assert.match(
|
||||
rowsProblem("o/r", [row({ description: "" }), row({ name: "" })]),
|
||||
/no-ads needs a description/,
|
||||
);
|
||||
});
|
||||
|
||||
test("opening a PR needs no PR number, which a run does", () => {
|
||||
assert.equal(prNumber(""), null);
|
||||
assert.equal(rowsProblem("o/r", [row()]), null);
|
||||
assert.equal(prNumber(" 7 "), 7);
|
||||
assert.equal(prNumber("0"), null);
|
||||
assert.equal(prNumber("7a"), null);
|
||||
});
|
||||
|
||||
test("a row becomes the request's classification", () => {
|
||||
assert.deepEqual(
|
||||
toBody(
|
||||
row({ name: " no-ads ", description: " No ads. ", threshold: " 60 " }),
|
||||
),
|
||||
{
|
||||
name: "no-ads",
|
||||
description: " No ads. ",
|
||||
polarity: "negative",
|
||||
threshold: 60,
|
||||
},
|
||||
);
|
||||
assert.equal(thresholdValue("101"), null);
|
||||
});
|
||||
|
||||
test("a loaded rule becomes a row that sends back the same rule", () => {
|
||||
const rule = {
|
||||
name: "no-ads",
|
||||
description: "No ads.",
|
||||
polarity: "negative",
|
||||
threshold: 80,
|
||||
};
|
||||
const d = draftFromRule(rule, 3);
|
||||
assert.deepEqual(d, { key: 3, ...rule, threshold: "80" });
|
||||
assert.deepEqual(toBody(d), rule);
|
||||
});
|
||||
|
||||
test("only a typed name or description counts as the user's work", () => {
|
||||
assert.equal(hasTypedText([row({ name: " ", description: "" })]), false);
|
||||
assert.equal(hasTypedText([row({ name: "", description: "x" })]), true);
|
||||
});
|
||||
Loading…
Reference in a new issue