Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ We keep the code simple and consistent:
`scripts/rules.sh` holds the conventions a person can break in a second: a
comment where the code should speak for itself, `unsafe` outside the `-sys`
crates, the core printing to a terminal or reaching for a platform, Spanish in
an identifier, two crates naming an example the same, and a file grown past
an identifier or in the name of a test of the window, two crates naming an example the same, and a file grown past
what anybody reads through. `scripts/commits.sh` holds the commit convention
below. Both answer
the same whether you run them or CI does, and they say every rule that broke
Expand All @@ -141,7 +141,8 @@ tag it asks `scripts/news.sh` whether `app/src/news.json` says what changed in
that version — the screen that tells a person what is new is the only place the
app says it, and a tag is the last moment to notice it is empty. A candidate is
exempt: the screen only shows versions at or below the one running, and `3.0.0`
is above `3.0.0-rc1`. Nothing slower goes in any of
is above `3.0.0-rc1`. So is a patch whose minor release already has its entry:
`3.0.1` fixes what `3.0.0` shipped, and the window keeps telling `3.0.0`'s news. Nothing slower goes in any of
them: the suite, the build and the markdown lint are minutes, and they belong to
CI.

Expand Down
18 changes: 9 additions & 9 deletions app/src/tests/bindings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ function rowsOn(mac: boolean): Binding[] {
});
}

describe("la tabla de atajos", () => {
it("promete solo teclas que el panel mira de verdad, en Windows y en un Mac", () => {
describe("the shortcut table", () => {
it("promises only keys the panel really watches, on Windows and on a Mac", () => {
for (const mac of [false, true]) {
const where = mac ? "macOS" : "Windows";
for (const row of rowsOn(mac)) {
Expand All @@ -177,7 +177,7 @@ describe("la tabla de atajos", () => {
}
});

it("dice en voz alta lo que en un Mac solo se dibuja", () => {
it("says out loud what a Mac only draws", () => {
for (const tongue of ["es", "en"] as const) {
adopt(tongue);
for (const row of panelKeys(true)) {
Expand All @@ -197,7 +197,7 @@ describe("la tabla de atajos", () => {
expect(panelKeys(true).filter((one) => one.id === "remove")[0].said).toBe("Command Backspace");
});

it("no ofrece en un Mac teclas que su teclado no tiene", () => {
it("does not offer a Mac keys its keyboard lacks", () => {
const forbidden = [/\bF\d/, /\bSupr\b/, /\bDelete\b/, /\bCtrl\b/, /\bAlt\b/, /\bShift\b/];
for (const row of rowsOn(true)) {
for (const one of forbidden) {
Expand All @@ -208,7 +208,7 @@ describe("la tabla de atajos", () => {
}
});

it("lo que solo responde en un Mac va detrás de la plataforma", () => {
it("what only answers on a Mac sits behind the platform", () => {
const only = ['event.text == ","', "event.text == Key.Backspace && event.modifiers.control"];
for (const one of only) {
const branch = BRANCHES.find((said) => said.includes(one));
Expand All @@ -224,7 +224,7 @@ describe("la tabla de atajos", () => {
);
});

it("dice lo mismo en los dos idiomas, fila por fila", () => {
it("says the same in both languages, row by row", () => {
for (const mac of [false, true]) {
adopt("es");
const es = panelKeys(mac);
Expand All @@ -240,7 +240,7 @@ describe("la tabla de atajos", () => {
}
});

it("un clic con modificador lo lee de verdad lo que se pincha", () => {
it("a click with a modifier really reads what is clicked", () => {
const cards = ui("cards.slint");
// the layers row tells this one in words instead of naming a key, so nothing above reaches it
expect(cards, "no clic suma tipos en vez de cambiarlos").toContain(
Expand All @@ -265,7 +265,7 @@ describe("la tabla de atajos", () => {
}
});

it("el botón que promete sumar tipos existe en el panel", () => {
it("the button that promises to add kinds exists in the panel", () => {
for (const tongue of ["es", "en"] as const) {
adopt(tongue);
const row = panelKeys(false).find((one) =>
Expand All @@ -276,7 +276,7 @@ describe("la tabla de atajos", () => {
expect(PANEL, "nothing in the panel toggles the mode").toContain("keep-toggled");
});

it("filtra por tipos que el buscador conoce", () => {
it("filters by kinds the search box knows", () => {
const view = readFileSync(
join(__dirname, "..", "..", "..", "crates", "cp-panel", "src", "view.rs"),
"utf8",
Expand Down
6 changes: 3 additions & 3 deletions app/src/tests/kept.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ async function heardOn(name: string): Promise<Heard> {
return call[1];
}

describe("los ajustes guardados desde otra ventana", () => {
describe("settings saved from another window", () => {
beforeEach(() => {
vi.clearAllMocks();
});

it("se adoptan cuando esta ventana no tiene nada por guardar", async () => {
it("are adopted when this window has nothing left to save", async () => {
const { result } = renderHook(() => useKept());
await waitFor(() => expect(result.current.kept).not.toBeNull());

Expand All @@ -36,7 +36,7 @@ describe("los ajustes guardados desde otra ventana", () => {
expect(result.current.kept?.["keeps-days"]).toBe(7);
});

it("no pisan un cambio de esta ventana que todavía se está guardando", async () => {
it("do not overwrite a change of this window that is still being saved", async () => {
const { invoke } = await import("@tauri-apps/api/core");
const real = vi.mocked(invoke).getMockImplementation();
let release: () => void = () => {};
Expand Down
8 changes: 4 additions & 4 deletions app/src/tests/keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ function press(code: string, held: Partial<Record<"ctrl" | "alt" | "shift" | "me
};
}

describe("la combinación que el usuario presiona", () => {
it("se escribe como el sistema la espera", () => {
describe("the combination the user presses", () => {
it("is written the way the system expects it", () => {
expect(combination(press("KeyV", { ctrl: true, alt: true }))).toBe("Ctrl+Alt+V");
expect(combination(press("F9", { ctrl: true, alt: true }))).toBe("Ctrl+Alt+F9");
expect(combination(press("Digit1", { ctrl: true, shift: true }))).toBe("Ctrl+Shift+1");
expect(combination(press("Space", { meta: true, alt: true }))).toBe("Alt+Cmd+Space");
});

it("no acepta una tecla suelta, que secuestraría el teclado entero", () => {
it("refuses a lone key, which would hijack the whole keyboard", () => {
expect(combination(press("KeyV", {}))).toBeNull();
expect(combination(press("F9", {}))).toBeNull();
});

it("no acepta modificadores sin una tecla de verdad", () => {
it("refuses modifiers without a real key", () => {
expect(combination(press("ControlLeft", { ctrl: true }))).toBeNull();
expect(combination(press("AltLeft", { ctrl: true, alt: true }))).toBeNull();
});
Expand Down
6 changes: 3 additions & 3 deletions app/src/tests/links.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ function covers(pattern: string, url: string): boolean {
return url.startsWith(pattern.slice(0, star)) && url.endsWith(pattern.slice(star + 1));
}

describe("los enlaces del acerca de", () => {
it("todos están permitidos, así que ninguno nace muerto", () => {
describe("the links in About", () => {
it("are all allowed, so none is born dead", () => {
const patterns = allowed();
for (const url of [...LINKS, ...TOOLS]) {
expect(
Expand All @@ -38,7 +38,7 @@ describe("los enlaces del acerca de", () => {
}
});

it("las otras herramientas llevan a su propia página, no al repositorio", () => {
it("the other tools lead to their own page, not to the repository", () => {
for (const url of TOOLS) {
expect(url.startsWith("https://rgdevment.com/")).toBe(true);
}
Expand Down
22 changes: 11 additions & 11 deletions app/src/tests/notices.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function answering(notices: () => Promise<string>) {
};
}

describe("los avisos que cada licencia empaquetada pide", () => {
describe("the notices each bundled licence asks for", () => {
const undo: (() => void)[] = [];

afterEach(() => {
Expand All @@ -31,7 +31,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
}
});

it("se muestran desde la ventana, y solo se piden cuando se abren", async () => {
it("are shown from the window, and only fetched when opened", async () => {
const who = userEvent.setup();
const said = await answering(() => Promise.resolve("MIT License\n\nCopyright (c) alguien"));
undo.push(said.undo);
Expand All @@ -52,7 +52,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
expect(button.getAttribute("aria-expanded")).toBe("false");
});

it("se dibujan como texto, no como el markdown en que están escritos", async () => {
it("are drawn as text, not as the markdown they are written in", async () => {
const who = userEvent.setup();
const said = await answering(() =>
Promise.resolve(
Expand All @@ -71,7 +71,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
expect(screen.queryByText(/Do not edit by hand/)).toBeNull();
});

it("no ejecutan lo que traigan escrito como html", async () => {
it("do not run whatever html they carry", async () => {
const who = userEvent.setup();
const said = await answering(() => Promise.resolve("<img src=x onerror=alert(1)> y nada más"));
undo.push(said.undo);
Expand All @@ -83,7 +83,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
expect(container.querySelector(".notices img")).toBeNull();
});

it("un enlace de dentro se abre fuera, sin llevarse la ventana", async () => {
it("a link inside opens outside, without taking the window with it", async () => {
const who = userEvent.setup();
const { invoke } = await import("@tauri-apps/api/core");
const said = await answering(() => Promise.resolve("Ver https://crates.io/crates/slint"));
Expand All @@ -96,7 +96,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
expect(invoke).toHaveBeenCalledWith("open_web", { url: "https://crates.io/crates/slint" });
});

it("todo enlace del archivo de verdad lleva su sitio, porque uno relativo apunta a la ventana", () => {
it("every link in the real file names its site, because a relative one points at the window", () => {
const holder = document.createElement("div");
holder.innerHTML = composed(readFileSync("../THIRD-PARTY-BUNDLED.md", "utf8"));
const hrefs = Array.from(holder.querySelectorAll("a")).map((one) => one.getAttribute("href"));
Expand All @@ -106,7 +106,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
}
});

it("un reintento que sale bien se lleva el aviso del fallo anterior", async () => {
it("a retry that works clears the notice of the earlier failure", async () => {
const who = userEvent.setup();
let tries = 0;
const said = await answering(() => {
Expand All @@ -125,7 +125,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
expect(screen.queryByText("No se pudieron leer los avisos de terceros")).toBeNull();
});

it("los textos de las licencias tienen su propio botón, y solo se piden al abrirlo", async () => {
it("the licence texts have their own button, and are only fetched when it opens", async () => {
const who = userEvent.setup();
const { invoke } = await import("@tauri-apps/api/core");
const real = vi.mocked(invoke).getMockImplementation() as Invoke;
Expand Down Expand Up @@ -156,7 +156,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
});
});

it("si los textos no se pueden leer, lo dice", async () => {
it("says so when the texts cannot be read", async () => {
const who = userEvent.setup();
const { invoke } = await import("@tauri-apps/api/core");
const real = vi.mocked(invoke).getMockImplementation() as Invoke;
Expand All @@ -172,7 +172,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
).toBeDefined();
});

it("todo enlace de los textos de verdad lleva su sitio", () => {
it("every link in the real texts names its site", () => {
const holder = document.createElement("div");
holder.innerHTML = composed(readFileSync("../THIRD-PARTY-LICENSES.md", "utf8"));
for (const href of Array.from(holder.querySelectorAll("a")).map((one) =>
Expand All @@ -183,7 +183,7 @@ describe("los avisos que cada licencia empaquetada pide", () => {
expect(holder.querySelectorAll("pre").length).toBeGreaterThan(100);
});

it("si no se pueden leer, lo dice en vez de quedarse callado", async () => {
it("says so when they cannot be read instead of staying silent", async () => {
const who = userEvent.setup();
const said = await answering(() => Promise.reject(new Error("no")));
undo.push(said.undo);
Expand Down
10 changes: 5 additions & 5 deletions app/src/tests/prose.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ import { t } from "../locales";
import { asProse } from "../ui/Bits";

describe("asProse", () => {
it("cierra cada frase, que sueltas se leen pegadas", () => {
it("closes every sentence, since loose ones read glued together", () => {
expect(asProse(["una cosa", "otra cosa"])).toBe("una cosa. otra cosa.");
});

it("no dobla el punto de una frase que ya lo trae", () => {
it("does not double the full stop of a sentence that already has one", () => {
expect(asProse(["ya termina.", "y esta no"])).toBe("ya termina. y esta no.");
});

it("respeta los dos puntos y los signos de cierre", () => {
it("respects colons and closing marks", () => {
expect(asProse(["mira esto:", "¿seguro?", "¡claro!"])).toBe("mira esto: ¿seguro? ¡claro!");
});

it("descarta lo vacio en vez de dejar un punto suelto", () => {
it("drops what is empty instead of leaving a stray full stop", () => {
expect(asProse(["", " ", "solo esto"])).toBe("solo esto.");
expect(asProse([])).toBe("");
});

it("deja el resumen de CopyPaste 2 como un parrafo con puntos", () => {
it("leaves the CopyPaste 2 summary as one paragraph with full stops", () => {
const said = asProse([
t("formerKeeps"),
t("formerLosesPlain"),
Expand Down
6 changes: 3 additions & 3 deletions app/src/tests/rail.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ async function heardOn(name: string): Promise<Heard> {
return (call as [string, Heard])[1];
}

describe("la ventana", () => {
describe("the window", () => {
beforeEach(() => {
vi.clearAllMocks();
});

it("aterriza en los atajos cuando el panel pide los ajustes", async () => {
it("lands on the shortcuts when the panel asks for settings", async () => {
render(<App />);
await screen.findByLabelText("Idioma");

Expand All @@ -30,7 +30,7 @@ describe("la ventana", () => {
expect(await screen.findByText("Atajo del panel")).toBeDefined();
});

it("no se mueve si le piden una sección que no existe", async () => {
it("does not move when asked for a section that does not exist", async () => {
render(<App />);
await screen.findByLabelText("Idioma");

Expand Down
8 changes: 4 additions & 4 deletions app/src/tests/refusals.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async function insteadOf(handle: (what: string, real?: Invoke) => Promise<unknow
return () => vi.mocked(invoke).mockImplementation(real as never);
}

describe("cuando el backend dice que no", () => {
describe("when the backend says no", () => {
const undo: (() => void)[] = [];

afterEach(() => {
Expand All @@ -24,7 +24,7 @@ describe("cuando el backend dice que no", () => {
}
});

it("muestra el motivo y vuelve a leer lo que quedó guardado", async () => {
it("shows the reason and reads back what was saved", async () => {
const who = userEvent.setup();
undo.push(
await insteadOf((what) =>
Expand All @@ -46,7 +46,7 @@ describe("cuando el backend dice que no", () => {
});
});

it("calla sobre el atajo si ni siquiera puede preguntar", async () => {
it("says nothing about the shortcut if it cannot even ask", async () => {
undo.push(
await insteadOf((what) => (what === "keys" ? Promise.reject(new Error("no answer")) : null)),
);
Expand All @@ -57,7 +57,7 @@ describe("cuando el backend dice que no", () => {
expect(screen.queryByText(/Otro programa ya usa/)).toBeNull();
});

it("avisa del atajo tomado aunque no consiga proponer otros", async () => {
it("warns the shortcut is taken even when it cannot offer others", async () => {
undo.push(
await insteadOf((what) => {
if (what === "keys") {
Expand Down
8 changes: 4 additions & 4 deletions app/src/tests/theme.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { describe, expect, it } from "vitest";

const sheet = readFileSync("src/index.css", "utf8");

describe("los tres temas", () => {
it("el claro es la base, así que sin elección no se cae al oscuro", () => {
describe("the three themes", () => {
it("light is the base, so with no choice it does not fall to dark", () => {
const root = sheet.slice(sheet.indexOf(":root {"), sheet.indexOf("}"));
expect(root).toContain("--panel: #f7f8fb");
expect(root).toContain("color-scheme: light");
});

it("el del sistema sigue al sistema", () => {
it("the system one follows the system", () => {
expect(sheet).toContain("@media (prefers-color-scheme: dark)");
expect(sheet).toContain(':root:not([data-theme="light"])');
});

it("elegir uno gana sobre lo que diga el sistema, en los dos sentidos", () => {
it("choosing one wins over what the system says, both ways", () => {
expect(sheet).toContain(':root[data-theme="dark"]');
const guarded = sheet.indexOf(':root:not([data-theme="light"])');
expect(guarded).toBeGreaterThan(-1);
Expand Down
Loading
Loading