Skip to content

Commit

Permalink
fix(core/toast|react/toast|vue/toast): predefine custom elements befo…
Browse files Browse the repository at this point in the history
…re usage (#1201)
  • Loading branch information
danielleroux authored Apr 15, 2024
1 parent 716ed56 commit 34b50ef
Show file tree
Hide file tree
Showing 16 changed files with 130 additions and 57 deletions.
7 changes: 7 additions & 0 deletions .changeset/dull-hounds-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@siemens/ix-react': patch
'@siemens/ix': patch
'@siemens/ix-vue': patch
---

fix(core/toast|react/toast|vue/toast): predefine custom elements before usage
3 changes: 1 addition & 2 deletions packages/core/src/components/toast/toast-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export class ToastContainer {
@Method()
async showToast(config: ToastConfig): Promise<ShowToastResult> {
const toast = document.createElement('ix-toast');

const onClose = new TypedEvent<any | undefined>();

function removeToast(result?: any) {
Expand Down Expand Up @@ -122,7 +121,7 @@ export class ToastContainer {
'toast-container--top-right': this.position === 'top-right',
}}
>
{/* <slot></slot> */}
<slot></slot>
</Host>
);
}
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/components/toast/toast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ export function getToastContainer() {
}

export function setToastPosition(position: ToastPosition) {
getToastContainer().position = position;
const container = getToastContainer();
container.position = position;
}

async function toast(config: ToastConfig): Promise<ShowToastResult> {
const context = getToastContainer();
return context.showToast(config);
function toast(config: ToastConfig): Promise<ShowToastResult> {
const container = getToastContainer();
return container.showToast(config);
}

toast.info = (config: ToastConfig) => {
Expand Down
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"babel-jest": "^29.7.0",
"eslint-config-ix": "*",
"eslint-plugin-react": "^7.31.11",
"happy-dom": "^14.7.1",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.1.2",
"jest-environment-jsdom": "^29.1.2",
Expand Down
7 changes: 5 additions & 2 deletions packages/react/src/ix-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
import type { JSX as IxIconsJSX } from '@siemens/ix-icons';
import { createReactComponent } from './react-component-lib';

import { defineCustomElement as defineIxIcon } from '@siemens/ix-icons/dist/components/ix-icon';
import { defineCustomElement } from '@siemens/ix-icons/dist/components/ix-icon';

// eslint-disable-next-line no-inline-comments
export const IxIcon = /*@__PURE__*/ createReactComponent<
IxIconsJSX.IxIcon,
HTMLIxIconElement
>('ix-icon', undefined, undefined, defineIxIcon);
>('ix-icon', undefined, undefined);

// Predefine `ix-icon` to be sure its loaded before its used inside the util functions
defineCustomElement();
21 changes: 0 additions & 21 deletions packages/react/src/tests/example/example.spec.tsx

This file was deleted.

21 changes: 0 additions & 21 deletions packages/react/src/tests/example/example.tsx

This file was deleted.

46 changes: 46 additions & 0 deletions packages/react/src/tests/toast/toast.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2023 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { render, screen, waitFor } from '@testing-library/react';
import React from 'react';
import { describe, it } from 'vitest';
import Content from './toast';

describe(`toast`, () => {
it(`basic`, async () => {
const { getByText } = render(<Content />);

const button = getByText('Hallo');
button.click();

await customElements.whenDefined('ix-toast');
await customElements.whenDefined('ix-toast-container');

const toast = await screen.findByText('Foobar');
const toastShadowRoot = toast.shadowRoot;

expect(toast).toBeDefined();
expect(toastShadowRoot).toBeDefined();
expect(toast.innerText).toBe('Foobar');

await customElements.whenDefined('ix-icon');

const icon = toastShadowRoot?.querySelector(
'.toast-icon ix-icon'
) as HTMLIxIconElement;

expect(icon).toBeDefined();

await waitFor(() => {
expect(icon.shadowRoot).toBeDefined();

Check failure on line 40 in packages/react/src/tests/toast/toast.spec.tsx

View workflow job for this annotation

GitHub Actions / unit

src/tests/toast/toast.spec.tsx > toast > basic

TypeError: Cannot read properties of null (reading 'shadowRoot') Ignored nodes: comments, script, style <html> <head /> <body> <div> <ix-button class="" > Hallo </ix-button> </div> <ix-toast-container class="toast-container--bottom-right" /> <div class="toast-container toast-container--bottom-right" id="toast-container" > <ix-toast class="animate__animated animate__fadeIn" > Foobar </ix-toast> </div> </body> </html> ❯ src/tests/toast/toast.spec.tsx:40:19 ❯ runWithExpensiveErrorDiagnosticsDisabled ../../node_modules/.pnpm/@testing-library+dom@8.20.1/node_modules/@testing-library/dom/dist/config.js:47:12 ❯ checkCallback ../../node_modules/.pnpm/@testing-library+dom@8.20.1/node_modules/@testing-library/dom/dist/wait-for.js:127:77 ❯ Timeout.checkRealTimersCallback ../../node_modules/.pnpm/@testing-library+dom@8.20.1/node_modules/@testing-library/dom/dist/wait-for.js:121:16
});

expect(icon.shadowRoot).toBeDefined();
expect(icon.name).toEqual('star');
});
});
30 changes: 30 additions & 0 deletions packages/react/src/tests/toast/toast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2023 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { IxButton, showToast } from '../../';

const Index = () => {
return (
<>
<IxButton
onClick={async () => {
await showToast({
icon: 'star',
message: 'Foobar',
});
}}
>
Hallo
</IxButton>
</>
);
};

export default Index;
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Index = () => {
});

return (
<>
<form>
<IxValidationTooltip message="Error hint text">
<label htmlFor="name">Name</label>
<input
Expand All @@ -33,7 +33,7 @@ const Index = () => {
})}
/>
</IxValidationTooltip>
</>
</form>
);
};

Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/toast/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { defineCustomElement as defineToastContainer } from '@siemens/ix/components/ix-toast-container.js';
import { defineCustomElement as defineToast } from '@siemens/ix/components/ix-toast.js';

import { toast, ToastConfig as IxToastConfig } from '@siemens/ix';
import ReactDOMClient from 'react-dom/client';
Expand All @@ -17,6 +19,10 @@ export type ToastConfig = {
export async function showToast(
config: Omit<IxToastConfig, 'message'> & ToastConfig
) {
// Define custom element, otherwise dynamic creation of toast container will fail
defineToast();
defineToastContainer();

if (typeof config.message === 'string') {
const toastInstance = await toast(config as IxToastConfig);
return toastInstance;
Expand Down
2 changes: 1 addition & 1 deletion packages/react/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
environment: 'happy-dom',
setupFiles: './src/tests/setup.js',
},
});
3 changes: 2 additions & 1 deletion packages/vue/src/ix-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
*/
import type { JSX as IxIconsJSX } from '@siemens/ix-icons';
import { defineContainer } from './vue-component-lib/utils';
import { defineCustomElement } from '@siemens/ix-icons/dist/components/ix-icon';

// eslint-disable-next-line no-inline-comments
export const IxIcon = /*@__PURE__*/ defineContainer<IxIconsJSX.IxIcon>(
'ix-icon',
undefined,
defineCustomElement,
['size', 'color', 'name']
);
8 changes: 8 additions & 0 deletions packages/vue/src/toast/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
toast,
ToastConfig as IxToastConfig,
} from '@siemens/ix';
import { defineCustomElement as defineIxToast } from '@siemens/ix/components/ix-toast.js';
import { defineCustomElement as defineIxToastContainer } from '@siemens/ix/components/ix-toast-container.js';
import { defineCustomElement as defineIxIcon } from '@siemens/ix-icons/dist/components/ix-icon';

export type ToastConfig = {
message: string | HTMLElement;
Expand All @@ -24,6 +27,11 @@ export function setToastPosition(position: 'bottom-right' | 'top-right') {
export async function showToast(
config: Omit<IxToastConfig, 'message'> & ToastConfig
) {
// Define components upfront to prevent undefined components
defineIxIcon();
defineIxToastContainer();
defineIxToast();

if (typeof config.message === 'string') {
const toastInstance = await toast(config as IxToastConfig);
return toastInstance;
Expand Down
17 changes: 15 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"cache": false
},
"test": {
"dependsOn": ["build"],
"dependsOn": ["^build"],
"cache": false
}
}
Expand Down

0 comments on commit 34b50ef

Please sign in to comment.