fix release v2 review issues
This commit is contained in:
1 parent
ef2ed6c602
commit
ca856f9f54
29 files changed
+508
-131
No files matched your search
@@ -3,7 +3,8 @@ import { test } from "node:test";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
import { checkFeatureContracts } from "./contracts.mts";
|
||||
import { planFeatureGeneration } from "./generate-feature.mts";
|
||||
import { formatFeatureChanges, planFeatureGeneration } from "./generate-feature.mts";
|
||||
// oxlint-disable-next-line import/no-unassigned-import -- Registers shared contract tests in this suite.
|
||||
import "./check-feature.contract.mts";
|
||||
|
||||
const root = resolve(import.meta.dirname, "../..");
|
||||
@@ -12,26 +13,30 @@ test("the checked-in feature contracts are consistent", () => {
|
||||
assert.deepEqual(checkFeatureContracts(root), []);
|
||||
});
|
||||
|
||||
test("paired generation plans every contract without writing", () => {
|
||||
const changes = planFeatureGeneration(root, {
|
||||
integration: {
|
||||
kind: "exampleService",
|
||||
name: "Example Service",
|
||||
slug: "example-service",
|
||||
description: "Example native integration.",
|
||||
category: "miscellaneous",
|
||||
secretKinds: ["apiKey"],
|
||||
iconUrl: "https://example.com/icon.svg",
|
||||
},
|
||||
widget: {
|
||||
kind: "exampleStatus",
|
||||
name: "Example Status",
|
||||
slug: "example-status",
|
||||
description: "Example native widget.",
|
||||
icon: "IconBox",
|
||||
supportedIntegrations: ["exampleService"],
|
||||
},
|
||||
});
|
||||
test("paired generation plans every formatter-clean contract without writing", async () => {
|
||||
const description =
|
||||
"A deliberately long feature description that verifies generated source stays formatter-clean when contributor input exceeds the configured print width.";
|
||||
const changes = await formatFeatureChanges(
|
||||
planFeatureGeneration(root, {
|
||||
integration: {
|
||||
kind: "exampleService",
|
||||
name: 'Example "Home" Service',
|
||||
slug: "example-service",
|
||||
description,
|
||||
category: "miscellaneous",
|
||||
secretKinds: ["apiKey"],
|
||||
iconUrl: "https://example.com/icon.svg",
|
||||
},
|
||||
widget: {
|
||||
kind: "exampleStatus",
|
||||
name: 'Example "Home" Status',
|
||||
slug: "example-status",
|
||||
description,
|
||||
icon: "IconBox",
|
||||
supportedIntegrations: ["exampleService"],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
assert.equal(changes.length, 20);
|
||||
assert.equal(new Set(changes.map((change) => change.path)).size, changes.length);
|
||||
@@ -41,6 +46,10 @@ test("paired generation plans every contract without writing", () => {
|
||||
assert.ok(changes.some((change) => change.path === "apps/docs/docs/widgets/example-status/index.mdx"));
|
||||
const integrationTest = changes.find((change) => change.path.endsWith("example-service-integration.spec.ts"));
|
||||
assert.match(integrationTest?.content ?? "", /simulateResponseContractAsync/);
|
||||
assert.match(
|
||||
integrationTest?.content ?? "",
|
||||
/expect\(\n results\.every\(\(result\) => result\.passed\),\n results,\n \)\.toBe\(true\)/,
|
||||
);
|
||||
const widgetDefinition = changes.find((change) => change.path.endsWith("example-status/index.ts"));
|
||||
assert.match(widgetDefinition?.content ?? "", /nativeFeatureCapabilities\.exampleStatus\.integrations/);
|
||||
const capabilityDescriptor = changes.find(
|
||||
@@ -52,6 +61,7 @@ test("paired generation plans every contract without writing", () => {
|
||||
const parsed = JSON.parse(translations.content) as { integration: object; widget: object };
|
||||
assert.ok("exampleService" in parsed.integration);
|
||||
assert.ok("exampleStatus" in parsed.widget);
|
||||
assert.deepEqual(await formatFeatureChanges(changes), changes);
|
||||
});
|
||||
|
||||
test("generation stops before overwriting an existing feature", () => {
|
||||
@@ -71,3 +81,22 @@ test("generation stops before overwriting an existing feature", () => {
|
||||
/already exists/,
|
||||
);
|
||||
});
|
||||
|
||||
test("generation rejects slugs that cannot form TypeScript identifiers", () => {
|
||||
for (const slug of ["2fa-status", "example-2fa"]) {
|
||||
assert.throws(
|
||||
() =>
|
||||
planFeatureGeneration(root, {
|
||||
widget: {
|
||||
kind: "twoFactorStatus",
|
||||
name: "2FA Status",
|
||||
slug,
|
||||
description: "Must not generate an invalid component name.",
|
||||
icon: "IconBox",
|
||||
supportedIntegrations: [],
|
||||
},
|
||||
}),
|
||||
/must start with a lowercase letter and use kebab-case/,
|
||||
);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user