diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a7ad9d4d614..e03e5521a72 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -166,8 +166,8 @@ jobs: with: name: components-js-vrt-puppeteer-regression path: ./packages/components-js/tests/vrt/puppeteer/results - components-js-vrt-playwright: - name: 'Components JS VRT (Playwright)' + components-js-common-vrt-playwright-chrome: + name: 'Components JS VRT Common (Playwright Chrome)' runs-on: ubuntu-latest steps: - name: 'Checkout' @@ -182,12 +182,58 @@ jobs: uses: ./.github/actions/docker-run-playwright with: entrypoint: run-test-vrt-playwright - args: --components-js + args: --components-js:chrome:common + - name: 'VRT Regression (Playwright)' + if: failure() + uses: actions/upload-artifact@v3 + with: + name: components-js-vrt-common-playwright-chrome-regression + path: ./packages/components-js/tests/vrt/playwright/results + components-js-custom-states-vrt-playwright-chrome: + name: 'Components JS VRT Custom/States (Playwright Chrome)' + runs-on: ubuntu-latest + steps: + - name: 'Checkout' + uses: actions/checkout@v3 + - name: 'Setup and install' + uses: ./.github/actions/setup-and-install + with: + github-token: ${{ secrets.github-token }} + - name: 'Build assets, component-meta, components, components-js, shared and utilities' + uses: ./.github/actions/build-components-js + - name: 'VRT Test (Playwright)' + uses: ./.github/actions/docker-run-playwright + with: + entrypoint: run-test-vrt-playwright + args: --components-js:chrome:customAndStates - name: 'VRT Regression (Playwright)' if: failure() uses: actions/upload-artifact@v3 with: - name: components-js-vrt-playwright-regression + name: components-js-vrt-custom-states-playwright-chrome-regression + path: ./packages/components-js/tests/vrt/playwright/results + components-js-vrt-playwright-safari: + name: 'Components JS VRT (Playwright Safari)' + runs-on: ubuntu-latest + steps: + - name: 'Checkout' + uses: actions/checkout@v3 + - name: 'Setup and install' + uses: ./.github/actions/setup-and-install + with: + github-token: ${{ secrets.github-token }} + - name: 'Build assets, component-meta, components, components-js, shared and utilities' + uses: ./.github/actions/build-components-js + - name: 'VRT Test (Playwright)' + uses: ./.github/actions/docker-run-playwright + with: + entrypoint: run-test-vrt-playwright + args: --components-js:safari + - name: 'VRT Regression (Playwright)' + if: failure() + uses: actions/upload-artifact@v3 + with: + name: components-js-vrt-playwright-safari-regression path: ./packages/components-js/tests/vrt/playwright/results components-angular: name: 'Components Angular' @@ -292,6 +338,11 @@ jobs: with: entrypoint: run-build args: --components-react + - name: 'E2E Test components-react/remix' + uses: ./.github/actions/docker-run-playwright + with: + entrypoint: run-test-e2e + args: --components-react/remix - name: 'VRT Test components-react/remix' uses: ./.github/actions/docker-run-playwright with: diff --git a/docker-compose.yml b/docker-compose.yml index 4ce10cec0bc..b53b24f14d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.5" services: design-system: - image: ghcr.io/porsche-design-system/porsche-design-system/playwright:v1.39.0-focal-test + image: ghcr.io/porsche-design-system/porsche-design-system/playwright:v1.39.0-focal-test2 working_dir: /opt/porsche-design-system-app user: "${RUN_UID}:${RUN_GID}" ports: @@ -64,7 +64,7 @@ services: - utilities-utilities-node-modules:/opt/porsche-design-system-app/packages/utilities/projects/utilities/node_modules - utilities-styles-node-modules:/opt/porsche-design-system-app/packages/utilities/projects/styles/node_modules change-volume-owner: - image: ghcr.io/porsche-design-system/porsche-design-system/playwright:v1.39.0-focal-test + image: ghcr.io/porsche-design-system/porsche-design-system/playwright:v1.39.0-focal-test2 volumes: - home:/opt/porsche-design-system-volumes/home - monorepo-node-modules:/opt/porsche-design-system-volumes/root-node_modules diff --git a/docker/node/bin/run-test-e2e b/docker/node/bin/run-test-e2e index b95cba47b94..9b05640cb8c 100755 --- a/docker/node/bin/run-test-e2e +++ b/docker/node/bin/run-test-e2e @@ -7,6 +7,7 @@ if [[ "--components-angular" == "${1}" ]] || [[ "--components-react" == "${1}" ]] || [[ "--components-react/nextjs" == "${1}" ]] || + [[ "--components-react/remix" == "${1}" ]] || [[ "--components-vue" == "${1}" ]] || [[ "--crawler" == "${1}" ]] || [[ "--storefront" == "${1}" ]] diff --git a/docker/node/bin/run-test-vrt-playwright b/docker/node/bin/run-test-vrt-playwright index e826a1f2e81..5149b7f0b9c 100755 --- a/docker/node/bin/run-test-vrt-playwright +++ b/docker/node/bin/run-test-vrt-playwright @@ -4,7 +4,10 @@ set -o errexit set -o pipefail if - [[ "--components-js" == "${1}" ]] + [[ "--components-js" == "${1}" ]] || + [[ "--components-js:safari" == "${1}" ]] || + [[ "--components-js:chrome:customAndStates" == "${1}" ]] || + [[ "--components-js:chrome:common" == "${1}" ]]; then yarn test:vrt:playwright:${1:2} fi diff --git a/docker/node/build-and-push-base-image-playwright.sh b/docker/node/build-and-push-base-image-playwright.sh index 3cba18f2be6..871812aeacd 100755 --- a/docker/node/build-and-push-base-image-playwright.sh +++ b/docker/node/build-and-push-base-image-playwright.sh @@ -2,7 +2,7 @@ REGISTRY=ghcr.io/chbinousamy/porsche-design-system IMAGE=playwright -TAG=v1.39.0-focal-test +TAG=v1.39.0-focal-test2 docker pull $REGISTRY/$IMAGE:latest diff --git a/docs/dependencies.md b/docs/dependencies.md index 754b466e59f..1c9c1405c00 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -48,6 +48,8 @@ Angular versions used to build any of its dependent libraries. We are now on `Angular v15` after conformation of our consuming teams. Before upgrading to a new version, ensure all consuming teams are already on the next major. +Helpful overview: https://angular.io/guide/versions#actively-supported-versions + ### Affected dependencies: - `typescript` diff --git a/package.json b/package.json index ec04a681890..7b3114cf9a4 100644 --- a/package.json +++ b/package.json @@ -115,12 +115,16 @@ "test:e2e:components-angular": "yarn --cwd ./packages/components-angular test:e2e", "test:e2e:components-react": "yarn --cwd ./packages/components-react test:e2e", "test:e2e:components-react/nextjs": "yarn --cwd ./packages/components-react/projects/nextjs test:e2e", + "test:e2e:components-react/remix": "yarn --cwd ./packages/components-react/projects/remix test:e2e", "test:e2e:components-vue": "yarn --cwd ./packages/components-vue test:e2e", "test:e2e:crawler": "yarn --cwd ./packages/crawler test:e2e", "test:e2e:storefront": "yarn --cwd ./packages/storefront test:e2e", "test:a11y:storefront": "yarn --cwd ./packages/storefront test:a11y", "test:vrt:puppeteer:components-js": "yarn --cwd ./packages/components-js test:vrt:puppeteer", "test:vrt:playwright:components-js": "yarn --cwd ./packages/components-js test:vrt:playwright", + "test:vrt:playwright:components-js:chrome:common": "yarn --cwd ./packages/components-js test:vrt:playwright:chrome:common", + "test:vrt:playwright:components-js:chrome:customAndStates": "yarn --cwd ./packages/components-js test:vrt:playwright:chrome:customAndStates", + "test:vrt:playwright:components-js:safari": "yarn --cwd ./packages/components-js test:vrt:playwright:safari", "test:vrt:components-angular": "yarn --cwd ./packages/components-angular test:vrt", "test:vrt:components-react": "yarn --cwd ./packages/components-react test:vrt", "test:vrt:components-react/nextjs": "yarn --cwd ./packages/components-react/projects/nextjs test:vrt", diff --git a/packages/component-meta/scripts/generateComponentMeta.ts b/packages/component-meta/scripts/generateComponentMeta.ts index 16edfc320ad..b3fbd7cc9d7 100644 --- a/packages/component-meta/scripts/generateComponentMeta.ts +++ b/packages/component-meta/scripts/generateComponentMeta.ts @@ -216,12 +216,12 @@ const generateComponentMeta = (): void => { propValue === 'true' ? true : propValue === 'false' - ? false - : // undefined values get lost in JSON.stringify, but null is allowed - propValue - ?.replace(/^['"](.*)['"]$/, '$1') // propValue is a string and might contain a string wrapped in quotes since it is extracted like this - .replace(/\s+/g, ' ') // remove new lines and multiple spaces - .replace(/,( })/, '$1') || null; // remove trailing comma in original multiline objects + ? false + : // undefined values get lost in JSON.stringify, but null is allowed + propValue + ?.replace(/^['"](.*)['"]$/, '$1') // propValue is a string and might contain a string wrapped in quotes since it is extracted like this + .replace(/\s+/g, ' ') // remove new lines and multiple spaces + .replace(/,( })/, '$1') || null; // remove trailing comma in original multiline objects if (typeof cleanedValue === 'string') { if (cleanedValue.match(/^\d+$/)) { @@ -470,7 +470,16 @@ const generateComponentMeta = (): void => { } // named slots - const namedSlots = Array.from(source.matchAll(/ slotName); + const namedSlots = Array.from(source.matchAll(/ slotName + ); + + if (source.includes(' { fs.copyFileSync(filePath, backupFilePath); // create backup const fileContent = fs.readFileSync(filePath, 'utf8'); - const modifiedFileContent = transformIndexHtml({}, fileContent); + const modifiedFileContent = injectPartials({}, fileContent); fs.writeFileSync(filePath, modifiedFileContent); }; injectPartialsIntoKarmaContextHtml(); diff --git a/packages/components-angular/package.json b/packages/components-angular/package.json index e785d46c4ee..6184150b752 100644 --- a/packages/components-angular/package.json +++ b/packages/components-angular/package.json @@ -38,7 +38,7 @@ "@angular/platform-browser": "^15.2.10", "@angular/platform-browser-dynamic": "^15.2.10", "@angular/router": "^15.2.10", - "@porsche-design-system/components-angular": "3.8.0", + "@porsche-design-system/components-angular": "3.9.0", "angular-imask": "^6.6.3", "imask": "^7.1.3", "rxjs": "^7.8.1", diff --git a/packages/components-angular/projects/angular-wrapper/package.json b/packages/components-angular/projects/angular-wrapper/package.json index 16c3f7717c5..ba1c1192eee 100644 --- a/packages/components-angular/projects/angular-wrapper/package.json +++ b/packages/components-angular/projects/angular-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@porsche-design-system/components-angular", - "version": "3.8.0", + "version": "3.9.0", "description": "Porsche Design System is a component library designed to help developers create the best experience for software or services distributed by Dr. Ing. h.c. F. Porsche AG.", "keywords": [ "porsche", @@ -17,12 +17,13 @@ "license": "SEE LICENSE IN LICENSE", "homepage": "https://designsystem.porsche.com", "dependencies": { - "@porsche-design-system/components-js": "3.8.0", + "@porsche-design-system/components-js": "3.9.0", "tslib": "^2.6.1" }, "peerDependencies": { "@angular/common": ">=15.0.0 <18.0.0", - "@angular/core": ">=15.0.0 <18.0.0" + "@angular/core": ">=15.0.0 <18.0.0", + "rxjs": "^6.5.3 || ^7.4.0" }, "exports": { "./jsdom-polyfill": { diff --git a/packages/components-angular/projects/angular-wrapper/src/porsche-design-system.module.ts b/packages/components-angular/projects/angular-wrapper/src/porsche-design-system.module.ts index 7baf24567d8..6b501213c03 100644 --- a/packages/components-angular/projects/angular-wrapper/src/porsche-design-system.module.ts +++ b/packages/components-angular/projects/angular-wrapper/src/porsche-design-system.module.ts @@ -1,24 +1,40 @@ -import { ModuleWithProviders, NgModule, Optional } from '@angular/core'; -import { DECLARATIONS } from './lib/components/barrel'; +import { inject, type ModuleWithProviders, NgModule, Optional } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; import { load } from '@porsche-design-system/components-js'; +import { DECLARATIONS } from './lib/components/barrel'; +import type { Theme } from './lib/types'; +import { THEME_TOKEN } from './utils'; export type PorscheDesignSystemModuleConfig = { prefix?: string; cdn?: 'auto' | 'cn'; + theme?: Theme; }; export class DefaultConfig implements PorscheDesignSystemModuleConfig { prefix = ''; + theme: 'light'; // since theme exists on almost every component, it is defined here kind of like a global prop + // other component configurations should probably go into a separate `components`, `componentProps` or `componentDefaults` + // property similar to https://mui.com/material-ui/customization/theme-components/ } // TODO: unit tests are missing @NgModule({ declarations: DECLARATIONS, exports: DECLARATIONS, + providers: [ + { + provide: THEME_TOKEN, + useValue: new BehaviorSubject('light'), + }, + ], }) export class PorscheDesignSystemModule { + private theme$ = inject(THEME_TOKEN); + constructor(@Optional() configParam: DefaultConfig) { - const configs = (configParam || ([new DefaultConfig()] as unknown)) as PorscheDesignSystemModuleConfig[]; + const configs = (configParam as unknown as DefaultConfig[]) || [new DefaultConfig()]; + this.theme$.next(configs[0].theme || 'light'); // first config sets the theme configs.forEach(load); } diff --git a/packages/components-angular/projects/angular-wrapper/src/public-api.ts b/packages/components-angular/projects/angular-wrapper/src/public-api.ts index aa3c98e21e8..a8226e21f9a 100644 --- a/packages/components-angular/projects/angular-wrapper/src/public-api.ts +++ b/packages/components-angular/projects/angular-wrapper/src/public-api.ts @@ -1,6 +1,6 @@ export { componentsReady } from '@porsche-design-system/components-js'; export * from './lib/components/barrel'; export * from './lib/types'; -export { PorscheDesignSystemModule } from './porsche-design-system.module'; -export type { PorscheDesignSystemModuleConfig } from './porsche-design-system.module'; +export { PorscheDesignSystemModule, type PorscheDesignSystemModuleConfig } from './porsche-design-system.module'; +export { THEME_TOKEN } from './utils'; export { ToastManager } from './toast-manager'; diff --git a/packages/components-angular/projects/angular-wrapper/src/utils.ts b/packages/components-angular/projects/angular-wrapper/src/utils.ts index 7bc0f67c6a1..d684f1406db 100644 --- a/packages/components-angular/projects/angular-wrapper/src/utils.ts +++ b/packages/components-angular/projects/angular-wrapper/src/utils.ts @@ -1,47 +1,50 @@ -import { EventEmitter } from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + inject, + InjectionToken, + type OnChanges, + type OnDestroy, +} from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import type { Theme } from './lib/types'; -const proxyInputs = (component: any, inputs: string[]): void => { - const callback = (item: string): void => { - Object.defineProperty(component.prototype, item, { - get() { - return this.el[item]; - }, - set(val: any) { - this.z.runOutsideAngular(() => (this.el[item] = val)); - }, - }); - }; +export const THEME_TOKEN = new InjectionToken>('pdsTheme'); - inputs.forEach(callback); -}; +@Component({ + template: '', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export abstract class BaseComponent implements OnChanges { + protected el: HTMLElement; -// NOTE: only relevant if components use the @Method() decorator -// currently our AngularWrapperGenerator doesn't support this -// const proxyMethods = (Cmp: any, methods: string[]) => { -// const Prototype = Cmp.prototype; -// methods.forEach((methodName) => { -// Prototype[methodName] = function () { -// const args = arguments; -// return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args)); -// }; -// }); -// }; + constructor(cdr: ChangeDetectorRef, elementRef: ElementRef) { + cdr.detach(); + this.el = elementRef.nativeElement; + } -export const proxyOutputs = (instance: any, events: string[]): void => { - events.forEach((event) => (instance[event] = new EventEmitter())); -}; + ngOnChanges(props: Record): void { + for (const prop in props) { + this.el[prop] = props[prop].currentValue; + } + } +} -type ProxyCmpOptions = { inputs?: string[]; methods?: string[] }; +@Component({ + template: '', +}) +export abstract class BaseComponentWithTheme extends BaseComponent implements OnDestroy { + protected declare el: HTMLElement & { theme: Theme }; + private themeSubscription = inject(THEME_TOKEN).subscribe((theme) => { + this.el.theme = this.theme || theme; + }); + theme?: Theme; -// tslint:disable-next-line: only-arrow-functions -export function ProxyCmp({ inputs /*, methods*/ }: ProxyCmpOptions) { - return function (component: any) { - if (inputs) { - proxyInputs(component, inputs); - } - // if (methods) { - // proxyMethods(component, methods); - // } - return component; - }; + ngOnDestroy(): void { + // need to manually unsubscribe or otherwise subscription is still active even after unmount + // https://rafaelneto.dev/en/blog/unsubscribing-behaviorsubject-observable-angular/ + this.themeSubscription.unsubscribe(); + } } diff --git a/packages/components-angular/scripts/transformIndexHtml.js b/packages/components-angular/scripts/injectPartials.js similarity index 94% rename from packages/components-angular/scripts/transformIndexHtml.js rename to packages/components-angular/scripts/injectPartials.js index f358fbf15ea..171eb0c0102 100644 --- a/packages/components-angular/scripts/transformIndexHtml.js +++ b/packages/components-angular/scripts/injectPartials.js @@ -14,7 +14,7 @@ module.exports = (targetOptions, indexHtml) => { .join('\n') .replace(/https:\/\/cdn\.ui\.porsche\.com\/porsche-design-system/g, 'http://localhost:3001'); - console.log('Injected partials via transformIndexHtml'); + console.log('Injected partials via injectPartials'); return indexHtml.replace(/<\/head>/, `\n${headPartials}$&`).replace(/<\/body>/, `\n${bodyPartials}$&`); }; diff --git a/packages/components-angular/src/app/app-routing.module.ts b/packages/components-angular/src/app/app-routing.module.ts index 60c475565fc..f381144bbf7 100644 --- a/packages/components-angular/src/app/app-routing.module.ts +++ b/packages/components-angular/src/app/app-routing.module.ts @@ -1,16 +1,16 @@ import { NgModule } from '@angular/core'; -import { RouterModule, Route } from '@angular/router'; -import * as fromPages from './pages'; +import { RouterModule, type Route } from '@angular/router'; import * as fromExamples from './examples'; +import * as fromPages from './pages'; import * as fromStyles from './styles'; export type ExtendedRoute = Route & { - name: string; + name?: string; // optional to be filtered out for select options isDisabled?: boolean; }; export const routes: ExtendedRoute[] = [ - ...[...fromPages.generatedRoutes].sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())), + ...fromPages.generatedRoutes.sort((a, b) => a.name!.toLowerCase().localeCompare(b.name!.toLowerCase())), { name: '---', path: '---', @@ -47,6 +47,38 @@ export const routes: ExtendedRoute[] = [ path: 'form-wrapper-binding', component: fromPages.FormWrapperBindingComponent, }, + { + name: 'Tabs Bar Navigation', + path: 'tabs-bar-navigation', + redirectTo: 'tabs-bar-navigation/page-1', + }, + { + path: 'tabs-bar-navigation', + component: fromPages.TabsBarNavigationComponent, + children: [ + { path: 'page-1', component: fromPages.TabsBarNavigationPage1Component }, + { path: 'page-2', component: fromPages.TabsBarNavigationPage2Component }, + { path: 'page-3', component: fromPages.TabsBarNavigationPage3Component }, + ], + }, + { + name: 'Tabs Bar Navigation Bug', + path: 'tabs-bar-navigation-bug', + redirectTo: 'tabs-bar-navigation-bug/page-1', + }, + { + path: 'tabs-bar-navigation-bug', + children: [ + { path: 'page-1', component: fromPages.TabsBarNavigationBugPage1Component }, + { path: 'page-2', component: fromPages.TabsBarNavigationBugPage2Component }, + { path: 'page-3', component: fromPages.TabsBarNavigationBugPage3Component }, + ], + }, + { + name: 'Theme Injection', + path: 'theme-injection', + component: fromPages.ThemeInjectionComponent, + }, { name: 'Optional Properties', path: 'optional-properties', @@ -282,7 +314,7 @@ export const routes: ExtendedRoute[] = [ ]; @NgModule({ - imports: [RouterModule.forRoot(routes, {})], + imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {} diff --git a/packages/components-angular/src/app/app.component.ts b/packages/components-angular/src/app/app.component.ts index ab8802241f7..51e4cde7295 100644 --- a/packages/components-angular/src/app/app.component.ts +++ b/packages/components-angular/src/app/app.component.ts @@ -1,25 +1,31 @@ -import { Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { Router } from '@angular/router'; +import { type Theme, THEME_TOKEN } from '@porsche-design-system/components-angular'; import { routes } from './app-routing.module'; @Component({ selector: 'app-root', template: ` - + + + + +
- +
`, + changeDetection: ChangeDetectionStrategy.OnPush, }) export class AppComponent { + public router = inject(Router); public routes = routes.filter((route) => !!route.name); - - constructor(private router: Router) {} + public themes: Theme[] = ['light', 'dark', 'auto']; + public theme$ = inject(THEME_TOKEN); // equivalent to @Inject(THEME_TOKEN) in constructor public async changeRoute(path: string): Promise { await this.router.navigateByUrl(`/${path}`); diff --git a/packages/components-angular/src/app/app.module.ts b/packages/components-angular/src/app/app.module.ts index 8147995bb9b..04796e421b0 100644 --- a/packages/components-angular/src/app/app.module.ts +++ b/packages/components-angular/src/app/app.module.ts @@ -1,29 +1,31 @@ -import { BrowserModule } from '@angular/platform-browser'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { BrowserModule } from '@angular/platform-browser'; +import { IMaskModule } from 'angular-imask'; import { PorscheDesignSystemModule } from '@porsche-design-system/components-angular'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; -import { IMaskModule } from 'angular-imask'; import * as fromComponents from './components'; -import * as fromPages from './pages'; import * as fromExamples from './examples'; +import * as fromPages from './pages'; import * as fromStyles from './styles'; @NgModule({ declarations: [ AppComponent, - ...fromPages.pages, - ...fromPages.generatedPages, + ...fromComponents.components, ...fromExamples.examples, + ...fromPages.generatedPages, + ...fromPages.pages, ...fromStyles.examples, - ...fromComponents.components, ], imports: [ BrowserModule, + FormsModule, AppRoutingModule, IMaskModule, - PorscheDesignSystemModule.load({ prefix: '', cdn: 'auto' }), - PorscheDesignSystemModule.load({ prefix: 'my-prefix', cdn: 'auto' }), + PorscheDesignSystemModule.load({ prefix: '', cdn: 'auto' }), // first configured theme wins or fallback 'light' + PorscheDesignSystemModule.load({ prefix: 'my-prefix', cdn: 'auto', theme: 'dark' }), ], schemas: [CUSTOM_ELEMENTS_SCHEMA], bootstrap: [AppComponent], diff --git a/packages/components-angular/src/app/components/grid-layout.component.ts b/packages/components-angular/src/app/components/grid-layout.component.ts index c8d69dd357e..8373a2c4201 100644 --- a/packages/components-angular/src/app/components/grid-layout.component.ts +++ b/packages/components-angular/src/app/components/grid-layout.component.ts @@ -442,7 +442,7 @@ import type { AccordionUpdateEvent } from '@porsche-design-system/components-ang `, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class GridLayout { +export class GridLayoutComponent { counter(i: number) { return new Array(i); } diff --git a/packages/components-angular/src/app/components/index.ts b/packages/components-angular/src/app/components/index.ts index f336b7f70ae..cd03d078e4e 100644 --- a/packages/components-angular/src/app/components/index.ts +++ b/packages/components-angular/src/app/components/index.ts @@ -1,5 +1,7 @@ -import { GridLayout } from './grid-layout.component'; +import { GridLayoutComponent } from './grid-layout.component'; +import { NavigationComponent } from './navigation.component'; -export const components = [GridLayout]; +export const components = [GridLayoutComponent, NavigationComponent]; export * from './grid-layout.component'; +export * from './navigation.component'; diff --git a/packages/components-angular/src/app/components/navigation.component.ts b/packages/components-angular/src/app/components/navigation.component.ts new file mode 100644 index 00000000000..cf7331c9e7f --- /dev/null +++ b/packages/components-angular/src/app/components/navigation.component.ts @@ -0,0 +1,22 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'navigation', + template: ` + + Tab One + Tab Two + Tab Three + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class NavigationComponent { + @Input() activeTabIndex = 0; + @Input() baseRoute: string = 'tabs-bar-navigation-bug'; + @Output() update = new EventEmitter(); + + getRoute(url: string): string { + return `/${this.baseRoute}/${url}`; + } +} diff --git a/packages/components-angular/src/app/pages/index.ts b/packages/components-angular/src/app/pages/index.ts index 3bbb761a625..7e27e16d773 100644 --- a/packages/components-angular/src/app/pages/index.ts +++ b/packages/components-angular/src/app/pages/index.ts @@ -3,21 +3,30 @@ import { CoreInitializerPrefixedComponent } from './core-initializer-prefixed.co import { EventsComponent } from './events.component'; import { FormWrapperBindingComponent } from './form-wrapper-binding.component'; import { OptionalPropertiesComponent } from './optional-properties.component'; +import { ThemeInjectionComponent } from './theme-injection.component'; import { UtilitiesComponent } from './utilities.component'; +import { tabsBarNavigationComponents } from './tabs-bar-navigation'; +import { tabsBarNavigationBugComponents } from './tabs-bar-navigation-bug'; export const pages = [ CoreInitializerPrefixedComponent, EventsComponent, FormWrapperBindingComponent, OptionalPropertiesComponent, + ThemeInjectionComponent, UtilitiesComponent, + ...tabsBarNavigationComponents, + ...tabsBarNavigationBugComponents, ]; export * from './core-initializer-prefixed.component'; export * from './events.component'; export * from './form-wrapper-binding.component'; export * from './optional-properties.component'; +export * from './theme-injection.component'; export * from './utilities.component'; +export * from './tabs-bar-navigation'; +export * from './tabs-bar-navigation-bug'; /* Auto Generated Below */ export * from './generated/core-initializer.component'; diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/index.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/index.ts new file mode 100644 index 00000000000..99fe33efe50 --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/index.ts @@ -0,0 +1,13 @@ +import { TabsBarNavigationBugPage1Component } from './tabs-bar-navigation-bug-page-1.component'; +import { TabsBarNavigationBugPage2Component } from './tabs-bar-navigation-bug-page-2.component'; +import { TabsBarNavigationBugPage3Component } from './tabs-bar-navigation-bug-page-3.component'; + +export const tabsBarNavigationBugComponents = [ + TabsBarNavigationBugPage1Component, + TabsBarNavigationBugPage2Component, + TabsBarNavigationBugPage3Component, +]; + +export * from './tabs-bar-navigation-bug-page-1.component'; +export * from './tabs-bar-navigation-bug-page-2.component'; +export * from './tabs-bar-navigation-bug-page-3.component'; diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-1.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-1.component.ts new file mode 100644 index 00000000000..51807fd255c --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-1.component.ts @@ -0,0 +1,11 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation-bug-page-1', + template: ` + + Bug Page 1 + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationBugPage1Component {} diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-2.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-2.component.ts new file mode 100644 index 00000000000..f2e0a97bcfb --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-2.component.ts @@ -0,0 +1,11 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation-bug-page-2', + template: ` + + Bug Page 2 + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationBugPage2Component {} diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-3.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-3.component.ts new file mode 100644 index 00000000000..390e9fdc356 --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation-bug/tabs-bar-navigation-bug-page-3.component.ts @@ -0,0 +1,11 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation-bug-page-3', + template: ` + + Bug Page 3 + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationBugPage3Component {} diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation/index.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation/index.ts new file mode 100644 index 00000000000..228627181c7 --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation/index.ts @@ -0,0 +1,16 @@ +import { TabsBarNavigationComponent } from './tabs-bar-navigation.component'; +import { TabsBarNavigationPage1Component } from './tabs-bar-navigation-page-1.component'; +import { TabsBarNavigationPage2Component } from './tabs-bar-navigation-page-2.component'; +import { TabsBarNavigationPage3Component } from './tabs-bar-navigation-page-3.component'; + +export const tabsBarNavigationComponents = [ + TabsBarNavigationComponent, + TabsBarNavigationPage1Component, + TabsBarNavigationPage2Component, + TabsBarNavigationPage3Component, +]; + +export * from './tabs-bar-navigation.component'; +export * from './tabs-bar-navigation-page-1.component'; +export * from './tabs-bar-navigation-page-2.component'; +export * from './tabs-bar-navigation-page-3.component'; diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-1.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-1.component.ts new file mode 100644 index 00000000000..4d5b66de069 --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-1.component.ts @@ -0,0 +1,8 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation-page-1', + template: `Page 1`, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationPage1Component {} diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-2.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-2.component.ts new file mode 100644 index 00000000000..c3abb6e05fa --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-2.component.ts @@ -0,0 +1,8 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation-page-2', + template: `Page 2`, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationPage2Component {} diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-3.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-3.component.ts new file mode 100644 index 00000000000..c2c19f247a3 --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation-page-3.component.ts @@ -0,0 +1,8 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation-page-3', + template: `Page 3`, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationPage3Component {} diff --git a/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation.component.ts b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation.component.ts new file mode 100644 index 00000000000..5d3e54a1a26 --- /dev/null +++ b/packages/components-angular/src/app/pages/tabs-bar-navigation/tabs-bar-navigation.component.ts @@ -0,0 +1,17 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-tabs-bar-navigation', + template: ` + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TabsBarNavigationComponent { + activeTabIndex = 0; +} diff --git a/packages/components-angular/src/app/pages/theme-injection.component.ts b/packages/components-angular/src/app/pages/theme-injection.component.ts new file mode 100644 index 00000000000..03f0c4a6c13 --- /dev/null +++ b/packages/components-angular/src/app/pages/theme-injection.component.ts @@ -0,0 +1,18 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'page-theme-injection', + template: ` +
+ Light Button + Dark Button +
+ Show/Hide Button + Global Theme +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ThemeInjectionComponent { + isVisible = false; +} diff --git a/packages/components-angular/tests/e2e/specs/examples.e2e.ts b/packages/components-angular/tests/e2e/specs/examples.e2e.ts index 9a469cabeb1..ce35f8adc2c 100644 --- a/packages/components-angular/tests/e2e/specs/examples.e2e.ts +++ b/packages/components-angular/tests/e2e/specs/examples.e2e.ts @@ -20,7 +20,7 @@ const fileContent = fs.readFileSync(filePath, 'utf8'); const [, rawRoutes] = /const routes.*(\[[\s\S]*\]);/.exec(fileContent) || []; const routes: { name: string; path: string; component: string }[] = eval( rawRoutes - .replace(/\.\.\.\[[\s\S]*?\].*/, '') // get rid of generatedRoutes + .replace(/\.\.\.fromPages\.generatedRoutes.+/, '') // get rid of generatedRoutes .replace(/(from(?:Pages|Examples|Styles)\.\w+)/g, "'$1'") ).filter(({ component }) => component); diff --git a/packages/components-angular/tests/e2e/specs/provider.e2e.ts b/packages/components-angular/tests/e2e/specs/provider.e2e.ts new file mode 100644 index 00000000000..4d8750fcce6 --- /dev/null +++ b/packages/components-angular/tests/e2e/specs/provider.e2e.ts @@ -0,0 +1,45 @@ +import type { ElementHandle, Page } from 'puppeteer'; +import { goto } from '../helpers'; +import type { Theme } from '@porsche-design-system/components-angular'; + +let page: Page; +beforeEach(async () => (page = await browser.newPage())); +afterEach(async () => await page.close()); + +it('should provide global theme correctly to 4th p-button', async () => { + await goto(page, 'theme-injection'); + + const [button1, button2, button3, button4Initial] = await page.$$('p-button'); + const getTheme = (handle: ElementHandle): Promise => handle.evaluate((el) => (el as any).theme); + expect(await getTheme(button1)).toBe('light'); + expect(await getTheme(button2)).toBe('dark'); + expect(await getTheme(button3)).toBe('light'); + expect(button4Initial).toBeUndefined(); + + // conditionally render button4 + await button3.click(); + const [, , , button4Render1] = await page.$$('p-button'); + expect(button4Render1).toBeDefined(); + expect(await getTheme(button4Render1)).toBe('light'); + + // change global theme + await page.select('select[name="theme"]', 'dark'); + expect(await getTheme(button3)).toBe('dark'); + expect(await getTheme(button4Render1)).toBe('dark'); + + // remove button4 + await button3.click(); + const [, , , button4] = await page.$$('p-button'); + expect(button4).toBeUndefined(); + + // render button4 again + await button3.click(); + const [, , , button4Render2] = await page.$$('p-button'); + expect(button4Render2).toBeDefined(); + expect(await getTheme(button4Render2)).toBe('dark'); + + // change global theme + await page.select('select[name="theme"]', 'light'); + expect(await getTheme(button3)).toBe('light'); + expect(await getTheme(button4Render2)).toBe('light'); +}); diff --git a/packages/components-angular/tests/e2e/specs/tabs-bar-navigation-bug.e2e.ts b/packages/components-angular/tests/e2e/specs/tabs-bar-navigation-bug.e2e.ts new file mode 100644 index 00000000000..3f14b8433e8 --- /dev/null +++ b/packages/components-angular/tests/e2e/specs/tabs-bar-navigation-bug.e2e.ts @@ -0,0 +1,31 @@ +import type { Page } from 'puppeteer'; +import { goto } from '../helpers'; + +let page: Page; +beforeEach(async () => (page = await browser.newPage())); +afterEach(async () => await page.close()); + +it('should correctly set activeTabIndex on p-tabs-bar', async () => { + await goto(page, 'tabs-bar-navigation-bug'); + + const getTabsBarActiveTabIndex = (): Promise => page.$eval('p-tabs-bar', (el) => (el as any).activeTabIndex); + const getHeadingText = (): Promise => page.$eval('p-heading', (el) => el.textContent); + + expect(await getTabsBarActiveTabIndex()).toBe(0); + expect(await getHeadingText()).toBe('Bug Page 1'); + + const [, link2] = await page.$$('a'); + await Promise.all([page.waitForNavigation(), link2.click()]); + expect(await getTabsBarActiveTabIndex()).toBe(1); + expect(await getHeadingText()).toBe('Bug Page 2'); + + const [, , link3] = await page.$$('a'); + await Promise.all([page.waitForNavigation(), link3.click()]); + expect(await getTabsBarActiveTabIndex()).toBe(2); + expect(await getHeadingText()).toBe('Bug Page 3'); + + const [link1] = await page.$$('a'); + await Promise.all([page.waitForNavigation(), link1.click()]); + expect(await getTabsBarActiveTabIndex()).toBe(0); + expect(await getHeadingText()).toBe('Bug Page 1'); +}); diff --git a/packages/components-js/package.json b/packages/components-js/package.json index e73d1fe9c9b..b6645917572 100644 --- a/packages/components-js/package.json +++ b/packages/components-js/package.json @@ -6,12 +6,10 @@ "scope": "@porsche-design-system", "author": "Dr. Ing. h.c. F. Porsche AG", "scripts": { - "prestart": "yarn replace", - "prebuild-app": "yarn replace", "start": "concurrently -k -s 'first' -n 'cdn,app' 'serve-cdn' 'ws --spa index.html -p 8575 -d ./www'", "start-app": "yarn start", "build": "yarn clean:build && yarn build:components-manager-core && yarn build:components-manager-cli && yarn build:components-wrapper && yarn build:jsdom-polyfill && yarn build:partials && yarn build:styles && yarn build-app && yarn build:cleanEnvironment", - "build-app": "yarn build-app:base && yarn build-app:components && yarn build-app:assets && yarn build-app:shared && yarn build-app:imask && yarn build-app:componentsAngularReact", + "build-app": "yarn build-app:base && yarn build-app:components && yarn build-app:assets && yarn build-app:shared && yarn build-app:imask && yarn build-app:componentsAngularReact && yarn replace:injectPartials", "build-app:base": "mkdir -p ./www && cp -r ./src/. ./www && cp -r ./public/. ./www", "build-app:components": "cp ./dist/components-wrapper/cjs/index.cjs ./www/index.js", "build-app:assets": "cp ../icons/dist/esm/index.js ./www/assets/icons.js", @@ -32,8 +30,7 @@ "build:partials": "yarn --cwd ./projects/partials build", "build:styles": "TARGET=./dist/components-wrapper/styles && rm -rf $TARGET && cp -r ../utilities/projects/utilities/dist $TARGET", "replace": "yarn replace:initialStyles && yarn replace:fontLatin", - "replace:initialStyles": "placeholder='' && partial=$placeholder$(node -e 'console.log(require(\"@porsche-design-system/components-js/partials\").getInitialStyles({ prefix: [\"\", \"my-prefix\"] }))') && regex=$placeholder'.*' && sed -E -e \"s^$regex^$partial^\" public/index.html > public/index.tmp.html && rm public/index.html && mv public/index.tmp.html public/index.html", - "replace:fontLatin": "placeholder='' && partial=$placeholder$(node -e 'console.log(require(\"@porsche-design-system/components-js/partials\").getFontLinks({ weights: [\"regular\", \"semi-bold\", \"bold\"] }).replace(/https:\\/\\/cdn\\.ui\\.porsche\\.com\\/porsche-design-system/g, \"http://localhost:3001\"))') && regex=$placeholder'.*' && sed -E -e \"s^$regex^$partial^\" public/index.html > public/index.tmp.html && rm public/index.html && mv public/index.tmp.html public/index.html", + "replace:injectPartials": "ts-node scripts/injectPartials.ts", "generateVRTPages": "ts-node scripts/generateVRTPages.ts", "test": "yarn test:unit && yarn test:e2e && yarn test:vrt && yarn test:smoke", "test:unit": "yarn test:unit:components-manager-cli && yarn test:unit:components-manager-core && yarn test:unit:components-js && yarn test:unit:jsdom-polyfill && yarn test:unit:partials", @@ -46,6 +43,13 @@ "test:e2e:playwright": "playwright test --config=tests/e2e/playwright/config/playwright.config.ts", "test:vrt:puppeteer": "TYPE=VRT PORT=8575 jest --colors -c tests/vrt/puppeteer/config/jest.config.ts", "test:vrt:playwright": "playwright test --config=tests/vrt/playwright/config/playwright.config.ts", + "test:vrt:playwright:ui": "yarn test:vrt:playwright --ui", + "test:vrt:playwright:safari": "yarn test:vrt:playwright --project=safari", + "test:vrt:playwright:chrome": "yarn test:vrt:playwright --project=chrome", + "test:vrt:playwright:chrome:common": "yarn test:vrt:playwright:chrome common", + "test:vrt:playwright:chrome:states": "yarn test:vrt:playwright:chrome states", + "test:vrt:playwright:chrome:custom": "yarn test:vrt:playwright:chrome custom", + "test:vrt:playwright:chrome:customAndStates": "yarn test:vrt:playwright:chrome:custom && yarn test:vrt:playwright:chrome:states", "posttest:vrt:playwright": "ts-node ./tests/vrt/playwright/scripts/adjustRegressionFilenames.ts", "test:smoke": "yarn test:smoke:node && yarn test:smoke:puppeteer", "test:smoke:node": "NODE_OPTIONS=--experimental-vm-modules jest --colors -c tests/smoke/config/jest.config-node.ts", @@ -68,8 +72,8 @@ }, "dependencies": { "@porsche-design-system/assets": "5.0.2", - "@porsche-design-system/components": "3.8.0", - "@porsche-design-system/components-js": "3.8.0", + "@porsche-design-system/components": "3.9.0", + "@porsche-design-system/components-js": "3.9.0", "@porsche-design-system/components-manager-cli": "0.0.0", "@porsche-design-system/partials": "0.0.0", "imask": "^7.1.3" @@ -85,6 +89,7 @@ "js-beautify": "^1.14.11", "jsdom": "^22.1.0", "local-web-server": "^5.3.0", + "mime": "^3.0.0", "pdf-to-png-converter": "^3.1.0", "terser-webpack-plugin": "^5.3.9", "ts-node": "^10.9.1", diff --git a/packages/components-js/projects/components-wrapper/CustomNamedChunkIdsPlugin.js b/packages/components-js/projects/components-wrapper/CustomNamedChunkIdsPlugin.js index 964fe33c72e..adf9eb5dc20 100644 --- a/packages/components-js/projects/components-wrapper/CustomNamedChunkIdsPlugin.js +++ b/packages/components-js/projects/components-wrapper/CustomNamedChunkIdsPlugin.js @@ -71,7 +71,11 @@ const customGetShortChunkName = (chunk, chunkGraph, context, delimiter, associat const modules = chunkGraph.getChunkRootModules(chunk); const shortModuleNames = modules .map((m) => requestToId(getShortModuleName(m, context, associatedObjectForCache))) - .map((m) => /p-([a-z-]*)/.exec(m)[1]); // extract component name from something like: porsche-design-system.components_dist_esm_p-banner_entry_js.848dce0f7bfd1fde6bd3.js + .map((m) => { + const chunkName = /p-([a-z-]*)/.exec(m)[1]; + console.log('Short Chunk Name:', chunkName); + return chunkName; + }); // extract component name from something like: porsche-design-system.components_dist_esm_p-banner_entry_js.848dce0f7bfd1fde6bd3.js chunk.idNameHints.sort(); const chunkName = Array.from(chunk.idNameHints).concat(shortModuleNames).filter(Boolean).join(delimiter); diff --git a/packages/components-js/projects/components-wrapper/package.json b/packages/components-js/projects/components-wrapper/package.json index 09468742258..93caeaa809f 100644 --- a/packages/components-js/projects/components-wrapper/package.json +++ b/packages/components-js/projects/components-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@porsche-design-system/components-js", - "version": "3.8.0", + "version": "3.9.0", "description": "Porsche Design System is a component library designed to help developers create the best experience for software or services distributed by Dr. Ing. h.c. F. Porsche AG.", "keywords": [ "porsche", diff --git a/packages/components-js/projects/components-wrapper/webpack.config.ts b/packages/components-js/projects/components-wrapper/webpack.config.ts index 63371ed5bb9..9d3f0e83e6b 100644 --- a/packages/components-js/projects/components-wrapper/webpack.config.ts +++ b/packages/components-js/projects/components-wrapper/webpack.config.ts @@ -20,6 +20,11 @@ const config: webpack.Configuration = { publicPath: `${deployUrl}/`, }, optimization: { + // https://webpack.js.org/guides/code-splitting/ + // https://webpack.js.org/plugins/split-chunks-plugin/ + splitChunks: { + minSize: 30000, + }, usedExports: true, chunkIds: false, // when this is set false, we need to provide a custom plugin to generate our chunkIds minimize: true, diff --git a/packages/components-js/projects/partials/tests/unit/specs/__snapshots__/getInitialStyles.spec.ts.snap b/packages/components-js/projects/partials/tests/unit/specs/__snapshots__/getInitialStyles.spec.ts.snap index 714ce0598b5..e9e92359c6e 100644 --- a/packages/components-js/projects/partials/tests/unit/specs/__snapshots__/getInitialStyles.spec.ts.snap +++ b/packages/components-js/projects/partials/tests/unit/specs/__snapshots__/getInitialStyles.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`format: html should return core styles 1`] = `""`; +exports[`format: html should return core styles 1`] = `""`; exports[`format: html should return core styles 2`] = ` "html, @@ -127,7 +127,8 @@ p-wordmark { ) a { color: currentcolor !important; - transition: background var(--p-transition-duration, 0.24s) ease !important; + transition: background var(--p-transition-duration, 0.25s) + cubic-bezier(0.25, 0.1, 0.25, 1) !important; margin-left: -2px !important; margin-right: -2px !important; padding-left: 2px !important; @@ -247,7 +248,7 @@ p-tabs-bar ~ [tabindex="0"][role="tabpanel"]:focus:not(:focus-visible) { " `; -exports[`format: html should return core styles with custom prefix 1`] = `""`; +exports[`format: html should return core styles with custom prefix 1`] = `""`; exports[`format: html should return core styles with custom prefix 2`] = ` "html, @@ -374,7 +375,8 @@ custom-prefix-p-wordmark { ) a { color: currentcolor !important; - transition: background var(--p-transition-duration, 0.24s) ease !important; + transition: background var(--p-transition-duration, 0.25s) + cubic-bezier(0.25, 0.1, 0.25, 1) !important; margin-left: -2px !important; margin-right: -2px !important; padding-left: 2px !important; @@ -502,7 +504,7 @@ custom-prefix-p-tabs-bar " `; -exports[`format: html should return core styles with multiple custom prefixes 1`] = `""`; +exports[`format: html should return core styles with multiple custom prefixes 1`] = `""`; exports[`format: html should return core styles with multiple custom prefixes 2`] = ` "html, @@ -801,7 +803,8 @@ another-prefix-p-wordmark { ) a { color: currentcolor !important; - transition: background var(--p-transition-duration, 0.24s) ease !important; + transition: background var(--p-transition-duration, 0.25s) + cubic-bezier(0.25, 0.1, 0.25, 1) !important; margin-left: -2px !important; margin-right: -2px !important; padding-left: 2px !important; @@ -1098,7 +1101,7 @@ another-prefix-p-tabs-bar " `; -exports[`format: jsx should return core styles 1`] = `""`; +exports[`format: jsx should return core styles 1`] = `""`; exports[`format: jsx should return core styles 2`] = ` "html, @@ -1225,7 +1228,8 @@ p-wordmark { ) a { color: currentcolor !important; - transition: background var(--p-transition-duration, 0.24s) ease !important; + transition: background var(--p-transition-duration, 0.25s) + cubic-bezier(0.25, 0.1, 0.25, 1) !important; margin-left: -2px !important; margin-right: -2px !important; padding-left: 2px !important; @@ -1345,7 +1349,7 @@ p-tabs-bar ~ [tabindex="0"][role="tabpanel"]:focus:not(:focus-visible) { " `; -exports[`format: jsx should return core styles with custom prefix 1`] = `""`; +exports[`format: jsx should return core styles with custom prefix 1`] = `""`; exports[`format: jsx should return core styles with custom prefix 2`] = ` "html, @@ -1472,7 +1476,8 @@ custom-prefix-p-wordmark { ) a { color: currentcolor !important; - transition: background var(--p-transition-duration, 0.24s) ease !important; + transition: background var(--p-transition-duration, 0.25s) + cubic-bezier(0.25, 0.1, 0.25, 1) !important; margin-left: -2px !important; margin-right: -2px !important; padding-left: 2px !important; @@ -1600,7 +1605,7 @@ custom-prefix-p-tabs-bar " `; -exports[`format: jsx should return core styles with multiple custom prefixes 1`] = `""`; +exports[`format: jsx should return core styles with multiple custom prefixes 1`] = `""`; exports[`format: jsx should return core styles with multiple custom prefixes 2`] = ` "html, @@ -1899,7 +1904,8 @@ another-prefix-p-wordmark { ) a { color: currentcolor !important; - transition: background var(--p-transition-duration, 0.24s) ease !important; + transition: background var(--p-transition-duration, 0.25s) + cubic-bezier(0.25, 0.1, 0.25, 1) !important; margin-left: -2px !important; margin-right: -2px !important; padding-left: 2px !important; diff --git a/packages/components-js/projects/partials/tests/unit/specs/getInitialStyles.spec.ts b/packages/components-js/projects/partials/tests/unit/specs/getInitialStyles.spec.ts index e672d60607c..1fadc5bdd57 100644 --- a/packages/components-js/projects/partials/tests/unit/specs/getInitialStyles.spec.ts +++ b/packages/components-js/projects/partials/tests/unit/specs/getInitialStyles.spec.ts @@ -52,16 +52,16 @@ describe('format: jsx', () => { describe('format: sha256', () => { it('should return hash for core styles', async () => { const result = getInitialStyles({ format: 'sha256' }); - expect(result).toMatchInlineSnapshot(`"'sha256-0cTVTcUQMEBGeoYyg2Sg0p14y9fsulp3XCTljJlXl9E='"`); + expect(result).toMatchInlineSnapshot(`"'sha256-7W+9h38YfcXwncu6iNGYRieAYr3dSfjPvM3HtFZ9/vs='"`); }); it('should return hash for core styles with custom prefix', async () => { const result = getInitialStyles({ format: 'sha256', prefix: 'custom-prefix' }); - expect(result).toMatchInlineSnapshot(`"'sha256-0GH/5YJd73BcjtMX6xLS/HNO/KdK9smCb0hRfGODAPM='"`); + expect(result).toMatchInlineSnapshot(`"'sha256-UL/ni9ffAJSXII7qvzkY2t/0MIK3ZIfhX13DYWgeQt8='"`); }); it('should return hash for core styles with multiple custom prefixes', async () => { const result = getInitialStyles({ format: 'sha256', prefix: ['', 'some-prefix', 'another-prefix'] }); - expect(result).toMatchInlineSnapshot(`"'sha256-Bjcp4ji4cmAzmI6mDfmFTN6R3cZUWFdt+UykdUggD8k='"`); + expect(result).toMatchInlineSnapshot(`"'sha256-F8RT4slD88Vv7DYmdaCrSknbyozWivtTUFJL5z0d4t4='"`); }); }); diff --git a/packages/components-js/public/index.html b/packages/components-js/public/index.html index ff6acf43730..f5867b44c2f 100644 --- a/packages/components-js/public/index.html +++ b/packages/components-js/public/index.html @@ -12,8 +12,6 @@ - - @@ -163,15 +161,16 @@ const theme = getTheme(); const dir = getDir(); const directory = page.match(/^[a-z-]+-example/) ? 'examples' : 'pages'; + document.querySelector('html').setAttribute('dir', dir); app.innerHTML = ''; - app.innerHTML = (await (await fetch(`/${directory}/${page}.html`)).text()).replace(/>(\s)*<'); - app.querySelectorAll('*').forEach((el) => (el.theme = theme)); - app.querySelectorAll('.playground').forEach((el) => { - el.classList.remove('light', 'dark', 'auto'); - el.classList.add(theme); - }); - document.querySelector('html').setAttribute('dir', dir); + app.innerHTML = (await (await fetch(`/${directory}/${page}.html`)).text()) + .replace(/>(\s)*<') // trim whitespace between tags + .replace( + /(<(?:my-prefix-)?p-[a-z-]+[\S\s]*?)>/g, // tweak components + (m, g1) => g1.includes('theme') ? g1.replace(/theme="[a-z]+"/, `theme="${theme}"`) : `${g1} theme="${theme}">` + ) + .replace(/(? { + const indexHtmlFilePath = path.resolve(__dirname, '../www/index.html'); + const oldContent = fs.readFileSync(indexHtmlFilePath, 'utf8'); + + const headPartials = [ + getComponentChunkLinks({ components: [...COMPONENT_CHUNK_NAMES] }), + getIconLinks({ icons: [...ICON_NAMES] }), + getInitialStyles({ prefix: ['', 'my-prefix'] }), + getFontLinks({ weights: ['regular', 'semi-bold', 'bold'] }), + ] + .join('\n') + .replace(/https:\/\/cdn\.ui\.porsche\.com\/porsche-design-system/g, 'http://localhost:3001'); + + const bodyPartials = [getBrowserSupportFallbackScript(), getCookiesFallbackScript()] + .join('\n') + .replace(/https:\/\/cdn\.ui\.porsche\.com\/porsche-design-system/g, 'http://localhost:3001'); + + const newContent = oldContent.replace(/<\/head>/, `\n${headPartials}$&`).replace(/<\/body>/, `\n${bodyPartials}$&`); + fs.writeFileSync(indexHtmlFilePath, newContent); + console.log('Injected partials via injectPartials'); +}; + +injectPartials(); diff --git a/packages/components-js/src/pages/accordion.html b/packages/components-js/src/pages/accordion.html index 7c9803cc5e3..2a3fe5c4a79 100644 --- a/packages/components-js/src/pages/accordion.html +++ b/packages/components-js/src/pages/accordion.html @@ -1,25 +1,25 @@ -
+
-
+
Slotted heading
-
+
-
+
-
+
Multiline heading, some extra long heading that should break to the second line @@ -80,7 +80,7 @@ >
-
+
Some slotted and deeply nested anchor, bold, strong, @@ -89,14 +89,14 @@
-
+
Some label
diff --git a/packages/components-js/src/pages/display.html b/packages/components-js/src/pages/display.html index 051c172434b..faf20905777 100644 --- a/packages/components-js/src/pages/display.html +++ b/packages/components-js/src/pages/display.html @@ -3,7 +3,7 @@ The quick brown fox jumps over the lazy dog
-
+
Start Left (deprecated) Center @@ -11,14 +11,14 @@ Right (deprecated)
-
+
Text ellipsis - Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
-
+
Some slotted and deeply nested anchor, bold, strong, @@ -27,7 +27,7 @@
-
+

The quick brown fox jumps over the lazy dog

The quick brown fox jumps over the lazy dog

The quick brown fox jumps over the lazy dog

@@ -36,14 +36,14 @@
The quick brown fox jumps over the lazy dog
-
+
The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog
-
+
The quick brown fox jumps over the lazy dog diff --git a/packages/components-js/src/pages/select-wrapper.html b/packages/components-js/src/pages/select-wrapper.html index b5b5a6fa795..5049a574a5d 100644 --- a/packages/components-js/src/pages/select-wrapper.html +++ b/packages/components-js/src/pages/select-wrapper.html @@ -11,15 +11,17 @@ top. - - - - - - - - - + + + + + + + + + + +
diff --git a/packages/components-js/src/pages/text-field-wrapper.html b/packages/components-js/src/pages/text-field-wrapper.html index 9b8d9cd01d0..4b593ea9991 100644 --- a/packages/components-js/src/pages/text-field-wrapper.html +++ b/packages/components-js/src/pages/text-field-wrapper.html @@ -157,10 +157,7 @@ - + @@ -174,10 +171,7 @@
- + @@ -190,10 +184,32 @@ - + + + + + + + + + + + + +
diff --git a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/checkbox-wrapper.e2e.ts.snap b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/checkbox-wrapper.e2e.ts.snap index 3940e963e43..59bbc9435a9 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/checkbox-wrapper.e2e.ts.snap +++ b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/checkbox-wrapper.e2e.ts.snap @@ -107,55 +107,59 @@ exports[`accessibility should expose correct accessibility tree when loading=tru "role": "StaticText", }, ], - "role": "none", - }, - { - "children": [ - { - "checked": false, - "disabled": true, - "name": "Some Label", - "role": "checkbox", - }, - ], - "role": "none", + "disabled": true, + "name": "", + "role": "LabelText", }, { "children": [ { "children": [ { - "children": [ - { - "name": " ", - "role": "StaticText", - }, - ], - "role": "none", + "checked": false, + "name": "Some Label", + "role": "checkbox", }, + ], + "role": "none", + }, + { + "children": [ { "children": [ { + "children": [ + { + "name": " ", + "role": "StaticText", + }, + ], "role": "none", }, { + "children": [ + { + "role": "none", + }, + { + "role": "none", + }, + ], "role": "none", }, ], - "role": "none", + "name": "Loading state of Some Label", + "role": "alert", }, ], - "name": "Loading state of Some Label", - "role": "alert", + "name": "", + "role": "generic", }, ], - "name": "", - "role": "generic", + "role": "none", }, ], - "disabled": true, - "name": "", - "role": "LabelText", + "role": "none", } `; diff --git a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/default-dom.e2e.ts.snap b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/default-dom.e2e.ts.snap index 0558e17f119..d07cd1984dc 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/default-dom.e2e.ts.snap +++ b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/default-dom.e2e.ts.snap @@ -82,10 +82,14 @@ exports[`should have no basic DOM regression for p-carousel 1`] = ` `; exports[`should have no basic DOM regression for p-checkbox-wrapper 1`] = ` -"" +"
+ +
+ + +
+
" `; exports[`should have no basic DOM regression for p-content-wrapper 1`] = ` @@ -288,20 +292,20 @@ exports[`should have no basic DOM regression for p-model-signature 1`] = `" -
" `; exports[`should have no basic DOM regression for p-multi-select-option 1`] = ` @@ -338,13 +342,15 @@ exports[`should have no basic DOM regression for p-pagination 1`] = ` `; exports[`should have no basic DOM regression for p-pin-code 1`] = ` -" -
- - - - +"
+ +
+ + + + +
" `; @@ -358,10 +364,14 @@ exports[`should have no basic DOM regression for p-popover 1`] = ` `; exports[`should have no basic DOM regression for p-radio-button-wrapper 1`] = ` -"" +"
+ +
+ + +
+
" `; exports[`should have no basic DOM regression for p-scroller 1`] = ` @@ -405,14 +415,16 @@ exports[`should have no basic DOM regression for p-segmented-control-item 1`] = exports[`should have no basic DOM regression for p-select-wrapper 1`] = ` "
-
" `; @@ -549,10 +561,12 @@ exports[`should have no basic DOM regression for p-text 1`] = ` exports[`should have no basic DOM regression for p-text-field-wrapper 1`] = ` "
-
" `; @@ -571,10 +585,14 @@ exports[`should have no basic DOM regression for p-text-list-item 1`] = ` `; exports[`should have no basic DOM regression for p-textarea-wrapper 1`] = ` -"" +"
+ +
+ + +
+
" `; exports[`should have no basic DOM regression for p-toast 1`] = `""`; diff --git a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/multi-select.e2e.ts.snap b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/multi-select.e2e.ts.snap index 7cdd80ef6fc..95c77eb7fd8 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/multi-select.e2e.ts.snap +++ b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/multi-select.e2e.ts.snap @@ -41,8 +41,7 @@ exports[`accessibility should expose correct accessibility tree if option is hig { "children": [ { - "name": "", - "role": "LabelText", + "role": "none", }, { "children": [ @@ -68,11 +67,6 @@ exports[`accessibility should expose correct accessibility tree if option is hig ], "role": "none", }, - ], - "role": "none", - }, - { - "children": [ { "children": [ { @@ -90,44 +84,48 @@ exports[`accessibility should expose correct accessibility tree if option is hig { "children": [ { - "name": "Option A", - "role": "StaticText", + "children": [ + { + "name": "Option A", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "LabelText", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "name": "Option A", - "role": "option", + "children": [ + { + "children": [ + { + "name": "Option A", + "role": "option", + }, + ], + "role": "none", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "generic", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { "children": [ { @@ -141,44 +139,48 @@ exports[`accessibility should expose correct accessibility tree if option is hig { "children": [ { - "name": "Option B", - "role": "StaticText", + "children": [ + { + "name": "Option B", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "LabelText", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "name": "Option B", - "role": "option", + "children": [ + { + "children": [ + { + "name": "Option B", + "role": "option", + }, + ], + "role": "none", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "generic", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { "children": [ { @@ -192,76 +194,84 @@ exports[`accessibility should expose correct accessibility tree if option is hig { "children": [ { - "name": "Option C", - "role": "StaticText", + "children": [ + { + "name": "Option C", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "LabelText", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "name": "Option C", - "role": "option", + "children": [ + { + "children": [ + { + "name": "Option C", + "role": "option", + }, + ], + "role": "none", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "generic", }, ], - "name": "", - "role": "generic", + "role": "none", }, ], - "role": "none", + "multiselectable": true, + "name": "", + "orientation": "vertical", + "role": "listbox", }, ], - "multiselectable": true, "name": "", - "orientation": "vertical", - "role": "listbox", + "role": "generic", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "role": "none", + "children": [ + { + "name": "Option A not selected (1 of 3)", + "role": "StaticText", + }, + ], + "name": "", + "role": "status", }, - ], - "role": "none", - }, - { - "children": [ { - "name": "Option A not selected (1 of 3)", - "role": "StaticText", + "children": [ + { + "role": "none", + }, + ], + "role": "none", }, ], - "name": "", - "role": "status", + "role": "none", }, ], - "name": "", - "role": "generic", + "role": "none", }, ], "name": "", @@ -295,7 +305,7 @@ exports[`accessibility should expose correct accessibility tree if option is sel "expanded": true, "focused": true, "haspopup": "listbox", - "name": "Option A", + "name": "", "role": "combobox", } `; @@ -313,20 +323,17 @@ exports[`accessibility should expose correct accessibility tree if option is sel "children": [ { "children": [ + { + "role": "none", + }, { "children": [ { - "children": [ - { - "name": "1 options selected", - "role": "StaticText", - }, - ], - "role": "none", + "name": "1 options selected", + "role": "StaticText", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, { "children": [ @@ -345,9 +352,17 @@ exports[`accessibility should expose correct accessibility tree if option is sel "expanded": true, "focused": true, "haspopup": "listbox", - "name": "Option A", + "name": "", "role": "combobox", }, + { + "children": [ + { + "role": "none", + }, + ], + "role": "none", + }, { "children": [ { @@ -382,19 +397,6 @@ exports[`accessibility should expose correct accessibility tree if option is sel "name": "", "role": "generic", }, - { - "children": [ - { - "role": "none", - }, - ], - "role": "none", - }, - ], - "role": "none", - }, - { - "children": [ { "children": [ { @@ -412,45 +414,49 @@ exports[`accessibility should expose correct accessibility tree if option is sel { "children": [ { - "name": "Option A", - "role": "StaticText", + "children": [ + { + "name": "Option A", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "LabelText", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "name": "Option A", - "role": "option", - "selected": true, + "children": [ + { + "children": [ + { + "name": "Option A", + "role": "option", + "selected": true, + }, + ], + "role": "none", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "generic", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { "children": [ { @@ -464,44 +470,48 @@ exports[`accessibility should expose correct accessibility tree if option is sel { "children": [ { - "name": "Option B", - "role": "StaticText", + "children": [ + { + "name": "Option B", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "LabelText", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "name": "Option B", - "role": "option", + "children": [ + { + "children": [ + { + "name": "Option B", + "role": "option", + }, + ], + "role": "none", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "generic", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { "children": [ { @@ -515,62 +525,81 @@ exports[`accessibility should expose correct accessibility tree if option is sel { "children": [ { - "name": "Option C", - "role": "StaticText", + "children": [ + { + "name": "Option C", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "LabelText", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { - "name": "Option C", - "role": "option", + "children": [ + { + "children": [ + { + "name": "Option C", + "role": "option", + }, + ], + "role": "none", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "name": "", - "role": "LabelText", + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "", + "role": "generic", }, ], - "name": "", - "role": "generic", + "role": "none", }, ], - "role": "none", + "multiselectable": true, + "name": "", + "orientation": "vertical", + "role": "listbox", }, ], - "multiselectable": true, "name": "", - "orientation": "vertical", - "role": "listbox", + "role": "generic", + }, + { + "children": [ + { + "name": "Option A, selected (1 of 3)", + "role": "StaticText", + }, + ], + "name": "", + "role": "status", }, - ], - "name": "", - "role": "generic", - }, - { - "children": [ { "children": [ { "children": [ { + "children": [ + { + "role": "none", + }, + ], "role": "none", }, ], @@ -582,19 +611,8 @@ exports[`accessibility should expose correct accessibility tree if option is sel ], "role": "none", }, - { - "children": [ - { - "name": "Option A, selected (1 of 3)", - "role": "StaticText", - }, - ], - "name": "", - "role": "status", - }, ], - "name": "", - "role": "generic", + "role": "none", }, ], "name": "", @@ -680,6 +698,11 @@ exports[`accessibility should expose correct accessibility tree of option list i { "children": [ { + "children": [ + { + "role": "none", + }, + ], "role": "none", }, ], @@ -726,6 +749,11 @@ exports[`accessibility should expose correct accessibility tree of option list i { "children": [ { + "children": [ + { + "role": "none", + }, + ], "role": "none", }, ], @@ -772,6 +800,11 @@ exports[`accessibility should expose correct accessibility tree of option list i { "children": [ { + "children": [ + { + "role": "none", + }, + ], "role": "none", }, ], diff --git a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/pin-code.e2e.ts.snap b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/pin-code.e2e.ts.snap index 2fd7aa2f0dd..dbc9683f77b 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/pin-code.e2e.ts.snap +++ b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/pin-code.e2e.ts.snap @@ -109,6 +109,7 @@ exports[`accessibility should expose correct accessibility tree in error state: exports[`accessibility should expose correct accessibility tree in loading state 1`] = ` { "description": "Some label Some description", + "disabled": true, "name": "1-4", "role": "textbox", } diff --git a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/radio-button-wrapper.e2e.ts.snap b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/radio-button-wrapper.e2e.ts.snap index aa37f30a138..569b7e57bd5 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/radio-button-wrapper.e2e.ts.snap +++ b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/radio-button-wrapper.e2e.ts.snap @@ -97,6 +97,72 @@ exports[`accessibility should expose correct accessibility tree properties in er } `; +exports[`accessibility should expose correct accessibility tree when loading=true 1`] = ` +{ + "children": [ + { + "children": [ + { + "name": "Some label", + "role": "StaticText", + }, + ], + "disabled": true, + "name": "", + "role": "LabelText", + }, + { + "children": [ + { + "children": [ + { + "checked": false, + "name": "Some label", + "role": "radio", + }, + ], + "role": "none", + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "name": " ", + "role": "StaticText", + }, + ], + "role": "none", + }, + { + "children": [ + { + "role": "none", + }, + { + "role": "none", + }, + ], + "role": "none", + }, + ], + "name": "Loading state of Some label", + "role": "alert", + }, + ], + "name": "", + "role": "generic", + }, + ], + "role": "none", + }, + ], + "role": "none", +} +`; + exports[`accessibility should expose correct initial accessibility tree 1`] = ` { "checked": false, diff --git a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/text-field-wrapper.e2e.ts.snap b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/text-field-wrapper.e2e.ts.snap index 2985ae4b0a0..7489cd7c08f 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/text-field-wrapper.e2e.ts.snap +++ b/packages/components-js/tests/e2e/puppeteer/specs/__snapshots__/text-field-wrapper.e2e.ts.snap @@ -69,6 +69,16 @@ exports[`accessibility should expose correct accessibility tree for input type=s "children": [ { "children": [ + { + "children": [ + { + "name": "Some label", + "role": "StaticText", + }, + ], + "name": "", + "role": "LabelText", + }, { "children": [ { @@ -86,62 +96,60 @@ exports[`accessibility should expose correct accessibility tree for input type=s "role": "generic", }, ], - "name": "", + "name": "Some label", "role": "searchbox", "value": "value", }, ], "role": "none", }, - ], - "name": "", - "role": "LabelText", - }, - { - "children": [ { + "children": [ + { + "role": "none", + }, + ], "role": "none", }, - ], - "role": "none", - }, - { - "children": [ { "children": [ { "children": [ { + "children": [ + { + "role": "none", + }, + ], "role": "none", }, - ], - "role": "none", - }, - { - "children": [ { "children": [ { - "name": "Clear field", - "role": "StaticText", + "children": [ + { + "name": "Clear field", + "role": "StaticText", + }, + ], + "role": "none", }, ], "role": "none", }, ], - "role": "none", + "name": "Clear field", + "role": "button", }, ], - "name": "Clear field", - "role": "button", + "name": "", + "role": "generic", }, ], - "name": "", - "role": "generic", + "role": "none", }, ], - "name": "", - "role": "generic", + "role": "none", }, ], "role": "none", diff --git a/packages/components-js/tests/e2e/puppeteer/specs/banner.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/banner.e2e.ts index db1cffcc886..d6ac4ef6602 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/banner.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/banner.e2e.ts @@ -14,9 +14,6 @@ import { import type { ElementHandle, Page } from 'puppeteer'; import type { BannerState } from '@porsche-design-system/components/dist/types/bundle'; -const CSS_FADE_IN_DURATION = 600; -const CSS_FADE_OUT_DURATION = 600; - let page: Page; beforeEach(async () => (page = await browser.newPage())); afterEach(async () => await page.close()); @@ -44,8 +41,6 @@ const getHost = () => selectNode(page, 'p-banner'); const getInlineNotification = () => selectNode(page, 'p-banner >>> p-inline-notification'); const getCloseButton = () => selectNode(page, 'p-banner >>> p-inline-notification >>> p-button-pure.close'); -const buttonHasFocus = () => page.evaluate(() => document.activeElement === document.querySelector('p-button-pure')); - it('should forward props correctly to p-inline-notification', async () => { await setContentWithDesignSystem( page, diff --git a/packages/components-js/tests/e2e/puppeteer/specs/checkbox-wrapper.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/checkbox-wrapper.e2e.ts index b6638f1ec47..03307995b13 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/checkbox-wrapper.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/checkbox-wrapper.e2e.ts @@ -21,9 +21,10 @@ beforeEach(async () => (page = await browser.newPage())); afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-checkbox-wrapper'); +const getRoot = () => selectNode(page, 'p-checkbox-wrapper >>> .root'); const getInput = () => selectNode(page, 'p-checkbox-wrapper input[type="checkbox"]'); +const getWrapper = () => selectNode(page, 'p-checkbox-wrapper >>> .wrapper'); const getLabel = () => selectNode(page, 'p-checkbox-wrapper >>> label'); -const getLabelText = () => selectNode(page, 'p-checkbox-wrapper >>> .text'); const getMessage = () => selectNode(page, 'p-checkbox-wrapper >>> .message'); const setIndeterminate = async (element: ElementHandle, value: boolean) => { @@ -76,23 +77,6 @@ const initCheckbox = (opts?: InitOptions): Promise => { ); }; -it('should not render label if label prop is not defined but should render if changed programmatically', async () => { - await setContentWithDesignSystem( - page, - ` - - - ` - ); - - const host = await getHost(); - expect(await getLabelText()).toBeNull(); - - await setProperty(host, 'label', 'Some Label'); - await waitForStencilLifecycle(page); - expect(await getLabelText()).not.toBeNull(); -}); - it('should add/remove message text with message if state changes programmatically', async () => { await initCheckbox(); const host = await getHost(); @@ -205,7 +189,7 @@ it('should keep focus if state switches to loading', async () => { it('should toggle checkbox when label text is clicked and not set input as active element', async () => { await initCheckbox(); - const label = await getLabelText(); + const label = await getLabel(); const input = await getInput(); const isInputChecked = (): Promise => getProperty(input, 'checked'); @@ -253,20 +237,38 @@ it('should check/uncheck checkbox when checkbox property is changed programmatic it('should disable checkbox when disabled property is set programmatically', async () => { await initCheckbox(); + const host = await getHost(); const input = await getInput(); - const getCursor = () => getElementStyle(input, 'cursor'); + const wrapper = await getWrapper(); + + const getWrapperCursor = () => getElementStyle(wrapper, 'cursor'); + const getInputCursor = () => getElementStyle(input, 'cursor'); + const getInputPointerEvents = () => getElementStyle(input, 'pointerEvents'); - expect(await getCursor()).toBe('pointer'); + expect(await getWrapperCursor()).toBe('auto'); + expect(await getInputCursor()).toBe('pointer'); + expect(await getInputPointerEvents()).toBe('auto'); await setProperty(input, 'disabled', true); await waitForInputTransition(page); - expect(await getCursor()).toBe('not-allowed'); + expect(await getWrapperCursor()).toBe('not-allowed'); + expect(await getInputCursor()).toBe('default'); + expect(await getInputPointerEvents()).toBe('none'); // prevents checkbox from being toggleable in disabled and especially loading state await setProperty(input, 'disabled', false); await waitForInputTransition(page); - expect(await getCursor()).toBe('pointer'); + expect(await getWrapperCursor()).toBe('auto'); + expect(await getInputCursor()).toBe('pointer'); + expect(await getInputPointerEvents()).toBe('auto'); + + await setProperty(host, 'loading', true); + await waitForInputTransition(page); + + expect(await getWrapperCursor()).toBe('not-allowed'); + expect(await getInputCursor()).toBe('default'); + expect(await getInputPointerEvents()).toBe('none'); // prevents checkbox from being toggleable in disabled and especially loading state }); describe('indeterminate state', () => { @@ -412,8 +414,8 @@ describe('accessibility', () => { it('should expose correct accessibility tree when loading=true', async () => { await initCheckbox({ loading: true }); - const label = await getLabel(); + const root = await getRoot(); - await expectA11yToMatchSnapshot(page, label, { interestingOnly: false }); + await expectA11yToMatchSnapshot(page, root, { interestingOnly: false }); }); }); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/flyout.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/flyout.e2e.ts index 019efd64d0b..9cd83e37848 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/flyout.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/flyout.e2e.ts @@ -101,12 +101,9 @@ const addButtonsBeforeAndAfterFlyout = () => }); const scrollFlyoutTo = async (selector: string) => - await page.evaluate( - (el) => { - el.scrollIntoView(); - }, - await selectNode(page, selector) - ); + await page.evaluate((el) => { + el.scrollIntoView(); + }, await selectNode(page, selector)); const expectDismissButtonToBeFocused = async (failMessage?: string) => { const host = await getHost(); @@ -129,11 +126,11 @@ it('should visible after opened', async () => { await initBasicFlyout({ open: false }); const host = await getHost(); await setProperty(host, 'open', true); - await waitForFlyoutTransition(); + expect(await getFlyoutVisibility()).toBe('visible'); }); -it('should have correct transform when dismissed and opened', async () => { +it('should have correct transform when opened and dismissed', async () => { await initBasicFlyout({ open: false }); const getFlyoutTransform = async () => getElementStyle(await getFlyout(), 'transform', { waitForTransition: true }); @@ -141,12 +138,13 @@ it('should have correct transform when dismissed and opened', async () => { expect(initialFlyoutTransform).toBe(`matrix(1, 0, 0, 1, ${flyoutMinWidth}, 0)`); await openFlyout(); - await waitForFlyoutTransition(); + const openFlyoutTransform = await getFlyoutTransform(); expect(openFlyoutTransform).toBe('none'); expect(initialFlyoutTransform).not.toBe(openFlyoutTransform); await dismissFlyout(); + // TODO: why is timeout needed? transition durations should be overwritten with 0s await waitForFlyoutTransition(); const finalFlyoutTransform = await getFlyoutTransform(); expect(finalFlyoutTransform).toBe(initialFlyoutTransform); @@ -388,20 +386,19 @@ describe('focus behavior', () => { ` ); await waitForStencilLifecycle(page); - await waitForFlyoutTransition(); expect(await getFlyoutVisibility(), 'initial').toBe('hidden'); expect(await getActiveElementTagName(page)).toBe('BODY'); await (await selectNode(page, '#btn-open')).click(); await waitForStencilLifecycle(page); - await waitForFlyoutTransition(); expect(await getFlyoutVisibility()).toBe('visible'); await page.keyboard.press('Escape'); await waitForStencilLifecycle(page); - await waitForFlyoutTransition(); + + // TODO: why is timeout needed? transition durations should be overwritten with 0s // TODO: Check why this is taking so much time? await waitForFlyoutTransition(); // Necessary extra time @@ -552,35 +549,122 @@ it('should open flyout at scroll top position zero when its content is scrollabl }); describe('scroll lock', () => { - const bodyLockedStyle = 'top: 0px; overflow-y: scroll; position: fixed;'; + describe('Desktop Browser', () => { + const bodyLockedStyle = 'overflow: hidden;'; - it('should prevent page from scrolling when open', async () => { - await initBasicFlyout({ open: false }); - expect(await getBodyStyle()).toBe(null); + it('should prevent page from scrolling when open', async () => { + await initBasicFlyout({ open: false }); + expect(await getBodyStyle()).toBe(null); - await openFlyout(); - expect(await getBodyStyle()).toBe(bodyLockedStyle); + await openFlyout(); + expect(await getBodyStyle()).toBe(bodyLockedStyle); - await setProperty(await getHost(), 'open', false); - await waitForStencilLifecycle(page); - expect(await getBodyStyle()).toBe(''); - }); + await setProperty(await getHost(), 'open', false); + await waitForStencilLifecycle(page); + expect(await getBodyStyle()).toBe(''); + }); + + it('should prevent page from scrolling when initially open', async () => { + await initBasicFlyout({ open: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyle); + }); + + it('should remove overflow hidden from body if unmounted', async () => { + await initBasicFlyout({ open: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyle); - it('should prevent page from scrolling when initially open', async () => { - await initBasicFlyout({ open: true }); - expect(await getBodyStyle()).toBe(bodyLockedStyle); + await page.evaluate(() => { + document.querySelector('p-flyout').remove(); + }); + await waitForStencilLifecycle(page); + + expect(await getBodyStyle()).toBe(''); + }); }); - it('should remove overflow hidden from body if unmounted', async () => { - await initBasicFlyout({ open: true }); - expect(await getBodyStyle()).toBe(bodyLockedStyle); + describe('iOS Safari', () => { + const bodyLockedStyleIOS = 'top: 0px; overflow-y: scroll; position: fixed;'; + + it('should prevent page from scrolling when open', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicFlyout({ open: false }); + expect(await getBodyStyle()).toBe(null); - await page.evaluate(() => { - document.querySelector('p-flyout').remove(); + await openFlyout(); + expect(await getBodyStyle()).toBe(bodyLockedStyleIOS); + + await setProperty(await getHost(), 'open', false); + await waitForStencilLifecycle(page); + expect(await getBodyStyle()).toBe(''); }); - await waitForStencilLifecycle(page); - expect(await getBodyStyle()).toBe(''); + it('should not override body styles on prop change', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicFlyout({ open: false }, {}, { markupBefore: '
' }); + expect(await getBodyStyle()).toBe(null); + + await page.evaluate(() => { + window.scrollTo(0, 500); + }); + + await openFlyout(); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + + await setProperty(await getHost(), 'aria', "{'aria-label': 'Other Heading'}"); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + }); + + it('should not override body styles on slot change', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + await initBasicFlyout({ open: false }, {}, { markupBefore: '
' }); + const host = await getHost(); + await page.evaluate(() => { + window.scrollTo(0, 500); + }); + + expect(await getBodyStyle()).toBe(null); + + await openFlyout(); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + + await host.evaluate((el) => { + el.innerHTML = ''; + }); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + }); + + it('should prevent page from scrolling when initially open', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicFlyout({ open: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyleIOS); + }); + + it('should remove overflowY, top and position styles from body if unmounted', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicFlyout({ open: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyleIOS); + + await page.evaluate(() => { + document.querySelector('p-flyout').remove(); + }); + await waitForStencilLifecycle(page); + + expect(await getBodyStyle()).toBe(''); + }); }); }); @@ -601,7 +685,6 @@ describe('lifecycle', () => { const host = await getHost(); await setProperty(host, 'open', false); - await waitForFlyoutTransition(); await waitForStencilLifecycle(page); const status = await getLifecycleStatus(page); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/modal.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/modal.e2e.ts index 2935d2cd7a6..83269ed873b 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/modal.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/modal.e2e.ts @@ -18,7 +18,6 @@ import { import type { ElementHandle, Page } from 'puppeteer'; import type { ModalAriaAttribute, SelectedAriaAttributes } from '@porsche-design-system/components/dist/types/bundle'; import type { TagName } from '@porsche-design-system/shared'; -import { footerShadowClass } from '@porsche-design-system/components/src/components/modal/modal-styles'; let page: Page; const CSS_TRANSITION_DURATION = 600; @@ -139,7 +138,7 @@ it('should render and be visible when open', async () => { it('should not be visible when not open', async () => { await initBasicModal({ isOpen: false }); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); // wait for visibility transition to finish + expect(await getModalVisibility()).toBe('hidden'); }); @@ -148,7 +147,7 @@ it('should have correct transform when dismissed and opened', async () => { const getModalTransform = async () => getElementStyle(await getModal(), 'transform', { waitForTransition: true }); const initialModalTransform = await getModalTransform(); - expect(initialModalTransform).toBe('matrix(0.9, 0, 0, 0.9, 0, 0)'); + expect(initialModalTransform).toBe('matrix(1, 0, 0, 1, 0, 33.5)'); await openModal(); const openModalTransform = await getModalTransform(); @@ -156,6 +155,8 @@ it('should have correct transform when dismissed and opened', async () => { expect(initialModalTransform).not.toBe(openModalTransform); await dismissModal(); + // TODO: why is timeout needed? transition durations should be overwritten with 0s + await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); // transition delay for visibility const finalModalTransform = await getModalTransform(); expect(finalModalTransform).toBe(initialModalTransform); }); @@ -378,19 +379,18 @@ describe('focus behavior', () => { }); ` ); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await getModalVisibility(), 'initial').toBe('hidden'); expect(await getActiveElementTagName(page)).toBe('BODY'); await (await selectNode(page, '#btn-open')).click(); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await getModalVisibility()).toBe('visible'); await page.keyboard.press('Escape'); await waitForStencilLifecycle(page); + // TODO: why is timeout needed? transition durations should be overwritten with 0s await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); // transition delay for visibility expect(await getModalVisibility(), 'after escape').toBe('hidden'); @@ -600,35 +600,125 @@ it('should open modal at scroll top position zero when its content is scrollable }); describe('scroll lock', () => { - const bodyLockedStyle = 'top: 0px; overflow-y: scroll; position: fixed;'; + describe('Desktop Browser', () => { + const bodyLockedStyle = 'overflow: hidden;'; - it('should prevent page from scrolling when open', async () => { - await initBasicModal({ isOpen: false }); - expect(await getBodyStyle()).toBe(null); + it('should prevent page from scrolling when open', async () => { + await initBasicModal({ isOpen: false }); + expect(await getBodyStyle()).toBe(null); - await openModal(); - expect(await getBodyStyle()).toBe(bodyLockedStyle); + await openModal(); + expect(await getBodyStyle()).toBe(bodyLockedStyle); - await setProperty(await getHost(), 'open', false); - await waitForStencilLifecycle(page); - expect(await getBodyStyle()).toBe(''); - }); + await setProperty(await getHost(), 'open', false); + await waitForStencilLifecycle(page); + expect(await getBodyStyle()).toBe(''); + }); + + it('should prevent page from scrolling when initially open', async () => { + await initBasicModal({ isOpen: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyle); + }); + + it('should remove overflow hidden from body if unmounted', async () => { + await initBasicModal({ isOpen: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyle); + + await page.evaluate(() => { + document.querySelector('p-modal').remove(); + }); + await waitForStencilLifecycle(page); - it('should prevent page from scrolling when initially open', async () => { - await initBasicModal({ isOpen: true }); - expect(await getBodyStyle()).toBe(bodyLockedStyle); + expect(await getBodyStyle()).toBe(''); + }); }); - it('should remove overflow hidden from body if unmounted', async () => { - await initBasicModal({ isOpen: true }); - expect(await getBodyStyle()).toBe(bodyLockedStyle); + describe('iOS Safari', () => { + const bodyLockedStyleIOS = 'top: 0px; overflow-y: scroll; position: fixed;'; + + it('should prevent page from scrolling when open', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicModal({ isOpen: false }); + expect(await getBodyStyle()).toBe(null); - await page.evaluate(() => { - document.querySelector('p-modal').remove(); + await openModal(); + expect(await getBodyStyle()).toBe(bodyLockedStyleIOS); + + await setProperty(await getHost(), 'open', false); + await waitForStencilLifecycle(page); + expect(await getBodyStyle()).toBe(''); }); - await waitForStencilLifecycle(page); - expect(await getBodyStyle()).toBe(''); + it('should not override body styles on prop change', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicModal({ isOpen: false, markupBefore: '
' }); + expect(await getBodyStyle()).toBe(null); + + await page.evaluate(() => { + window.scrollTo(0, 500); + }); + + await openModal(); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + + await setProperty(await getHost(), 'aria', "{'aria-label': 'Other Heading'}"); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + }); + + it('should not override body styles on slot change', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicModal({ + isOpen: false, + markupBefore: '
', + hasSlottedHeading: true, + }); + expect(await getBodyStyle()).toBe(null); + + await page.evaluate(() => { + window.scrollTo(0, 500); + }); + + await openModal(); + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + + await setProperty(await getHost(), 'heading', 'Some Heading'); + + expect(await getBodyStyle()).toBe('top: -500px; overflow-y: scroll; position: fixed;'); + }); + + it('should prevent page from scrolling when initially open', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicModal({ isOpen: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyleIOS); + }); + + it('should remove overflow hidden from body if unmounted', async () => { + await page.setUserAgent( + 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' + ); + + await initBasicModal({ isOpen: true }); + expect(await getBodyStyle()).toBe(bodyLockedStyleIOS); + + await page.evaluate(() => { + document.querySelector('p-modal').remove(); + }); + await waitForStencilLifecycle(page); + + expect(await getBodyStyle()).toBe(''); + }); }); }); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/multi-select.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/multi-select.e2e.ts index bfb6c18ec7d..ce0ff432a07 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/multi-select.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/multi-select.e2e.ts @@ -24,33 +24,22 @@ beforeEach(async () => (page = await browser.newPage())); afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-multi-select'); - const getMultiSelectValue = async (): Promise<(string | number)[]> => await getProperty(await getHost(), 'value'); - -const getInputContainer = () => selectNode(page, 'p-multi-select >>> .input-container'); - +const getInputContainer = () => selectNode(page, 'p-multi-select >>> .wrapper'); const getInput = () => selectNode(page, 'p-multi-select >>> input'); - const getInputValue = async (): Promise => getProperty(await getInput(), 'value'); - const getInputPlaceholder = async (): Promise => getAttribute(await getInput(), 'placeholder'); - const getDropdown = () => selectNode(page, 'p-multi-select >>> .listbox'); const getDropdownDisplay = async (): Promise => await getElementStyle(await getDropdown(), 'display'); - const getShadowDropdownOption = (n: number) => selectNode(page, `p-multi-select >>> .listbox div:nth-child(${n})`); - const getMultiSelectOption = (n: number) => selectNode(page, `p-multi-select p-multi-select-option:nth-child(${n + 1})`); // First one is native select - const getMultiSelectOptions = () => page.$$('p-multi-select p-multi-select-option'); - const getAmountOfVisibleMultiSelectOptions = async (): Promise => await page.$$eval( 'p-multi-select p-multi-select-option', (options) => options.filter((option: HTMLElement) => !option.hidden).length ); - const getSelectedMultiSelectOptionProperty = async ( property: K ): Promise => @@ -62,27 +51,19 @@ const getSelectedMultiSelectOptionProperty = async option[property]) as MultiSelectOption[K][], property ); - const getHighlightedOptionIndex = async (): Promise => await page.$$eval('p-multi-select p-multi-select-option', (options: MultiSelectOption[]) => options.filter((option) => !option.hidden).indexOf(options.find((option: MultiSelectOption) => option.highlighted)) ); - const getSelectedOptionIndicies = async (): Promise => await page.$$eval('p-multi-select p-multi-select-option', (options) => options.filter((option: any) => option.selected).map((option) => options.indexOf(option)) ); - const getNativeSelect = () => selectNode(page, 'p-multi-select select'); - const getNativeSelectValue = async (): Promise => await getProperty(await getNativeSelect(), 'value'); - const getNativeSelectOptions = () => page.$$('p-multi-select select option'); - -const getLabelText = () => selectNode(page, 'p-multi-select >>> .label__text'); - -const getResetButton = () => selectNode(page, 'p-multi-select >>> .reset-icon'); - +const getLabel = () => selectNode(page, 'p-multi-select >>> label'); +const getResetButton = () => selectNode(page, 'p-multi-select >>> .button'); const getAssertiveText = async () => await selectNode(page, 'span[aria-live="assertive"]'); const labelSlotContent = @@ -483,7 +464,7 @@ describe('focus', () => { it('should focus input when label text is clicked', async () => { await initMultiSelect({ props: { name: 'options', label: 'Some Label' } }); - const labelText = await getLabelText(); + const labelText = await getLabel(); const filterInput = await getInput(); await addEventListener(filterInput, 'focus'); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/pin-code.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/pin-code.e2e.ts index 077ff2f8e94..30561e947a3 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/pin-code.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/pin-code.e2e.ts @@ -23,11 +23,11 @@ beforeEach(async () => { afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-pin-code'); -const getLabel = () => selectNode(page, 'p-pin-code >>> .label__text'); +const getLabel = () => selectNode(page, 'p-pin-code >>> label'); const getCurrentInput = () => selectNode(page, 'p-pin-code >>> #current-input'); const getMessage = () => selectNode(page, 'p-pin-code >>> .message'); -const getHiddenInput = () => selectNode(page, 'p-pin-code input[slot="hidden-input"]'); -const getInput = (n: number) => selectNode(page, `p-pin-code >>> .input-container input:nth-child(${n})`); +const getHiddenInput = () => selectNode(page, 'p-pin-code input[slot="internal-input"]'); +const getInput = (n: number) => selectNode(page, `p-pin-code >>> .wrapper input:nth-child(${n})`); const getActiveElementsAriaLabelInShadowRoot = (element: ElementHandle): Promise => { return element.evaluate((el) => el.shadowRoot.activeElement.ariaLabel); }; @@ -63,17 +63,6 @@ const initPinCode = (opts?: InitOptions) => { }; describe('label', () => { - it('should not render label if label prop is not defined but should render if changed programmatically', async () => { - await initPinCode(); - const pinCodeComponent = await getHost(); - expect(await getLabel()).toBeNull(); - - await setProperty(pinCodeComponent, 'label', 'Some label'); - await waitForStencilLifecycle(page); - - expect(await getLabel()).not.toBeNull(); - }); - it('should focus input with id="current-input" when label text is clicked', async () => { await initPinCode({ props: { label: 'Some label' } }); const label = await getLabel(); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/radio-button-wrapper.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/radio-button-wrapper.e2e.ts index c82b925b57b..1b6540be53a 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/radio-button-wrapper.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/radio-button-wrapper.e2e.ts @@ -21,8 +21,10 @@ beforeEach(async () => (page = await browser.newPage())); afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-radio-button-wrapper'); +const getRoot = () => selectNode(page, 'p-radio-button-wrapper >>> .root'); const getInput = () => selectNode(page, 'p-radio-button-wrapper input'); -const getLabelText = () => selectNode(page, 'p-radio-button-wrapper >>> .text'); +const getWrapper = () => selectNode(page, 'p-radio-button-wrapper >>> .wrapper'); +const getLabel = () => selectNode(page, 'p-radio-button-wrapper >>> label'); const getMessage = () => selectNode(page, 'p-radio-button-wrapper >>> .message'); const getBackgroundStyle = (element: ElementHandle) => getElementStyle(element, 'background'); @@ -58,24 +60,6 @@ const initRadioButton = (opts?: InitOptions): Promise => { ); }; -it('should not render label if label prop is not defined but should render if changed programmatically', async () => { - await setContentWithDesignSystem( - page, - ` - - - ` - ); - - const radioComponent = await getHost(); - expect(await getLabelText()).toBeNull(); - - await setProperty(radioComponent, 'label', 'Some label'); - await waitForStencilLifecycle(page); - - expect(await getLabelText()).not.toBeNull(); -}); - it('should add/remove message text if state changes programmatically', async () => { await setContentWithDesignSystem( page, @@ -118,20 +102,38 @@ it('should disable radio-button when disabled property is set programmatically', ` ); + const host = await getHost(); const input = await getInput(); - const getCursor = () => getElementStyle(input, 'cursor'); + const wrapper = await getWrapper(); - expect(await getCursor()).toBe('pointer'); + const getWrapperCursor = () => getElementStyle(wrapper, 'cursor'); + const getInputCursor = () => getElementStyle(input, 'cursor'); + const getInputPointerEvents = () => getElementStyle(input, 'pointerEvents'); + + expect(await getWrapperCursor()).toBe('auto'); + expect(await getInputCursor()).toBe('pointer'); + expect(await getInputPointerEvents()).toBe('auto'); await setProperty(input, 'disabled', true); await waitForInputTransition(page); - expect(await getCursor()).toBe('not-allowed'); + expect(await getWrapperCursor()).toBe('not-allowed'); + expect(await getInputCursor()).toBe('default'); + expect(await getInputPointerEvents()).toBe('none'); // prevents radio-button from being clickable in disabled and especially loading state await setProperty(input, 'disabled', false); await waitForInputTransition(page); - expect(await getCursor()).toBe('pointer'); + expect(await getWrapperCursor()).toBe('auto'); + expect(await getInputCursor()).toBe('pointer'); + expect(await getInputPointerEvents()).toBe('auto'); + + await setProperty(host, 'loading', true); + await waitForInputTransition(page); + + expect(await getWrapperCursor()).toBe('not-allowed'); + expect(await getInputCursor()).toBe('default'); + expect(await getInputPointerEvents()).toBe('none'); // prevents radio-button from being clickable in disabled and especially loading state }); describe('checked state', () => { @@ -182,8 +184,8 @@ describe('checked state', () => { const input1 = await selectNode(page, '#radio-1 > input[type="radio"]'); const input2 = await selectNode(page, '#radio-2 > input[type="radio"]'); - const labelText1 = await selectNode(page, '#radio-1 >>> .text'); - const labelText2 = await selectNode(page, '#radio-2 >>> .text'); + const label1 = await selectNode(page, '#radio-1 >>> label'); + const label2 = await selectNode(page, '#radio-2 >>> label'); const initialStyleInput1 = await getBackgroundStyle(input1); const initialStyleInput2 = await getBackgroundStyle(input2); @@ -191,14 +193,14 @@ describe('checked state', () => { expect(await getActiveElementId(page)).toBe(''); expect(await getActiveElementTagName(page)).toBe('BODY'); - await labelText1.click(); + await label1.click(); await waitForInputTransition(page); expect(await getBackgroundStyle(input1)).not.toEqual(initialStyleInput1); expect(initialStyleInput2).toEqual(await getBackgroundStyle(input2)); expect(await getActiveElementTagName(page)).toBe('BODY'); - await labelText2.click(); + await label2.click(); await waitForInputTransition(page); expect(await getBackgroundStyle(input1)).toEqual(initialStyleInput1); @@ -451,4 +453,11 @@ describe('accessibility', () => { await page.keyboard.press('Tab'); expect(await getActiveElementId(page)).toBe('lastPageEl'); }); + + it('should expose correct accessibility tree when loading=true', async () => { + await initRadioButton({ loading: true }); + const root = await getRoot(); + + await expectA11yToMatchSnapshot(page, root, { interestingOnly: false }); + }); }); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-filter.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-filter.e2e.ts index c85ca6a554b..8d29cf5a40a 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-filter.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-filter.e2e.ts @@ -21,7 +21,7 @@ afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-select-wrapper'); const getSelect = () => selectNode(page, 'p-select-wrapper select'); -const getLabelText = () => selectNode(page, 'p-select-wrapper >>> .label__text'); +const getLabel = () => selectNode(page, 'p-select-wrapper >>> label'); const dropdownSelector = 'p-select-wrapper >>> p-select-wrapper-dropdown'; const filterInputSelector = `${dropdownSelector} >>> input`; @@ -117,13 +117,13 @@ describe('focus state', () => { it('should focus filter when label text is clicked', async () => { await initSelect(); - const labelText = await getLabelText(); + const label = await getLabel(); const filterInput = await getFilterInput(); await addEventListener(filterInput, 'focus'); expect((await getEventSummary(filterInput, 'focus')).counter).toBe(0); - await labelText.click(); + await label.click(); expect((await getEventSummary(filterInput, 'focus')).counter).toBe(1); }); }); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-native.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-native.e2e.ts index 5e43dac45b1..885bed9668b 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-native.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/select-wrapper-native.e2e.ts @@ -19,7 +19,7 @@ afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-select-wrapper'); const getSelect = () => selectNode(page, 'p-select-wrapper select'); const getMessage = () => selectNode(page, 'p-select-wrapper >>> .message'); -const getLabelText = () => selectNode(page, 'p-select-wrapper >>> .label__text'); +const getLabel = () => selectNode(page, 'p-select-wrapper >>> label'); type InitOptions = { useSlottedLabel?: boolean; @@ -65,28 +65,6 @@ const initSelect = (opts?: InitOptions): Promise => { ); }; -it('should not render label if label prop is not defined but should render if changed programmatically', async () => { - await setContentWithDesignSystem( - page, - ` - - - ` - ); - - expect(await getLabelText()).toBeNull(); - - const host = await getHost(); - await setProperty(host, 'label', 'Some label'); - await waitForStencilLifecycle(page); - - expect(await getLabelText()).not.toBeNull(); -}); - it('should add/remove message text and update aria-label attribute with message text if state changes programmatically', async () => { await initSelect(); const host = await getHost(); @@ -137,7 +115,7 @@ describe('focus state', () => { const select = await getSelect(); const hasSelectFocus = () => hasFocus(select); - const labelText = await getLabelText(); + const labelText = await getLabel(); expect(await hasSelectFocus()).toBe(false); await labelText.click(); @@ -152,11 +130,11 @@ xdescribe('hover state', () => { await page.mouse.move(0, 300); // avoid potential hover initially const select = await getSelect(); - const labelText = await getLabelText(); + const label = await getLabel(); const initialStyle = await getElementStyle(select, 'borderColor'); expect(initialStyle).toBe('rgb(107, 109, 112)'); - await labelText.hover(); + await label.hover(); const hoverColor = await getElementStyle(select, 'borderColor'); expect(hoverColor).toBe('rgb(1, 2, 5)'); }); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/text-field-wrapper.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/text-field-wrapper.e2e.ts index b437bbed0df..310870eaaf9 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/text-field-wrapper.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/text-field-wrapper.e2e.ts @@ -17,15 +17,13 @@ import { import type { ElementHandle, Page } from 'puppeteer'; import type { FormState } from '@porsche-design-system/components/dist/types/bundle'; -const CSS_TRANSITION_DURATION = 240; - let page: Page; beforeEach(async () => (page = await browser.newPage())); afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-text-field-wrapper'); const getInput = () => selectNode(page, 'input'); -const getLabel = () => selectNode(page, 'p-text-field-wrapper >>> .label__text'); +const getLabel = () => selectNode(page, 'p-text-field-wrapper >>> label'); const getCounterOrUnit = () => selectNode(page, 'p-text-field-wrapper >>> .unit'); const getToggleOrClearButtonHost = () => selectNode(page, 'p-text-field-wrapper >>> p-button-pure'); const getToggleOrClearButton = () => selectNode(page, 'p-text-field-wrapper >>> p-button-pure >>> button'); @@ -89,16 +87,6 @@ const initTextField = (opts?: InitOptions): Promise => { return setContentWithDesignSystem(page, content); }; -it('should not render label if label prop is not defined but should render if changed programmatically', async () => { - await initTextField(); - const textFieldComponent = await getHost(); - expect(await getLabel()).toBeNull(); - - await setProperty(textFieldComponent, 'label', 'Some label'); - await waitForStencilLifecycle(page); - expect(await getLabel()).not.toBeNull(); -}); - describe('input type="password"', () => { xit('should disable input when input is disabled programmatically', async () => { await initTextField({ type: 'password', hasLabel: true }); @@ -109,14 +97,12 @@ describe('input type="password"', () => { await setProperty(input, 'disabled', true); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await getElementStyle(input, 'cursor'), 'disabled cursor').not.toBe(initialCursor); expect(await getElementStyle(input, 'borderColor'), 'disabled border').not.toBe(initialBorderColor); await setProperty(input, 'disabled', false); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await getElementStyle(input, 'cursor'), 'not disabled cursor').toBe(initialCursor); expect(await getElementStyle(input, 'borderColor'), 'not disabled borderColor').toBe(initialBorderColor); @@ -299,13 +285,11 @@ describe('input type="search"', () => { await setProperty(input, 'disabled', true); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await isButtonDisabled(buttonHost)).toBe(true); await setProperty(input, 'disabled', false); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await isButtonDisabled(buttonHost)).toBe(false); }); @@ -319,13 +303,11 @@ describe('input type="search"', () => { await setProperty(input, 'readOnly', true); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await isButtonDisabled(buttonHost)).toBe(true); await setProperty(input, 'readOnly', false); await waitForStencilLifecycle(page); - await new Promise((resolve) => setTimeout(resolve, CSS_TRANSITION_DURATION)); expect(await isButtonDisabled(buttonHost)).toBe(false); }); @@ -585,7 +567,7 @@ describe('accessibility', () => { }); it('should expose correct accessibility tree for input type=search with value', async () => { - await initTextField({ type: 'search' }); + await initTextField({ type: 'search', hasLabel: true }); const host = await getHost(); const input = await getInput(); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/textarea-wrapper.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/textarea-wrapper.e2e.ts index bffc37d7df9..f2baba3abdd 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/textarea-wrapper.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/textarea-wrapper.e2e.ts @@ -21,7 +21,7 @@ afterEach(async () => await page.close()); const getHost = () => selectNode(page, 'p-textarea-wrapper'); const getTextarea = () => selectNode(page, 'p-textarea-wrapper textarea'); const getMessage = () => selectNode(page, 'p-textarea-wrapper >>> .message'); -const getLabel = () => selectNode(page, 'p-textarea-wrapper >>> .label__text'); +const getLabel = () => selectNode(page, 'p-textarea-wrapper >>> label'); const getCounter = () => selectNode(page, 'p-textarea-wrapper >>> .counter'); type InitOptions = { @@ -62,18 +62,6 @@ const initTextarea = (opts?: InitOptions): Promise => { ); }; -it('should not render label if label prop is not defined but should render if changed programmatically', async () => { - await initTextarea(); - const host = await getHost(); - - expect(await getLabel()).toBeNull(); - - await setProperty(host, 'label', 'Some label'); - await waitForStencilLifecycle(page); - - expect(await getLabel()).toBeDefined(); -}); - it('should focus textarea when label is clicked', async () => { await initTextarea({ hasLabel: true }); const label = await getLabel(); diff --git a/packages/components-js/tests/e2e/puppeteer/specs/toast.e2e.ts b/packages/components-js/tests/e2e/puppeteer/specs/toast.e2e.ts index 7701f836544..f6c38d9d231 100644 --- a/packages/components-js/tests/e2e/puppeteer/specs/toast.e2e.ts +++ b/packages/components-js/tests/e2e/puppeteer/specs/toast.e2e.ts @@ -178,7 +178,7 @@ describe('toast-item', () => { const animationIn = await getElementStyle(toastItem, 'animation'); expect(animationIn, 'for animationIn').toMatchInlineSnapshot( - '"0.6s cubic-bezier(0.45, 0, 0.55, 1) 0s 1 normal forwards running in"' + `"0.6s cubic-bezier(0, 0, 0.2, 1) 0s 1 normal forwards running in"` ); // toast stay open for a total of 1000ms, we need to hit the middle of closing animation @@ -186,7 +186,7 @@ describe('toast-item', () => { const animationOut = await getElementStyle(toastItem, 'animation'); expect(animationOut, 'for animationOut').toMatchInlineSnapshot( - '"0.6s cubic-bezier(0.5, 1, 0.89, 1) 0s 1 normal forwards running out"' + `"0.4s cubic-bezier(0.4, 0, 0.5, 1) 0s 1 normal forwards running out"` ); await waitForAnimationFinish(); // wait another 600ms to be sure animation has finished diff --git a/packages/components-js/tests/smoke/specs/puppeteer/cdn.smoke.ts b/packages/components-js/tests/smoke/specs/puppeteer/cdn.smoke.ts index 0a0b0ce795a..c214eef2a24 100644 --- a/packages/components-js/tests/smoke/specs/puppeteer/cdn.smoke.ts +++ b/packages/components-js/tests/smoke/specs/puppeteer/cdn.smoke.ts @@ -19,6 +19,7 @@ import { getFontFaceStylesheet } from '@porsche-design-system/components-js/part import { COMPONENT_CHUNKS_MANIFEST } from '../../../../projects/components-wrapper/lib/chunksManifest'; import { CDN_BASE_PATH_COMPONENTS, CDN_BASE_PATH_STYLES, CDN_BASE_URL_COM } from '../../../../../../cdn.config'; import { setContentWithDesignSystem } from './helpers'; +import * as mime from 'mime'; describe('cdn', () => { let page: Page; @@ -26,7 +27,7 @@ describe('cdn', () => { afterEach(async () => await page.close()); type RequestType = { url: string }; - type ResponseType = { url: string; status: number }; + type ResponseType = { url: string; status: number; headers: Record }; const requests: RequestType[] = []; const responses: ResponseType[] = []; @@ -52,10 +53,11 @@ describe('cdn', () => { page.on('response', (resp) => { const url = resp.url(); const status = resp.status(); + const headers = resp.headers(); if (url.includes('cdn.ui.porsche')) { // console.log(status, url); - responses.push({ url, status }); + responses.push({ url, status, headers }); } }); }); @@ -149,9 +151,17 @@ describe('cdn', () => { const bulkRequestItems = (items: string[], baseUrl: string) => { for (const item of items) { ((item: string) => { - it(`should exist: ${item}`, async () => { + it(`should exist and have correct headers: ${item}`, async () => { await fetchUrl(`${baseUrl}/${item}`); expect(responses.filter(isStatusNot200).length).toBe(0); + responses.forEach((response) => { + const ext = item.split('.').pop(); + // Mime library returns application/javascript but should be text/javascript + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + const mimeType = ext === 'js' ? 'text/javascript' : mime.getType(ext); + expect(response.headers['content-type']).toBe(mimeType); + expect(response.headers['access-control-allow-origin']).toBe('*'); + }); responseCounter += responses.length; const responseErrors = responses.filter(isStatus400); diff --git a/packages/components-js/tests/unit/fixtures/stats.json b/packages/components-js/tests/unit/fixtures/stats.json index b5be2120854..328c6753a41 100644 --- a/packages/components-js/tests/unit/fixtures/stats.json +++ b/packages/components-js/tests/unit/fixtures/stats.json @@ -1,262 +1,262 @@ [ { "chunkShortName": "accordion", - "size": 4547, - "gzipSize": 1966 + "size": 4577, + "gzipSize": 1978 }, { "chunkShortName": "banner", - "size": 5217, - "gzipSize": 2149 + "size": 5218, + "gzipSize": 2114 }, { "chunkShortName": "button", - "size": 7179, - "gzipSize": 2883 + "size": 7235, + "gzipSize": 2890 }, { "chunkShortName": "button-group", - "size": 1039, - "gzipSize": 588 + "size": 1049, + "gzipSize": 592 }, { "chunkShortName": "button-pure", - "size": 7940, - "gzipSize": 3283 + "size": 7976, + "gzipSize": 3293 }, { "chunkShortName": "button-tile", - "size": 6871, - "gzipSize": 2893 + "size": 6893, + "gzipSize": 2899 }, { "chunkShortName": "carousel", - "size": 44126, - "gzipSize": 17756 + "size": 44156, + "gzipSize": 17776 }, { "chunkShortName": "checkbox-wrapper", - "size": 8630, - "gzipSize": 3556 + "size": 9880, + "gzipSize": 4018 }, { "chunkShortName": "content-wrapper", - "size": 2416, - "gzipSize": 1181 + "size": 2426, + "gzipSize": 1183 }, { "chunkShortName": "crest", - "size": 2101, - "gzipSize": 1092 + "size": 2111, + "gzipSize": 1095 }, { "chunkShortName": "display", - "size": 3608, - "gzipSize": 1677 + "size": 3618, + "gzipSize": 1680 }, { "chunkShortName": "divider", - "size": 2350, - "gzipSize": 1030 + "size": 2360, + "gzipSize": 1037 }, { "chunkShortName": "fieldset", - "size": 3991, - "gzipSize": 1629 + "size": 4002, + "gzipSize": 1649 }, { "chunkShortName": "fieldset-wrapper", - "size": 4243, - "gzipSize": 1756 + "size": 4254, + "gzipSize": 1766 }, { "chunkShortName": "flex", - "size": 3557, - "gzipSize": 1375 + "size": 3567, + "gzipSize": 1382 }, { "chunkShortName": "flyout", - "size": 8325, - "gzipSize": 3344 + "size": 8545, + "gzipSize": 3404 }, { "chunkShortName": "grid", - "size": 2614, - "gzipSize": 1165 + "size": 2624, + "gzipSize": 1166 }, { "chunkShortName": "heading", - "size": 4266, - "gzipSize": 1832 + "size": 4276, + "gzipSize": 1835 }, { "chunkShortName": "headline", - "size": 4752, - "gzipSize": 1971 + "size": 4762, + "gzipSize": 1975 }, { "chunkShortName": "icon", - "size": 17617, - "gzipSize": 8349 + "size": 17628, + "gzipSize": 8346 }, { "chunkShortName": "inline-notification", - "size": 5436, + "size": 5443, "gzipSize": 2196 }, { "chunkShortName": "link", - "size": 6373, - "gzipSize": 2618 + "size": 6429, + "gzipSize": 2625 }, { "chunkShortName": "link-pure", - "size": 7562, - "gzipSize": 3074 + "size": 7574, + "gzipSize": 3078 }, { "chunkShortName": "link-social", - "size": 6149, - "gzipSize": 2580 + "size": 6205, + "gzipSize": 2582 }, { "chunkShortName": "link-tile", - "size": 6974, - "gzipSize": 2945 + "size": 6996, + "gzipSize": 2952 }, { "chunkShortName": "link-tile-model-signature", - "size": 6323, - "gzipSize": 2722 + "size": 6344, + "gzipSize": 2731 }, { "chunkShortName": "main", - "size": 74555, - "gzipSize": 24821 + "size": 75004, + "gzipSize": 25020 }, { "chunkShortName": "marque", - "size": 5537, - "gzipSize": 2220 + "size": 5547, + "gzipSize": 2225 }, { "chunkShortName": "modal", - "size": 9168, - "gzipSize": 3871 + "size": 9301, + "gzipSize": 3939 }, { "chunkShortName": "model-signature", - "size": 2789, - "gzipSize": 1409 + "size": 2799, + "gzipSize": 1413 }, { "chunkShortName": "multi-select", - "size": 21565, - "gzipSize": 7213 + "size": 22051, + "gzipSize": 7502 }, { "chunkShortName": "pagination", - "size": 7283, - "gzipSize": 2949 + "size": 7315, + "gzipSize": 2945 }, { "chunkShortName": "pin-code", - "size": 11509, - "gzipSize": 4470 + "size": 12493, + "gzipSize": 4867 }, { "chunkShortName": "popover", - "size": 8577, - "gzipSize": 3227 + "size": 8618, + "gzipSize": 3243 }, { "chunkShortName": "radio-button-wrapper", - "size": 8128, - "gzipSize": 3374 + "size": 9392, + "gzipSize": 3862 }, { "chunkShortName": "scroller", - "size": 8173, - "gzipSize": 3108 + "size": 8184, + "gzipSize": 3110 }, { "chunkShortName": "segmented-control", - "size": 7906, - "gzipSize": 3085 + "size": 7916, + "gzipSize": 3097 }, { "chunkShortName": "select-wrapper", - "size": 23467, - "gzipSize": 7672 + "size": 23755, + "gzipSize": 7917 }, { "chunkShortName": "spinner", "size": 2159, - "gzipSize": 1058 + "gzipSize": 1060 }, { "chunkShortName": "stepper-horizontal", - "size": 11564, - "gzipSize": 4663 + "size": 11576, + "gzipSize": 4664 }, { "chunkShortName": "switch", - "size": 5894, - "gzipSize": 2332 + "size": 5931, + "gzipSize": 2345 }, { "chunkShortName": "table", - "size": 8295, - "gzipSize": 3044 + "size": 8332, + "gzipSize": 3054 }, { "chunkShortName": "tabs", - "size": 6192, - "gzipSize": 2543 + "size": 6202, + "gzipSize": 2549 }, { "chunkShortName": "tabs-bar", - "size": 10509, - "gzipSize": 4088 + "size": 10474, + "gzipSize": 4125 }, { "chunkShortName": "tag", - "size": 5423, - "gzipSize": 2209 + "size": 5460, + "gzipSize": 2217 }, { "chunkShortName": "tag-dismissible", - "size": 4027, - "gzipSize": 1788 + "size": 4037, + "gzipSize": 1793 }, { "chunkShortName": "text", - "size": 5171, - "gzipSize": 2108 + "size": 5181, + "gzipSize": 2114 }, { "chunkShortName": "text-field-wrapper", - "size": 14561, - "gzipSize": 5449 + "size": 15233, + "gzipSize": 5744 }, { "chunkShortName": "text-list", - "size": 3905, - "gzipSize": 1701 + "size": 3915, + "gzipSize": 1705 }, { "chunkShortName": "textarea-wrapper", - "size": 8949, - "gzipSize": 3430 + "size": 9660, + "gzipSize": 3755 }, { "chunkShortName": "toast", - "size": 6798, - "gzipSize": 2894 + "size": 6790, + "gzipSize": 2896 }, { "chunkShortName": "wordmark", - "size": 2741, - "gzipSize": 1323 + "size": 2751, + "gzipSize": 1328 } ] \ No newline at end of file diff --git a/packages/components-js/tests/vrt/playwright/config/playwright.config.ts b/packages/components-js/tests/vrt/playwright/config/playwright.config.ts index 0673f75b3d8..5eb45a282e3 100644 --- a/packages/components-js/tests/vrt/playwright/config/playwright.config.ts +++ b/packages/components-js/tests/vrt/playwright/config/playwright.config.ts @@ -21,14 +21,14 @@ export default defineConfig({ */ timeout: 10000, toMatchSnapshot: { - maxDiffPixelRatio: 0, - maxDiffPixels: 0, - threshold: 0, + maxDiffPixelRatio: undefined, + maxDiffPixels: undefined, + threshold: 0.2, // default Playwright threshold }, toHaveScreenshot: { - maxDiffPixelRatio: 0, - maxDiffPixels: 0, - threshold: 0, + maxDiffPixelRatio: undefined, + maxDiffPixels: undefined, + threshold: 0.2, // default Playwright threshold }, }, snapshotPathTemplate: '{testDir}/__screenshots__/{arg}-{projectName}{ext}', diff --git a/packages/components-js/tests/vrt/playwright/helpers/playwright-helper.ts b/packages/components-js/tests/vrt/playwright/helpers/playwright-helper.ts index 658cf0bd11e..fe7d716df66 100644 --- a/packages/components-js/tests/vrt/playwright/helpers/playwright-helper.ts +++ b/packages/components-js/tests/vrt/playwright/helpers/playwright-helper.ts @@ -1,15 +1,20 @@ import { type Page } from '@playwright/test'; -import { getInitialStyles } from '@porsche-design-system/components-js/partials'; +import { getInitialStyles, getComponentChunkLinks, getIconLinks } from '@porsche-design-system/components-js/partials'; import { TAG_NAMES, type TagName } from '@porsche-design-system/shared'; import { getComponentMeta } from '@porsche-design-system/component-meta'; import { type Theme } from '@porsche-design-system/utilities-v2'; -import type { PlaywrightTestConfig } from 'playwright/types/test'; +import { COMPONENT_CHUNK_NAMES } from '../../../../projects/components-wrapper'; +import { ICON_NAMES } from '@porsche-design-system/assets'; -export const thresholdConfig: PlaywrightTestConfig['expect']['toHaveScreenshot'] = { - maxDiffPixelRatio: undefined, - maxDiffPixels: undefined, - threshold: 0.2, // default Playwright threshold -}; +const chunksLink = getComponentChunkLinks({ components: [...COMPONENT_CHUNK_NAMES] }).replace( + /https:\/\/cdn\.ui\.porsche\.com\/porsche-design-system/g, + 'http://localhost:3001' +); + +const iconsLink = getIconLinks({ icons: [...ICON_NAMES] }).replace( + /https:\/\/cdn\.ui\.porsche\.com\/porsche-design-system/g, + 'http://localhost:3001' +); // TODO: why are the following constants prefixed with base? export const baseThemes = ['light', 'dark'] as const; @@ -112,7 +117,6 @@ export const setupScenario = async ( scalePageFontSize, forceComponentTheme, forceDirMode, - emulateMediaPrint, }: SetupScenarioOptions = { javaScriptDisabled: false, forcedColorsEnabled: false, @@ -120,7 +124,6 @@ export const setupScenario = async ( scalePageFontSize: false, forceComponentTheme: undefined, forceDirMode: undefined, - emulateMediaPrint: false, ...options, }; if (javaScriptDisabled) { @@ -148,30 +151,17 @@ export const setupScenario = async ( } await page.setViewportSize({ width: viewportWidth, height: 600 }); - await page.goto(url); - await waitForComponentsReady(page); + const searchParams = new URLSearchParams(); if (forceComponentTheme) { - await waitForForcedComponentTheme(page, forceComponentTheme); + searchParams.append('theme', forceComponentTheme); } - if (forceDirMode) { - await page.evaluate((forceDirMode) => { - document.querySelector('html').setAttribute('dir', forceDirMode); - }, forceDirMode); - } - - if (scalePageFontSize) { - // resize before scaling helps load icons at least in select-wrapper - await page.setViewportSize({ - width: viewportWidth, - height: await page.evaluate(() => document.body.clientHeight), // TODO: why dynamic based on content here but fixed 600 everywhere else? - }); - } - - if (emulateMediaPrint) { - await page.emulateMedia({ media: 'print' }); + searchParams.append('dir', forceDirMode); } + const finalUrl = `${url}?${searchParams.toString()}`; + await page.goto(finalUrl); + await waitForComponentsReady(page); await page.setViewportSize({ width: viewportWidth, @@ -213,6 +203,8 @@ export const setContentWithDesignSystem = async ( ${getInitialStyles()} + ${chunksLink} + ${iconsLink} ${injectIntoHead} diff --git a/packages/components-js/tests/vrt/playwright/scripts/adjustRegressionFilenames.ts b/packages/components-js/tests/vrt/playwright/scripts/adjustRegressionFilenames.ts index 0360d23666f..a3b6261ffbe 100644 --- a/packages/components-js/tests/vrt/playwright/scripts/adjustRegressionFilenames.ts +++ b/packages/components-js/tests/vrt/playwright/scripts/adjustRegressionFilenames.ts @@ -41,8 +41,19 @@ const walk = (dir: any, done: any): void => { }); }; +const deleteRetryDirectories = (source: string): void => { + fs.readdirSync(source, { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => { + if (/retry\d+$/.test(dirent.name)) { + fs.rmSync(`./${dirent.path}/${dirent.name}`, { recursive: true, force: true }); + } + }); +}; + const path = 'tests/vrt/playwright/results'; if (fs.existsSync(path)) { + deleteRetryDirectories(path); walk(path, (error: any): void => { if (error) { throw error; diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-dark-chrome.png index 380a9ac8877..7872ff08a5d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-light-chrome.png index 48f28aebe71..be5be1ba1c0 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-rtl-mode-chrome.png index b5878d36812..e42ec26c0d5 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-scale-mode-chrome.png index 1e35e402e58..5621b36c5ee 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-chrome.png index e0561b14611..f2da640b547 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-safari.png index 4860245cb92..9b5d3cd0dfb 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-chrome.png index cde53175198..092a310b208 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-safari.png index db29cb2626b..7e80c4f1db8 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1300-chrome.png index 0bd25cea5fa..25f82d1558c 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1760-chrome.png index 26b871afd05..a1381f3c0ec 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-320-chrome.png index f57e56defe0..52aa447d007 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-480-chrome.png index 84b051a909a..fbec329241b 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-760-chrome.png index 625a55100c9..a31231e98b8 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-dark-chrome.png index fa581a338e1..45f86d2c189 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-light-chrome.png index f45246f59e6..f4b144290ce 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/accordion-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-dark-chrome.png index 18bd97cba2c..3a89df96472 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-light-chrome.png index 5ba2c8e03a7..e6a9694566c 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/banner-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-dark-chrome.png index f914bbb0809..6306db89a43 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-light-chrome.png index 10b9fc5e025..9eb0fa438d4 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/checkbox-wrapper-1000-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-dark-chrome.png index fa364e87656..b3854288784 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-light-chrome.png index 929a163edd6..9828f98435f 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-rtl-mode-chrome.png index a9f312ed053..4a4adc4f1b6 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-scale-mode-chrome.png index 6c4cac791ed..39336bdfaea 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-chrome.png index 0bced7555a4..ead2876ea1b 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-safari.png index 1ff9c9ac8b6..5f6f392f8d3 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-chrome.png index 6bc04c6f582..c5944ecb098 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-safari.png index 32300508b83..09c00dc7419 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1300-chrome.png index ad15a03287d..29e1ef1ace8 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1760-chrome.png index f5f60a7e8f4..0d45a46e836 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-320-chrome.png index a0a07958428..192e0e39452 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-480-chrome.png index 0cf38d6b39a..fc1eeeac95a 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-760-chrome.png index a1caed31ee8..84dfb4c070d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-print-theme-light-chrome.png index 89ff49397bf..5896aeb5858 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-dark-chrome.png index fa364e87656..b3854288784 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-light-chrome.png index 929a163edd6..9828f98435f 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-rtl-mode-chrome.png index a9f312ed053..4a4adc4f1b6 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-scale-mode-chrome.png index 6c4cac791ed..39336bdfaea 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-chrome.png index 0bced7555a4..fa27c3dac20 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-safari.png index 1ff9c9ac8b6..5f6f392f8d3 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-chrome.png index 6bc04c6f582..c5944ecb098 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-safari.png index 32300508b83..09c00dc7419 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1300-chrome.png index ad15a03287d..29e1ef1ace8 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1760-chrome.png index f5f60a7e8f4..0d45a46e836 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-320-chrome.png index a0a07958428..192e0e39452 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-480-chrome.png index 0cf38d6b39a..fc1eeeac95a 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-760-chrome.png index a1caed31ee8..84dfb4c070d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-print-theme-light-chrome.png index 89ff49397bf..5896aeb5858 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/fieldset-wrapper-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/flyout-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/flyout-print-theme-dark-chrome.png index 9b3b2c88848..1d700137291 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/flyout-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/flyout-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1000-states-theme-dark-chrome.png deleted file mode 100644 index 41b7e8c4119..00000000000 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1000-states-theme-dark-chrome.png and /dev/null differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1000-states-theme-light-chrome.png deleted file mode 100644 index 051aa17eec0..00000000000 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1000-states-theme-light-chrome.png and /dev/null differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1920-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1920-states-theme-dark-chrome.png new file mode 100644 index 00000000000..c06e85c5ade Binary files /dev/null and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1920-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1920-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1920-states-theme-light-chrome.png new file mode 100644 index 00000000000..786726f57c9 Binary files /dev/null and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/form-fields-1920-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-dark-chrome.png index bc9c274ac4b..e2fc4086099 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-light-chrome.png index f9f690925be..260467ea9d4 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-rtl-mode-chrome.png index 564b2d41a91..95c04bdb93e 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-scale-mode-chrome.png index 0fecbf29010..a2e48669236 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-dark-chrome.png index 93962cba0c1..5f52a560f7d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-light-chrome.png index 9b58e8135ee..893990a1e09 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-chrome.png index 073af901b2d..61eec705eae 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-safari.png index baee952b89d..78af0c39cd1 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-chrome.png index 71f0d0f54aa..5117c1b5454 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-safari.png index 6589d6c12b5..8cfdf24a328 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1300-chrome.png index 40cbb6e042e..b887a87c992 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1760-chrome.png index 5fdcc2fa3da..30f110608e9 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-320-chrome.png index eda92e8b976..ef8cd8db45d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-480-chrome.png index 5cae4a234a2..05ba556ea86 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-760-chrome.png index 5d1de020f1f..7d5006f227b 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-dark-chrome.png index 5e59b5d106b..2b137ae945b 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-light-chrome.png index 665a5987353..bb1d6341828 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/multi-select-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/overview-1920-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/overview-1920-chrome.png index fd4e70fa4db..46dcf691d48 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/overview-1920-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/overview-1920-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-dark-chrome.png index 8eaa443117d..0dd7d24ff97 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-light-chrome.png index 1683294c922..2ffea22c7c4 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-dark-chrome.png index f62bf407fc2..afd57f8e64c 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-light-chrome.png index 662723baaf9..7dc4068cf7e 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/pin-code-1000-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/popover-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/popover-1000-rtl-mode-chrome.png index 6955143280d..94b9889eaa6 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/popover-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/popover-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-dark-chrome.png index 9a201733512..1051d8fbfff 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-light-chrome.png index 4620e284f6c..59b108b828c 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/radio-button-wrapper-1000-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-dark-chrome.png index e9ecc67dce2..b70d97b6a3d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-light-chrome.png index 34680d074b9..bc1eae8d412 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-rtl-mode-chrome.png index e2889de46ac..68e62f13fa3 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-scale-mode-chrome.png index 35b32669511..97a44248d1e 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-dark-chrome.png index 243d0eb0b2f..cfbd8272294 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-light-chrome.png index 14f305c3213..3e4fcbf96f7 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-chrome.png index 7c792f59f59..eca9980f050 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-safari.png index a1e4a2c0d99..b9cacfae514 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-chrome.png index d39193db55d..4d05182ba34 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-safari.png index 40c2a52318e..d3ad695a946 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1300-chrome.png index a208af34160..4c61c23911d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1760-chrome.png index 504d5fff37a..84e2a5a6108 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-320-chrome.png index 7dd005e771f..545ded562a9 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-480-chrome.png index 9df1e22e4e4..822e28017a3 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-760-chrome.png index 6e30096efc8..daaaad57d61 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-dark-chrome.png index 8722da3e24f..1a51151a8c2 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-light-chrome.png index ccfefb2e3a6..e3587c3d982 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/select-wrapper-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/stepper-horizontal-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/stepper-horizontal-1000-rtl-mode-chrome.png index 42331eb56ff..ec9e8665694 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/stepper-horizontal-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/stepper-horizontal-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-dark-chrome.png index 2d091603eca..baefccc019b 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-light-chrome.png index 133f8fa2aa3..d75c85d0dc3 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-rtl-mode-chrome.png index d0da5acb2c7..21c79ff77dc 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-scale-mode-chrome.png index f9eddc7a5b0..8c586bc3dbd 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-dark-chrome.png index c9940f6f944..665ef14740c 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-light-chrome.png index 9b737d39c45..b4b0c51075d 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-states-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-chrome.png index 164a35058c7..9a333f07edb 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-safari.png index 92b0ab64053..6730fd08474 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-chrome.png index e3765fd6ea7..c1d7abdddff 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-safari.png index 6b547720821..8aa0f4e4211 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1300-chrome.png index 4c9e99a6345..15da6ca6d11 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1760-chrome.png index ed578b050f1..95112ce680e 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-320-chrome.png index de9a800d824..fa84a0c2104 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-480-chrome.png index 8276593b5d3..27149c033a9 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-760-chrome.png index 3d6311e53a3..0dc43eb2de8 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-dark-chrome.png index fbe252d3744..7ee143d3b55 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-light-chrome.png index b1bd8f46858..30983250767 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/text-field-wrapper-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-dark-chrome.png index d6db494761f..4d60b15efea 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-light-chrome.png index d1f282830af..d101dbbf95b 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-high-contrast-scheme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-rtl-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-rtl-mode-chrome.png index 638a2c1a410..952687c5e96 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-rtl-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-rtl-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-scale-mode-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-scale-mode-chrome.png index 69f06a291ca..1186d748194 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-scale-mode-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-scale-mode-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-chrome.png index 6ea63d5be81..ad5bfb2d3a8 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-safari.png index b44a876484f..340d12bb0fc 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-dark-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-chrome.png index d387b55623c..5370dfc96eb 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-safari.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-safari.png index 24fa905cab8..1feef434b77 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-safari.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1000-theme-light-safari.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1300-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1300-chrome.png index f3de0b0effd..7e9fcf16bcb 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1300-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1300-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1760-chrome.png index 355932dfcb1..15b8aa3b293 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-1760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-320-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-320-chrome.png index 33b1e58c96a..59578cec4ec 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-320-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-320-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-480-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-480-chrome.png index 2d33766c74a..80a842a0709 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-480-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-480-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-760-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-760-chrome.png index 54073dd397d..ca75ebff465 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-760-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-760-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-dark-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-dark-chrome.png index 00271a3ea71..c706e397214 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-dark-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-dark-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-light-chrome.png b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-light-chrome.png index 081423a8409..327e0b69742 100644 Binary files a/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-light-chrome.png and b/packages/components-js/tests/vrt/playwright/specs/__screenshots__/textarea-wrapper-print-theme-light-chrome.png differ diff --git a/packages/components-js/tests/vrt/playwright/specs/common/components.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/common/components.vrt.ts index 511421d7377..978a3e700f0 100644 --- a/packages/components-js/tests/vrt/playwright/specs/common/components.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/common/components.vrt.ts @@ -1,12 +1,5 @@ import { expect, test } from '@playwright/test'; -import { - baseSchemes, - baseThemes, - baseViewportWidth, - baseViewportWidths, - thresholdConfig, - setupScenario, -} from '../../helpers'; +import { baseSchemes, baseThemes, baseViewportWidth, baseViewportWidths, setupScenario } from '../../helpers'; import { TAG_NAMES, type TagName } from '@porsche-design-system/shared'; import { getComponentMeta } from '@porsche-design-system/component-meta'; import { pdfToPng } from 'pdf-to-png-converter'; @@ -19,35 +12,15 @@ const components = (TAG_NAMES as unknown as TagName[]) .map((tagName) => { return tagName.substring(2); }) - .filter((tagName) => { - // TODO: how does this work? why slice it on every iteration? - const argv = process.argv.slice(5); - return !argv.length || argv.includes(tagName); - }); +// Use for local testing +// .filter((tagName) => { +// // TODO: how does this work? why slice it on every iteration? +// const argv = process.argv.slice(5); +// return !argv.length || argv.includes(tagName); +// }); const isComponentThemeable = (component: string): boolean => getComponentMeta(`p-${component}` as TagName).isThemeable; -// These components show slight pixel variations, particularly in border styles, frosted glass effects and shadows. -// So, we're using a different threshold in our screenshot comparisons for them. -const flakyCommonComponents = [ - 'tag', - 'tabs', - 'tabs-bar', - 'table', - 'stepper-horizontal', - 'select-wrapper', - 'scroller', - 'multi-select', - 'modal', - 'link-tile', - 'link-tile-model-signature', - 'link-social', - 'button-tile', - 'button', -]; - -const isComponentFlaky = (component: string): boolean => flakyCommonComponents.includes(component); - test(`should have certain amount of components`, () => { expect(components.length).toBe(51); }); @@ -68,10 +41,7 @@ components.forEach((component) => { await setupScenario(page, `/${component}`, baseViewportWidth, { forceComponentTheme: isComponentThemeable(component) ? theme : undefined, }); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-theme-${theme}.png`, - isComponentFlaky(component) ? thresholdConfig : undefined - ); + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${baseViewportWidth}-theme-${theme}.png`); }); }); }); @@ -84,10 +54,7 @@ components.forEach((component) => { baseViewportWidths.forEach((viewportWidth) => { test(`should have no visual regression for viewport ${viewportWidth}`, async ({ page }) => { await setupScenario(page, `/${component}`, viewportWidth); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${viewportWidth}.png`, - isComponentFlaky(component) ? thresholdConfig : undefined - ); + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${viewportWidth}.png`); }); }); @@ -106,10 +73,7 @@ components.forEach((component) => { forceComponentTheme: 'auto', prefersColorScheme: scheme, }); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-theme-${scheme}.png`, - isComponentFlaky(component) ? thresholdConfig : undefined - ); // fixture is aliased since result has to be equal + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${baseViewportWidth}-theme-${scheme}.png`); // fixture is aliased since result has to be equal }); // high contrast mode @@ -121,22 +85,17 @@ components.forEach((component) => { prefersColorScheme: scheme, }); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-high-contrast-scheme-${scheme}.png`, - isComponentFlaky(component) ? thresholdConfig : undefined + `${component}-${baseViewportWidth}-high-contrast-scheme-${scheme}.png` ); }); }); // 200% font scaling test(`should have no visual regression for viewport ${baseViewportWidth} in scale mode`, async ({ page }) => { - test.skip(component === 'select-wrapper', 'select-wrapper is flaky'); await setupScenario(page, `/${component}`, baseViewportWidth, { scalePageFontSize: true, }); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-scale-mode.png`, - isComponentFlaky(component) ? thresholdConfig : undefined - ); + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${baseViewportWidth}-scale-mode.png`); }); // rtl mode @@ -146,22 +105,16 @@ components.forEach((component) => { await setupScenario(page, `/${component}`, baseViewportWidth, { forceDirMode: 'rtl', }); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-rtl-mode.png`, - isComponentFlaky(component) ? thresholdConfig : undefined - ); + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${baseViewportWidth}-rtl-mode.png`); }); // print view baseThemes.forEach((theme) => { test(`should have no visual regression for printed pdf with theme ${theme}`, async ({ page }) => { - test.skip( - component === 'toast' || component === 'stepper-horizontal', - 'Toast and stepper-horizontal are flaky' - ); + const flakyPrintComponents = ['scroller', 'stepper-horizontal', 'tabs', 'tabs-bar', 'toast', 'flyout']; + test.skip(flakyPrintComponents.includes(component), `${component} is flaky`); await setupScenario(page, `/${component}`, baseViewportWidth, { - // emulateMediaPrint: true, // no need to emulate when we actually print forceComponentTheme: isComponentThemeable(component) ? theme : undefined, }); @@ -187,7 +140,7 @@ components.forEach((component) => { // so for now we convert the pdf to png and compare it via toMatchSnapshot() const [img] = await pdfToPng(pdfBuffer); - expect(img.content).toMatchSnapshot({ name: `${component}-print-theme-${theme}.png` }); + expect(img.content).toMatchSnapshot(`${component}-print-theme-${theme}.png`); }); }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/common/overview.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/common/overview.vrt.ts index 3570cbc6b6e..c88a73a62cd 100644 --- a/packages/components-js/tests/vrt/playwright/specs/common/overview.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/common/overview.vrt.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { setupScenario, thresholdConfig } from '../../helpers'; +import { setupScenario } from '../../helpers'; // executed in Chrome only test.describe('overview', async () => { @@ -9,7 +9,7 @@ test.describe('overview', async () => { const viewportWidth = 1920; await setupScenario(page, `/overview`, viewportWidth); await page.mouse.click(0, 0); - await expect(page.locator('#app')).toHaveScreenshot(`overview-${viewportWidth}.png`, thresholdConfig); + await expect(page.locator('#app')).toHaveScreenshot(`overview-${viewportWidth}.png`); }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/custom/form-fields.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/custom/form-fields.vrt.ts index 60c0e3123b8..2468c4507a7 100644 --- a/packages/components-js/tests/vrt/playwright/specs/custom/form-fields.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/custom/form-fields.vrt.ts @@ -1,7 +1,6 @@ import { expect, type Page, test } from '@playwright/test'; import { baseThemes, - baseViewportWidth, getPlaygroundPseudoStatesMarkup, setContentWithDesignSystem, forceFocusHoverState, @@ -13,6 +12,7 @@ import { type Theme } from '@porsche-design-system/utilities-v2'; import { type TagName } from '@porsche-design-system/shared'; const component = 'form-fields'; +const viewportWidth = 1920; const scenario = async (page: Page, theme: Theme): Promise => { const head = ` @@ -81,7 +81,7 @@ const scenario = async (page: Page, theme: Theme): Promise => { await forceHoverState(page, '.hover input'); await forceHoverState(page, '.hover select'); await forceHoverState(page, '.hover textarea'); - await forceHoverState(page, '.hover p-multi-select >>> .input-container'); + await forceHoverState(page, '.hover p-multi-select >>> input'); await forceHoverState(page, `.hover p-pin-code >>> #${valueOfForAttribute}`); await forceFocusState(page, '.focus input'); await forceFocusState(page, '.focus select'); @@ -102,9 +102,8 @@ test.describe(component, async () => { baseThemes.forEach((theme) => { test(`should have no visual regression for :hover + :focus-visible with theme ${theme}`, async ({ page }) => { await scenario(page, theme); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${theme}.png` - ); + await page.setViewportSize({ width: viewportWidth, height: 600 }); + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${viewportWidth}-states-theme-${theme}.png`); }); }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/banner.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/banner.vrt.ts index bd5321de1db..320ca2474d6 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/banner.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/banner.vrt.ts @@ -9,7 +9,6 @@ import { getPlaygroundPseudoStatesMarkup, type PrefersColorScheme, setContentWithDesignSystem, - thresholdConfig, } from '../../helpers'; import { Theme } from '@porsche-design-system/utilities-v2'; @@ -56,8 +55,7 @@ test.describe(component, async () => { test(`should have no visual regression for :hover + :focus-visible with theme ${theme}`, async ({ page }) => { await scenario(page, theme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${theme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${theme}.png` ); }); }); @@ -68,8 +66,7 @@ test.describe(component, async () => { }) => { await scenario(page, 'auto', scheme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${scheme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${scheme}.png` ); // fixture is aliased since result has to be equal }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/checkbox-wrapper.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/checkbox-wrapper.vrt.ts index 93e8c2f76ac..c4fd0fb8d2a 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/checkbox-wrapper.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/checkbox-wrapper.vrt.ts @@ -83,13 +83,13 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): }); await forceHoverState(page, '.hover p-checkbox-wrapper:not(.force-label) input[type="checkbox"]'); - await forceHoverState(page, '.hover p-checkbox-wrapper.force-label >>> span'); + await forceHoverState(page, '.hover p-checkbox-wrapper.force-label >>> label'); await forceHoverState(page, '.hover p-checkbox-wrapper span a'); await forceFocusState(page, '.focus p-checkbox-wrapper input[type="checkbox"]'); await forceFocusState(page, '.focus p-checkbox-wrapper span a'); await forceFocusHoverState(page, '.focus-hover p-checkbox-wrapper:not(.force-label) input[type="checkbox"]'); await forceFocusState(page, '.focus-hover p-checkbox-wrapper.force-label input[type="checkbox"]'); - await forceHoverState(page, '.focus-hover p-checkbox-wrapper.force-label >>> span'); + await forceHoverState(page, '.focus-hover p-checkbox-wrapper.force-label >>> label'); await forceFocusHoverState(page, '.focus-hover p-checkbox-wrapper span a'); }; diff --git a/packages/components-js/tests/vrt/playwright/specs/states/link-tile-model-signature.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/link-tile-model-signature.vrt.ts index 49c109187eb..c0e39f25747 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/link-tile-model-signature.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/link-tile-model-signature.vrt.ts @@ -7,7 +7,6 @@ import { getPlaygroundPseudoStatesMarkup, type PrefersColorScheme, setContentWithDesignSystem, - thresholdConfig, } from '../../helpers'; import { type Theme } from '@porsche-design-system/utilities-v2'; @@ -52,9 +51,6 @@ test.describe(component, async () => { test(`should have no visual regression for :hover + :focus-visible with theme light`, async ({ page }) => { await scenario(page, undefined); - await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-light.png`, - thresholdConfig - ); + await expect(page.locator('#app')).toHaveScreenshot(`${component}-${baseViewportWidth}-states-theme-light.png`); }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/multi-select.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/multi-select.vrt.ts index 4fc505f7617..26239b72cd0 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/multi-select.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/multi-select.vrt.ts @@ -123,7 +123,7 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): selects.forEach((select: any) => (select.value = ['a'])) ); - await forceHoverState(page, '.hover p-multi-select >>> .input-container'); + await forceHoverState(page, '.hover p-multi-select >>> input'); await forceHoverState(page, '.hover p-multi-select span a'); await forceFocusState(page, '.focus p-multi-select span a'); await forceFocusState(page, '.focus p-multi-select >>> input'); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/pin-code.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/pin-code.vrt.ts index d8d1c511094..8a9a2efbd0c 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/pin-code.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/pin-code.vrt.ts @@ -61,7 +61,7 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): }); await forceHoverState(page, '.hover p-pin-code:not(.force-label) >>> input'); - await forceHoverState(page, '.hover p-pin-code.force-label >>> span'); + await forceHoverState(page, '.hover p-pin-code.force-label >>> label'); await forceHoverState( page, `.hover p-pin-code.force-label >>> #${await getValueOfForAttribute(page, 'p-pin-code >>> label')}` @@ -71,7 +71,7 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): await forceFocusState(page, '.focus p-pin-code span a'); await forceFocusHoverState(page, '.focus-hover p-pin-code:not(.force-label) >>> input'); await forceFocusState(page, '.focus-hover p-pin-code.force-label >>> input'); - await forceHoverState(page, '.focus-hover p-pin-code.force-label >>> span'); + await forceHoverState(page, '.focus-hover p-pin-code.force-label >>> label'); await forceFocusHoverState(page, '.focus-hover p-pin-code span a'); }; diff --git a/packages/components-js/tests/vrt/playwright/specs/states/radio-button-wrapper.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/radio-button-wrapper.vrt.ts index 2809ead3caf..8b106b1f449 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/radio-button-wrapper.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/radio-button-wrapper.vrt.ts @@ -83,13 +83,13 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): }); await forceHoverState(page, '.hover p-radio-button-wrapper:not(.force-label) input[type="radio"]'); - await forceHoverState(page, '.hover p-radio-button-wrapper.force-label >>> span'); + await forceHoverState(page, '.hover p-radio-button-wrapper.force-label >>> label'); await forceHoverState(page, '.hover p-radio-button-wrapper span a'); await forceFocusState(page, '.focus p-radio-button-wrapper input[type="radio"]'); await forceFocusState(page, '.focus p-radio-button-wrapper span a'); await forceFocusHoverState(page, '.focus-hover p-radio-button-wrapper:not(.force-label) input[type="radio"]'); await forceFocusState(page, '.focus-hover p-radio-button-wrapper.force-label input[type="radio"]'); - await forceHoverState(page, '.focus-hover p-radio-button-wrapper.force-label >>> span'); + await forceHoverState(page, '.focus-hover p-radio-button-wrapper.force-label >>> label'); await forceFocusHoverState(page, '.focus-hover p-radio-button-wrapper span a'); }; diff --git a/packages/components-js/tests/vrt/playwright/specs/states/scroller.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/scroller.vrt.ts index 793b2e4b258..e76f62ff03c 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/scroller.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/scroller.vrt.ts @@ -8,7 +8,6 @@ import { getPlaygroundPseudoStatesMarkup, type PrefersColorScheme, setContentWithDesignSystem, - thresholdConfig, } from '../../helpers'; import { type Theme } from '@porsche-design-system/utilities-v2'; @@ -47,8 +46,7 @@ test.describe(component, async () => { test(`should have no visual regression for :hover + :focus-visible with theme ${theme}`, async ({ page }) => { await scenario(page, theme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${theme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${theme}.png` ); }); }); @@ -59,8 +57,7 @@ test.describe(component, async () => { }) => { await scenario(page, 'auto', scheme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${scheme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${scheme}.png` ); // fixture is aliased since result has to be equal }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/switch.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/switch.vrt.ts index 4598d9e4691..9f9b2a08175 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/switch.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/switch.vrt.ts @@ -9,7 +9,6 @@ import { getPlaygroundPseudoStatesMarkup, type PrefersColorScheme, setContentWithDesignSystem, - thresholdConfig, } from '../../helpers'; import { type Theme } from '@porsche-design-system/utilities-v2'; @@ -50,8 +49,7 @@ test.describe(component, async () => { test(`should have no visual regression for :hover + :focus-visible with theme ${theme}`, async ({ page }) => { await scenario(page, theme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${theme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${theme}.png` ); }); }); @@ -62,8 +60,7 @@ test.describe(component, async () => { }) => { await scenario(page, 'auto', scheme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${scheme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${scheme}.png` ); // fixture is aliased since result has to be equal }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/table.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/table.vrt.ts index b0e5e3e5017..68dbcf2681e 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/table.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/table.vrt.ts @@ -10,7 +10,6 @@ import { type PrefersColorScheme, setContentWithDesignSystem, setSortToAllTableHeadCell, - thresholdConfig, } from '../../helpers'; import { type Theme } from '@porsche-design-system/utilities-v2'; @@ -70,8 +69,7 @@ test.describe(component, async () => { test(`should have no visual regression for :hover + :focus-visible with theme ${theme}`, async ({ page }) => { await scenario(page, theme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${theme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${theme}.png` ); }); }); @@ -82,8 +80,7 @@ test.describe(component, async () => { }) => { await scenario(page, 'auto', scheme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${scheme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${scheme}.png` ); // fixture is aliased since result has to be equal }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/tag.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/tag.vrt.ts index 9400e821b50..c2b6cb6ba62 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/tag.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/tag.vrt.ts @@ -3,7 +3,6 @@ import { baseSchemes, baseThemes, baseViewportWidth, - thresholdConfig, forceFocusState, forceHoverState, getPlaygroundPseudoStatesMarkup, @@ -50,8 +49,7 @@ test.describe(component, async () => { test(`should have no visual regression for :hover + :focus-visible with theme ${theme}`, async ({ page }) => { await scenario(page, theme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${theme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${theme}.png` ); }); }); @@ -62,8 +60,7 @@ test.describe(component, async () => { }) => { await scenario(page, 'auto', scheme); await expect(page.locator('#app')).toHaveScreenshot( - `${component}-${baseViewportWidth}-states-theme-${scheme}.png`, - thresholdConfig + `${component}-${baseViewportWidth}-states-theme-${scheme}.png` ); // fixture is aliased since result has to be equal }); }); diff --git a/packages/components-js/tests/vrt/playwright/specs/states/text-field-wrapper.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/text-field-wrapper.vrt.ts index f4256537bc8..c597fb24873 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/text-field-wrapper.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/text-field-wrapper.vrt.ts @@ -152,9 +152,9 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): await Promise.all( textFieldWrappers.map( async (item) => - ( - await item.evaluateHandle((el) => el.shadowRoot.querySelector('p-button-pure')) - ).evaluate((el: HTMLElement) => el.click()) // js element.click() instead of puppeteer ElementHandle.click() to workaround element off screen issue + (await item.evaluateHandle((el) => el.shadowRoot.querySelector('p-button-pure'))).evaluate((el: HTMLElement) => + el.click() + ) // js element.click() instead of puppeteer ElementHandle.click() to workaround element off screen issue ) ); @@ -162,7 +162,7 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): await page.mouse.click(0, 0); await forceHoverState(page, '.hover p-text-field-wrapper:not(.force-label) input'); - await forceHoverState(page, '.hover p-text-field-wrapper.force-label >>> span'); + await forceHoverState(page, '.hover p-text-field-wrapper.force-label >>> label'); await forceHoverState(page, '.hover p-text-field-wrapper a'); await forceHoverState(page, '.hover p-text-field-wrapper >>> p-button-pure >>> button'); await forceFocusState(page, '.focus p-text-field-wrapper input'); @@ -170,7 +170,7 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): await forceFocusState(page, '.focus p-text-field-wrapper >>> p-button-pure >>> button'); await forceFocusHoverState(page, '.focus-hover p-text-field-wrapper:not(.force-label) input'); await forceFocusState(page, '.focus-hover p-text-field-wrapper.force-label input'); - await forceHoverState(page, '.focus-hover p-text-field-wrapper.force-label >>> span'); + await forceHoverState(page, '.focus-hover p-text-field-wrapper.force-label >>> label'); await forceFocusHoverState(page, '.focus-hover p-text-field-wrapper a'); await forceFocusHoverState(page, '.focus-hover p-text-field-wrapper >>> p-button-pure >>> button'); }; diff --git a/packages/components-js/tests/vrt/playwright/specs/states/textarea-wrapper.vrt.ts b/packages/components-js/tests/vrt/playwright/specs/states/textarea-wrapper.vrt.ts index 4da0e36a250..af695fc99c0 100644 --- a/packages/components-js/tests/vrt/playwright/specs/states/textarea-wrapper.vrt.ts +++ b/packages/components-js/tests/vrt/playwright/specs/states/textarea-wrapper.vrt.ts @@ -116,13 +116,13 @@ const scenario = async (page: Page, theme: Theme, scheme?: PrefersColorScheme): }); await forceHoverState(page, '.hover p-textarea-wrapper:not(.force-label) textarea'); - await forceHoverState(page, '.hover p-textarea-wrapper.force-label >>> span'); + await forceHoverState(page, '.hover p-textarea-wrapper.force-label >>> label'); await forceHoverState(page, '.hover p-textarea-wrapper a'); await forceFocusState(page, '.focus p-textarea-wrapper textarea'); await forceFocusState(page, '.focus p-textarea-wrapper a'); await forceFocusHoverState(page, '.focus-hover p-textarea-wrapper:not(.force-label) textarea'); await forceFocusState(page, '.focus-hover p-textarea-wrapper.force-label textarea'); - await forceHoverState(page, '.focus-hover p-textarea-wrapper.force-label >>> span'); + await forceHoverState(page, '.focus-hover p-textarea-wrapper.force-label >>> label'); await forceFocusHoverState(page, '.focus-hover p-textarea-wrapper a'); }; diff --git a/packages/components-react/package.json b/packages/components-react/package.json index a2a05f1bf3f..922cfa0dcd0 100644 --- a/packages/components-react/package.json +++ b/packages/components-react/package.json @@ -28,7 +28,7 @@ "clean:build": "rm -rf ./dist && yarn --cwd projects/nextjs clean:build && yarn --cwd projects/remix clean:build && yarn --cwd projects/uxpin-wrapper clean:build" }, "dependencies": { - "@porsche-design-system/components-react": "3.8.0", + "@porsche-design-system/components-react": "3.9.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-imask": "^7.1.3", diff --git a/packages/components-react/projects/nextjs/app/layout.tsx b/packages/components-react/projects/nextjs/app/layout.tsx index bfa685a854c..f10fbc51c89 100644 --- a/packages/components-react/projects/nextjs/app/layout.tsx +++ b/packages/components-react/projects/nextjs/app/layout.tsx @@ -1,6 +1,6 @@ import NextScript from 'next/script'; import type { PropsWithChildren } from 'react'; -import { FooterPartials, HeaderPartials, Select } from '../components'; +import { FooterPartials, HeaderPartials } from '../components'; import { Providers } from './providers'; export default function RootLayout({ children }: PropsWithChildren<{}>): JSX.Element { @@ -17,7 +17,6 @@ export default function RootLayout({ children }: PropsWithChildren<{}>): JSX.Ele - { - const { value } = e.target; - router.push(value); - }} - > - - {routes.map((route) => ( -
-
@@ -188,7 +200,7 @@ exports[`manual test cases should pass internal props correctly to p-grid-item 2 shadowrootmode="open" > @@ -234,7 +246,7 @@ exports[`manual test cases should pass internal props correctly to p-link-tile-m shadowrootmode="open" >
+
- -
- + +
+ +
+
@@ -1008,7 +1041,7 @@ exports[`manual test cases should pass internal props correctly to p-segmented-c shadowrootmode="open" > + + Toggle password visibility + +
- - +
@@ -1951,7 +1992,7 @@ exports[`manual test cases should pass internal props correctly to p-text-list-i shadowrootmode="open" > @@ -1972,10 +2013,13 @@ exports[`should render dsr component for PAccordion 1`] = ` > @@ -2878,7 +2926,7 @@ exports[`should render dsr component for PCarousel 1`] = ` > - +
+
@@ -3403,7 +3474,7 @@ exports[`should render dsr component for PFieldsetWrapper 1`] = ` >
@@ -3445,8 +3516,8 @@ exports[`should render dsr component for PFlex 1`] = ` >
+
- Some child @@ -5758,7 +5869,7 @@ span { display: flex; justify-content: center; align-items: center; - transition: color var(--p-transition-duration, .24s) ease,border-color var(--p-transition-duration, .24s) ease,background-color var(--p-transition-duration, .24s) ease; + transition: background-color var(--p-transition-duration, 0.25s) cubic-bezier(0.25,0.1,0.25,1), border-color var(--p-transition-duration, 0.25s) cubic-bezier(0.25,0.1,0.25,1), color var(--p-transition-duration, 0.25s) cubic-bezier(0.25,0.1,0.25,1); position: relative; width: clamp(36px, calc(calc(6px + 2.125ex) + 10vw - 20px), 40px); height: clamp(36px, calc(calc(6px + 2.125ex) + 10vw - 20px), 40px); @@ -5950,14 +6061,13 @@ exports[`should render dsr component for PPinCode 1`] = ` > -
+ +``` + +##### Text List + +- Props `listType` and `orderType` are deprecated, use `type` instead. + +```diff +- ++ + +- ++ + +- ++ +``` + +#### Added + +- `Text`, `Icon`, `Button Pure` and `Link Pure` support value `xx-small` for prop `size` +- `Display` supports value `small` for prop `size` +- Partials: `getInitialStyles` supports multi prefix, e.g. + `getInitialStyles({ prefix: ['', 'some-prefix', 'another-prefix'] });` +- Styles: `displaySmallStyle` and `$pds-display-small` +- Styles: `textXXSmallStyle` and `$pds-text-xx-small` +- Styles: `fontSizeDisplaySmall` and `$pds-font-size-display-small` +- Styles: `fontSizeTextXXSmall` and `$pds-font-size-text-xx-small` +- Styles: `getHoverStyle` and `pds-hover()` +- `Banner` has `heading` and `description` prop as well as `slot="heading"` and deprecated `slot="title"` +- Custom events have consistent names across components and deprecated old event names + - `Accordion` emits `change` and deprecated `accordionChange` event + - `Carousel` emits `change` and deprecated `carouselChange` event + - `Modal` emits `dismiss` and deprecated `close` event + - `Pagination` emits `change` and deprecated `pageChange` event + - `Segmented Control` emits `change` and deprecated `segmentedControlChange` event + - `Stepper Horizontal` emits `change` and deprecated `stepChange` event + - `Switch` emits `change` and deprecated `switchChange` event + - `Table` emits `change` and deprecated `sortingChange` event + - `Tabs` emits `change` and deprecated `tabChange` event + - `Tabs Bar` emits `change` and deprecated `tabChange` event +- Props have consistent names across components and deprecated old props + - `Carousel` got `pagination` prop and deprecated `disablePagination` prop + - `Divider` got `direction` prop and deprecated `orientation` prop + - `Modal` got `dismissButton` prop and deprecated `disableCloseButton` prop + - `Pagination` got `intl` prop and deprecated `allyLabelNext`, `allyLabelPage`, `allyLabelPrev` and `allyLabel` props + - `Scroller` got `gradientColor` prop and deprecated `gradientColorScheme` prop + - `Scroller` got `alignScrollIndicator` prop and deprecated `scrollIndicatorPosition` prop + - `Tabs` got `gradientColor` prop and deprecated `gradientColorScheme` prop + - `Tabs Bar` got `gradientColor` prop and deprecated `gradientColorScheme` prop + - `Text Field Wrapper` got `showCounter` prop and deprecated `showCharacterCount` prop + - `Textarea Wrapper` got `showCounter` prop and deprecated `showCharacterCount` prop + - `Text List` got `type` prop and deprecated `listType` and `orderType` prop +- Props have consistent values across components and deprecated old values + - `Icon` prop `color` got value `state-disabled` and removed `disabled` value + - `Link Tile` prop `weight` got value `semi-bold` and deprecated `semibold` value + - `Tabs Bar` and `Tabs` prop `weight` got value `semi-bold` and deprecated `semibold` value + - `Tag` prop `color` got values `notification-info-soft`, `notification-warning-soft`, `notification-success-soft`, + `notification-error-soft` and deprecated `notification-warning`, `notification-success`, `notification-error` values + +#### Changed + +- `Display` uses font-weight regular and font-style normal +- Partials: `getInitialStyles` matches new design language +- Partials: All component related, slotted Light DOM styles have been moved to `getInitialStyles` +- Styles: `getFocusStyle` and `pds-focus()` doesn't need `theme` parameter anymore +- Styles: `breakpoint{Base|XS|S|M|L|XL|XXL}` and `$pds-breakpoint-{base|xs|s|m|l|xl|xxl}` are provided as number without + unit (px) +- `Link Tile` matches new design language +- Typings for all component props start with the component name, e.g. `SwitchAlignLabel`, `TabsBarGradientColor` or + `LinkPureIcon` +- `Icon` prop `color` value `disabled` is renamed to `state-disabled` +- `Tag` prop `color` value `notification-info` is renamed to `notification-info-soft` + +#### Fixed + +- `Text Field Wrapper` calendar and time indicator icons respect color definition in dark theme +- `Text Field Wrapper` has correct height when type date or time is used +- Partials: Typings of return value with and without options parameter +- `Modal` scrolling behavior on mouse drag + +#### Removed + +- `Heading`: value `xxx-large` for prop `size` +- Styles: `headingXXXLargeStyle` and `$pds-heading-xxx-large` +- Styles: `fontSizeHeadingXXLarge` and `$pds-font-size-heading-xx-large` + +### [3.0.0-alpha.2] - 2023-02-27 + +#### 🤖 Property deprecations 🤖 + +##### Carousel: + +- Prop `wrap-content` is deprecated. + +```diff +- ++ +``` + +##### Divider: + +- Prop values `neutral-contrast-low | neutral-contrast-medium | neutral-contrast-high` of `color` prop are deprecated. + +```diff +- ++ + +- ++ + +- ++ +``` + +#### Changed + +- `Divider`, `Button Group`, `Carousel` and `Text List` match new design language +- Background color of `Scroller`'s `prev` and `next` buttons in dark theme +- Partials: Removed deprecated `withoutTags` option for all partials, please use `format: 'jsx'` instead +- `Content Wrapper` default value of prop `width` has changed from `basic` to `extended` + +#### Added + +- `Model Signature` +- Props `align-header` and `width` for `Carousel` +- Vue: plugin functions `createPorscheDesignSystem` and `usePorscheDesignSystemPlugin` + +#### Fixed + +- `Radio Button Wrapper` keyboard arrow navigation +- `Button Pure` and `Link Pure` lagging active state background when scrolling on iOS + +### [3.0.0-alpha.1] - 2023-02-16 + +#### Added + +- Porsche Next font supports Vietnamese charset +- Prop `color` of `Icon` supports `disabled` +- React: `patchRemixRunProcessBrowserGlobalIdentifier` binary to support SSR components with Remix + +#### Changed + +- `Stepper Horizontal` matches new design language +- Styles: Optimize design tokens "spacing", "typography" and "theme" provided by styles sub-package + `@porsche-design-system/components-{js|angular|react|vue}/styles` +- Styles: Use calc() instead of max() to calculate padding for `gridStyle` (JS) and `pds-grid()` (SCSS) +- Styles: `gridStyle` (JS) and `pds-grid()` (SCSS) uses optimized grid gap + +### [3.0.0-alpha.0] - 2023-02-08 + +#### Note to the new `v3` major release of the Porsche Design System + +With the new **Porsche Design Language** comes a lot of changes regarding layout and design principles. To keep +refactoring efforts as low as possible when upgrading from `v2` to `v3`, **breaking changes** were avoided as far as +possible. Nevertheless, there are a few breaking changes and some more deprecations which should receive attention. + +#### 👹 Breaking Changes 👹 + +##### Button: + +- Removed deprecated prop `tabbable`. + +```diff +- Some label ++ Some label +``` + +- Default value of prop `icon` has changed from `arrow-head-right` to `none`. Therefore, the `icon` property **must** be + set if the component has the `hide-label` property. + +```diff +- Some label ++ Some label + +- Some label ++ Some label +``` + +##### Button Pure: + +- Removed `subline` slot (visually not intended anymore). + +```diff + + Some label +-

Some Subline

+
+``` + +- Removed deprecated prop `tabbable`. + +```diff +- Some label ++ Some label +``` + +##### Icon: + +- Value `inherit` for prop `color` works slightly different to the previous major version. A CSS filter is required to + apply custom coloring to take advantage of using an SVG embedded in an `` for better SSR support and loading + performance in general. + +```diff +- ++ +``` + +- Camel case syntax for `name` prop isn't supported, please use param case syntax instead (TypeScript typings have been + updated too). + +```diff +- ++ +``` + +##### Link: + +- Default value of prop `icon` has changed from `arrow-head-right` to `none`. Therefore, the `icon` property **must** be + set if the component has the `hide-label` property. + +```diff +- Some label ++ Some label + +- Some label ++ Some label +``` + +##### Link Pure: + +- Removed `subline` slot (visually not intended anymore). + +```diff + + Some label +-

Some Subline

+
+``` + +##### Marque: + +- Removed `variant` property. + +```diff +- ++ +// or even better, replace component by wordmark ++ +``` + +##### Switch: + +- Removed deprecated prop `tabbable`. + +```diff +- Some label ++ Some label +``` + +##### Partials: + +- `getIconLinks()` partial accepts only param-cased icon names. + +```diff +- require('@porsche-design-system/components-js/partials').getIconLinks({ icons: ['arrowRight'] }) + ++ require('@porsche-design-system/components-js/partials').getIconLinks({ icons: ['arrow-right'] }) +``` + +##### CSS global scope: + +- Changed naming of CSS global variables names. + +```diff +- --p-animation-duration__spinner +- --p-animation-duration__banner ++ --p-animation-duration +``` + +#### 🤡 Component deprecations 🤡 + +All deprecated components are refactored to match the new design language, therefor it's technically not breaking, but +we highly recommend to migrate to the mentioned alternative, since those deprecated components will be removed with next +major version. + +##### Content Wrapper: + +- Component is deprecated and will be removed with the next major release. Please use **[Porsche Grid](styles/grid)** + instead, which is based on [CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid) covering the specific + layout needs for a harmonic appearance across all digital Porsche touch-points. + +##### Flex: + +- Component is deprecated and will be removed with the next major release. In general, please use native + [CSS Flex](https://css-tricks.com/snippets/css/a-guide-to-flexbox) instead for better performance and more + standardized layout technique. + +##### Grid: + +- Component is deprecated and will be removed with the next major release. In general, please use native + [CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid) in combination with + **[Porsche Grid](styles/grid)** instead for better performance and more standardized layout technique. + +##### Headline: + +```diff +- The quick brown fox jumps over the lazy dog ++ The quick brown fox jumps over the lazy dog +``` + +##### Link Social: + +- Component is deprecated and will be removed with the next major release. Please use the **[Link](components/link)** + component instead. + +#### 🤖 Property deprecations 🤖 + +All deprecated properties are still present without any effect, therefor it's technically not breaking, but we highly +recommend to migrate and remove the deprecated props since those ones will be removed with next major version. + +##### Button Pure: + +- Prop `weight` is deprecated, only regular font weight will be applied. + +```diff +- Some label +- Some label +- Some label +- Some label ++ Some label +``` + +##### Content Wrapper (deprecated): + +- Prop `theme` and `background-color` are deprecated. + +```diff +- Some content ++ Some content +``` + +##### Grid (deprecated): + +- The `gutter` property is deprecated and has no effect anymore. Instead, a fluid gutter depending on the viewport width + is used. + +```diff +- Some content +- Some content +- Some content ++ Some content +``` + +##### Icon: + +- Prop `lazy` is deprecated. + +```diff +- ++ +``` + +##### Link Pure: + +- Prop `weight` is deprecated, only regular font weight will be applied. + +```diff +- Some label +- Some label +- Some label +- Some label ++ Some label +``` + +##### Segmented Control: + +- Prop `background-color` is deprecated. + +```diff +- + XS + S + ++ + XS + S + +``` + +#### 👾 Property value deprecations 👾 + +All deprecated values are mapped to new ones, therefor it's technically not breaking, but we highly recommend to migrate +to the new values since those ones will be removed with next major version. + +##### Banner: + +- Prop value `fluid` of `width` prop is deprecated. + +```diff +- ++ +``` + +- Prop value `neutral` of `state` prop is deprecated. + +```diff +- + Some banner title + Some banner description. You can also add inline
links to route to another page. + ++ + Some banner title + Some banner description. You can also add inline links to route to another page. + +``` + +##### Content Wrapper: + +- Prop value `fluid` of `width` prop is deprecated. + +```diff +- Some content ++ Some content +``` + +##### Icon: + +- Prop values + `brand | default | neutral-contrast-low | neutral-contrast-medium | neutral-contrast-high | notification-neutral` of + `color` prop are deprecated. + +```diff +- ++ + +- ++ + +- ++ + +- ++ + +- ++ + +- ++ +``` + +##### Inline Notification: + +- Prop value `neutral` of `state` prop is deprecated. + +```diff +- ++ +``` + +##### Tag: + +- Prop value `notification-neutral | neutral-contrast-high | background-default` of `color` prop is deprecated. + +```diff +- Color label ++ Color label + +- Color label ++ Color label + +- Color label ++ Color label +``` + +##### Tag Dismissible: + +- Prop value `background-default` of `color` prop is deprecated. + +```diff +- Color label ++ Color label +``` + +##### Text: + +- Prop value `thin | semibold` of `weight` prop is deprecated. + +```diff +- Some text ++ Some text + +- Some text ++ Some text +``` + +- Prop value + `brand | default | neutral-contrast-low | neutral-contrast-medium | neutral-contrast-high | notification-neutral` of + `color` prop is deprecated. + +```diff +- Some text ++ Some text + +- Some text ++ Some text + +- Some text ++ Some text + +- Some text ++ Some text + +- Some text ++ Some text + +- Some text ++ Some text +``` + +##### ToastManager: + +- Prop value `neutral` of `state` parameter is deprecated. + +```diff +- …addMessage({ text: `Some message`, state: 'neutral' }) ++ …addMessage({ text: `Some message`, state: 'info' }) +``` + +#### Added + +- `Display` component +- `Heading` component +- Prop `underline` for `Link Pure` +- Prop `theme` for `Checkbox Wrapper`, `Radio Button Wrapper`, `Popover`, `Tag Dismissible`, `Textarea Wrapper`, + `Text Field Wrapper` and `Fieldset Wrapper` +- Prop `size` for `Icon` supports `x-small` and `x-large` +- Prop `size` for `Accordion` `compact="true"` supports `medium` + +#### Changed + +- `Spinner`, `Icon`, `Link Pure`, `Button Pure`, `Link`, `Link Social`, `Button`, `Checkbox Wrapper`, + `Radio Button Wrapper`, `Popover`, `Modal`, `Select Wrapper`, `Tag`, `Tag Dismissible`, `Textarea Wrapper`, + `Inline Notification`, `Banner`, `Toast`, `Grid`, `Flex`, `Pagination`, `Scroller`, `Accordion`, `Text`, + `Text Field Wrapper`, `Content Wrapper`, `Segmented Control`, `Tabs`, `Tabs Bar`, `Headline` and `Fieldset Wrapper` + match new design language +- `Icon` supports + `primary | contrast-low | contrast-medium | contrast-high | notification-success | notification-warning | notification-error | notification-info | inherit` + for `color` prop +- Default value of prop `width` of `Banner` has changed from `basic` to `extended` +- Default value of prop `action-icon` of `Inline Notification` has changed from `arrow-head-right` to `arrow-right` +- Default value of prop `name` of `Icon` has changed from `arrow-head-right` to `arrow-right` +- Default value of prop `variant` of `Link` and `Button` has changed from `secondary` to `primary` + +#### Removed + +- Custom slotted CSS for mostly all components. Equivalent styles are now provided by `getInitialStyles()` partial + instead. +- `applyNormalizeStyles` option from `getInitialStyles()` partial which is applied by default now. + +### [2.20.0] - 2023-02-06 + +### [2.20.0-rc.1] - 2023-02-06 + +### [2.20.0-rc.0] - 2023-01-30 + +#### Added + +- `applyNormalizeStyles` option for `getInitialStyles()` partial which includes basic css styles for Light DOM + +### [2.19.1-rc.1] - 2023-01-18 + +#### Added + +- `jsdom-polyfill` subpackage is available at `@porsche-design-system/components-{js|angular|react|vue}/jsdom-polyfill` + and can be used to have working web components in jsdom based tests (e.g. jest) +- `testing` subpackage is available at `@porsche-design-system/components-{js|angular|react|vue}/testing` to provide + `getByRoleShadowed`, `getByLabelTextShadowed` and `getByTextShadowed` utilities which use `@testing-library/dom` + queries internally to support Shadow DOM +- Validation if `prefix` is already reserved by a different version upon initialization of the Porsche Design System + +#### Fixed + +- `componentsReady()` waits for Porsche Design System being initialized before checking components which can happen in + certain test scenarios without partials + +### [2.19.1-rc.0] - 2023-01-18 + +#### Fixed + +- Bug in `@porsche-design-system/components-react/ssr` where in some cases during SSG an error was thrown when + components render their children conditionally + +### [2.19.0] - 2022-12-22 + +### [2.19.0-rc.2] - 2022-12-22 + +### [2.19.0-rc.1] - 2022-12-22 + +#### Fixed + +- `Stepper Horizontal` calculation of scroll position when used within any parent that has a margin or padding + +### [2.19.0-rc.0] - 2022-12-21 + +#### Added + +- Vue: typed components are available via the `@porsche-design-system/components-vue` package + +#### Fixed + +- `Modal` focus cycle when pressing Shift Tab right after it was opened + +### [2.18.0] - 2022-12-15 + +### [2.18.0-rc.2] - 2022-12-14 + +#### Added + +- Validation to ensure crucial partials are used. + **Disclaimer:** The Porsche Design System will **not** inject its initial styles anymore. Please use the + `getInitialStyles()` partial to reduce flash of unstyled content (FOUC) as described here: + [getInitialStyles() documentation](https://designsystem.porsche.com/latest/partials/initial-styles) + +#### Changed + +- `line-height` calculation for all components is handled CSS only now by using `ex`-unit in combination with `calc()` + which gives the best performance, the easiest possible integration and respects UI best practices in having **larger** + `line-height` values for **small** `font-size` definitions and **smaller** `line-height` values for **larger** + `font-size` definitions. The calculated values by CSS slightly differ compared to the ones calculated by JavaScript, + which might result in minor visual changes. + +#### Fixed + +- Screen reader announcements of `Textfield` and `Textarea` in `counter` mode +- Screen reader announcements in `Select Wrapper` + +### [2.18.0-rc.1] - 2022-11-24 + +#### Added + +- `Carousel` now has a `rewind` property, better prev/next icons, a `max-width` for `heading` and `description` and + support for slotted `description` + +#### Fixed + +- `Select Wrapper` height if text is zoomed up to 200% + +### [2.18.0-rc.0] - 2022-11-17 + +#### Added + +- SSR/SSG ready components using Declarative Shadow DOM for Next JS are shipped via + `@porsche-design-system/components-react/ssr`. To use it simply change your imports. + +**Important:** make sure to apply the new `getDSRPonyfill()` partial right before your closing `` tag. More +information can be found here: +[getDSRPonyfill() documentation](https://designsystem.porsche.com/latest/partials/dsr-ponyfill) + +```diff +- import { PorscheDesignSystemProvider, PButton, ... } from '@porsche-design-system/components-react'; ++ import { PorscheDesignSystemProvider, PButton, ... } from '@porsche-design-system/components-react/ssr'; ++ import { getDSRPonyfill } from '@porsche-design-system/components-react/partials'; +``` + +#### Changed + +- Improve height calculation for `Accordion` +- Slotted anchor support for `Link Pure` is stricter (In case slotted `` is used it must be a direct child of + `Link Pure`) +- `getFontLinks()` partial now has `{ weights: ['regular', 'semi-bold'] }` for a default + +### [2.17.0] - 2022-10-31 + +### [2.17.0-rc.0] - 2022-10-31 + +#### Added + +- `Link Tile` + +#### Fixed + +- `Scroller` bug where scrollable content was not fully hidden by the gradient, when zoomed into the page. + +#### Changed + +- Removed `!important` keyword from css property `display` of `Link Pure` and `Button Pure` + +### [2.16.3] - 2022-10-21 + +### [2.16.3-rc.0] - 2022-10-21 + +#### Fixed + +- `Button Pure` and `Link Pure` error when using `size="inherit"` and `icon="none"` + +#### Changed + +- Replaced all internal usage of `Text` and `Headline` components + +### [2.16.2] - 2022-09-15 + +### [2.16.2-rc.0] - 2022-09-15 + +#### Fixed + +- Issue with `Popover` where drop-shadow is not shown correctly in Chrome >= 105 +- Issue with `Carousel` and `wrap-content="true"` where the layout was out of sync with `Content Wrapper` for + viewports >= 1760px. +- `Select Wrapper` with custom dropdown keeps attribute changes of native select options in sync if changed + programmatically + +### [2.16.1] - 2022-09-09 + +#### Fixed + +- Issue with `Options` typing import for `Carousel` + +### [2.16.0] - 2022-09-08 + +### [2.15.1-rc.1] - 2022-09-08 + +#### Added + +- `Carousel` +- `Scroller` + +#### Changed + +- `Stepper Horizontal` now has `size` property +- `Stepper Horizontal` uses improved focus behavior in case it becomes scrollable and scroll indicators are centered + correctly. +- `Tabs Bar` uses improved focus behavior in case it becomes scrollable and scroll indicators are centered correctly. + +### [2.15.1-rc.0] - 2022-08-24 + +#### Fixed + +- `Radio Button Wrapper` visual selection change bug in Safari >= 15.5 + +### [2.15.0] - 2022-08-22 + +### [2.15.0-rc.1] - 2022-08-18 + +#### Changed + +- Downgraded `@angular` to `v13` to ensure backwards compatibility of `@porsche-design-system/components-angular` + +### [2.15.0-rc.0] - 2022-08-16 + +#### Fixed + +- `Popover` visual shadow bug in Safari +- `Stepper Horizontal Item` bug where pseudo styles of the counter element were overridable + +### [2.15.0-beta.0] - 2022-08-05 + +#### Fixed + +- `Tabs` & `Tabs Bar` `size` property when using `BreakpointCustomizable` + +#### Changed + +- `Modal` uses poly fluid sizing for outer spacing +- `Banner` uses poly fluid sizing for outer spacing +- `Content Wrapper` uses poly fluid sizing for inner spacing +- `Modal` min-width is slightly updated to perfectly fit into content area of `Content Wrapper` at 320px viewport width + +#### Added + +- Validation of properties for all components +- `Text Field Wrapper` with `input type="search"` is clearable via Escape key and custom clear button across browsers +- `Text Field Wrapper` with `input type="search"` shows a "Locate me" button when `actionIcon="locate"` is set, emits + the `action` event on click and can be put into a loading state via `actionLoading="true"` + +### [2.14.0] - 2022-07-11 + +### [2.14.0-rc.1] - 2022-07-11 + +### [2.14.0-rc.0] - 2022-07-11 + +#### Added + +- `getBrowserSupportFallbackScript()` partial supporting `cdn` and `format` options as replacement for + `includeOverlay()` of `@porsche-design-system/browser-notification` npm package +- `getCookiesFallbackScript()` partial supporting `cdn` and `format` options as replacement for `includeCookieOverlay()` + of `@porsche-design-system/browser-notification` npm package + +#### Changed + +- `getMetaTagsAndIconLinks()` partial to return `theme-color` meta tags with `prefers-color-scheme: {light|dark}` media + query + +### [2.13.0] - 2022-06-23 + +### [2.13.0-rc.5] - 2022-06-23 + +#### Fixed + +- `Stepper Horizontal Item` `state` validation +- `Button` and `Link` with `theme="dark" variant="tertiary"` and `Tag Dismissible` bug on Safari < v15.5 where wrong + colors on hover were shown + +### [2.13.0-rc.4] - 2022-06-22 + +#### Added + +- `Stepper Horizontal` + +### [2.13.0-rc.3] - 2022-06-22 + +#### Added + +- `Segmented Control` + +### [2.13.0-rc.2] - 2022-06-21 + +### [2.13.0-rc.1] - 2022-06-21 + +### [2.13.0-rc.0] - 2022-06-21 + +#### Changed + +- `Button`, `Button Pure` and `Switch` apply `aria-disabled="true"` instead of `disabled` attribute to native button + internally in case `disabled` and/or `loading` property is set + +### [2.12.1] - 2022-05-25 + +### [2.12.1-rc.0] - 2022-05-25 + +#### Fixed + +- Issue with `JssStyle` typing import + +### [2.12.0] - 2022-05-19 + +#### Changed + +- npm package is prepared for public release on [npmjs.org](https://npmjs.com) + +### [2.12.0-rc.2] - 2022-05-12 + +### [2.12.0-rc.1] - 2022-05-11 + +### [2.12.0-rc.0] - 2022-05-04 + +#### Added + +- `Table Head Cell` now has a `multiline` property + +#### Changed + +- `Headline` has no `hypens` / `overflow-wrap` style by default +- Partials now throw an exception if they are executed in browser + +#### Fixed + +- Exception in `Headline`, `Select Wrapper`, `Text` and `Text List` when changing `theme` prop from `dark` to `light` +- `getInitialStyles()` partial now returns `.hydrated` styles, too + +### [2.11.0-skeletons] - 2022-04-21 + +### [2.11.0] - 2022-04-21 + +### [2.11.0-rc.0] - 2022-04-20 + +#### Added + +- `Tag` +- `Tag Dismissible` + +### [2.10.0-skeletons] - 2022-04-13 + +### [2.10.0] - 2022-04-13 + +### [2.9.3-rc.1] - 2022-04-06 + +#### Added + +- `Text Field Wrapper` now has a `showCharacterCount` property which can be used to hide the character count when a + `maxLength` attribute is set on the wrapped `input`. +- `Textarea Wrapper` now has a `showCharacterCount` property which can be used to hide the character count when a + `maxLength` attribute is set on the wrapped `textarea`. + +### [2.9.3-rc.0-skeletons] - 2022-03-29 + +### [2.9.3-rc.0] - 2022-03-28 + +#### Added + +- `Text Field Wrapper` supports `unit` property on `input type="text"` +- `Marque` optional configurable clickable/focusable area by defining padding on host element + +#### Fixed + +- `Tabs Item` improved accessibility +- Angular: circular dependency in development mode in `2.9.2-skeletons` + +### [2.9.2-skeletons] - 2022-03-24 + +#### Added + +- **[EXPERIMENTAL]** `getInitialStyles` partial now accepts a `skeletonTagNames` array of component names that will + initially have skeleton styles while the Porsche Design System is loading +- **[EXPERIMENTAL]** `Button`, `Button Pure`, `Checkbox Wrapper`, `Fieldset Wrapper`, `Link`, `Link Pure`, + `Link Social`, `Radio Button Wrapper`, `Select Wrapper`, `Text Field Wrapper`, `Textarea Wrapper` can now have initial + skeleton styles when passed as `skeletonTagNames` to the `getInitialStyles` partial + +### [2.9.2] - 2022-03-24 + +### [2.9.2-rc.1] - 2022-03-23 + +#### Fixed + +- Bug caused by Chrome where hover styles of `Link Pure` are not displayed correctly + +### [2.9.2-rc.0] - 2022-03-22 + +#### Added + +- Normalized font behavior (`hyphen`, `overflow-wrap` and `text-size-adjust`) across components + +#### Fixed + +- `Modal` scrolling and pinch to zoom on iOS +- `Modal` initial position if scrollable +- `Table Head Cell` sort icon `asc` + `desc` + +### [2.9.1] - 2022-03-10 + +### [2.9.1-rc.0] - 2022-03-09 + +#### Added + +- Styles for slotted `