Test the application Hints about PorscheDesignSystemProvider Additional information when using @testing-library/react Unsupported APIs
CSSStyleSheet.replace(), Intersection Observer, Element.prototype.scrollTo and others.@porsche-design-system/components-react package.setupTest.{js|ts} file.PorscheDesignSystemProvider in order to avoid exceptions.Attention
// setupTest.{js|ts}
import '@porsche-design-system/components-react/jsdom-polyfill';
// SingleComponent.tsx
import { useCallback, useState } from 'react';
import { PTabsBar, type TabsBarUpdateEventDetail } from '@porsche-design-system/components-react/ssr';
export const SingleComponent = (): JSX.Element => {
const [activeTab, setActiveTab] = useState(0);
const onUpdate = useCallback((e: CustomEvent<TabsBarUpdateEventDetail>) => {
setActiveTab(e.detail.activeTabIndex);
}, []);
return (
<>
<PTabsBar activeTabIndex={activeTab} onUpdate={onUpdate} data-testid="host">
<button data-testid="button1">Some label</button>
<button data-testid="button2">Some label</button>
<button data-testid="button3">Some label</button>
</PTabsBar>
<div data-testid="debug">{`Active Tab: ${activeTab + 1}`}</div>
</>
);
};
// SingleComponent.test.tsx
import { PorscheDesignSystemProvider, componentsReady } from '@porsche-design-system/components-react/ssr';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('renders Tabs Bar from Porsche Design System and uses its events', async () => {
const { getByTestId } = render(
<PorscheDesignSystemProvider>
{' '}
{/* required for the component to work */}
<SingleComponent />
</PorscheDesignSystemProvider>
);
await componentsReady(); // we need to make sure Porsche Design System components are initialized
const debug = getByTestId('debug');
const button1 = getByTestId('button1');
const button2 = getByTestId('button2');
const button3 = getByTestId('button3');
expect(debug.innerHTML).toBe('Active Tab: 1');
await userEvent.click(button2);
expect(debug.innerHTML).toBe('Active Tab: 2');
await userEvent.click(button3);
expect(debug.innerHTML).toBe('Active Tab: 3');
await userEvent.click(button1);
expect(debug.innerHTML).toBe('Active Tab: 1');
});
PorscheDesignSystemProvider. Therefore, we offer the
following advice.PorscheDesignSystemProvider
and calls the render function of @testing-library/react:// helper.tsx
import { render, RenderResult } from '@testing-library/react';
import { PorscheDesignSystemProvider } from '@porsche-design-system/components-react/ssr';
export const renderWithProvider = (component: JSX.Element): RenderResult => {
return render(<PorscheDesignSystemProvider>{component}</PorscheDesignSystemProvider>);
};
skipCheckForPorscheDesignSystemProviderDuringTests() that can be used
within your tests. It only takes effect during testing since it relies on process.env.NODE_ENV === 'test'.// setupTest.{js|ts}
import { skipCheckForPorscheDesignSystemProviderDuringTests } from '@porsche-design-system/components-react/ssr';
skipCheckForPorscheDesignSystemProviderDuringTests();
// SomeComponent.test.tsx
import { skipCheckForPorscheDesignSystemProviderDuringTests } from '@porsche-design-system/components-react/ssr';
describe('SomeComponent', () => {
beforeEach(() => {
// either like this
skipCheckForPorscheDesignSystemProviderDuringTests();
});
it('should work', () => {
// or like this
skipCheckForPorscheDesignSystemProviderDuringTests();
// ...
});
});
skipPorscheDesignSystemCDNRequestsDuringTests() that can be used within your tests when
you use the @porsche-design-system/components-react/jsdom-polyfill in your setup. It will suppress all CDN request of
the Porsche Design System.// setupTest.{js|ts}
import { skipPorscheDesignSystemCDNRequestsDuringTests } from '@porsche-design-system/components-react/ssr';
skipPorscheDesignSystemCDNRequestsDuringTests();
// SomeComponent.test.tsx
import { skipPorscheDesignSystemCDNRequestsDuringTests } from '@porsche-design-system/components-react/ssr';
describe('SomeComponent', () => {
beforeEach(() => {
// either like this
skipPorscheDesignSystemCDNRequestsDuringTests();
});
it('should work', () => {
// or like this
skipPorscheDesignSystemCDNRequestsDuringTests();
// ...
});
});
@testing-library/react and jsdom. It is
simply not provided (see Simulate.import { Simulate } from 'react-dom/test-utils';
const button = getByText('SomePorscheDesignSystemButton');
Simulate.submit('button');
getByRole to query Porsche Design System components when using @testing-library because it
uses default roles. For example a <button> gets the role button without explicitly setting the attribute. To
achieve this it uses getByRoleShadowed utility function that can be used as a drop-in replacement for
getByRole.import { getByRoleShadowed } from '@porsche-design-system/components-react/testing';
it('should work for PButton', async () => {
render(<PButton>Button</PButton>);
await componentsReady();
expect(getByRoleShadowed('button')).toBeInTheDocument();
});
getByLabelTextShadowed and getByTextShadowed.import { getByTextShadowed } from '@porsche-design-system/components-react/testing';
it('should work for PInputText', async () => {
render(<PInputText label="Some label" name="some-name" />);
await componentsReady();
const shadowedInput: HTMLInputElement = getByRoleShadowed('textbox', { name: 'Some label' });
expect(shadowedInput).toBeInTheDocument();
expect(shadowedInput.tagName).toBe('INPUT');
});
p-modal, p-flyout, p-flyout-multilevelHTMLDialogElement.prototype.show = jest.fn();
HTMLDialogElement.prototype.showModal = jest.fn();
HTMLDialogElement.prototype.close = jest.fn();
p-textareaHTMLElement.prototype.attachInternals = jest.fn(
() =>
({
setFormValue: jest.fn(),
setValidity: jest.fn(),
}) as ElementInternals
);
p-tabs-bar, p-tabsElement.prototype.animate = vi.fn(
() =>
({
onfinish: null,
cancel: vi.fn(),
finish: vi.fn(),
}) as unknown as Animation
);
