Porsche Design SystemSearchNavigate to GitHub repository of Porsche Design SystemOpen sidebar
Getting StartedTestingAdvanced
Angular Table of Contents Testing with Jest Jest uses jsdom and supports ShadowDOM since Version 12.2.0. However, it doesn't support JavaScript modules as described in this issue. Also, it doesn't support CSSStyleSheet.replace(), Intersection Observer, Element.prototype.scrollTo and others. As a workaround we provide a polyfill as part of the @porsche-design-system/components-angular package. To apply the polyfill, simply import it in your setupTest.{js|ts} file. Certain modern browser APIs are not supported in the jsdom environment. See Unsupported APIs for more information. Setup file
// setupTest.{js|ts} import '@porsche-design-system/components-angular/jsdom-polyfill';
Example component
// single-component.ts import { ChangeDetectionStrategy, Component } from '@angular/core'; import type { TabsBarUpdateEventDetail } from '@porsche-design-system/components-angular'; @Component({ selector: 'single-component', template: ` <p-tabs-bar [activeTabIndex]="tabIndex" (update)="onUpdate($event)"> <button data-testid="button1" type="button">Tab One</button> <button data-testid="button2" type="button">Tab Two</button> <button data-testid="button3" type="button">Tab Three</button> </p-tabs-bar> <div data-testid="debug">Active Tab: { tabIndex + 1 }</div> `, changeDetection: ChangeDetectionStrategy.OnPush, }) export class SingleComponent { tabIndex: number = 0; onUpdate(e: CustomEvent<TabsBarUpdateEventDetail>) { this.tabIndex = e.detail.activeTabIndex; } }
Test example component
// single-component.test.ts import { componentsReady } from '@porsche-design-system/components-angular'; import { render } from '@testing-library/angular'; import userEvent from '@testing-library/user-event'; import '@porsche-design-system/components-angular/jsdom-polyfill'; it('should render Tabs Bar from Porsche Design System and use its events', async () => { const { getByTestId } = await render(SingleComponent); await componentsReady(); 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'); });
More test examples can be found at the componentsReady() documentation. Testing with Karma Config Since the getInitialStyles() partial is mandatory for using Porsche Design System, the partial needs to be included within test environments. With help of @angular-builders/custom-webpack and its indexTransform option, the partial can be injected into the index.html. See getInitialStyles() for a manual how to integrate the partial within build and serve environment. Since Karma does not use the index.html, but instead relies on karma-context.html the transformation of index.html is not applicable for testing with Karma. There are different approaches to inject the partial into karma-context.html: karma.conf.js option customContextFile would be easiest, but this is overridden by @angular-devkit/build-angular/plugins/karma karma.conf.js custom middleware which injects the getInitialStyles() partial on the fly manipulation of karma-context.html via post-install or within karma.conf.js
// yarn add --dev glob <!-- karma.conf.js --> const path = require('path'); const fs = require('fs'); const { globSync } = require('glob'); const injectPartials = require('./scripts/injectPartials'); // script referenced by injectPartials for `build` and `serve` const injectPartialsIntoKarmaContextHtml = () => { const packagePath = path.resolve(require.resolve('@angular-devkit/build-angular'), '..'); const [filePath] = globSync(packagePath + '/**/karma-context.html'); const backupFilePath = filePath.replace(/\.html$/, '-original$&'); // restore backup if (fs.existsSync(backupFilePath)) { fs.copyFileSync(backupFilePath, filePath); fs.rmSync(backupFilePath); } fs.copyFileSync(filePath, backupFilePath); // create backup const fileContent = fs.readFileSync(filePath, 'utf8'); const modifiedFileContent = injectPartials({}, fileContent); fs.writeFileSync(filePath, modifiedFileContent); }; injectPartialsIntoKarmaContextHtml(); module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular-devkit/build-angular'], // ... rest of config }); }
More test examples can be found at the componentsReady() documentation. We also provide test examples in our sample integration project. Unsupported APIs Certain modern browser APIs are not supported in the jsdom environment. Dialog API Affected Components: p-modal, p-flyout, p-flyout-multilevel Due to the lack of native support in jsdom, the Dialog API needs to be either manually polyfilled or mocked. You can use the available dialog-polyfill package or create a custom mock implementation. Example mock:
HTMLDialogElement.prototype.show = jest.fn(); HTMLDialogElement.prototype.showModal = jest.fn(); HTMLDialogElement.prototype.close = jest.fn();
Element Internals API Affected Components: p-textarea Current polyfills for the Element Internals API are incompatible with Stencil. Therefore, the API must be mocked within the test setup. Example mock:
HTMLElement.prototype.attachInternals = jest.fn( () => ({ setFormValue: jest.fn(), setValidity: jest.fn(), }) as ElementInternals );
Global settingsThemeChanges the theme of the application and any Porsche Design System component. It's possible to choose between forced theme light and dark. It's also possible to use auto, which applies light or dark theme depending on the operating system settings automatically.LightDarkAuto (sync with operating system)DirectionChanges the direction of HTML elements, mostly used on<html> tag to support languages which are read from right to left like e.g. Arabic.LTR (left-to-right)RTL (right-to-left)AutoText ZoomChanges the text size and values with unit rem or em relatively. This setting can be defined in browser settings for any website or by an application itself on<html> tag. To achieve WCAG 2.2 AA compliance it's obligatory to support text zoom up to at least 200%.100%130%150%200%