forked from lingodotdev/lingo.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.spec.ts
More file actions
255 lines (204 loc) · 8.6 KB
/
index.spec.ts
File metadata and controls
255 lines (204 loc) · 8.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import { describe, it, expect, vi } from "vitest";
import { LingoDotDevEngine } from "./index";
describe("ReplexicaEngine", () => {
it("should pass", () => {
expect(1).toBe(1);
});
describe("localizeHtml", () => {
it("should correctly extract, localize, and reconstruct HTML content", async () => {
// Setup test HTML with various edge cases
const inputHtml = `
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
<meta name="description" content="Page description">
</head>
<body>
standalone text
<div>
<h1>Hello World</h1>
<p>
This is a paragraph with
<a href="/test" title="Link title">a link</a>
and an
<img src="/test.jpg" alt="Test image">
and some <b>bold <i>and italic</i></b> text.
</p>
<script>
const doNotTranslate = "this text should be ignored";
</script>
<input type="text" placeholder="Enter text">
</div>
</body>
</html>`.trim();
// Mock the internal localization method
const engine = new LingoDotDevEngine({ apiKey: "test" });
const mockLocalizeRaw = vi.spyOn(engine as any, "_localizeRaw");
mockLocalizeRaw.mockImplementation(async (content: any) => {
// Simulate translation by adding 'ES:' prefix to all strings
return Object.fromEntries(Object.entries(content).map(([key, value]) => [key, `ES:${value}`]));
});
// Execute the localization
const result = await engine.localizeHtml(inputHtml, {
sourceLocale: "en",
targetLocale: "es",
});
// Verify the extracted content passed to _localizeRaw
expect(mockLocalizeRaw).toHaveBeenCalledWith(
{
"head/0/0": "Test Page",
"head/1#content": "Page description",
"body/0": "standalone text",
"body/1/0/0": "Hello World",
"body/1/1/0": "This is a paragraph with",
"body/1/1/1#title": "Link title",
"body/1/1/1/0": "a link",
"body/1/1/2": "and an",
"body/1/1/3#alt": "Test image",
"body/1/1/4": "and some",
"body/1/1/5/0": "bold",
"body/1/1/5/1/0": "and italic",
"body/1/1/6": "text.",
"body/1/3#placeholder": "Enter text",
},
{
sourceLocale: "en",
targetLocale: "es",
},
undefined,
undefined,
);
// Verify the final HTML structure
expect(result).toContain('<html lang="es">');
expect(result).toContain("<title>ES:Test Page</title>");
expect(result).toContain('content="ES:Page description"');
expect(result).toContain(">ES:standalone text<");
expect(result).toContain("<h1>ES:Hello World</h1>");
expect(result).toContain('title="ES:Link title"');
expect(result).toContain('alt="ES:Test image"');
expect(result).toContain('placeholder="ES:Enter text"');
expect(result).toContain('const doNotTranslate = "this text should be ignored"');
});
});
describe("AbortController support", () => {
it("should abort localizeText when signal is triggered", async () => {
const engine = new LingoDotDevEngine({ apiKey: "test" });
const mockFetch = vi.spyOn(global, "fetch").mockImplementation(async (url, options) => {
// Check if the request was aborted
if (options?.signal?.aborted) {
throw new DOMException("The operation was aborted.", "AbortError");
}
// Add a delay to simulate network request
await new Promise(resolve => setTimeout(resolve, 100));
// After the delay, check again if aborted during the delay
if (options?.signal?.aborted) {
throw new DOMException("The operation was aborted.", "AbortError");
}
return new Response(JSON.stringify({ data: { text: "translated text" } }));
});
const controller = new AbortController();
const signal = controller.signal;
// Start the request first, then abort after a small delay
const promise = engine.localizeText("Hello world", {
sourceLocale: "en",
targetLocale: "es"
}, undefined, signal);
// Small delay to make sure the request starts
await new Promise(resolve => setTimeout(resolve, 10));
// Now abort
controller.abort();
await expect(promise).rejects.toThrow("Localization was aborted");
mockFetch.mockRestore();
});
it("should abort localizeHtml when signal is triggered", async () => {
const engine = new LingoDotDevEngine({ apiKey: "test" });
// Mock _localizeRaw to throw AbortError when signal is aborted
vi.spyOn(engine as any, "_localizeRaw").mockImplementation(async (...args: any[]) => {
const signal = args[3]; // signal is the 4th argument
if (signal?.aborted) {
const error = new DOMException("The operation was aborted.", "AbortError");
throw error;
}
// Add a delay to simulate network request
await new Promise(resolve => setTimeout(resolve, 100));
// Check again if aborted during the delay
if (signal?.aborted) {
const error = new DOMException("The operation was aborted.", "AbortError");
throw error;
}
return {};
});
const controller = new AbortController();
const signal = controller.signal;
const promise = engine.localizeHtml("<html><body>Test</body></html>", {
sourceLocale: "en",
targetLocale: "es"
}, undefined, signal);
// Small delay to ensure the request starts
await new Promise(resolve => setTimeout(resolve, 10));
// Abort after the delay
controller.abort();
await expect(promise).rejects.toThrow("Localization was aborted");
});
it("should abort batchLocalizeText and propagate to all child operations", async () => {
const engine = new LingoDotDevEngine({ apiKey: "test" });
// Track how many times localizeText is called
let localizeTextCalls = 0;
// Mock localizeText to simulate aborting
vi.spyOn(engine, "localizeText").mockImplementation(async (text, params, callback, signal) => {
localizeTextCalls++;
if (signal?.aborted) {
throw new Error("Localization was aborted");
}
// Simulate a longer delay
await new Promise(resolve => setTimeout(resolve, 100));
// Check again if aborted during the delay
if (signal?.aborted) {
throw new Error("Localization was aborted");
}
return "translated";
});
const controller = new AbortController();
const signal = controller.signal;
const promise = engine.batchLocalizeText("Hello world", {
sourceLocale: "en",
targetLocales: ["es", "fr", "de", "it"]
}, signal);
// Start the process
await new Promise(resolve => setTimeout(resolve, 20));
// Abort after the process has started
controller.abort();
await expect(promise).rejects.toThrow("Localization was aborted");
// Verify that we attempted to start some localizeText calls
expect(localizeTextCalls).toBeGreaterThan(0);
});
it("should abort recognizeLocale operation when signal is triggered", async () => {
const engine = new LingoDotDevEngine({ apiKey: "test" });
vi.spyOn(global, "fetch").mockImplementation(async (...args: any[]) => {
const options = args[1] as RequestInit; // options is the 2nd argument
// Check if already aborted
if (options?.signal?.aborted) {
throw new DOMException("The operation was aborted.", "AbortError");
}
// Check if the abort signal is passed to fetch
expect(options?.signal).toBeDefined();
// Simulate a delay
await new Promise(resolve => setTimeout(resolve, 100));
// Check if aborted during the delay
if (options?.signal?.aborted) {
throw new DOMException("The operation was aborted.", "AbortError");
}
return new Response(JSON.stringify({ locale: "en" }));
});
const controller = new AbortController();
const signal = controller.signal;
const promise = engine.recognizeLocale("Hello world", signal);
// Small delay to ensure the request starts
await new Promise(resolve => setTimeout(resolve, 10));
// Abort after the request has started
controller.abort();
await expect(promise).rejects.toThrow("Locale recognition was aborted");
});
});
});