Skip to content

Commit 24e32d3

Browse files
committed
Add automated testing
1 parent 226fc57 commit 24e32d3

7 files changed

Lines changed: 191 additions & 39 deletions

File tree

deno.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"imports": {
1212
"@hono/hono": "jsr:@hono/hono@4",
1313
"@std/assert": "jsr:@std/assert@1",
14+
"@std/expect": "jsr:@std/expect@^1.0.17",
1415
"@std/fs": "jsr:@std/fs@^1.0.20",
16+
"@std/testing": "jsr:@std/testing@^1.0.16",
1517
"typescript": "npm:typescript@^5.9.3",
1618
"@wuespace/honolate": "./lib/mod.ts"
1719
},

deno.lock

Lines changed: 39 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/locales/babeledit-project.babel

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<name>main</name>
2121
<children>
2222
<concept_node>
23-
<name>ABC {0} DEF</name>
23+
<name>Hello world!</name>
2424
<description/>
2525
<comment/>
2626
<translations>
@@ -35,7 +35,22 @@
3535
</translations>
3636
</concept_node>
3737
<concept_node>
38-
<name>Hello world!</name>
38+
<name>Lazy term</name>
39+
<description/>
40+
<comment/>
41+
<translations>
42+
<translation>
43+
<language>de-DE</language>
44+
<approved>false</approved>
45+
</translation>
46+
<translation>
47+
<language>en-US</language>
48+
<approved>false</approved>
49+
</translation>
50+
</translations>
51+
</concept_node>
52+
<concept_node>
53+
<name>This text contains {0} \{} curly braces and \\{\{}}\{0}.</name>
3954
<description/>
4055
<comment/>
4156
<translations>
@@ -50,17 +65,17 @@
5065
</translations>
5166
</concept_node>
5267
<concept_node>
53-
<name>Welcome to the {{}}}}{{ {0} {1} {{0}} {{1}} homepage {0}!</name>
68+
<name>Untranslated text</name>
5469
<description/>
5570
<comment/>
5671
<translations>
5772
<translation>
5873
<language>de-DE</language>
59-
<approved>true</approved>
74+
<approved>false</approved>
6075
</translation>
6176
<translation>
6277
<language>en-US</language>
63-
<approved>true</approved>
78+
<approved>false</approved>
6479
</translation>
6580
</translations>
6681
</concept_node>

example/locales/de.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
2-
"ABC {0} DEF": "Deutsches ABC {0} DEF",
32
"Hello world!": "Hallo Welt!",
4-
"Welcome to the {{}}}}{{ {0} {1} {{0}} {{1}} homepage {0}!": "Willkommen zur {{}}}}{{ {0} {1} {{0}} {{1}} Homepage {0}!"
3+
"Lazy term": "Fauler Begriff",
4+
"This text contains {0} \\{} curly braces and \\\\{\\{}}\\{0}.": "Dieser Text enthält {0} \\{} geschweifte Klammern und \\\\{\\{}}\\{0}.",
5+
"Untranslated text": ""
56
}

example/locales/en.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
2-
"ABC {0} DEF": "ABC {0} DEF",
32
"Hello world!": "Hello world!",
4-
"Welcome to the {{}}}}{{ {0} {1} {{0}} {{1}} homepage {0}!": "Welcome to the {{}}}}{{ {0} {1} {{0}} {{1}} homepage {0}!"
3+
"Lazy term": "Lazy term",
4+
"This text contains {0} \\{} curly braces and \\\\{\\{}}\\{0}.": "This text contains {0} \\{} curly braces and \\\\{\\{}}\\{0}.",
5+
"Untranslated text": "Untranslated text"
56
}

example/main.tsx

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
11
import { Hono } from "@hono/hono";
22
import { jsxRenderer } from "@hono/hono/jsx-renderer";
3-
// import { languageDetector } from '@hono/hono/language';
4-
import { t } from "@wuespace/honolate";
3+
import { lt, t, useLocale } from "@wuespace/honolate";
54
import { withI18n } from "./i18n.ts";
65

7-
const app = new Hono();
6+
const lazyTerm = lt`Lazy term`;
87

9-
app.use(
10-
"*",
11-
// languageDetector({
12-
// supportedLanguages: ['en', 'ar', 'ja', 'de'], // Must include fallback
13-
// fallbackLanguage: 'en', // Required
14-
// }),
15-
withI18n,
16-
jsxRenderer(),
17-
);
8+
export const app = new Hono()
9+
.use(
10+
withI18n,
11+
jsxRenderer(),
12+
)
13+
.get("/text", (c) => c.text(t`Hello world!`))
14+
.get("/locale", (c) => c.text(useLocale()))
15+
.get("/render", (c) => c.render(<h1>{t`Hello world!`}</h1>))
16+
.get("/component", (c) => c.render(<Component />))
17+
.get("/async-component", (c) => {
18+
return c.render(<AsyncComponent />);
19+
})
20+
.get("/async-component-alt", async (c) => {
21+
const component = await AsyncComponent();
22+
return c.render(component);
23+
})
24+
.get("/untranslated", (c) => c.text(t`Untranslated text`))
25+
.get("/lazy", (c) => c.text(t(lazyTerm)))
26+
.get(
27+
"/escape-test",
28+
(c) => c.text(t`This text contains ${1} {} curly braces and \\{{}}{0}.`),
29+
)
30+
.notFound((c) => c.text("Not Found", 404));
1831

19-
app.get("/", (c) => {
20-
return c.render(
21-
<div>
22-
{t`Welcome to the {{}}}}{{ {0} {1} {{0}} {{1}} homepage ${c.req.url}!`}
23-
{t`Hello world!`}
24-
{t`Test: ${<code>{t`Hello!`}</code>}`}
25-
<LocalePrinter />
26-
</div>,
27-
);
28-
});
32+
import.meta.main && Deno.serve(app.fetch);
2933

30-
function LocalePrinter() {
31-
const locale = t`ABC ${3} DEF`;
32-
return <div>Current locale: {locale}</div>;
34+
function Component() {
35+
const greeting = t`Hello world!`;
36+
return <h1>{greeting}</h1>;
3337
}
3438

35-
Deno.serve(app.fetch);
39+
async function AsyncComponent() {
40+
await Promise.resolve();
41+
const greeting = t`Hello world!`;
42+
return <h1>{greeting}</h1>;
43+
}

tests/hono-e2e.test.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { testClient } from "@hono/hono/testing";
2+
import { expect } from "@std/expect";
3+
import { describe, it } from "node:test";
4+
import { app } from "../example/main.tsx";
5+
6+
const testApp = testClient(app);
7+
8+
describe("Hono + Honolate E2E", () => {
9+
describe("t function in different contexts", () => {
10+
const paths = [
11+
"text",
12+
"render",
13+
"component",
14+
"async-component",
15+
"async-component-alt",
16+
] as const;
17+
for (const path of paths) {
18+
it(`GET /${path} should return localized 'Hello world!'`, async () => {
19+
const resDefault = await (await testApp[path].$get({})).text();
20+
const resEn = await (await testApp[path].$get({
21+
query: { lang: "en" },
22+
})).text();
23+
const resDe = await (await testApp[path].$get({
24+
query: { lang: "de" },
25+
})).text();
26+
27+
expect(resDefault).toContain("Hello world!");
28+
expect(resEn).toContain("Hello world!");
29+
expect(resDe).toContain("Hallo Welt!");
30+
});
31+
}
32+
});
33+
describe("Untranslated text", () => {
34+
it("GET /untranslated should return untranslated text", async () => {
35+
const resDefault = await (await testApp.untranslated.$get({})).text();
36+
const resEn = await (await testApp.untranslated.$get({
37+
query: { lang: "en" },
38+
})).text();
39+
const resDe = await (await testApp.untranslated.$get({
40+
query: { lang: "de" },
41+
})).text();
42+
43+
expect(resDefault).toBe("Untranslated text");
44+
expect(resEn).toBe("Untranslated text");
45+
expect(resDe).toBe("Untranslated text");
46+
});
47+
});
48+
describe("Lazy translation term", () => {
49+
it("GET /lazy should return localized lazy term", async () => {
50+
const resDefault = await (await testApp.lazy.$get({})).text();
51+
const resEn = await (await testApp.lazy.$get({
52+
query: { lang: "en" },
53+
})).text();
54+
const resDe = await (await testApp.lazy.$get({
55+
query: { lang: "de" },
56+
})).text();
57+
58+
expect(resDefault).toBe("Lazy term");
59+
expect(resEn).toBe("Lazy term");
60+
expect(resDe).toBe("Fauler Begriff");
61+
});
62+
});
63+
describe("Escape test", () => {
64+
it("GET /escape-test should return correctly escaped text", async () => {
65+
const res = await (await testApp["escape-test"].$get({})).text();
66+
expect(res).toBe("This text contains 1 {} curly braces and \\{{}}{0}.");
67+
const resDe = await (await testApp["escape-test"].$get({
68+
query: { lang: "de" },
69+
})).text();
70+
expect(resDe).toBe(
71+
"Dieser Text enthält 1 {} geschweifte Klammern und \\{{}}{0}.",
72+
);
73+
});
74+
});
75+
describe("Locale", () => {
76+
it("GET /locale should return correct locale", async () => {
77+
const resDefault = await (await testApp.locale.$get({})).text();
78+
const resEn = await (await testApp.locale.$get({
79+
query: { lang: "en" },
80+
})).text();
81+
const resDe = await (await testApp.locale.$get({
82+
query: { lang: "de" },
83+
})).text();
84+
85+
expect(resDefault).toBe("en");
86+
expect(resEn).toBe("en");
87+
expect(resDe).toBe("de");
88+
});
89+
});
90+
});

0 commit comments

Comments
 (0)