Skip to content

Commit 09fd1bd

Browse files
test(editor): fix format codeblock tests not actually running when running test commands
1 parent 20fa962 commit 09fd1bd

File tree

4 files changed

+85
-104
lines changed

4 files changed

+85
-104
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
"docs:preview": "pnpm http-server site -p 9000",
3333
"edit-docs:edit-demo": "pnpm run --filter edit-docs edit-demo",
3434
"test:all": "pnpm test:parallel && pnpm test:sequential",
35-
"test:parallel": "pnpm --filter=!server --filter=!ckeditor5-mermaid --filter=!ckeditor5-math --parallel test",
36-
"test:sequential": "pnpm --filter=server --filter=ckeditor5-mermaid --filter=ckeditor5-math --sequential test",
35+
"test:parallel": "pnpm --filter=!server --filter=!ckeditor5-mermaid --filter=!ckeditor5-math --filter=!@triliumnext/ckeditor5 --parallel test",
36+
"test:sequential": "pnpm --filter=server --filter=ckeditor5-mermaid --filter=ckeditor5-math --filter=@triliumnext/ckeditor5 --sequential test",
3737
"typecheck": "tsc --build",
3838
"dev:format-check": "eslint -c eslint.format.config.mjs .",
3939
"dev:format-fix": "eslint -c eslint.format.config.mjs . --fix",

packages/ckeditor5/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"private": true,
66
"type": "module",
77
"main": "./src/index.ts",
8+
"scripts": {
9+
"test": "vitest"
10+
},
811
"dependencies": {
912
"@triliumnext/commons": "workspace:*",
1013
"@triliumnext/ckeditor5-admonition": "workspace:*",

packages/ckeditor5/tests/format_codeblock_button.test.ts

Lines changed: 72 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
Notification,
55
Paragraph,
66
_setModelData as setModelData,
7-
_getModelData as getModelData,
87
} from "ckeditor5";
98
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
109
import FormatCodeblockButton from "../src/plugins/format_codeblock/format_codeblock_button";
@@ -58,6 +57,23 @@ function setCodeBlockContent(
5857
});
5958
}
6059

60+
/**
61+
* Extract plain text from the first codeBlock element in the editor model.
62+
* Mirrors FormatCodeblockCommand.extractCodeText so assertions test the same
63+
* value the formatter operates on.
64+
*/
65+
function getCodeBlockText(editor: ClassicEditor): string | undefined {
66+
const root = editor.model.document.getRoot()!;
67+
for (const child of root.getChildren()) {
68+
if (child.is("element", "codeBlock")) {
69+
return Array.from(child.getChildren())
70+
.map((c) => (c.is("$text") ? c.data : "\n"))
71+
.join("");
72+
}
73+
}
74+
return undefined;
75+
}
76+
6177
describe("FormatCodeblockButton", () => {
6278
let domElement: HTMLDivElement;
6379
let editor: ClassicEditor;
@@ -123,7 +139,6 @@ describe("FormatCodeblockButton", () => {
123139
LANG_SCSS,
124140
LANG_LESS,
125141
LANG_HTML,
126-
LANG_XML,
127142
LANG_YAML,
128143
LANG_MARKDOWN,
129144
LANG_GRAPHQL,
@@ -146,7 +161,7 @@ describe("FormatCodeblockButton", () => {
146161
});
147162

148163
describe("should be disabled for unsupported languages", () => {
149-
const unsupportedLanguages = [LANG_PYTHON, LANG_RUST, LANG_C];
164+
const unsupportedLanguages = [LANG_XML, LANG_PYTHON, LANG_RUST, LANG_C];
150165

151166
for (const lang of unsupportedLanguages) {
152167
it(`should be disabled for "${lang}"`, () => {
@@ -173,20 +188,19 @@ describe("FormatCodeblockButton", () => {
173188

174189
describe("FormatCodeblockCommand#execute", () => {
175190
it("should format JavaScript code", async () => {
176-
setModelData(
177-
editor.model,
178-
`<codeBlock language="${LANG_JAVASCRIPT_FRONTEND}">const x=1;const y=2;const z=x+y[]</codeBlock>`,
191+
setCodeBlockContent(
192+
editor,
193+
LANG_JAVASCRIPT_FRONTEND,
194+
"const x=1;const y=2;const z=x+y",
179195
);
180196

181197
editor.execute("formatCodeblock");
182198

183199
await vi.waitFor(
184200
() => {
185-
const modelData = getModelData(editor.model, {
186-
withoutSelection: true,
187-
});
188-
expect(modelData).toEqual(
189-
"const x = 1;\nconst y = 2;\nconst z = x + y;",
201+
const text = getCodeBlockText(editor);
202+
expect(text).toEqual(
203+
"const x = 1;\nconst y = 2;\nconst z = x + y;\n",
190204
);
191205
},
192206
{ timeout: 10000 },
@@ -204,11 +218,9 @@ describe("FormatCodeblockButton", () => {
204218

205219
await vi.waitFor(
206220
() => {
207-
const modelData = getModelData(editor.model, {
208-
withoutSelection: true,
209-
});
210-
expect(modelData).toEqual(
211-
'{\n "a": 1,\n "b": 2,\n "c": [\n 1,\n 2,\n 3\n ]\n}',
221+
const text = getCodeBlockText(editor);
222+
expect(text).toEqual(
223+
'{ "a": 1, "b": 2, "c": [1, 2, 3] }\n',
212224
);
213225
},
214226
{ timeout: 10000 },
@@ -226,11 +238,9 @@ describe("FormatCodeblockButton", () => {
226238

227239
await vi.waitFor(
228240
() => {
229-
const modelData = getModelData(editor.model, {
230-
withoutSelection: true,
231-
});
232-
expect(modelData).toEqual(
233-
"body {\n color: red;\n background: blue;\n}",
241+
const text = getCodeBlockText(editor);
242+
expect(text).toEqual(
243+
"body {\n color: red;\n background: blue;\n}\n",
234244
);
235245
},
236246
{ timeout: 10000 },
@@ -248,88 +258,65 @@ describe("FormatCodeblockButton", () => {
248258

249259
await vi.waitFor(
250260
() => {
251-
const modelData = getModelData(editor.model, {
252-
withoutSelection: true,
253-
});
254-
expect(modelData).toEqual(
255-
"interface Foo {\n bar: string;\n baz: number;\n}",
261+
const text = getCodeBlockText(editor);
262+
expect(text).toEqual(
263+
"interface Foo {\n bar: string;\n baz: number;\n}\n",
256264
);
257265
},
258266
{ timeout: 10000 },
259267
);
260268
});
261269

262270
it("should not modify already-formatted code", async () => {
263-
const formattedCode = "const x = 1;";
264-
setModelData(
265-
editor.model,
266-
`<codeBlock language="${LANG_JAVASCRIPT_FRONTEND}">${formattedCode}[]</codeBlock>`,
271+
// Prettier always appends a trailing newline, so the input must
272+
// already include one (represented as a softBreak) to be truly
273+
// "already formatted".
274+
setCodeBlockContent(
275+
editor,
276+
LANG_JAVASCRIPT_FRONTEND,
277+
"const x = 1;\n",
267278
);
268279

269-
const modelDataBefore = getModelData(editor.model, {
270-
withoutSelection: true,
271-
});
280+
const textBefore = getCodeBlockText(editor);
272281

273282
editor.execute("formatCodeblock");
274283

284+
// Give the async formatter a chance to run, then verify no change.
275285
await vi.waitFor(() => {
276-
const modelDataAfter = getModelData(editor.model, {
277-
withoutSelection: true,
278-
});
279-
expect(modelDataAfter).toBe(modelDataBefore);
286+
const textAfter = getCodeBlockText(editor);
287+
expect(textAfter).toBe(textBefore);
280288
});
281289

282-
const modelDataAfter = getModelData(editor.model, {
283-
withoutSelection: true,
284-
});
285-
expect(modelDataAfter).toBe(modelDataBefore);
290+
const textAfter = getCodeBlockText(editor);
291+
expect(textAfter).toBe(textBefore);
286292
});
287293

288294
it("should not modify empty code blocks", () => {
289-
setModelData(
290-
editor.model,
291-
`<codeBlock language="${LANG_JAVASCRIPT_FRONTEND}">[]</codeBlock>`,
292-
);
295+
setCodeBlockContent(editor, LANG_JAVASCRIPT_FRONTEND, "");
293296

294-
const modelDataBefore = getModelData(editor.model, {
295-
withoutSelection: true,
296-
});
297+
const textBefore = getCodeBlockText(editor);
297298

298299
editor.execute("formatCodeblock");
299300

300-
const modelDataAfter = getModelData(editor.model, {
301-
withoutSelection: true,
302-
});
303-
expect(modelDataAfter).toBe(modelDataBefore);
301+
const textAfter = getCodeBlockText(editor);
302+
expect(textAfter).toBe(textBefore);
304303
});
305304

306305
it("should not modify whitespace-only code blocks", () => {
307-
setModelData(
308-
editor.model,
309-
`<codeBlock language="${LANG_JAVASCRIPT_FRONTEND}"> []</codeBlock>`,
310-
);
306+
setCodeBlockContent(editor, LANG_JAVASCRIPT_FRONTEND, " ");
311307

312-
const modelDataBefore = getModelData(editor.model, {
313-
withoutSelection: true,
314-
});
308+
const textBefore = getCodeBlockText(editor);
315309

316310
editor.execute("formatCodeblock");
317311

318-
const modelDataAfter = getModelData(editor.model, {
319-
withoutSelection: true,
320-
});
321-
expect(modelDataAfter).toBe(modelDataBefore);
312+
const textAfter = getCodeBlockText(editor);
313+
expect(textAfter).toBe(textBefore);
322314
});
323315

324316
it("should not execute when language is unsupported", () => {
325-
setModelData(
326-
editor.model,
327-
`<codeBlock language="${LANG_PYTHON}">x=1[]</codeBlock>`,
328-
);
317+
setCodeBlockContent(editor, LANG_PYTHON, "x=1");
329318

330-
const modelDataBefore = getModelData(editor.model, {
331-
withoutSelection: true,
332-
});
319+
const textBefore = getCodeBlockText(editor);
333320

334321
// Manually try to execute — the command should be disabled, so
335322
// calling execute directly on the command should be a no-op.
@@ -338,57 +325,41 @@ describe("FormatCodeblockButton", () => {
338325
)! as FormatCodeblockCommand;
339326
command.execute();
340327

341-
const modelDataAfter = getModelData(editor.model, {
342-
withoutSelection: true,
343-
});
344-
expect(modelDataAfter).toBe(modelDataBefore);
328+
const textAfter = getCodeBlockText(editor);
329+
expect(textAfter).toBe(textBefore);
345330
});
346331

347332
it("should handle multiline code with softBreaks in the model", async () => {
348-
editor.model.change((writer) => {
349-
const root = editor.model.document.getRoot()!;
350-
351-
writer.remove(writer.createRangeIn(root));
352-
353-
const codeBlock = writer.createElement("codeBlock", {
354-
language: LANG_JAVASCRIPT_FRONTEND,
355-
});
356-
writer.appendText("const x=1;", codeBlock);
357-
writer.appendElement("softBreak", codeBlock);
358-
writer.appendText("const y=2;", codeBlock);
359-
360-
writer.append(codeBlock, root);
361-
362-
writer.setSelection(codeBlock, "end");
363-
});
333+
setCodeBlockContent(
334+
editor,
335+
LANG_JAVASCRIPT_FRONTEND,
336+
"const x=1;\nconst y=2;",
337+
);
364338

365339
editor.execute("formatCodeblock");
366340

367341
await vi.waitFor(
368342
() => {
369-
const modelData = getModelData(editor.model, {
370-
withoutSelection: true,
371-
});
372-
expect(modelData).toEqual("const x = 1;\nconst y = 2;");
343+
const text = getCodeBlockText(editor);
344+
expect(text).toEqual("const x = 1;\nconst y = 2;\n");
373345
},
374346
{ timeout: 10000 },
375347
);
376348
});
377349

378350
it("should format YAML code", async () => {
379-
setModelData(
380-
editor.model,
381-
`<codeBlock language="${LANG_YAML}">foo: bar\nbaz: qux[]</codeBlock>`,
351+
setCodeBlockContent(
352+
editor,
353+
LANG_YAML,
354+
"foo: bar\nbaz: qux",
382355
);
383356

384357
editor.execute("formatCodeblock");
385358

386359
await vi.waitFor(
387360
() => {
388-
const modelData = getModelData(editor.model, {
389-
withoutSelection: true,
390-
});
391-
expect(modelData).toEqual("foo: bar\nbaz: qux");
361+
const text = getCodeBlockText(editor);
362+
expect(text).toEqual("foo: bar\nbaz: qux\n");
392363
},
393364
{ timeout: 10000 },
394365
);

packages/ckeditor5/vite.config.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// <reference types='vitest' />
22
import { defineConfig } from 'vite';
33
import dts from 'vite-plugin-dts';
4+
import { webdriverio } from "@vitest/browser-webdriverio";
45
import * as path from 'path';
56

67
export default defineConfig(() => ({
@@ -34,7 +35,13 @@ export default defineConfig(() => ({
3435
},
3536
},
3637
test: {
37-
environment: "happy-dom",
38+
browser: {
39+
enabled: true,
40+
provider: webdriverio(),
41+
headless: true,
42+
ui: false,
43+
instances: [{ browser: 'chrome' }]
44+
},
3845
include: [
3946
'tests/**/*.[jt]s'
4047
],

0 commit comments

Comments
 (0)