Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcbc36be38 | ||
|
|
9448783bb1 | ||
|
|
720a3cea99 | ||
|
|
b81d85a401 | ||
|
|
aecbc92e30 | ||
|
|
bf7922c8b3 | ||
|
|
2a3c26e44d | ||
|
|
ddd8b92235 | ||
|
|
9a092c03cc | ||
|
|
a3ebca0f26 | ||
|
|
e10f49c43d | ||
|
|
e41a1a127b | ||
|
|
67bee73513 | ||
|
|
0c4e1fcdb4 | ||
|
|
9603a4de36 | ||
|
|
10c38d0354 | ||
|
|
e86f4f1cc9 | ||
|
|
5bc439961f | ||
|
|
9262f7da15 | ||
|
|
c47a16d6c3 | ||
|
|
0847c2ac2c | ||
|
|
ad65824722 | ||
|
|
aed7a03532 | ||
|
|
998870f55d | ||
|
|
0fb88315df | ||
|
|
0860ea0951 | ||
|
|
71e485d770 |
@@ -7,6 +7,8 @@ inputs:
|
||||
description: 'Playwright total number of test shards (ex: 4)'
|
||||
update:
|
||||
description: 'Whether or not to update the reference snapshots'
|
||||
component:
|
||||
description: 'The component to update the reference snapshots'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
@@ -23,9 +25,29 @@ runs:
|
||||
run: npm install && npx playwright install && npx playwright install-deps
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
- id: clean-component-name
|
||||
name: Clean Component Name
|
||||
# Remove `ion-` prefix from the `component` variable if it exists.
|
||||
run: |
|
||||
echo "component=$(echo ${{ inputs.component }} | sed 's/ion-//g')" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- id: set-test-file
|
||||
name: Set Test File
|
||||
# Screenshots can be updated for all components or specified component(s).
|
||||
# If the `component` variable is set, then the test has the option to
|
||||
# - run all the file paths that are in a component folder.
|
||||
# -- For example: if the `component` value is "item", then the test will run all the file paths that are in the "src/components/item" folder.
|
||||
# -- For example: if the `component` value is "item chip", then the test will run all the file paths that are in the "src/components/item" and "src/components/chip" folders.
|
||||
run: |
|
||||
if [ -n "${{ steps.clean-component-name.outputs.component }}" ]; then
|
||||
echo "testFile=\$(echo '${{ steps.clean-component-name.outputs.component }}' | awk '{for(i=1;i<=NF;i++) \$i=\"src/components/\"\$i}1')" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "testFile=$(echo '')" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
shell: bash
|
||||
- name: Test
|
||||
if: inputs.update != 'true'
|
||||
run: npm run test.e2e -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
run: npm run test.e2e ${{ steps.set-test-file.outputs.testFile }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
shell: bash
|
||||
working-directory: ./core
|
||||
- name: Test and Update
|
||||
@@ -47,7 +69,7 @@ runs:
|
||||
# which is why we not using the upload-archive
|
||||
# composite step here.
|
||||
run: |
|
||||
npm run test.e2e -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }} --update-snapshots
|
||||
npm run test.e2e ${{ steps.set-test-file.outputs.testFile }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }} --update-snapshots
|
||||
git add src/\*.png --force
|
||||
mkdir updated-screenshots
|
||||
cd ../ && rsync -R --progress $(git diff --name-only --cached) core/updated-screenshots
|
||||
|
||||
18
.github/workflows/assign-issues.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Assign issues to triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
auto-assign:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: 'Auto-assign issue'
|
||||
uses: pozil/auto-assign-issue@edee9537367a8fbc625d27f9e10aa8bad47b8723 # v1.13.0
|
||||
with:
|
||||
assignees: liamdebeasi, sean-perkins, brandyscarney, amandaejohnston, mapsandapps, thetaPC
|
||||
numOfAssignee: 1
|
||||
allowSelfAssign: false
|
||||
42
.github/workflows/nightly.yml
vendored
@@ -37,45 +37,3 @@ jobs:
|
||||
version: ${{ needs.create-nightly-hash.outputs.nightly-hash }}
|
||||
secrets:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
finalize-release:
|
||||
needs: [create-nightly-hash, release-ionic]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.IONITRON_TOKEN }}
|
||||
fetch-depth: 0
|
||||
- name: Configure Identity
|
||||
# Commits from github-actions do not
|
||||
# trigger other GitHub Actions. As a result,
|
||||
# we publish releases from Ionitron instead
|
||||
# so actions run when merging the release branch
|
||||
# back into main.
|
||||
run: |
|
||||
git config user.name ionitron
|
||||
git config user.email hi@ionicframework.com
|
||||
shell: bash
|
||||
- name: Checkout Nightly Branch
|
||||
# There are branch protection rules for our version
|
||||
# branches (i.e. "6.2.x"), so we cannot name the branch
|
||||
# the nightly hash as it would fall under the protection
|
||||
# rule. As a result, we prefix "tmp-" to the branch.
|
||||
run: |
|
||||
git checkout -b tmp-${{ needs.create-nightly-hash.outputs.nightly-hash }}
|
||||
git push origin tmp-${{ needs.create-nightly-hash.outputs.nightly-hash }}
|
||||
shell: bash
|
||||
- name: Create GitHub Release
|
||||
run: lerna version ${{ needs.create-nightly-hash.outputs.nightly-hash }} --yes --force-publish='*' --conventional-commits --conventional-prerelease --create-release github
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
# We need to push the commit changes in order for the tags
|
||||
# to get updated, but we don't need to keep the changelog
|
||||
# changes around.
|
||||
- name: Delete Nightly Branch
|
||||
run: |
|
||||
git checkout main
|
||||
git branch -D tmp-${{ needs.create-nightly-hash.outputs.nightly-hash }}
|
||||
git push origin --delete tmp-${{ needs.create-nightly-hash.outputs.nightly-hash }}
|
||||
shell: bash
|
||||
|
||||
7
.github/workflows/release.yml
vendored
@@ -79,6 +79,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
# Pull the latest version of the reference
|
||||
# branch instead of the revision that triggered
|
||||
# the workflow otherwise we won't get the commit
|
||||
# created in the previous job and this next job
|
||||
# will fail.
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
- name: Configure Identity
|
||||
# Commits from github-actions do not
|
||||
# trigger other GitHub Actions. As a result,
|
||||
|
||||
6
.github/workflows/update-screenshots.yml
vendored
@@ -2,6 +2,11 @@ name: 'Update Reference Screenshots'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
component:
|
||||
description: 'What component(s) should be updated? (leave blank to update all or use a space-separated list for multiple components)'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
build-core:
|
||||
@@ -34,6 +39,7 @@ jobs:
|
||||
shard: ${{ matrix.shard }}
|
||||
totalShards: ${{ matrix.totalShards }}
|
||||
update: true
|
||||
component: ${{ inputs.component }}
|
||||
|
||||
update-reference-screenshots:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
21
CHANGELOG.md
@@ -3,13 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [7.6.5](https://github.com/ionic-team/ionic-framework/compare/v7.6.3...v7.6.5) (2024-01-17)
|
||||
## [7.6.6](https://github.com/ionic-team/ionic-framework/compare/v7.6.5...v7.6.6) (2024-01-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **alert:** remove border-right on ios stacked buttons ([#28821](https://github.com/ionic-team/ionic-framework/issues/28821)) ([ad65824](https://github.com/ionic-team/ionic-framework/commit/ad65824722da0eed90ef9e595b743754bfd360b8))
|
||||
* **datetime:** do not animate to new value when multiple values in different months are set ([#28847](https://github.com/ionic-team/ionic-framework/issues/28847)) ([9262f7d](https://github.com/ionic-team/ionic-framework/commit/9262f7da15969706039e9d5f11ef5c7bd73ced0d)), closes [#28602](https://github.com/ionic-team/ionic-framework/issues/28602)
|
||||
* **datetime:** enter closes keyboard when typing time ([#28848](https://github.com/ionic-team/ionic-framework/issues/28848)) ([c47a16d](https://github.com/ionic-team/ionic-framework/commit/c47a16d6c3c57f56b053727dd10ead0bfe547e50)), closes [#28325](https://github.com/ionic-team/ionic-framework/issues/28325)
|
||||
* **menu:** improve reliability of main content not being scrollable when menu opens ([#28829](https://github.com/ionic-team/ionic-framework/issues/28829)) ([9603a4d](https://github.com/ionic-team/ionic-framework/commit/9603a4de363d2b42622ff3585cd6e4787d9581d1)), closes [#28399](https://github.com/ionic-team/ionic-framework/issues/28399)
|
||||
* **popover:** content inside of popover scrolls correctly ([#28861](https://github.com/ionic-team/ionic-framework/issues/28861)) ([10c38d0](https://github.com/ionic-team/ionic-framework/commit/10c38d0354e61e20bec9a313de84b22c3b85c323)), closes [#28455](https://github.com/ionic-team/ionic-framework/issues/28455)
|
||||
* **segment:** setting value via binding updates button state ([#28837](https://github.com/ionic-team/ionic-framework/issues/28837)) ([0847c2a](https://github.com/ionic-team/ionic-framework/commit/0847c2ac2c52b5fa6d30e381685d6cbf7a41231a)), closes [#28816](https://github.com/ionic-team/ionic-framework/issues/28816)
|
||||
* **select:** click handlers on slotted content fire ([#28839](https://github.com/ionic-team/ionic-framework/issues/28839)) ([aed7a03](https://github.com/ionic-team/ionic-framework/commit/aed7a03532b88628a4358c8cbae1a1cbb861462b)), closes [#28818](https://github.com/ionic-team/ionic-framework/issues/28818)
|
||||
* **vue:** tabs and parameterized routes work with latest vue ([#28846](https://github.com/ionic-team/ionic-framework/issues/28846)) ([5bc4399](https://github.com/ionic-team/ionic-framework/commit/5bc439961fda2c595666e67688fdd1b8ff4dd0bf)), closes [#28774](https://github.com/ionic-team/ionic-framework/issues/28774)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.6.5](https://github.com/ionic-team/ionic-framework/compare/v7.6.4...v7.6.5) (2024-01-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** add old IonBackButtonDelegate import ([#28831](https://github.com/ionic-team/ionic-framework/issues/28831)) ([fb77353](https://github.com/ionic-team/ionic-framework/commit/fb7735397ed53323dd93a172407117228610b929)), closes [#28827](https://github.com/ionic-team/ionic-framework/issues/28827)
|
||||
* **input:** slotted buttons are clickable ([#28772](https://github.com/ionic-team/ionic-framework/issues/28772)) ([4ccc150](https://github.com/ionic-team/ionic-framework/commit/4ccc150edff4e3f33f453343aedb081d920b2f90)), closes [#28762](https://github.com/ionic-team/ionic-framework/issues/28762)
|
||||
* **list:** remove uneeded border radius from items in inset list ([#28830](https://github.com/ionic-team/ionic-framework/issues/28830)) ([dbaaa5b](https://github.com/ionic-team/ionic-framework/commit/dbaaa5bd9f43b8ba589b3f9c4b4204d2f203ef18))
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [7.6.6](https://github.com/ionic-team/ionic-framework/compare/v7.6.5...v7.6.6) (2024-01-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **alert:** remove border-right on ios stacked buttons ([#28821](https://github.com/ionic-team/ionic-framework/issues/28821)) ([ad65824](https://github.com/ionic-team/ionic-framework/commit/ad65824722da0eed90ef9e595b743754bfd360b8))
|
||||
* **datetime:** do not animate to new value when multiple values in different months are set ([#28847](https://github.com/ionic-team/ionic-framework/issues/28847)) ([9262f7d](https://github.com/ionic-team/ionic-framework/commit/9262f7da15969706039e9d5f11ef5c7bd73ced0d)), closes [#28602](https://github.com/ionic-team/ionic-framework/issues/28602)
|
||||
* **datetime:** enter closes keyboard when typing time ([#28848](https://github.com/ionic-team/ionic-framework/issues/28848)) ([c47a16d](https://github.com/ionic-team/ionic-framework/commit/c47a16d6c3c57f56b053727dd10ead0bfe547e50)), closes [#28325](https://github.com/ionic-team/ionic-framework/issues/28325)
|
||||
* **menu:** improve reliability of main content not being scrollable when menu opens ([#28829](https://github.com/ionic-team/ionic-framework/issues/28829)) ([9603a4d](https://github.com/ionic-team/ionic-framework/commit/9603a4de363d2b42622ff3585cd6e4787d9581d1)), closes [#28399](https://github.com/ionic-team/ionic-framework/issues/28399)
|
||||
* **popover:** content inside of popover scrolls correctly ([#28861](https://github.com/ionic-team/ionic-framework/issues/28861)) ([10c38d0](https://github.com/ionic-team/ionic-framework/commit/10c38d0354e61e20bec9a313de84b22c3b85c323)), closes [#28455](https://github.com/ionic-team/ionic-framework/issues/28455)
|
||||
* **segment:** setting value via binding updates button state ([#28837](https://github.com/ionic-team/ionic-framework/issues/28837)) ([0847c2a](https://github.com/ionic-team/ionic-framework/commit/0847c2ac2c52b5fa6d30e381685d6cbf7a41231a)), closes [#28816](https://github.com/ionic-team/ionic-framework/issues/28816)
|
||||
* **select:** click handlers on slotted content fire ([#28839](https://github.com/ionic-team/ionic-framework/issues/28839)) ([aed7a03](https://github.com/ionic-team/ionic-framework/commit/aed7a03532b88628a4358c8cbae1a1cbb861462b)), closes [#28818](https://github.com/ionic-team/ionic-framework/issues/28818)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.6.5](https://github.com/ionic-team/ionic-framework/compare/v7.6.3...v7.6.5) (2024-01-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **input:** slotted buttons are clickable ([#28772](https://github.com/ionic-team/ionic-framework/issues/28772)) ([4ccc150](https://github.com/ionic-team/ionic-framework/commit/4ccc150edff4e3f33f453343aedb081d920b2f90)), closes [#28762](https://github.com/ionic-team/ionic-framework/issues/28762)
|
||||
* **list:** remove uneeded border radius from items in inset list ([#28830](https://github.com/ionic-team/ionic-framework/issues/28830)) ([dbaaa5b](https://github.com/ionic-team/ionic-framework/commit/dbaaa5bd9f43b8ba589b3f9c4b4204d2f203ef18))
|
||||
|
||||
|
||||
|
||||
@@ -1362,8 +1362,8 @@ ion-tabs,shadow
|
||||
ion-tabs,method,getSelected,getSelected() => Promise<string | undefined>
|
||||
ion-tabs,method,getTab,getTab(tab: string | HTMLIonTabElement) => Promise<HTMLIonTabElement | undefined>
|
||||
ion-tabs,method,select,select(tab: string | HTMLIonTabElement) => Promise<boolean>
|
||||
ion-tabs,event,ionTabsDidChange,{ tab: string; },false
|
||||
ion-tabs,event,ionTabsWillChange,{ tab: string; },false
|
||||
ion-tabs,event,ionTabsDidChange,TabsEventDetail,false
|
||||
ion-tabs,event,ionTabsWillChange,TabsEventDetail,false
|
||||
|
||||
ion-text,shadow
|
||||
ion-text,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
|
||||
18
core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "7.6.5",
|
||||
"version": "7.6.6",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "7.6.5",
|
||||
"version": "7.6.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.10.0",
|
||||
@@ -14,7 +14,7 @@
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.8.3",
|
||||
"@axe-core/playwright": "^4.8.4",
|
||||
"@capacitor/core": "^5.6.0",
|
||||
"@capacitor/haptics": "^5.0.6",
|
||||
"@capacitor/keyboard": "^5.0.7",
|
||||
@@ -56,9 +56,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@axe-core/playwright": {
|
||||
"version": "4.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.3.tgz",
|
||||
"integrity": "sha512-YtbkAWeOp5oQeI8vS6KYqJDa5yTl5O1wJP8KOZAAVjhxeiK/Y1ssxnZuGRobARyVh3eS6O3jdxTv/iCK1RfgaA==",
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.4.tgz",
|
||||
"integrity": "sha512-xpwd+T0BODt19hnXW0eX9xf+H/Ns1rdWwZNmuCV9UoTqjZ9mGm1F80pvh/A1r317ooltq8nwqcoVO9jbHWKSdA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"axe-core": "~4.8.3"
|
||||
@@ -10899,9 +10899,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@axe-core/playwright": {
|
||||
"version": "4.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.3.tgz",
|
||||
"integrity": "sha512-YtbkAWeOp5oQeI8vS6KYqJDa5yTl5O1wJP8KOZAAVjhxeiK/Y1ssxnZuGRobARyVh3eS6O3jdxTv/iCK1RfgaA==",
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.4.tgz",
|
||||
"integrity": "sha512-xpwd+T0BODt19hnXW0eX9xf+H/Ns1rdWwZNmuCV9UoTqjZ9mGm1F80pvh/A1r317ooltq8nwqcoVO9jbHWKSdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"axe-core": "~4.8.3"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "7.6.5",
|
||||
"version": "7.6.6",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -36,7 +36,7 @@
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.8.3",
|
||||
"@axe-core/playwright": "^4.8.4",
|
||||
"@capacitor/core": "^5.6.0",
|
||||
"@capacitor/haptics": "^5.0.6",
|
||||
"@capacitor/keyboard": "^5.0.7",
|
||||
|
||||
10
core/src/components.d.ts
vendored
@@ -38,6 +38,7 @@ import { SegmentButtonLayout } from "./components/segment-button/segment-button-
|
||||
import { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./components/select/select-interface";
|
||||
import { SelectPopoverOption } from "./components/select-popover/select-popover-interface";
|
||||
import { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface";
|
||||
import { TabsEventDetail } from "./components/tabs/tabs-interface";
|
||||
import { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface";
|
||||
import { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions, ToastSwipeGestureDirection } from "./components/toast/toast-interface";
|
||||
import { ToggleChangeEventDetail } from "./components/toggle/toggle-interface";
|
||||
@@ -74,6 +75,7 @@ export { SegmentButtonLayout } from "./components/segment-button/segment-button-
|
||||
export { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./components/select/select-interface";
|
||||
export { SelectPopoverOption } from "./components/select-popover/select-popover-interface";
|
||||
export { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface";
|
||||
export { TabsEventDetail } from "./components/tabs/tabs-interface";
|
||||
export { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface";
|
||||
export { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions, ToastSwipeGestureDirection } from "./components/toast/toast-interface";
|
||||
export { ToggleChangeEventDetail } from "./components/toggle/toggle-interface";
|
||||
@@ -4503,8 +4505,8 @@ declare global {
|
||||
};
|
||||
interface HTMLIonTabsElementEventMap {
|
||||
"ionNavWillLoad": void;
|
||||
"ionTabsWillChange": { tab: string };
|
||||
"ionTabsDidChange": { tab: string };
|
||||
"ionTabsWillChange": TabsEventDetail;
|
||||
"ionTabsDidChange": TabsEventDetail;
|
||||
}
|
||||
interface HTMLIonTabsElement extends Components.IonTabs, HTMLStencilElement {
|
||||
addEventListener<K extends keyof HTMLIonTabsElementEventMap>(type: K, listener: (this: HTMLIonTabsElement, ev: IonTabsCustomEvent<HTMLIonTabsElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
@@ -7711,11 +7713,11 @@ declare namespace LocalJSX {
|
||||
/**
|
||||
* Emitted when the navigation has finished transitioning to a new component.
|
||||
*/
|
||||
"onIonTabsDidChange"?: (event: IonTabsCustomEvent<{ tab: string }>) => void;
|
||||
"onIonTabsDidChange"?: (event: IonTabsCustomEvent<TabsEventDetail>) => void;
|
||||
/**
|
||||
* Emitted when the navigation is about to transition to a new component.
|
||||
*/
|
||||
"onIonTabsWillChange"?: (event: IonTabsCustomEvent<{ tab: string }>) => void;
|
||||
"onIonTabsWillChange"?: (event: IonTabsCustomEvent<TabsEventDetail>) => void;
|
||||
"useRouter"?: boolean;
|
||||
}
|
||||
interface IonText {
|
||||
|
||||
@@ -382,7 +382,10 @@ export class Accordion implements ComponentInterface {
|
||||
};
|
||||
|
||||
private toggleExpanded() {
|
||||
const { accordionGroupEl, value, state } = this;
|
||||
const { accordionGroupEl, disabled, readonly, value, state } = this;
|
||||
|
||||
if (disabled || readonly) return;
|
||||
|
||||
if (accordionGroupEl) {
|
||||
/**
|
||||
* Because the accordion group may or may
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
|
||||
test.describe(title('accordion: states'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
});
|
||||
test('should properly set readonly on child accordions', async ({ page }) => {
|
||||
const accordionGroup = page.locator('ion-accordion-group');
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveJSProperty('readonly', false);
|
||||
|
||||
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
|
||||
el.readonly = true;
|
||||
});
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveJSProperty('readonly', true);
|
||||
});
|
||||
|
||||
test('should properly set disabled on child accordions', async ({ page }) => {
|
||||
const accordionGroup = page.locator('ion-accordion-group');
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveJSProperty('disabled', false);
|
||||
|
||||
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
|
||||
el.disabled = true;
|
||||
});
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveJSProperty('disabled', true);
|
||||
});
|
||||
});
|
||||
});
|
||||
137
core/src/components/accordion/test/disabled/accordion.e2e.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
// NOTE: these tests cannot be re-written as spec tests because the `getAccordions` method in accordion-group.tsx uses a `:scope` selector
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
|
||||
test.describe(title('accordion: disabled'), () => {
|
||||
test('should properly set disabled on child accordions', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordionGroup = page.locator('ion-accordion-group');
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveJSProperty('disabled', false);
|
||||
|
||||
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
|
||||
el.disabled = true;
|
||||
});
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveJSProperty('disabled', true);
|
||||
});
|
||||
|
||||
test('should not open accordion on click when group is disabled', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false" disabled>
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
accordion.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
|
||||
test('should not open accordion on click when accordion is disabled', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion disabled>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
accordion.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
|
||||
test('should not open accordion via keyboard navigation when group is disabled', async ({ page, browserName }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false" disabled>
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
await page.keyboard.press(tabKey);
|
||||
await page.waitForChanges();
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
|
||||
test('should not open accordion via keyboard navigation when accordion is disabled', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion disabled>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
await page.keyboard.press(tabKey);
|
||||
await page.waitForChanges();
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
});
|
||||
});
|
||||
91
core/src/components/accordion/test/disabled/index.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Accordion - Disabled</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
grid-row-gap: 20px;
|
||||
grid-column-gap: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-title>Accordion - Disabled</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content fullscreen="true" color="light">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar color="light">
|
||||
<ion-title size="large">Accordion - Disabled</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<div class="grid ion-padding">
|
||||
<div class="grid-item">
|
||||
<ion-accordion-group>
|
||||
<ion-accordion value="first">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>First Accordion</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">First Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="second" disabled="true">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Second Accordion (Disabled)</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Second Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="third">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Third Accordion</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Third Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<ion-accordion-group disabled="true">
|
||||
<ion-accordion value="first">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>First Accordion in Disabled Group</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">First Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="second">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Second Accordion in Disabled Group</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Second Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="third">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Third Accordion in Disabled Group</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Third Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<ion-accordion value="second" disabled="true">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Accordion Without Group (Disabled)</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Second Content</div>
|
||||
</ion-accordion>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
137
core/src/components/accordion/test/readonly/accordion.e2e.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
// NOTE: these tests cannot be re-written as spec tests because the `getAccordions` method in accordion-group.tsx uses a `:scope` selector
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, title }) => {
|
||||
test.describe(title('accordion: readonly'), () => {
|
||||
test('should properly set readonly on child accordions', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordionGroup = page.locator('ion-accordion-group');
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveJSProperty('readonly', false);
|
||||
|
||||
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
|
||||
el.readonly = true;
|
||||
});
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveJSProperty('readonly', true);
|
||||
});
|
||||
|
||||
test('should not open accordion on click when group is readonly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false" readonly>
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
accordion.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
|
||||
test('should not open accordion on click when accordion is readonly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion readonly>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
accordion.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
|
||||
test('should not open accordion via keyboard navigation when group is readonly', async ({ page, browserName }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false" readonly>
|
||||
<ion-accordion>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
await page.keyboard.press(tabKey);
|
||||
await page.waitForChanges();
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
|
||||
test('should not open accordion via keyboard navigation when accordion is readonly', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-accordion-group animated="false">
|
||||
<ion-accordion readonly>
|
||||
<ion-item slot="header">Label</ion-item>
|
||||
<div slot="content">Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const accordion = page.locator('ion-accordion');
|
||||
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
|
||||
await page.keyboard.press(tabKey);
|
||||
await page.waitForChanges();
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(accordion).toHaveClass(/accordion-collapsed/);
|
||||
});
|
||||
});
|
||||
});
|
||||
91
core/src/components/accordion/test/readonly/index.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Accordion - Readonly</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
grid-row-gap: 20px;
|
||||
grid-column-gap: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-title>Accordion - Readonly</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content fullscreen="true" color="light">
|
||||
<ion-header collapse="condense">
|
||||
<ion-toolbar color="light">
|
||||
<ion-title size="large">Accordion - Readonly</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<div class="grid ion-padding">
|
||||
<div class="grid-item">
|
||||
<ion-accordion-group>
|
||||
<ion-accordion value="first">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>First Accordion</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">First Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="second" readonly="true">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Second Accordion (Readonly)</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Second Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="third">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Third Accordion</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Third Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<ion-accordion-group readonly="true">
|
||||
<ion-accordion value="first">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>First Accordion in Readonly Group</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">First Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="second">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Second Accordion in Readonly Group</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Second Content</div>
|
||||
</ion-accordion>
|
||||
<ion-accordion value="third">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Third Accordion in Readonly Group</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Third Content</div>
|
||||
</ion-accordion>
|
||||
</ion-accordion-group>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<ion-accordion value="second" readonly="true">
|
||||
<ion-item slot="header" color="light">
|
||||
<ion-label>Accordion Without Group (Readonly)</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding" slot="content">Second Content</div>
|
||||
</ion-accordion>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
@@ -265,6 +265,22 @@
|
||||
flex-wrap: $alert-ios-button-group-flex-wrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* The right border should only be applied to the first button
|
||||
* when the group has 2 or less buttons (horizontal).
|
||||
* Otherwise, the right border should not be applied
|
||||
* when the group has 3 or more buttons (vertical).
|
||||
*/
|
||||
.alert-button-group-vertical .alert-button {
|
||||
border-right: none;
|
||||
|
||||
&:last-child {
|
||||
@include rtl() {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alert-button {
|
||||
/**
|
||||
* This padding ensures that alerts
|
||||
|
||||
@@ -73,11 +73,6 @@ configs().forEach(({ config, screenshot, title }) => {
|
||||
await alertFixture.screenshot('longMessage');
|
||||
});
|
||||
|
||||
test('more than two buttons', async () => {
|
||||
await alertFixture.open('#multipleButtons');
|
||||
await alertFixture.screenshot('multipleButtons');
|
||||
});
|
||||
|
||||
test('no message', async () => {
|
||||
await alertFixture.open('#noMessage');
|
||||
await alertFixture.screenshot('noMessage');
|
||||
@@ -105,6 +100,41 @@ configs().forEach(({ config, screenshot, title }) => {
|
||||
});
|
||||
});
|
||||
|
||||
configs({ themes: ['light', 'dark'] }).forEach(({ config, screenshot, title }) => {
|
||||
test.describe(title('should not have visual regressions'), () => {
|
||||
test('more than two buttons', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-alert
|
||||
header="Alert"
|
||||
sub-header="Subtitle"
|
||||
message="This is an alert message."
|
||||
is-open="true"
|
||||
></ion-alert>
|
||||
|
||||
<script>
|
||||
const alert = document.querySelector('ion-alert');
|
||||
alert.buttons = [
|
||||
'Open Modal',
|
||||
{
|
||||
text: 'Delete',
|
||||
id: 'delete-button',
|
||||
role: 'destructive',
|
||||
},
|
||||
'Cancel'
|
||||
];
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const alert = page.locator('ion-alert');
|
||||
|
||||
await expect(alert).toHaveScreenshot(screenshot(`alert-multipleButtons`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class AlertFixture {
|
||||
readonly page: E2EPage;
|
||||
readonly screenshotFn?: (file: string) => string;
|
||||
|
||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
@@ -57,7 +57,7 @@ configs({ modes: ['md'] }).forEach(({ config, screenshot, title }) => {
|
||||
await page.mouse.down();
|
||||
}
|
||||
|
||||
await page.waitForSelector('#default.ion-activated');
|
||||
await page.locator('#default.ion-activated').waitFor();
|
||||
|
||||
await expect(button).toHaveScreenshot(screenshot(`button-ripple-effect`));
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
@@ -15,7 +15,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
});
|
||||
test('should switch to a date-only view when the date button is clicked', async ({ page }) => {
|
||||
const datetime = page.locator('ion-datetime');
|
||||
@@ -45,7 +45,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('Jan 1, 2022');
|
||||
await expect(page.locator('#time-button')).toContainText('6:30 AM');
|
||||
@@ -58,7 +58,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('January 2022');
|
||||
await expect(page.locator('#time-button')).toBeHidden();
|
||||
@@ -71,7 +71,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('2022');
|
||||
await expect(page.locator('#time-button')).toBeHidden();
|
||||
@@ -84,7 +84,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('January');
|
||||
await expect(page.locator('#time-button')).toBeHidden();
|
||||
@@ -97,7 +97,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#time-button')).toContainText('6:30 AM');
|
||||
await expect(page.locator('#date-button')).toBeHidden();
|
||||
@@ -110,7 +110,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const dateTarget = page.locator('#date-button');
|
||||
@@ -135,7 +135,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('January 2022');
|
||||
await expect(page.locator('#time-button')).toBeHidden();
|
||||
@@ -153,7 +153,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('2022');
|
||||
await expect(page.locator('#time-button')).toBeHidden();
|
||||
@@ -169,7 +169,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
/**
|
||||
* The entire text reads 1 ene 2022, but some browsers will add
|
||||
@@ -187,7 +187,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#time-button')).toContainText('16:30');
|
||||
});
|
||||
@@ -199,7 +199,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const timeTarget = page.locator('#time-button');
|
||||
await expect(timeTarget).toContainText('6:30');
|
||||
@@ -223,7 +223,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('Jan 1, 2022 6:30 AM');
|
||||
await expect(page.locator('#time-button')).not.toBeVisible();
|
||||
@@ -238,7 +238,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('Jan 1, 2022 6:30 AM');
|
||||
await expect(page.locator('#time-button')).not.toBeVisible();
|
||||
|
||||
@@ -11,7 +11,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toBeDisabled();
|
||||
await expect(page.locator('#time-button')).toBeDisabled();
|
||||
@@ -24,7 +24,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetimeButton = page.locator('ion-datetime-button');
|
||||
await expect(datetimeButton).toHaveScreenshot(screenshot(`datetime-button-disabled`));
|
||||
|
||||
@@ -20,7 +20,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toContainText('3 days');
|
||||
});
|
||||
@@ -32,7 +32,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toHaveText('0 days');
|
||||
});
|
||||
@@ -49,7 +49,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toHaveText('Jun 1, 2022');
|
||||
});
|
||||
@@ -69,7 +69,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toHaveText('Selected: 3');
|
||||
});
|
||||
@@ -86,7 +86,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionValueChange = await page.spyOnEvent('ionValueChange');
|
||||
@@ -111,7 +111,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page.locator('#date-button')).toHaveText('Jun 1, 2022');
|
||||
await expect(page.locator('#time-button')).toHaveText('4:30 PM');
|
||||
|
||||
@@ -1284,21 +1284,42 @@ export class Datetime implements ComponentInterface {
|
||||
(month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
|
||||
const bodyIsVisible = el.classList.contains('datetime-ready');
|
||||
const { isGridStyle, showMonthAndYear } = this;
|
||||
if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
|
||||
this.animateToDate(targetValue);
|
||||
} else {
|
||||
/**
|
||||
* We only need to do this if we didn't just animate to a new month,
|
||||
* since that calls prevMonth/nextMonth which calls setWorkingParts for us.
|
||||
*/
|
||||
this.setWorkingParts({
|
||||
month,
|
||||
day,
|
||||
year,
|
||||
hour,
|
||||
minute,
|
||||
ampm,
|
||||
});
|
||||
|
||||
let areAllSelectedDatesInSameMonth = true;
|
||||
if (Array.isArray(valueToProcess)) {
|
||||
const firstMonth = valueToProcess[0].month;
|
||||
for (const date of valueToProcess) {
|
||||
if (date.month !== firstMonth) {
|
||||
areAllSelectedDatesInSameMonth = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is more than one date selected
|
||||
* and the dates aren't all in the same month,
|
||||
* then we should neither animate to the date
|
||||
* nor update the working parts because we do
|
||||
* not know which date the user wants to view.
|
||||
*/
|
||||
if (areAllSelectedDatesInSameMonth) {
|
||||
if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
|
||||
this.animateToDate(targetValue);
|
||||
} else {
|
||||
/**
|
||||
* We only need to do this if we didn't just animate to a new month,
|
||||
* since that calls prevMonth/nextMonth which calls setWorkingParts for us.
|
||||
*/
|
||||
this.setWorkingParts({
|
||||
month,
|
||||
day,
|
||||
year,
|
||||
hour,
|
||||
minute,
|
||||
ampm,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
|
||||
const container = page.locator('#container');
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`datetime-scale`));
|
||||
});
|
||||
@@ -87,7 +87,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const clearButton = page.locator('#clear-button button');
|
||||
const selectedDay = page.locator('.calendar-day-active');
|
||||
@@ -114,7 +114,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const calendarMonthYear = page.locator('ion-datetime .calendar-month-year');
|
||||
const calendarBody = page.locator('.calendar-body');
|
||||
await expect(calendarMonthYear).toHaveText('February 2022');
|
||||
|
||||
@@ -110,7 +110,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
|
||||
@@ -255,7 +255,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const calendarBody = page.locator('ion-datetime .calendar-body');
|
||||
const calendarHeader = page.locator('ion-datetime .calendar-month-year');
|
||||
@@ -275,7 +275,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const calendarBody = page.locator('ion-datetime .calendar-body');
|
||||
const calendarHeader = page.locator('ion-datetime .calendar-month-year');
|
||||
@@ -297,7 +297,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const calendarBody = page.locator('ion-datetime .calendar-body');
|
||||
const calendarHeader = page.locator('ion-datetime .calendar-month-year');
|
||||
@@ -331,7 +331,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const monthYearButton = page.locator('ion-datetime .calendar-month-year');
|
||||
const monthYearInterface = page.locator('ion-datetime .datetime-year');
|
||||
@@ -349,7 +349,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement) => el.style.removeProperty('display'));
|
||||
await expect(datetime).toBeVisible();
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
// month/year interface should be reset
|
||||
await expect(monthYearInterface).toBeHidden();
|
||||
@@ -399,7 +399,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const selectedDay = page.locator('ion-datetime .calendar-day-active');
|
||||
|
||||
@@ -428,7 +428,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const calendarButtons = page.locator('.calendar-day:not([disabled])');
|
||||
@@ -447,7 +447,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const datetime = page.locator('ion-datetime');
|
||||
@@ -487,7 +487,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(datetime.locator('.calendar-day-today')).toHaveScreenshot(
|
||||
screenshot(`datetime-today-calendar-button`)
|
||||
@@ -517,7 +517,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`date-highlight-start-of-month`));
|
||||
|
||||
@@ -543,7 +543,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
});
|
||||
|
||||
test('should switch the calendar header when moving to a month with a different number of days', async ({
|
||||
|
||||
@@ -113,7 +113,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
test.describe('check example usages', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/disable-dates', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').first().waitFor();
|
||||
});
|
||||
|
||||
test('should disable a specific date', async ({ page }) => {
|
||||
|
||||
@@ -27,7 +27,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const febFirstButton = page.locator(`.calendar-day[data-day='1'][data-month='2']`);
|
||||
|
||||
@@ -42,7 +42,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const calendarMonthYear = page.locator('ion-datetime .calendar-month-year');
|
||||
await expect(calendarMonthYear.locator('button')).toBeDisabled();
|
||||
});
|
||||
@@ -71,7 +71,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const clearButton = page.locator('#clear-button button');
|
||||
|
||||
@@ -86,7 +86,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const calendarMonthYear = page.locator('ion-datetime .calendar-month-year');
|
||||
const calendarBody = page.locator('.calendar-body');
|
||||
await expect(calendarMonthYear).toHaveText('February 2022');
|
||||
|
||||
@@ -15,7 +15,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-date-time`));
|
||||
});
|
||||
@@ -26,7 +26,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-time-date`));
|
||||
});
|
||||
@@ -37,7 +37,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-time`));
|
||||
});
|
||||
@@ -48,7 +48,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-date`));
|
||||
});
|
||||
@@ -69,7 +69,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-cover-date-time`));
|
||||
});
|
||||
@@ -80,7 +80,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-cover-time-date`));
|
||||
});
|
||||
@@ -91,7 +91,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-cover-time`));
|
||||
});
|
||||
@@ -102,7 +102,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await expect(datetime).toHaveScreenshot(screenshot(`datetime-display-cover-date`));
|
||||
});
|
||||
@@ -119,7 +119,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test('month selection should work after changing presentation', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/display', config);
|
||||
const ionWorkingPartsDidChange = await page.spyOnEvent('ionWorkingPartsDidChange');
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const select = page.locator('select#presentation');
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetimeButtons = page.locator('ion-datetime .calendar-day:not([disabled])');
|
||||
|
||||
@@ -111,7 +111,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetimeYear = page.locator('ion-datetime .year-column .picker-item[data-value="2022"]');
|
||||
|
||||
@@ -147,7 +147,7 @@ class DatetimeLocaleFixture {
|
||||
|
||||
this.datetime = this.page.locator('ion-datetime');
|
||||
|
||||
await this.page.waitForSelector('.datetime-ready');
|
||||
await this.page.locator('.datetime-ready').waitFor();
|
||||
}
|
||||
|
||||
async expectLocalizedDatePicker(screenshot: ScreenshotFn) {
|
||||
|
||||
@@ -36,7 +36,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const prevButton = page.locator('ion-datetime .calendar-next-prev ion-button:nth-child(1)');
|
||||
const nextButton = page.locator('ion-datetime .calendar-next-prev ion-button:nth-child(2)');
|
||||
@@ -61,7 +61,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
await page.goto('/src/components/datetime/test/minmax', config);
|
||||
const calendarMonths = page.locator('ion-datetime#inside .calendar-month');
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').first().waitFor();
|
||||
|
||||
await expect(calendarMonths.nth(0)).not.toHaveClass(/calendar-month-disabled/);
|
||||
await expect(calendarMonths.nth(1)).not.toHaveClass(/calendar-month-disabled/);
|
||||
@@ -70,7 +70,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
|
||||
test('datetime: minmax navigation disabled', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/minmax', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').first().waitFor();
|
||||
|
||||
const navButtons = page.locator('ion-datetime#outside .calendar-next-prev ion-button');
|
||||
|
||||
@@ -80,7 +80,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
|
||||
test('datetime: min including day should not disable month', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/minmax', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').first().waitFor();
|
||||
|
||||
const calendarMonths = page.locator('ion-datetime#min-with-day .calendar-month');
|
||||
|
||||
@@ -102,7 +102,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
|
||||
@@ -124,7 +124,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
test.describe('setting value outside bounds should show in-bounds month', () => {
|
||||
const testDisplayedMonth = async (page: E2EPage, content: string, expectedString = /June 2021/) => {
|
||||
await page.setContent(content, config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const calendarMonthYear = page.locator('ion-datetime .calendar-month-year');
|
||||
await expect(calendarMonthYear).toHaveText(expectedString);
|
||||
@@ -174,7 +174,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetimeMonthDidChange = await page.spyOnEvent('datetimeMonthDidChange');
|
||||
const eventButton = page.locator('button#bind');
|
||||
@@ -260,7 +260,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
@@ -283,7 +283,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
@@ -311,7 +311,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
const monthColumnItems = page.locator('ion-datetime .month-column .picker-item:not(.picker-item-empty)');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await monthColumnItems.nth(0).click(); // switch to January
|
||||
await ionChange.next();
|
||||
@@ -346,7 +346,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
// Select Jan 10, 2022
|
||||
const maxDate = page.locator('ion-datetime .calendar-day[data-day="10"][data-month="1"][data-year="2022"]');
|
||||
|
||||
@@ -8,7 +8,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test.describe(title('datetime: month-year picker'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/month-year-picker', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').first().waitFor();
|
||||
});
|
||||
|
||||
test('should hide the footer when picker is open', async ({ page }) => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
const SINGLE_DATE = '2022-06-01';
|
||||
const MULTIPLE_DATES = ['2022-06-01', '2022-06-02', '2022-06-03'];
|
||||
const MULTIPLE_DATES_SEPARATE_MONTHS = ['2022-04-01', '2022-05-01', '2022-06-01'];
|
||||
const MULTIPLE_DATES_SEPARATE_MONTHS = ['2022-03-01', '2022-04-01', '2022-05-01'];
|
||||
|
||||
interface DatetimeMultipleConfig {
|
||||
multiple?: boolean;
|
||||
@@ -62,7 +62,7 @@ class DatetimeMultipleFixture {
|
||||
);
|
||||
|
||||
this.datetime = this.page.locator('ion-datetime');
|
||||
await this.page.waitForSelector('.datetime-ready');
|
||||
await this.page.locator('.datetime-ready').waitFor();
|
||||
|
||||
return this.datetime;
|
||||
}
|
||||
@@ -158,10 +158,32 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
});
|
||||
});
|
||||
|
||||
test('multiple default values across months should display at least one value', async () => {
|
||||
test('should scroll to new month when value is updated with multiple dates in the same month', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/28602',
|
||||
});
|
||||
const datetime = await datetimeFixture.goto(config, MULTIPLE_DATES_SEPARATE_MONTHS);
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement, dates: string[]) => {
|
||||
el.value = dates;
|
||||
}, MULTIPLE_DATES);
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
const monthYear = datetime.locator('.calendar-month-year');
|
||||
await expect(monthYear).toHaveText(/April 2022/);
|
||||
await expect(monthYear).toHaveText(/June 2022/);
|
||||
});
|
||||
|
||||
test('should not scroll to new month when value is updated with dates in different months', async ({ page }) => {
|
||||
const datetime = await datetimeFixture.goto(config, MULTIPLE_DATES);
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement, dates: string[]) => {
|
||||
el.value = dates;
|
||||
}, MULTIPLE_DATES_SEPARATE_MONTHS);
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
const monthYear = datetime.locator('.calendar-month-year');
|
||||
await expect(monthYear).toHaveText(/June 2022/);
|
||||
});
|
||||
|
||||
test('with buttons, should only update value when confirm is called', async ({ page }) => {
|
||||
@@ -282,7 +304,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector(`.datetime-ready`);
|
||||
await page.locator(`.datetime-ready`).waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const header = datetime.locator('.datetime-selected-date');
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
await openDateTimeBtn.click();
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page).toHaveScreenshot(screenshot(`datetime-position-base`));
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page).toHaveScreenshot(screenshot(`datetime-wheel-date-diff`));
|
||||
});
|
||||
@@ -34,7 +34,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page).toHaveScreenshot(screenshot(`datetime-wheel-date-time-diff`));
|
||||
});
|
||||
@@ -45,7 +45,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
await expect(page).toHaveScreenshot(screenshot(`datetime-wheel-time-date-diff`));
|
||||
});
|
||||
@@ -56,7 +56,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
|
||||
@@ -80,7 +80,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('ion-datetime .day-column .picker-item[data-value]');
|
||||
expect(await dayValues.count()).toEqual(27);
|
||||
@@ -93,7 +93,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('ion-datetime .day-column .picker-item[data-value]');
|
||||
expect(await dayValues.count()).toEqual(1);
|
||||
@@ -116,7 +116,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const disabledMonths = page.locator('.month-column .picker-item[disabled]');
|
||||
const disabledYears = page.locator('.year-column .picker-item[disabled]');
|
||||
@@ -141,7 +141,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
|
||||
const yearValues = page.locator('.year-column .picker-item:not(.picker-item-empty)');
|
||||
@@ -175,7 +175,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
|
||||
@@ -209,7 +209,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');
|
||||
@@ -230,7 +230,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const yearValues = page.locator('.year-column .picker-item:not(.picker-item-empty)');
|
||||
@@ -253,7 +253,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const datetime = page.locator('ion-datetime');
|
||||
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement) => (el.value = '2021-05-25T12:40:00.000Z'));
|
||||
@@ -285,7 +285,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
|
||||
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');
|
||||
@@ -306,7 +306,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const columns = page.locator('ion-picker-column-internal');
|
||||
|
||||
@@ -327,7 +327,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const columns = page.locator('ion-picker-column-internal');
|
||||
|
||||
@@ -346,7 +346,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('ion-datetime .date-column .picker-item[data-value]');
|
||||
expect(await dayValues.count()).toEqual(57);
|
||||
@@ -359,7 +359,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('ion-datetime .date-column .picker-item[data-value]');
|
||||
expect(await dayValues.count()).toEqual(41);
|
||||
@@ -382,7 +382,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const disabledDates = page.locator('.date-column .picker-item[disabled]');
|
||||
|
||||
@@ -403,7 +403,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dateValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -424,7 +424,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dateValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -444,7 +444,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dateColumn = page.locator('.date-column');
|
||||
const dateValues = dateColumn.locator('.picker-item:not(.picker-item-empty)');
|
||||
@@ -474,7 +474,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -494,7 +494,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -511,7 +511,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
@@ -531,7 +531,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('ion-datetime .date-column .picker-item[data-value]');
|
||||
expect(await dayValues.count()).toEqual(57);
|
||||
@@ -544,7 +544,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('ion-datetime .date-column .picker-item[data-value]');
|
||||
expect(await dayValues.count()).toEqual(41);
|
||||
@@ -567,7 +567,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const disabledDates = page.locator('.date-column .picker-item[disabled]');
|
||||
|
||||
@@ -588,7 +588,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dateValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -609,7 +609,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dateValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -629,7 +629,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dateColumn = page.locator('.date-column');
|
||||
const dateValues = dateColumn.locator('.picker-item:not(.picker-item-empty)');
|
||||
@@ -659,7 +659,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
@@ -679,7 +679,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const monthYearButton = page.locator('ion-datetime .calendar-month-year');
|
||||
@@ -189,7 +189,7 @@ class DatetimePresentationFixture {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await this.page.waitForSelector('.datetime-ready');
|
||||
await this.page.locator('.datetime-ready').waitFor();
|
||||
this.datetime = this.page.locator('ion-datetime');
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ class TimePickerFixture {
|
||||
`,
|
||||
config
|
||||
);
|
||||
await this.page.waitForSelector('.datetime-ready');
|
||||
await this.page.locator('.datetime-ready').waitFor();
|
||||
this.timePicker = this.page.locator('ion-datetime');
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const febFirstButton = page.locator(`.calendar-day[data-day='1'][data-month='2']`);
|
||||
|
||||
@@ -43,7 +43,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
);
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const calendarMonthYear = page.locator('ion-datetime .calendar-month-year');
|
||||
await expect(calendarMonthYear).toHaveText('February 2022');
|
||||
|
||||
@@ -66,7 +66,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
|
||||
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
const calendarMonthYear = page.locator('ion-datetime .calendar-month-year');
|
||||
const monthYearButton = page.locator('.calendar-month-year ion-item');
|
||||
await expect(calendarMonthYear).toHaveText('February 2022');
|
||||
@@ -157,7 +157,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config, scree
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const clearButton = page.locator('#clear-button button');
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test.describe(title('datetime: set-value'), () => {
|
||||
test('should update the active date when value is initially set', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/set-value', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement) => (el.value = '2021-11-25T12:40:00.000Z'));
|
||||
@@ -18,7 +18,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
test('should update the active time when value is initially set', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/set-value', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement) => (el.value = '2021-11-25T12:40:00.000Z'));
|
||||
@@ -37,7 +37,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const activeDayButton = page.locator('.calendar-day-active');
|
||||
@@ -53,7 +53,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
test('should scroll to new month when value is initially set and then updated', async ({ page }) => {
|
||||
await page.goto('/src/components/datetime/test/set-value', config);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
await datetime.evaluate((el: HTMLIonDatetimeElement) => (el.value = '2021-05-25T12:40:00.000Z'));
|
||||
|
||||
@@ -10,7 +10,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const timeLabel = page.locator('ion-datetime .time-header');
|
||||
await expect(timeLabel).toHaveText('Time');
|
||||
@@ -22,7 +22,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const timeLabel = page.locator('ion-datetime .time-header');
|
||||
await expect(timeLabel).toHaveText('');
|
||||
|
||||
@@ -10,7 +10,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
`,
|
||||
config
|
||||
);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const items = page.locator('.calendar-day:not([disabled])');
|
||||
|
||||
@@ -91,7 +91,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const minuteItems = page.locator(
|
||||
'ion-picker-column-internal:nth-of-type(2) .picker-item:not(.picker-item-empty)'
|
||||
@@ -137,7 +137,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const monthItems = page.locator('.month-column .picker-item:not(.picker-item-empty)');
|
||||
await expect(monthItems).toHaveText(['January']);
|
||||
@@ -169,7 +169,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const todayButton = page.locator('.calendar-day[data-day="10"][data-month="10"][data-year="2022"]');
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
|
||||
await content.evaluate(async (el: HTMLIonContentElement) => {
|
||||
await el.scrollToBottom();
|
||||
});
|
||||
await page.waitForSelector('#largeTitleHeader.header-collapse-condense-inactive');
|
||||
await page.locator('#largeTitleHeader.header-collapse-condense-inactive').waitFor();
|
||||
|
||||
await expect(smallTitleHeader).toHaveScreenshot(screenshot(`header-condense-large-title-collapsed-diff`));
|
||||
|
||||
@@ -30,7 +30,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
|
||||
await content.evaluate(async (el: HTMLIonContentElement) => {
|
||||
await el.scrollToTop();
|
||||
});
|
||||
await page.waitForSelector('#smallTitleHeader.header-collapse-condense-inactive');
|
||||
await page.locator('#smallTitleHeader.header-collapse-condense-inactive').waitFor();
|
||||
|
||||
await expect(smallTitleHeader).toHaveAttribute('aria-hidden', 'true');
|
||||
});
|
||||
|
||||
@@ -51,15 +51,6 @@
|
||||
* @prop --highlight-color-valid: The color of the highlight on the item when valid. Only applies to inputs and textareas using the legacy form syntax. DEPRECATED: Highlights can be styled on `ion-input` or `ion-textarea` when using the modern form syntax.
|
||||
* @prop --highlight-color-invalid: The color of the highlight on the item when invalid. Only applies to inputs and textareas using the legacy form syntax. DEPRECATED: Highlights can be styled on `ion-input` or `ion-textarea` when using the modern form syntax.
|
||||
*/
|
||||
|
||||
/**
|
||||
* We change the minimum width as the
|
||||
* font size changes. Using a fixed minimum
|
||||
* width means that fewer and fewer characters
|
||||
* can be displayed in the same space as the
|
||||
* text grows.
|
||||
*/
|
||||
--inner-min-width: 4rem;
|
||||
--border-radius: 0px;
|
||||
--border-width: 0px;
|
||||
--border-style: solid;
|
||||
@@ -230,11 +221,6 @@
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
// Flex wrap is required here in order to wrap
|
||||
// the start slot + .item-inner content that
|
||||
// doesn't fit on the same line
|
||||
flex-wrap: wrap;
|
||||
|
||||
align-items: inherit;
|
||||
justify-content: inherit;
|
||||
|
||||
@@ -258,11 +244,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// TODO(FW-5289): remove
|
||||
:host(.item-legacy) .item-native {
|
||||
flex-wrap: unset;
|
||||
}
|
||||
|
||||
.item-native::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
@@ -307,34 +288,13 @@ button, a {
|
||||
// This is required to work with an inset highlight
|
||||
position: relative;
|
||||
|
||||
// This flex property is required in order to make
|
||||
// the elements wrap when there is a slotted start
|
||||
// element and a label
|
||||
flex: 1 0 0;
|
||||
flex: 1;
|
||||
|
||||
flex-direction: inherit;
|
||||
|
||||
// Flex wrap is required here in order to wrap
|
||||
// .input-wrapper content + the end slot that
|
||||
// doesn't fit on the same line
|
||||
flex-wrap: wrap;
|
||||
|
||||
align-items: inherit;
|
||||
align-self: stretch;
|
||||
|
||||
/**
|
||||
* The min-width defines when the
|
||||
* content in the default slot should
|
||||
* stop wrapping/truncating within its own
|
||||
* container. At this point the entire
|
||||
* container will wrap to the next line.
|
||||
*/
|
||||
min-width: var(--inner-min-width);
|
||||
|
||||
// Max width must be set to 100%, otherwise the
|
||||
// elements will overflow this container instead
|
||||
// of wrapping
|
||||
max-width: 100%;
|
||||
min-height: inherit;
|
||||
|
||||
border-width: var(--inner-border-width);
|
||||
@@ -346,15 +306,6 @@ button, a {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// TODO(FW-5289): remove
|
||||
:host(.item-legacy) .item-inner {
|
||||
flex: 1;
|
||||
|
||||
flex-wrap: unset;
|
||||
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
// Item Bottom
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -448,38 +399,19 @@ button, a {
|
||||
// This flex property is required in order to keep
|
||||
// the label from shrinking when there are wide
|
||||
// elements next to it
|
||||
flex: 1 0 auto;
|
||||
flex: 1;
|
||||
|
||||
flex-direction: inherit;
|
||||
|
||||
// Flex wrap is required here in order to wrap
|
||||
// content in the default slot (such as a label
|
||||
// and a button) that doesn't fit on the same line
|
||||
flex-wrap: wrap;
|
||||
|
||||
align-items: inherit;
|
||||
align-self: stretch;
|
||||
|
||||
// Max width must be set to 100%, otherwise the
|
||||
// elements will overflow this container instead
|
||||
// of wrapping
|
||||
max-width: 100%;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
overflow: inherit;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// TODO(FW-5289): remove
|
||||
:host(.item-legacy) .input-wrapper {
|
||||
flex: 1;
|
||||
|
||||
flex-wrap: unset;
|
||||
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
:host(.item-label-stacked),
|
||||
:host(.item-label-floating) {
|
||||
align-items: start;
|
||||
|
||||
@@ -150,6 +150,12 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
||||
|
||||
@State() counterString: string | null | undefined;
|
||||
|
||||
@Watch('button')
|
||||
buttonChanged() {
|
||||
// Update the focusable option when the button option is changed
|
||||
this.focusable = this.isFocusable();
|
||||
}
|
||||
|
||||
@Watch('counterFormatter')
|
||||
counterFormatterChanged() {
|
||||
this.updateCounterOutput(this.getFirstInput());
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 39 KiB |
22
core/src/components/item/test/item.spec.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { h } from '@stencil/core';
|
||||
import { newSpecPage } from '@stencil/core/testing';
|
||||
|
||||
import { Item } from '../item';
|
||||
|
||||
describe('item', () => {
|
||||
it('should change focusable option after switching button option status', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Item],
|
||||
template: () => <ion-item button={false}></ion-item>,
|
||||
});
|
||||
|
||||
const item = page.body.querySelector('ion-item')!;
|
||||
// Change button attribute to true
|
||||
item.setAttribute('button', 'true');
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
// Check if it has the expected class that gives the highlight style to .item-highlight element
|
||||
expect(item).toHaveClass('ion-focusable');
|
||||
});
|
||||
});
|
||||
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 238 KiB |
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 20 KiB |