Merge upstream v0.4.0 into Gitea fork
This commit is contained in:
@@ -19,6 +19,9 @@ import { KeyboardSection } from "../components/settings/keyboard-section.tsx";
|
||||
import type { GraphSettings } from "../src/core/index.ts";
|
||||
import { SettingsDialogBody, SettingsDialogProvider } from "../components/settings/settings-dialog.tsx";
|
||||
import { KEYBOARD_ACTIONS } from "../src/core/index.ts";
|
||||
import { DictationLanguageSetting } from "../components/dictation-language.tsx";
|
||||
import { SettingsMenuTrigger, SettingsRow } from "../components/settings/controls.tsx";
|
||||
import { SubscriptionConnections } from "../components/settings/subscription-connections.tsx";
|
||||
|
||||
/** The full opening tag of the element carrying a testid — attribute
|
||||
* order in React output is not contractual, so assertions run on the
|
||||
@@ -29,6 +32,17 @@ function tagOf(html: string, testid: string): string {
|
||||
return html.slice(html.lastIndexOf("<", i), html.indexOf(">", i) + 1);
|
||||
}
|
||||
|
||||
describe("SettingsRow hint composition", () => {
|
||||
it("preserves rich React hints while translating only text", () => {
|
||||
const rich = renderToStaticMarkup(<SettingsRow label="Hint" hint={<a href="#details">Details</a>}><input /></SettingsRow>);
|
||||
assert.match(rich, /<a href="#details">Details<\/a>/);
|
||||
const text = renderToStaticMarkup(<SettingsRow label="Hint" hint="A text hint"><input /></SettingsRow>);
|
||||
assert.match(text, /A text hint/);
|
||||
const numeric = renderToStaticMarkup(<SettingsRow label="Hint" hint={42}><input /></SettingsRow>);
|
||||
assert.match(numeric, />42<\/span>/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("SettingsDialog (the designed surface, SSR)", () => {
|
||||
it("provider CLOSED: children only — no dialog, no portal content", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
@@ -60,6 +74,52 @@ describe("SettingsDialog (the designed surface, SSR)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("the shared settings dropdown trigger", () => {
|
||||
it("Agent, Appearance and dictation use the same compact dark mono trigger", () => {
|
||||
const surfaces = [
|
||||
[renderToStaticMarkup(<AgentSection agent={undefined} models={undefined} graph={undefined} onSectionChange={() => {}} onModelsChange={() => {}} />), "slot-model-strong"],
|
||||
[renderToStaticMarkup(<AppearanceSection appearance={undefined} onSectionChange={() => {}} />), "font-trigger"],
|
||||
[renderToStaticMarkup(<DictationLanguageSetting />), "language-select-sttLanguage"],
|
||||
] as const;
|
||||
for (const [html, id] of surfaces) {
|
||||
const tag = tagOf(html, id);
|
||||
const classes = tag.match(/class="([^"]+)"/)![1]!.split(" ");
|
||||
for (const token of ["h-7", "rounded-sm", "border", "border-border", "bg-background", "px-1.5", "font-ui", "text-xs", "hover:border-muted-foreground/50"]) {
|
||||
assert.ok(classes.includes(token), `${id}: ${token}`);
|
||||
}
|
||||
assert.ok(html.includes("▾"), `${id}: shared dropdown indicator`);
|
||||
}
|
||||
});
|
||||
|
||||
it("preserves native disabling separately from callers' existing click-gated unavailable state", () => {
|
||||
const disabled = tagOf(renderToStaticMarkup(<SettingsMenuTrigger value="English" disabled data-testid="disabled-trigger" />), "disabled-trigger");
|
||||
const unavailable = tagOf(renderToStaticMarkup(<SettingsMenuTrigger value="Automatic" unavailable data-testid="unavailable-trigger" />), "unavailable-trigger");
|
||||
assert.ok(disabled.includes('disabled=""'));
|
||||
assert.ok(!unavailable.includes('disabled=""'));
|
||||
assert.ok(unavailable.includes("cursor-not-allowed"));
|
||||
assert.ok(!unavailable.includes("hover:border-muted-foreground/50"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Providers settings-label typography", () => {
|
||||
it("the fork's speech-language label keeps the standard sans SettingsRow styling and mono trigger", () => {
|
||||
const html = renderToStaticMarkup(<DictationLanguageSetting />);
|
||||
assert.ok(html.includes('<span class="block font-prose text-(length:--lh-prose-size)">Speech recognition language</span>'));
|
||||
assert.ok(tagOf(html, "language-select-sttLanguage").includes("font-ui text-xs"));
|
||||
});
|
||||
|
||||
it("only Providers subscription labels use sans; setup labels retain their compact mono styling", () => {
|
||||
const settings = renderToStaticMarkup(<SubscriptionConnections />);
|
||||
const setup = renderToStaticMarkup(<SubscriptionConnections setup />);
|
||||
for (const label of ["ChatGPT", "GitHub Copilot", "Grok"]) {
|
||||
assert.ok(settings.includes(`<span class="font-prose text-(length:--lh-prose-size) text-foreground">${label}</span>`), `${label}: settings sans label`);
|
||||
assert.ok(setup.includes(`<span class="font-ui text-xs text-foreground">${label}</span>`), `${label}: unchanged setup label`);
|
||||
}
|
||||
assert.equal((settings.match(/>Connect<\/button>/g) ?? []).length, 3);
|
||||
assert.equal((setup.match(/>Connect<\/button>/g) ?? []).length, 3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("AgentSection (thin SSR)", () => {
|
||||
it("renders the three model SLOT rows (slots-only, fix wave: unpicked reads —, no Default option)", () => {
|
||||
const html = renderToStaticMarkup(<AgentSection agent={undefined} models={undefined} graph={undefined} onSectionChange={() => {}} onModelsChange={() => {}} />);
|
||||
|
||||
Reference in New Issue
Block a user