Skip to content

Commit e725074

Browse files
committed
chore(138): utrecht-button#undefined error
1 parent 3f6a2d3 commit e725074

File tree

8 files changed

+87
-63
lines changed

8 files changed

+87
-63
lines changed

packages/editor/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"preview": "vite preview",
3030
"pretest": "pnpm exec playwright install --with-deps",
3131
"test": "pnpm run --recursive '/^test:.+$/'",
32-
"test:vitest": "vitest",
32+
"test:vitest": "vitest --run",
3333
"test-coverage": "vitest run --coverage"
3434
},
3535
"dependencies": {
@@ -55,7 +55,7 @@
5555
"@tiptap/extension-underline": "3.11.1",
5656
"@tiptap/extensions": "3.11.1",
5757
"@tiptap/pm": "3.11.1",
58-
"@utrecht/web-component-library-stencil": "3.7.0",
58+
"@utrecht/web-component-library-stencil": "4.0.0",
5959
"lit": "3.3.1",
6060
"prosemirror-model": "1.25.4"
6161
},

packages/editor/src/components/toolbar/shortcuts-dialog/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { customElement, property } from 'lit/decorators.js';
44
import { ref, type Ref } from 'lit/directives/ref.js';
55
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
66
import shortcutsDialogStyles from './styles.ts';
7+
import './../toolbar-button';
78

89
@customElement('clippy-shortcuts')
910
export class ShortcutsDialog extends LitElement {

packages/editor/src/components/toolbar/toolbar-format-select/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ export class FormatSelect extends LitElement {
7171

7272
override render() {
7373
return html`
74-
<select class="clippy-toolbar-button" @change=${this.#handleTextFormatChange}>
74+
<select
75+
class="clippy-toolbar-button"
76+
@change=${this.#handleTextFormatChange}
77+
aria-label="Tekst formaat selecteren"
78+
>
7579
${map(
7680
this.options,
7781
(option) => html`<option ?selected=${option.active} value=${option.value}>${option.label}</option>`,

packages/editor/src/components/toolbar/toolbar-link/index.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,17 @@ import { customElement, state } from 'lit/decorators.js';
55
import { createRef, ref, type Ref } from 'lit/directives/ref.js';
66
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
77
import { editor } from '@/decorators/TipTapDecorator.ts';
8+
import './../toolbar-button';
89

9-
@customElement('clippy-toolbar-link')
10+
const tag = 'clippy-toolbar-link';
11+
12+
declare global {
13+
interface HTMLElementTagNameMap {
14+
[tag]: ToolbarLink;
15+
}
16+
}
17+
18+
@customElement(tag)
1019
export class ToolbarLink extends LitElement {
1120
static override readonly styles = [];
1221

@@ -62,20 +71,12 @@ export class ToolbarLink extends LitElement {
6271
<div>
6372
<label>Link to:<input value=${this.previousUrl} ${ref(this.#inputRef)} type="text" /></label>
6473
</div>
65-
<utrecht-button-group>
66-
<utrecht-button @click=${() => this.#dialogRef.value?.close()}>Sluiten</utrecht-button>
67-
<utrecht-button @click=${this.#unsetLink}>Verwijder link</utrecht-button>
68-
<utrecht-button appearance="secondary-action-button" @click=${this.#updateLink}>
69-
Link toevoegen
70-
</utrecht-button>
71-
</utrecht-button-group>
74+
<div>
75+
<button @click=${() => this.#dialogRef.value?.close()}>Sluiten</button>
76+
<button @click=${this.#unsetLink}>Verwijder link</button>
77+
<button @click=${this.#updateLink}>Link toevoegen</button>
78+
</div>
7279
</dialog>
7380
`;
7481
}
7582
}
76-
77-
declare global {
78-
interface HTMLElementTagNameMap {
79-
'clippy-toolbar-link': ToolbarLink;
80-
}
81-
}

packages/editor/src/index.test.ts

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,26 @@
11
import userEvent from '@testing-library/user-event';
22
import './index.ts';
3-
import { defineCustomElements } from '@utrecht/web-component-library-stencil/loader';
4-
import { querySelectorAllDeep, querySelectorDeep } from 'query-selector-shadow-dom';
53
import { describe, it, expect, beforeEach } from 'vitest';
64
import { page } from 'vitest/browser';
75
import { isMacOS } from '@/utils/isMacOS.ts';
6+
import './index';
87

98
describe('<clippy-editor>', () => {
10-
beforeEach(async () => {
11-
defineCustomElements();
9+
let user: ReturnType<typeof userEvent.setup>;
10+
11+
beforeEach(() => {
12+
user = userEvent.setup();
1213
document.body.innerHTML =
1314
'<clippy-editor><div slot="content" hidden><h1>Start met kopniveau 1</h1></div></clippy-editor>';
14-
const editor = document.querySelector('clippy-editor');
15-
await editor?.updateComplete;
16-
17-
// Wait for all utrecht-button elements to be ready
18-
const buttons = querySelectorAllDeep('utrecht-button');
19-
await Promise.all(buttons.map((button) => button.componentOnReady()));
2015
});
2116

22-
it.skip('should change selected text to heading level 3', async () => {
23-
const user = userEvent.setup();
24-
await expect.element(page.getByRole('heading', { name: 'Start met kopniveau 1' })).toBeInTheDocument();
17+
it('should change selected text to heading level 3', async () => {
18+
await expect(page.getByRole('heading', { name: 'Start met kopniveau 1' })).toBeInTheDocument();
2519

26-
const boldButton = querySelectorDeep('button[aria-label="Bold"]');
20+
const boldButton = page.getByRole('button', { name: 'Bold' }).element();
2721

28-
const buttons = querySelectorAllDeep('utrecht-button');
29-
await Promise.all(buttons.map((button) => button.componentOnReady()));
30-
31-
expect(boldButton).toBeDefined();
32-
await userEvent.click(boldButton as HTMLButtonElement);
22+
expect(boldButton).toBeInTheDocument();
23+
await user.click(boldButton);
3324

3425
const text = page.getByText('Start met kopniveau 1').element();
3526
expect(text).toBeInTheDocument();
@@ -41,31 +32,30 @@ describe('<clippy-editor>', () => {
4132
{ keys: '[/MouseLeft]' },
4233
]);
4334

44-
const select = querySelectorDeep('select');
45-
expect(select).toBeDefined();
46-
await user.selectOptions(select as Element, 'h3');
35+
const select = page.getByLabelText('Tekst formaat selecteren');
36+
expect(select).toBeInTheDocument();
37+
await user.selectOptions(select.element(), 'h3');
4738

48-
const h3Option = querySelectorDeep('li[role="option"]#h3');
49-
await user.click(h3Option as Element);
39+
const h3Option = select.getByRole('option', { name: 'Kopniveau 1' }).element();
40+
await user.click(h3Option);
5041

5142
const h3Text = page.getByRole('heading', { level: 3 });
5243
expect(h3Text).toHaveTextContent('Start met kopniveau 1');
5344
});
5445

55-
it.skip('should open the shortcuts dialog with Command/Control + Alt + T', async () => {
56-
const user = userEvent.setup();
46+
it('should open the shortcuts dialog with Command/Control + Alt + T', async () => {
5747
const text = page.getByText('Start met kopniveau 1').element();
5848
expect(text).toBeInTheDocument();
59-
49+
expect(page.getByLabelText('Toegankelijkheidsfouten', { exact: true })).not.toHaveAttribute('open');
6050
await user.click(text);
6151
if (isMacOS()) {
6252
await user.keyboard('{meta>}{alt>}{t}{/alt}{/meta}');
6353
} else {
6454
await user.keyboard('{control>}{alt>}{t}{/alt}{/control}');
6555
}
66-
const a11yDialog = querySelectorDeep('#dialog-content');
67-
expect(a11yDialog?.hasAttribute('open')).toBe(true);
56+
const a11yDialog = page.getByRole('dialog').element();
57+
expect(a11yDialog).toHaveAttribute('open');
6858

69-
expect(a11yDialog?.querySelector('ul li')?.textContent).toBe('Geen toegankelijkheidsfouten gevonden.');
59+
expect(a11yDialog).toHaveTextContent('Geen toegankelijkheidsfouten gevonden.');
7060
});
7161
});

packages/editor/src/index.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { provide } from '@lit/context';
22
import { Editor as TiptapEditor } from '@tiptap/core';
3-
import { defineCustomElements } from '@utrecht/web-component-library-stencil/loader';
43
import './components/toolbar';
54
import './components/validations/gutter';
65
import './components/validations/drawer';
@@ -15,8 +14,6 @@ import editorStyles from './styles';
1514

1615
const EDITOR_ID = 'editor';
1716

18-
defineCustomElements();
19-
2017
const sanitizeTopHeadingLevel = (number: number): number => {
2118
if (!Number.isNaN(number) && number >= 1 && number <= 6) {
2219
return number;

packages/editor/test/helpers.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,46 @@ export const getDeeplyMountedCustomElement = async <T extends LitElement>(select
1414
const element = document.querySelector<T>(selector);
1515
if (!element) throw new Error(`<${selector}> was not found in the document`);
1616
await element.updateComplete;
17+
1718
const elements = collectAllElementsDeep('*', element);
18-
for (const el of elements) {
19-
const customEl = el as CustomElement;
20-
if (typeof customEl.componentOnReady === 'function') {
21-
await customEl.componentOnReady();
22-
}
23-
if (customEl.updateComplete instanceof Promise) {
24-
await customEl.updateComplete;
19+
20+
// First, ensure all custom elements are defined
21+
const customElementTags = new Set<string>();
22+
elements.forEach((el) => {
23+
const tagName = el.tagName.toLowerCase();
24+
if (tagName.includes('-')) {
25+
customElementTags.add(tagName);
2526
}
26-
}
27+
});
28+
29+
await Promise.all(
30+
Array.from(customElementTags).map(async (tagName) => {
31+
try {
32+
await customElements.whenDefined(tagName);
33+
} catch (error) {
34+
console.warn(`Custom element ${tagName} not defined, skipping`, error?.toString());
35+
}
36+
}),
37+
);
38+
39+
// Then wait for all components to be ready
40+
await Promise.all(
41+
elements.map(async (el) => {
42+
const customEl = el as CustomElement;
43+
44+
if (typeof customEl.componentOnReady === 'function') {
45+
try {
46+
await customEl.componentOnReady();
47+
} catch (error) {
48+
console.warn(`Failed to wait for ${customEl.tagName}:`, error);
49+
}
50+
}
51+
52+
if (customEl.updateComplete instanceof Promise) {
53+
await customEl.updateComplete;
54+
}
55+
}),
56+
);
57+
2758
return element;
2859
};

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)