diff --git a/.github/labeler.yml b/.github/labeler.yml index 545025db58..7ea70aaf7f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -6,16 +6,17 @@ # https://github.com/actions/labeler 'package: core': - - core/**/* +- changed-files: + - any-glob-to-any-file: ['core/**/*'] 'package: angular': - - packages/angular/**/* - - packages/angular-*/**/* +- changed-files: + - any-glob-to-any-file: ['packages/angular/**/*', 'packages/angular-*/**/*'] 'package: react': - - packages/react/**/* - - packages/react-*/**/* +- changed-files: + - any-glob-to-any-file: ['packages/react/**/*', 'packages/react-*/**/*'] 'package: vue': - - packages/vue/**/* - - packages/vue-*/**/* +- changed-files: + - any-glob-to-any-file: ['packages/vue/**/*', 'packages/vue-*/**/*'] diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml index 0241c7fa5b..a4e35060df 100644 --- a/.github/workflows/label.yml +++ b/.github/workflows/label.yml @@ -13,7 +13,7 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/labeler@main + - uses: actions/labeler@v5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" sync-labels: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e812f94e6..5031d391cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29) + + +### Bug Fixes + +* **alert:** date inputs render correctly in mobile safari ([#28495](https://github.com/ionic-team/ionic-framework/issues/28495)) ([b833f0e](https://github.com/ionic-team/ionic-framework/commit/b833f0e826ddd261230e2e29b70e2dc884d8cb04)), closes [#28494](https://github.com/ionic-team/ionic-framework/issues/28494) +* **datetime:** allow disabling datetime with prefer-wheel ([#28511](https://github.com/ionic-team/ionic-framework/issues/28511)) ([01130e1](https://github.com/ionic-team/ionic-framework/commit/01130e12e1d73bbf558da9d4dffd7122822ff39c)) + + + + + ## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21) diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 43aaeb2e54..fc2d3cbd3a 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29) + + +### Bug Fixes + +* **alert:** date inputs render correctly in mobile safari ([#28495](https://github.com/ionic-team/ionic-framework/issues/28495)) ([b833f0e](https://github.com/ionic-team/ionic-framework/commit/b833f0e826ddd261230e2e29b70e2dc884d8cb04)), closes [#28494](https://github.com/ionic-team/ionic-framework/issues/28494) +* **datetime:** allow disabling datetime with prefer-wheel ([#28511](https://github.com/ionic-team/ionic-framework/issues/28511)) ([01130e1](https://github.com/ionic-team/ionic-framework/commit/01130e12e1d73bbf558da9d4dffd7122822ff39c)) + + + + + ## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21) diff --git a/core/package-lock.json b/core/package-lock.json index 094268f95c..256d5876d6 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ionic/core", - "version": "7.5.6", + "version": "7.5.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ionic/core", - "version": "7.5.6", + "version": "7.5.7", "license": "MIT", "dependencies": { - "@stencil/core": "^4.7.2", + "@stencil/core": "^4.8.1", "ionicons": "^7.2.1", "tslib": "^2.1.0" }, @@ -1825,9 +1825,9 @@ } }, "node_modules/@stencil/core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.7.2.tgz", - "integrity": "sha512-sPPDYrXiTbfeUF5CCyfqysXK/yfTHC4xYR1+nHzGkS2vhRSBOLp0oPuB+xkJLKA+K2ZqDJUxpOnDxy1CLWwBXA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.1.tgz", + "integrity": "sha512-KG1H10j24rlyxIqOI4CG8/h9T7ObTv7giW2H3u1qXV4KKrLykDOpMcLzpqNXqL2Fki3s1QvHyl/oaRvi5waWVw==", "bin": { "stencil": "bin/stencil" }, @@ -12184,9 +12184,9 @@ "requires": {} }, "@stencil/core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.7.2.tgz", - "integrity": "sha512-sPPDYrXiTbfeUF5CCyfqysXK/yfTHC4xYR1+nHzGkS2vhRSBOLp0oPuB+xkJLKA+K2ZqDJUxpOnDxy1CLWwBXA==" + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.1.tgz", + "integrity": "sha512-KG1H10j24rlyxIqOI4CG8/h9T7ObTv7giW2H3u1qXV4KKrLykDOpMcLzpqNXqL2Fki3s1QvHyl/oaRvi5waWVw==" }, "@stencil/react-output-target": { "version": "0.5.3", diff --git a/core/package.json b/core/package.json index ce1b12b960..79e803f515 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@ionic/core", - "version": "7.5.6", + "version": "7.5.7", "description": "Base components for Ionic", "keywords": [ "ionic", @@ -31,7 +31,7 @@ "loader/" ], "dependencies": { - "@stencil/core": "^4.7.2", + "@stencil/core": "^4.8.1", "ionicons": "^7.2.1", "tslib": "^2.1.0" }, diff --git a/core/scripts/testing/themes/dark.css b/core/scripts/testing/themes/dark.css new file mode 100644 index 0000000000..e263803d56 --- /dev/null +++ b/core/scripts/testing/themes/dark.css @@ -0,0 +1,151 @@ +/* + * Dark Colors + * ------------------------------------------- + */ + +:root { + --ion-color-primary: #428cff; + --ion-color-primary-rgb: 66, 140, 255; + --ion-color-primary-contrast: #ffffff; + --ion-color-primary-contrast-rgb: 255, 255, 255; + --ion-color-primary-shade: #3a7be0; + --ion-color-primary-tint: #5598ff; + + --ion-color-secondary: #50c8ff; + --ion-color-secondary-rgb: 80, 200, 255; + --ion-color-secondary-contrast: #ffffff; + --ion-color-secondary-contrast-rgb: 255, 255, 255; + --ion-color-secondary-shade: #46b0e0; + --ion-color-secondary-tint: #62ceff; + + --ion-color-tertiary: #6a64ff; + --ion-color-tertiary-rgb: 106, 100, 255; + --ion-color-tertiary-contrast: #ffffff; + --ion-color-tertiary-contrast-rgb: 255, 255, 255; + --ion-color-tertiary-shade: #5d58e0; + --ion-color-tertiary-tint: #7974ff; + + --ion-color-success: #2fdf75; + --ion-color-success-rgb: 47, 223, 117; + --ion-color-success-contrast: #000000; + --ion-color-success-contrast-rgb: 0, 0, 0; + --ion-color-success-shade: #29c467; + --ion-color-success-tint: #44e283; + + --ion-color-warning: #ffd534; + --ion-color-warning-rgb: 255, 213, 52; + --ion-color-warning-contrast: #000000; + --ion-color-warning-contrast-rgb: 0, 0, 0; + --ion-color-warning-shade: #e0bb2e; + --ion-color-warning-tint: #ffd948; + + --ion-color-danger: #ff4961; + --ion-color-danger-rgb: 255, 73, 97; + --ion-color-danger-contrast: #ffffff; + --ion-color-danger-contrast-rgb: 255, 255, 255; + --ion-color-danger-shade: #e04055; + --ion-color-danger-tint: #ff5b71; + + --ion-color-dark: #f4f5f8; + --ion-color-dark-rgb: 244, 245, 248; + --ion-color-dark-contrast: #000000; + --ion-color-dark-contrast-rgb: 0, 0, 0; + --ion-color-dark-shade: #d7d8da; + --ion-color-dark-tint: #f5f6f9; + + --ion-color-medium: #989aa2; + --ion-color-medium-rgb: 152, 154, 162; + --ion-color-medium-contrast: #000000; + --ion-color-medium-contrast-rgb: 0, 0, 0; + --ion-color-medium-shade: #86888f; + --ion-color-medium-tint: #a2a4ab; + + --ion-color-light: #222428; + --ion-color-light-rgb: 34, 36, 40; + --ion-color-light-contrast: #ffffff; + --ion-color-light-contrast-rgb: 255, 255, 255; + --ion-color-light-shade: #1e2023; + --ion-color-light-tint: #383a3e; +} + +/* + * iOS Dark Theme + * ------------------------------------------- + */ + +.ios body { + --ion-background-color: #000000; + --ion-background-color-rgb: 0, 0, 0; + + --ion-text-color: #ffffff; + --ion-text-color-rgb: 255, 255, 255; + + --ion-color-step-50: #0d0d0d; + --ion-color-step-100: #1a1a1a; + --ion-color-step-150: #262626; + --ion-color-step-200: #333333; + --ion-color-step-250: #404040; + --ion-color-step-300: #4d4d4d; + --ion-color-step-350: #595959; + --ion-color-step-400: #666666; + --ion-color-step-450: #737373; + --ion-color-step-500: #808080; + --ion-color-step-550: #8c8c8c; + --ion-color-step-600: #999999; + --ion-color-step-650: #a6a6a6; + --ion-color-step-700: #b3b3b3; + --ion-color-step-750: #bfbfbf; + --ion-color-step-800: #cccccc; + --ion-color-step-850: #d9d9d9; + --ion-color-step-900: #e6e6e6; + --ion-color-step-950: #f2f2f2; + + --ion-toolbar-background: #0d0d0d; + + --ion-item-background: #000000; + + --ion-card-background: #1c1c1d; +} + +/* + * Material Design Dark Theme + * ------------------------------------------- + */ + +.md body { + --ion-background-color: #121212; + --ion-background-color-rgb: 18, 18, 18; + + --ion-text-color: #ffffff; + --ion-text-color-rgb: 255, 255, 255; + + --ion-border-color: #222222; + + --ion-color-step-50: #1e1e1e; + --ion-color-step-100: #2a2a2a; + --ion-color-step-150: #363636; + --ion-color-step-200: #414141; + --ion-color-step-250: #4d4d4d; + --ion-color-step-300: #595959; + --ion-color-step-350: #656565; + --ion-color-step-400: #717171; + --ion-color-step-450: #7d7d7d; + --ion-color-step-500: #898989; + --ion-color-step-550: #949494; + --ion-color-step-600: #a0a0a0; + --ion-color-step-650: #acacac; + --ion-color-step-700: #b8b8b8; + --ion-color-step-750: #c4c4c4; + --ion-color-step-800: #d0d0d0; + --ion-color-step-850: #dbdbdb; + --ion-color-step-900: #e7e7e7; + --ion-color-step-950: #f3f3f3; + + --ion-item-background: #1e1e1e; + + --ion-toolbar-background: #1f1f1f; + + --ion-tab-bar-background: #1f1f1f; + + --ion-card-background: #1e1e1e; +} diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 69a911e19e..dcfee8f33e 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -1162,7 +1162,7 @@ export namespace Components { */ "autocorrect": 'on' | 'off'; /** - * This Boolean attribute lets you specify that a form control should have input focus when the page loads. + * Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element. This may not be sufficient for the element to be focused on page load. See [managing focus](/docs/developing/managing-focus) for more information. */ "autofocus": boolean; /** @@ -1274,7 +1274,7 @@ export namespace Components { */ "required": boolean; /** - * Sets focus on the native `input` in `ion-input`. Use this method instead of the global `input.focus()`. Developers who wish to focus an input when a page enters should call `setFocus()` in the `ionViewDidEnter()` lifecycle method. Developers who wish to focus an input when an overlay is presented should call `setFocus` after `didPresent` has resolved. + * Sets focus on the native `input` in `ion-input`. Use this method instead of the global `input.focus()`. Developers who wish to focus an input when a page enters should call `setFocus()` in the `ionViewDidEnter()` lifecycle method. Developers who wish to focus an input when an overlay is presented should call `setFocus` after `didPresent` has resolved. See [managing focus](/docs/developing/managing-focus) for more information. */ "setFocus": () => Promise; /** @@ -2605,7 +2605,7 @@ export namespace Components { */ "searchIcon"?: string; /** - * Sets focus on the native `input` in `ion-searchbar`. Use this method instead of the global `input.focus()`. Developers who wish to focus an input when a page enters should call `setFocus()` in the `ionViewDidEnter()` lifecycle method. Developers who wish to focus an input when an overlay is presented should call `setFocus` after `didPresent` has resolved. + * Sets focus on the native `input` in `ion-searchbar`. Use this method instead of the global `input.focus()`. Developers who wish to focus an input when a page enters should call `setFocus()` in the `ionViewDidEnter()` lifecycle method. Developers who wish to focus an input when an overlay is presented should call `setFocus` after `didPresent` has resolved. See [managing focus](/docs/developing/managing-focus) for more information. */ "setFocus": () => Promise; /** @@ -2954,7 +2954,7 @@ export namespace Components { */ "autocapitalize": string; /** - * This Boolean attribute lets you specify that a form control should have input focus when the page loads. + * Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element. This may not be sufficient for the element to be focused on page load. See [managing focus](/docs/developing/managing-focus) for more information. */ "autofocus": boolean; /** @@ -3054,7 +3054,7 @@ export namespace Components { */ "rows"?: number; /** - * Sets focus on the native `textarea` in `ion-textarea`. Use this method instead of the global `textarea.focus()`. + * Sets focus on the native `textarea` in `ion-textarea`. Use this method instead of the global `textarea.focus()`. See [managing focus](/docs/developing/managing-focus) for more information. */ "setFocus": () => Promise; /** @@ -5877,7 +5877,7 @@ declare namespace LocalJSX { */ "autocorrect"?: 'on' | 'off'; /** - * This Boolean attribute lets you specify that a form control should have input focus when the page loads. + * Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element. This may not be sufficient for the element to be focused on page load. See [managing focus](/docs/developing/managing-focus) for more information. */ "autofocus"?: boolean; /** @@ -7730,7 +7730,7 @@ declare namespace LocalJSX { */ "autocapitalize"?: string; /** - * This Boolean attribute lets you specify that a form control should have input focus when the page loads. + * Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element. This may not be sufficient for the element to be focused on page load. See [managing focus](/docs/developing/managing-focus) for more information. */ "autofocus"?: boolean; /** diff --git a/core/src/components/action-sheet/action-sheet.tsx b/core/src/components/action-sheet/action-sheet.tsx index 813e38c7f9..984e24cdaa 100644 --- a/core/src/components/action-sheet/action-sheet.tsx +++ b/core/src/components/action-sheet/action-sheet.tsx @@ -337,6 +337,17 @@ export class ActionSheet implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } render() { diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index 4568e45a38..90a1c281bb 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -376,6 +376,17 @@ export class Alert implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/components/input/input.tsx b/core/src/components/input/input.tsx index 28ee6816a6..e8cc049274 100644 --- a/core/src/components/input/input.tsx +++ b/core/src/components/input/input.tsx @@ -97,7 +97,9 @@ export class Input implements ComponentInterface { @Prop() autocorrect: 'on' | 'off' = 'off'; /** - * This Boolean attribute lets you specify that a form control should have input focus when the page loads. + * Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element. + * + * This may not be sufficient for the element to be focused on page load. See [managing focus](/docs/developing/managing-focus) for more information. */ @Prop() autofocus = false; @@ -426,6 +428,8 @@ export class Input implements ComponentInterface { * * Developers who wish to focus an input when an overlay is presented * should call `setFocus` after `didPresent` has resolved. + * + * See [managing focus](/docs/developing/managing-focus) for more information. */ @Method() async setFocus() { diff --git a/core/src/components/loading/loading.tsx b/core/src/components/loading/loading.tsx index 0892b082d1..05e40669d9 100644 --- a/core/src/components/loading/loading.tsx +++ b/core/src/components/loading/loading.tsx @@ -225,6 +225,17 @@ export class Loading implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } disconnectedCallback() { diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index 3c8a091901..ef6114b18b 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -368,6 +368,17 @@ export class Modal implements ComponentInterface, OverlayInterface { raf(() => this.present()); } this.breakpointsChanged(this.breakpoints); + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/components/picker/picker.tsx b/core/src/components/picker/picker.tsx index 19d03d2f8b..4232288919 100644 --- a/core/src/components/picker/picker.tsx +++ b/core/src/components/picker/picker.tsx @@ -209,6 +209,17 @@ export class Picker implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/components/popover/popover.tsx b/core/src/components/popover/popover.tsx index 75e16ad70d..21dce20a5d 100644 --- a/core/src/components/popover/popover.tsx +++ b/core/src/components/popover/popover.tsx @@ -370,6 +370,17 @@ export class Popover implements ComponentInterface, PopoverInterface { this.dismiss(undefined, undefined, false); }); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.configureTriggerInteraction(); } /** diff --git a/core/src/components/searchbar/searchbar.tsx b/core/src/components/searchbar/searchbar.tsx index 84ae9b2acc..21fed733d2 100644 --- a/core/src/components/searchbar/searchbar.tsx +++ b/core/src/components/searchbar/searchbar.tsx @@ -257,6 +257,8 @@ export class Searchbar implements ComponentInterface { * * Developers who wish to focus an input when an overlay is presented * should call `setFocus` after `didPresent` has resolved. + * + * See [managing focus](/docs/developing/managing-focus) for more information. */ @Method() async setFocus() { diff --git a/core/src/components/textarea/textarea.tsx b/core/src/components/textarea/textarea.tsx index 1cb263fb8d..f971c8ee65 100644 --- a/core/src/components/textarea/textarea.tsx +++ b/core/src/components/textarea/textarea.tsx @@ -95,7 +95,9 @@ export class Textarea implements ComponentInterface { @Prop() autocapitalize = 'none'; /** - * This Boolean attribute lets you specify that a form control should have input focus when the page loads. + * Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element. + * + * This may not be sufficient for the element to be focused on page load. See [managing focus](/docs/developing/managing-focus) for more information. */ @Prop() autofocus = false; @@ -374,6 +376,8 @@ export class Textarea implements ComponentInterface { /** * Sets focus on the native `textarea` in `ion-textarea`. Use this method instead of the global * `textarea.focus()`. + * + * See [managing focus](/docs/developing/managing-focus) for more information. */ @Method() async setFocus() { diff --git a/core/src/components/toast/toast.tsx b/core/src/components/toast/toast.tsx index da25cf5174..fe960d3e32 100644 --- a/core/src/components/toast/toast.tsx +++ b/core/src/components/toast/toast.tsx @@ -332,6 +332,17 @@ export class Toast implements ComponentInterface, OverlayInterface { if (this.isOpen === true) { raf(() => this.present()); } + + /** + * When binding values in frameworks such as Angular + * it is possible for the value to be set after the Web Component + * initializes but before the value watcher is set up in Stencil. + * As a result, the watcher callback may not be fired. + * We work around this by manually calling the watcher + * callback when the component has loaded and the watcher + * is configured. + */ + this.triggerChanged(); } /** diff --git a/core/src/utils/test/playwright/generator.ts b/core/src/utils/test/playwright/generator.ts index e2cdd940f9..41b2abc183 100644 --- a/core/src/utils/test/playwright/generator.ts +++ b/core/src/utils/test/playwright/generator.ts @@ -1,5 +1,12 @@ export type Mode = 'ios' | 'md'; export type Direction = 'ltr' | 'rtl'; +/** + * The theme to use for the playwright test. + * + * - `light`: The fallback theme values. Theme stylesheet will not be included. + * - `dark`: The dark theme values. + */ +export type Theme = 'light' | 'dark'; export type TitleFn = (title: string) => string; export type ScreenshotFn = (fileName: string) => string; @@ -7,6 +14,7 @@ export type ScreenshotFn = (fileName: string) => string; export interface TestConfig { mode: Mode; direction: Direction; + theme: Theme; } interface TestUtilities { @@ -18,6 +26,7 @@ interface TestUtilities { interface TestConfigOption { modes?: Mode[]; directions?: Direction[]; + themes?: Theme[]; } /** @@ -27,9 +36,19 @@ interface TestConfigOption { * each test title is unique. */ const generateTitle = (title: string, config: TestConfig): string => { - const { mode, direction } = config; + const { mode, direction, theme } = config; - return `${title} - ${mode}/${direction}`; + if (theme === 'light') { + /** + * Ionic has many existing tests that existed prior to + * the introduction of theme testing. To maintain backwards + * compatibility, we will not include the theme in the test + * title if the theme is set to light. + */ + return `${title} - ${mode}/${direction}`; + } + + return `${title} - ${mode}/${direction}/${theme}`; }; /** @@ -37,9 +56,19 @@ const generateTitle = (title: string, config: TestConfig): string => { * and a test config. */ const generateScreenshotName = (fileName: string, config: TestConfig): string => { - const { mode, direction } = config; + const { mode, direction, theme } = config; - return `${fileName}-${mode}-${direction}.png`; + if (theme === 'light') { + /** + * Ionic has many existing tests that existed prior to + * the introduction of theme testing. To maintain backwards + * compatibility, we will not include the theme in the screenshot + * name if the theme is set to light. + */ + return `${fileName}-${mode}-${direction}.png`; + } + + return `${fileName}-${mode}-${direction}-${theme}.png`; }; /** @@ -54,12 +83,15 @@ export const configs = (testConfig: TestConfigOption = DEFAULT_TEST_CONFIG_OPTIO * If certain options are not provided, * fall back to the defaults. */ - const processedMode: Mode[] = modes ?? DEFAULT_MODES; - const processedDirection: Direction[] = directions ?? DEFAULT_DIRECTIONS; + const processedMode = modes ?? DEFAULT_MODES; + const processedDirection = directions ?? DEFAULT_DIRECTIONS; + const processedTheme = testConfig.themes ?? DEFAULT_THEMES; - processedMode.forEach((mode: Mode) => { - processedDirection.forEach((direction: Direction) => { - configs.push({ mode, direction }); + processedMode.forEach((mode) => { + processedDirection.forEach((direction) => { + processedTheme.forEach((theme) => { + configs.push({ mode, direction, theme }); + }); }); }); @@ -74,6 +106,7 @@ export const configs = (testConfig: TestConfigOption = DEFAULT_TEST_CONFIG_OPTIO const DEFAULT_MODES: Mode[] = ['ios', 'md']; const DEFAULT_DIRECTIONS: Direction[] = ['ltr', 'rtl']; +const DEFAULT_THEMES: Theme[] = ['light']; const DEFAULT_TEST_CONFIG_OPTION = { modes: DEFAULT_MODES, diff --git a/core/src/utils/test/playwright/page/utils/set-content.ts b/core/src/utils/test/playwright/page/utils/set-content.ts index 3087789cdf..1f0e6b2a4a 100644 --- a/core/src/utils/test/playwright/page/utils/set-content.ts +++ b/core/src/utils/test/playwright/page/utils/set-content.ts @@ -1,5 +1,5 @@ import type { Page, TestInfo } from '@playwright/test'; -import type { E2EPageOptions, Mode, Direction } from '@utils/test/playwright'; +import type { E2EPageOptions, Mode, Direction, Theme } from '@utils/test/playwright'; /** * Overwrites the default Playwright page.setContent method. @@ -19,25 +19,30 @@ export const setContent = async (page: Page, html: string, testInfo: TestInfo, o let mode: Mode; let direction: Direction; + let theme: Theme; if (options == undefined) { mode = testInfo.project.metadata.mode; direction = testInfo.project.metadata.rtl ? 'rtl' : 'ltr'; + theme = testInfo.project.metadata.theme; } else { mode = options.mode; direction = options.direction; + theme = options.theme; } const baseUrl = process.env.PLAYWRIGHT_TEST_BASE_URL; const output = ` - + + Ionic Playwright Test + ${theme !== 'light' ? `` : ''} diff --git a/packages/vue/test/base/src/components/NavRoot.vue b/packages/vue/test/base/src/components/NavRoot.vue index ec2fe1c513..ffd18e6765 100644 --- a/packages/vue/test/base/src/components/NavRoot.vue +++ b/packages/vue/test/base/src/components/NavRoot.vue @@ -8,11 +8,14 @@ - Go to Nav Child + + Go to Nav Child - diff --git a/packages/vue/test/base/tests/e2e/specs/navigation.cy.js b/packages/vue/test/base/tests/e2e/specs/navigation.cy.js index d8f75e7163..25788bf759 100644 --- a/packages/vue/test/base/tests/e2e/specs/navigation.cy.js +++ b/packages/vue/test/base/tests/e2e/specs/navigation.cy.js @@ -10,4 +10,10 @@ describe('Navigation', () => { cy.get('#nav-child-content').should('have.text', 'Custom Title'); }); + + it('nav should support kebab-case root-params', () => { + cy.get('#open-nav-modal').click(); + + cy.get('#nav-root-params').should('have.text', 'Message: Hello World!'); + }); });