Compare commits

..

78 Commits

Author SHA1 Message Date
Sean Perkins
918edf2f72 feat(input): mask controller set-up (#27346)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

N/A

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

Introduces a `MaskController` class to handle the implementation details
of input masking. The implementation is stubbed out to guide future PRs
that will implement the underlying details.

The design is implemented based on
[maskito](https://github.com/Tinkoff/maskito). Ionic Framework supports
newer versions of Firefox than this library targets, so we can diverge
on the implementation and access modern APIs in portions of the
implementation.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

In terms of testing, you could run the mask test template and verify
that different `console.debug` messages are logging when interacting
with the control.
2023-05-05 13:38:36 -04:00
Sean Perkins
ba894d05a8 feat(input): component api for input masking (#27339)
Issue number: Internal

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

N/A

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Adds `mask`, `maskVisibility` and `maskPlaceholder` properties to
`ion-input` for input masking

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------
2023-05-03 15:25:24 -04:00
Sean Perkins
9313a914b7 fix(overlays): assign incremental id to overlay host (#27278)
Issue number: Internal

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The counter for incrementing the `id` and `z-index` of an overlay is
incremented whenever the `connectedCallback` is fired for an overlay.

When an overlay is presented and/or conditionally rendered, the overlay
`id` can increment by `n+2` instead of `n+1`.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Increments all overlay ids consistently
- Removes legacy `ion-modal-{id}` and `ion-popover-{id}` logic
- Adds unit tests for the id behavior
- Tests are split up into separate files so that the counter is always
starting from `0`
- Adds an integration test with the Angular test app to verify
conditional rendering behavior

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-03 17:24:19 +00:00
Liam DeBeasi
27a9aaaedc chore(ci): update workflow for upcoming deprecation (#27366)
Issue number: N/A

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

`set-output` usage is deprecated in favor of environment files.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updates the `test-core-screenshot` workflow to remove `set-output` in
favor of environment files.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-03 17:09:03 +00:00
Liam DeBeasi
35256d70ec test(radio, radio-group): migrate to generators (#27365)
Issue number: N/A

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Radio and radio group tests are using legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Radio and radio group tests are using generator syntax 


c0256f3ce1

- The radio group basic interaction tests do not vary across modes, so I
removed those extra checks.


579bcacab2

- The basic radio directory had some old screenshots that were not being
used, so I removed them.


997d652864

- The legacy radio keyboard behavior does not vary across modes, so I
removed that extra check

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-03 15:53:35 +00:00
Liam DeBeasi
ce0767bbb0 test(tabs, tab-bar, tab-button): migrate to generators (#27356)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Tabs, tab bar, and tab button are using legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Tabs, tab bar, and tab button are using modern syntax


962754d094

- A translucent screenshot test was written in `tab-bar/test/basic` but
it is already being tested in `tab-bar/test/translucent`, so I deleted
the duplicate test/screenshots.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-03 15:51:48 +00:00
Liam DeBeasi
b1369a94ae test(picker-internal, picker-column-internal): migrate to generators (#27354)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Picker internal and picker column internal tests are using legacy
syntax.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Picker internal and picker column internal tests use generator syntax.


38187b744c

I updated these tests to disable multi-mode and direction testing since
the behaviors this file is testing do not vary across modes/directions.


89436784b0

- I removed the RTL screenshots here because the disabled state does not
vary across directions.


8d31eba5f2

- I removed the RTL screenshots here because the overlay rendering
behavior does not vary across directions. There is RTL behavior that we
need to test, but that is already captured in the screenshots in
`picker-internal/basic`.


d2a1531e6a

- Removed the mode and direction tests because this behavior does not
vary across modes/directions.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-03 15:22:39 +00:00
Liam DeBeasi
c98ad6f16a fix(modal, popover): wait for contents to mount (#27344)
Issue number: resolves #27343

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

In
30e3a1485d
I removed the `deepWait` call from popover/modal in custom element
bundle environments (React and Vue as of writing). This had an
unintended side effect where WebKit/iOS would not play the modal enter
animation correctly because the inner contents are mounted
mid-animation. This does not impact other mobile platforms.

This only impacted the modal because popover had a patch in
be9a399eee
which causes it to wait for the JS Framework to finish mounting before
proceeding with the transition.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Modal now emits `ionMount` event and waits 2 frames before proceeding
with the animation.

Note 1: The JS Framework overlay components were already updated to
support this `ionMount` event in
be9a399eee.

I also updated the modal Angular component to listen for `ionMount`. It
is not needed right now because Angular does not use the custom elements
bundle and therefore does not call `ionMount` (it runs the `deepReady`
function though). However, if we move Angular to support the custom
elements bundle in the future this may become an issue. This behavior
currently exists in the popover component for Angular too.

Note 2: This does appear to be a WebKit bug since it does not happen on
Android. However, this patch seems fairly safe which is why I've opted
to try and fix it internally instead of waiting for a patch from Apple.


| before | after |
| - | - |
| <video
src="https://user-images.githubusercontent.com/2721089/235495325-2f258526-0c43-422b-84c3-ac4f5e228bbd.MP4"></video>
| <video
src="https://user-images.githubusercontent.com/2721089/235495362-9b3bb35d-782c-4a8f-ac13-8aaa8f17729b.MP4"></video>
|


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-03 14:32:25 +00:00
Brandy Carney
f27c899d13 chore: remove unnecessary comments in PR template (#27358)
Removes the comments about reading the contributing guide from our pull
request template. GitHub recommends the contributing guide in a popup to
new contributors, and it also recommends it if anything has changed
recently.
2023-05-03 13:56:50 +00:00
Liam DeBeasi
16ee234258 merge release-7.0.5
Release 7.0.5
2023-05-03 09:17:41 -04:00
ionitron
4804b67785 chore(): update package lock files 2023-05-03 12:49:38 +00:00
ionitron
55a3d0fd14 v7.0.5 2023-05-03 12:49:22 +00:00
Liam DeBeasi
df3aaff7c3 test(picker, picker-column): migrate to generators (#27352)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Picker and picker column tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Picker and picker column tests use generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-02 15:38:00 +00:00
Sean Perkins
19c53c471b chore(react,react-router): bump typescript dev dependency to v4 (#27348)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Both react and the react-router packages are on v3 of Typescript. 

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updates the react and reac-router package to a minimum dev-dependency
of Typescript 4.0.5 (aligning with core)
- Fixes a conflict with the react router types when upgrading to v4 of
Typescript

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-02 14:30:46 +00:00
Liam DeBeasi
ce863354e4 test(textarea): migrate to generators (#27349)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Textarea tests are using legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Textarea tests use generator syntax

A few notable changes:


3d44815462

I removed the RTL tests as autogrow behavior does not vary across
directions. I removed the associated screenshot files too.


4fcb9a8c57

I added an `index.html` file as per the E2E test best practices. There
were some screenshots that were no longer in use, so I removed them.


753d95fd55

There were some screenshots that were not being tested here as well in
the `bottom-content.e2e-legacy.ts` directories (the associated test file
no longer exists).


bc0d15fed6

I updated the legacy autogrow tests to not check RTL. Same reasoning as
the other autogrow tests above.


3c373b5aef

I updated the event tests to not run across modes because that behavior
does not vary.


All other tests were ported directly to generator syntax.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-02 12:49:52 +00:00
dependabot[bot]
557f6ea97f chore(deps): bump @stencil/core from 3.2.1 to 3.2.2 in /core (#27350)
Bumps [@stencil/core](https://github.com/ionic-team/stencil) from 3.2.1
to 3.2.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/stencil/releases"><code>@​stencil/core</code>'s
releases</a>.</em></p>
<blockquote>
<h2>🏒 3.2.2 (2023-05-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>declarations:</strong> add <code>onCancel</code> to dialog
attributes (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4280">#4280</a>)
(<a
href="725ff7e5a4">725ff7e</a>),
fixes <a
href="https://redirect.github.com/ionic-team/stencil/issues/4267">#4267</a></li>
<li><strong>runtime:</strong> initialize custom elements even when there
is no styles (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4296">#4296</a>)
(<a
href="23f1e66fb1">23f1e66</a>),
fixes <a
href="https://redirect.github.com/ionic-team/stencil/issues/4221">#4221</a></li>
<li><strong>testing:</strong> jest component disconnected callback (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4269">#4269</a>)
(<a
href="4ec3b69445">4ec3b69</a>),
fixes <a
href="https://redirect.github.com/ionic-team/stencil/issues/4053">#4053</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/stencil/blob/main/CHANGELOG.md"><code>@​stencil/core</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>🏒 <a
href="https://github.com/ionic-team/stencil/compare/v3.2.1...v3.2.2">3.2.2</a>
(2023-05-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>declarations:</strong> add <code>onCancel</code> to dialog
attributes (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4280">#4280</a>)
(<a
href="725ff7e5a4">725ff7e</a>),
fixes <a
href="https://redirect.github.com/ionic-team/stencil/issues/4267">#4267</a></li>
<li><strong>runtime:</strong> initialize custom elements even when there
is no styles (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4296">#4296</a>)
(<a
href="23f1e66fb1">23f1e66</a>),
fixes <a
href="https://redirect.github.com/ionic-team/stencil/issues/4221">#4221</a></li>
<li><strong>testing:</strong> jest component disconnected callback (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4269">#4269</a>)
(<a
href="4ec3b69445">4ec3b69</a>),
fixes <a
href="https://redirect.github.com/ionic-team/stencil/issues/4053">#4053</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="39796e2a20"><code>39796e2</code></a>
🏒 v3.2.2</li>
<li><a
href="b69cfa87ad"><code>b69cfa8</code></a>
chore(deps): update dependency ts-node to v10.9.1 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4345">#4345</a>)</li>
<li><a
href="c83c496e4a"><code>c83c496</code></a>
chore(deps): update dependency karma-jasmine to v5.1.0 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4344">#4344</a>)</li>
<li><a
href="9cc9ce3e6d"><code>9cc9ce3</code></a>
chore(test): remove strictNullChecks from remove-unused-styles (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4325">#4325</a>)</li>
<li><a
href="c3bcf0a1bd"><code>c3bcf0a</code></a>
chore(types): remove property on path normalization (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4327">#4327</a>)</li>
<li><a
href="4ab9083e33"><code>4ab9083</code></a>
chore(test): fix worker-manager snc violations (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4326">#4326</a>)</li>
<li><a
href="a4feb66c56"><code>a4feb66</code></a>
chore(deps): update dependency karma-chrome-launcher to v3.2.0 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4342">#4342</a>)</li>
<li><a
href="670caeb19a"><code>670caeb</code></a>
chore(deps): update node.js to v12.22.12 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4337">#4337</a>)</li>
<li><a
href="6deef286b2"><code>6deef28</code></a>
chore(deps): update dependency <code>@​types/node</code> to v18.16.0 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4341">#4341</a>)</li>
<li><a
href="cdc7c15127"><code>cdc7c15</code></a>
chore(deps): update actions/checkout action to v3.5.2 (<a
href="https://redirect.github.com/ionic-team/stencil/issues/4338">#4338</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/ionic-team/stencil/compare/v3.2.1...v3.2.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@stencil/core&package-manager=npm_and_yarn&previous-version=3.2.1&new-version=3.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 03:08:36 +00:00
Liam DeBeasi
aae9b61f76 test(input): migrate to generators (#27321)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Input tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Input tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-05-01 21:30:17 +00:00
Liam DeBeasi
02d722e9e1 chore(): add missing screenshot function (#27334)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
 
item sliding tests were missing a `screenshot` function

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Added the function
- Also removed stray `config` params

This was not caught because these tests are currently skipped.


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 20:31:37 +00:00
Sean Perkins
0bb84bb1c0 test(radio): enable keyboard tests (#27262)
Issue number: Internal

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

`Tab` keyboard navigation tests are disabled for `ion-radio` because
they were extremely flaky in CI.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Re-enables `ion-radio` `Tab` keyboard navigation tests
- Ports a slimmed down version of Wordpress' playwright utilities for
using modifier keys with `Tab` keyboard navigation on environments that
do not support "natural tab navigation"

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

This utility should likely be used in all places where we are using the
`Alt+Tab` logic for webkit-based browsers today. If/when the changes are
agreed upon, I can follow-up with PR that adds this behavior to those
tests.
2023-04-28 17:28:47 +00:00
Liam DeBeasi
fe86d9a586 test(note): migrate to generators (#27333)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Note tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Note tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 17:03:50 +00:00
Liam DeBeasi
f5e668c390 test(nav): migrate to generators (#27332)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Nav tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Nav tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 17:02:31 +00:00
Liam DeBeasi
bfe7b38831 fix(many): form components do not take up full width in slot (#27306)
Issue number: resolves #27305

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Checkbox, radio, range, select, and toggle take up 100% of its width
even when in a start/end slot.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Checkbox, radio, range, select, and toggle do not take up 100% of its
width even when in a start/end slot.
. The "no slot" behavior is unchanged and aligns with the legacy select.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 16:13:34 +00:00
Liam DeBeasi
f62ba3e8a6 test(menu): migrate to generators (#27330)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Menu sliding tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Menu sliding tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 16:07:48 +00:00
Liam DeBeasi
c3a3961478 test(item): migrate to generators (#27322)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Item tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Item tests use modern syntax


414494a56d

- This behavior does not vary across directions, so I removed the RTL
screenshots.


8e9d0d5cbd

- This behavior does not vary across directions, so I removed the RTL
screenshots.


0d46d00eb0

- This behavior does not vary across directions, so I removed the RTL
screenshots.


505c054bd8

- This behavior does not vary across directions, so I removed the RTL
screenshots.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 16:04:12 +00:00
Liam DeBeasi
32ab63ac7d test(datetime): migrate to generators (#27304)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Datetime tests use the legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Datetime tests use the generator syntax

**Note to reviewers:**

I recommend reviewing this commit by commit because datetime has a lot
of tests. A few commits I'd like to call out:


77d9ab0ff2

- I removed several screenshots that were not being tested anymore. It
seems the actual test was modified/removed in the past, but the
screenshot ground truths remained.


ed45c7fa05

- This test checks that the datetime can properly expand in width based
on the `cover` property. As a result, no RTL tests are needed because
the behavior does not vary across directions. I narrowed the config of
this test to only check LTR and removed extraneous screenshots.


96c08410f2

- This test only checks that the correct text content is used within the
component. As a result, I narrowed the config to only check LTR
direction and removed extraneous screenshots.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:56:43 +00:00
Liam DeBeasi
dc4165874a test(label): migrate to generators (#27325)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Label sliding tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Label sliding tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:50:03 +00:00
Liam DeBeasi
89f710c6c9 test(list): migrate to generators (#27327)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

List sliding tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- List sliding tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:47:32 +00:00
Liam DeBeasi
9aea956e5b test(loading): migrate to generators (#27328)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Loading sliding tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Loading sliding tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:43:35 +00:00
Liam DeBeasi
ae554165fe test(item-sliding): migrate to generators (#27324)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Item sliding tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Item sliding tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:37:34 +00:00
Liam DeBeasi
225fd2ae0e test(item-divider): migrate to generators (#27323)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Item divider tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Item divider tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:31:56 +00:00
Liam DeBeasi
d4dc29b1bc test(icon): migrate to generators (#27318)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Icon tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Icon tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:12:15 +00:00
Liam DeBeasi
17b43293bb test(img): migrate to generators (#27319)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Img tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Img tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:10:51 +00:00
Liam DeBeasi
bc05c57c3c test(infinite-scroll): migrate to generators (#27320)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Infinite scroll tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Infinite scroll tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 15:08:41 +00:00
Ryan Waskiewicz
dbb139afa0 chore(ci): fix stencil nightly legacy check (#27317)
Issue number: #

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

the legacy screenshot test verification step can fail due to improper
configuration
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

this commit updates the name of the legacy screenshot test so that we
properly gate on verifying that the legacy tests passed

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

I tested this by kicking off the workflow -
https://github.com/ionic-team/ionic-framework/actions/runs/4830665737

Yesterday, I [put up a
PR](https://github.com/ionic-team/ionic-framework/pull/27298) that did
the same. However, I failed to verify it succeeded (since we don't gate
on Stencil nightly) - only that it started (since that was the point of
failure yesterday).

Today, I have verified that it passes all the way through
![Screenshot 2023-04-28 at 9 12 25
AM](https://user-images.githubusercontent.com/1930213/235156949-67aa1b35-d141-4951-9f2c-c0722f11a520.png)

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-28 13:13:46 +00:00
Liam DeBeasi
e3a0935c95 test(header): migrate to generators (#27311)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Header tests us legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Header tests us generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 21:42:00 +00:00
Liam DeBeasi
43a61b0e46 test(checkbox): migrate to generators (#27300)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Checkbox tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Checkbox tests use generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 21:41:47 +00:00
Liam DeBeasi
a6bf51fe2f test(grid): migrate to generators (#27310)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Grid tests use legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Grid tests use modern syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 21:30:26 +00:00
Liam DeBeasi
4a25913669 test(fab, fab-button): migrate to generators (#27308)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

- Fab and fab button tests are using legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Fab and fab button tests use generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 21:27:30 +00:00
Liam DeBeasi
945624c0db test(datetime-button): migrate to generators (#27307)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Datetime button tests use the legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Datetime button tests use the generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 20:54:53 +00:00
Liam DeBeasi
293f128c14 test(footer): migrate to generators (#27309)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Footer tests us legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Footer tests us generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 20:46:07 +00:00
Liam DeBeasi
87b2aedc94 test(button): migrate to generator (#27293)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Button is using legacy test format

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Button uses generator test format 
## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 15:53:46 +00:00
Liam DeBeasi
dc0f701c39 test(content): migrate to generators (#27302)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Content tests are using legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Content tests use generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 15:36:37 +00:00
Liam DeBeasi
69ed6d9099 test(card, card-header): migrate to generators (#27299)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Card and card header are using the legacy test syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Card and card header use generators

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 15:32:11 +00:00
Liam DeBeasi
a1fca33f2d test(avatar): migrate to generators (#27288)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Avatar E2E tests are using legacy format

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- E2E tests use generator format

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 15:27:15 +00:00
Liam DeBeasi
b44ad49a4a test(chip): migrate to generators (#27301)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Chip tests are using legacy syntax

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Chip tests are using generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 15:22:59 +00:00
Liam DeBeasi
20d9d97dcf test(app): migrate to generators (#27287)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

App tests are using legacy E2E format

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- App E2E tests us generator format

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 15:10:05 +00:00
Liam DeBeasi
642faed272 test(breadcrumbs): migrate to generators (#27291)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

- Breadcrumbs uses legacy test format

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Breadcrumbs uses generator syntax

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 14:48:55 +00:00
Liam DeBeasi
1af71522f3 test(badge): migrate to generators (#27290)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Badge uses legacy test format

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Badge uses generator format

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 14:46:31 +00:00
Liam DeBeasi
667eb20b4d test(back-button): migrate to generators (#27289)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

Back button uses legacy E2E format

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Back button uses generator format

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 14:45:48 +00:00
Ryan Waskiewicz
ab992b02c6 chore(ci): fix stencil nightly job dependencies (#27298)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The Stencil nightly job fails with the following error:

```
The workflow is not valid. .github/workflows/stencil-nightly.yml (Line: 101, Col: 13): Job 'test-core-screenshot-legacy' depends on unknown job 'build-core'. 

.github/workflows/stencil-nightly.yml (Line: 122, Col: 12): Job 'verify-screenshots-legacy' depends on job 'test-core-screenshot-legacy' which creates a cycle in the dependency graph.
```

This started to fail last night. I believe this is a result of
https://github.com/ionic-team/ionic-framework/pull/27228, specifically
this line
4fe8de7df7 (diff-2f087e8fac034d51c50fc9350e10ceb4034298c16dd0d4f414f79d88ebb71aa0R101)

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

this commit updates the job dependency hierarchy for
test-core-screenshot-legacy from `build-core` to
`build-core-with-stencil-nightly`. the former is not a valid job name
for the `stencil-nightly` workflow, likely just a copy/paste error

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

To test this, I was able to kick off a version of this job with this
branch:
https://github.com/ionic-team/ionic-framework/actions/runs/4819613134
and saw the new/legacy screenshot tests running:
![Screenshot 2023-04-27 at 8 29 14
AM](https://user-images.githubusercontent.com/1930213/234862292-61896fa2-f5be-4c96-bfe3-2f2198315763.png)


<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-27 12:37:06 +00:00
Liam DeBeasi
a667b3e5b3 test(action-sheet): migrate to generator (#27246)
Issue number: N/A

---------

This PR migrates the action sheet tests to use the generator
infrastructure.
2023-04-26 20:38:45 +00:00
Liam DeBeasi
37aa7e9bdb test(alert): migrate to generator (#27247)
Issue number: N/A

---------

This PR migrates the alert tests to use the generator infrastructure.

In
91ba3a1290
I migrated the basic test to use [Playwright
Fixtures](https://playwright.dev/docs/test-fixtures#creating-a-fixture)
instead since it is a) a best practice and b) easier to add the
generator support to.
2023-04-26 20:01:28 +00:00
Liam DeBeasi
ff7e3740ad test(accordion): migrate to generator (#27243)
Issue number: N/A

---------

This PR migrates the accordion tests to use the generator
infrastructure.
2023-04-26 19:30:25 +00:00
Liam DeBeasi
1439ff9c43 test(docs): add documentation on custom Ionic functions (#27248)
Issue number: N/A

---------

This PR adds documentation for the following:

1. A step-by-step guide for migrating to generators.
2. Documentation on the custom tooling we built on top of Playwright
3. A best practice guide. Note: This was originally in the Ionic
internal Notion, but I moved it here because it is of value to community
contributors.

I also added a few new best practices that were not on the Notion guide:

- Components must have a `basic` test with an `index.html` file
- Slow tests should be broken up across multiple files for CI
performance
- Rendering and functionality tests should be broken up across multiple
test.describe blocks or files

---------

Co-authored-by: Amanda Johnston <90629384+amandaejohnston@users.noreply.github.com>
2023-04-26 19:01:13 +00:00
Liam DeBeasi
ea4c24a8af test(utils): add support for generators (#27241)
Issue number: N/A

---------

This PR adds support for writing tests with generators.


8febaddee9

- Adds the underlying generator code necessary to create multiple
variants of a single test
- Note: This PR does not add support for dark mode generators. This will
be added in a separate PR.


5c498d8daf

- Adds the type declarations on `page.goto` and `page.setContent`
necessary to accept the config result provided by the `configs`
generator function.


df8c44b563

- Updates the `goto` and `setContent` functionality to support the
generator config with backwards compatibility for the legacy tests.
2023-04-26 18:54:22 +00:00
Liam DeBeasi
4826a3d9f5 test(config): introduce legacy and modern playwright projects (#27228)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

This is the first PR to introduce the infrastructure required to add
test generators to the Ionic Framework project. This PR introduces the
file name changes necessary to support two playwright configs, so I
recommend reviewing the PR by commit:


1e5012cea1

- Created a `playwright.config-legacy.ts` file and updates
`package.json`.
- Running `npm run test.e2e` will run the generator tests, and running
`npm run test.e2e.legacy` will run the legacy tests.


4fe8de7df7

- Updates the GitHub Action scripts to run both the modern and legacy
E2E tests. I added command modifiers to avoid collisions with output
directories.


e8bcfaf926

- Updates `*.e2e.ts` files to have the legacy format name:
`*.e2e-legacy.ts`. This naming scheme is required for the two Playwright
configs to pull in the correct files. When migrating tests to
generators, team members will rename the file to remove the `-legacy`
part.


5bf196c36d
(warning: lots of files!)

- Updates the `*.e2e.ts-snapshots` directories to have the legacy format
name: `*.e2e-legacy.ts-snapshots`. The screenshot directory in
Playwright is generated based on the test file name which is why we are
updating the screenshot directory. When migrating tests to generators,
team members will rename the directory to remove the `-legacy` part.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-26 18:27:17 +00:00
Ryan Waskiewicz
eed7f50b30 chore(repo): update old heroku app links (#27284)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

there are a few outdated links to a dead heroku app in the repo

## What is the new behavior?

<!-- Please describe the behavior or changes that are being added by
this PR. -->
this commit removes old links within the repo that point to a heroku app
that is no longer working/maintained. the original intent was to update
stencil-related links initially (as stencil still focuses on slack for
community communications). however, there were two references to the
ionic worldwide slack, which has been since replaced with discord. i've
updated those link (which were only in comments) as well. after applying
this commit, there are no references to 'heroku' in the repo

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Feel free to reject this/request we remove these links altogether. I'm
not entirely sure we want to continue to provide them in the `core/` and
`angular/` directories (when we don't have them in `packages/react/` nor
`packages/vue/`
2023-04-26 15:47:46 +00:00
Shawn Taylor
db121ac473 docs(tabs): document methods only available for vanilla (#27269)
When using Angular, React, or Vue, the use of tabs is coupled to the
framework's routing. These methods are only available when using tabs
with vanilla JavaScript.

Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Adds more context to the description of the methods on tabs

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-26 14:57:00 +00:00
Liam DeBeasi
7e1f996dc6 fix(scroll-assist): set correct scroll padding (#27261)
Issue number: resolves #27257

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

1. Scroll assist was appending padding data every time it ran which
caused the amount of padding to infinitely grow until an input was
blurred
2. Calling `inputEl.focus()` caused scroll assist to run again which
caused unexpected scrolls

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- `currentPadding` is either preserved or set, never incremented
- Added a special attribute to inputs that are manually focused so
scroll assist knows not to re-run

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-26 14:50:26 +00:00
Liam DeBeasi
65245826e3 fix(toggle): swipe gesture applies to knob (#27255)
Issue number: resolves #27254

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The swipe gesture is currently applied to the entire `ion-toggle`
element. This was fine for the legacy syntax, but with the modern syntax
it means users can swipe on the label text which is not correct.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- The toggle now creates the gesture on the `.toggle-icon` element which
is the container for the knob for both modern and legacy syntaxes.
- Moved `touch-action: none` to the host of the legacy toggle. This was
preventing scrolling from happening on the modern toggle. I double
checked with native iOS and you can scroll when a pointer moves over a
toggle.

The structure of this fix was designed to match what `ion-range` does:
a8749929e0/core/src/components/range/range.tsx (L282-L296)

| Modern | Legacy |
| - | - |
| <video
src="https://user-images.githubusercontent.com/2721089/233431240-11f0c94f-d86b-4975-afd5-e534262a6f16.mov"></video>
| <video
src="https://user-images.githubusercontent.com/2721089/233431275-6c6f7fef-6cc0-4adc-8915-6fd5c3795ade.mov"></video>
|



## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-26 14:50:00 +00:00
Liam DeBeasi
8ee16f2a6b merge release-7.0.4
Release 7.0.4
2023-04-26 09:33:19 -04:00
ionitron
c9dbbc3ca5 chore(): update package lock files 2023-04-26 13:01:13 +00:00
ionitron
d9d11ede0a v7.0.4 2023-04-26 13:01:00 +00:00
Liam DeBeasi
c569761c89 chore(ci): remove --no-package-lock flag (#27276)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Original Discussion:
https://github.com/ionic-team/stencil-ds-output-targets/pull/327#discussion_r1176950960

This flag was left over from our migration from custom build scripts to
Lerna. Since we use `npm ci` the `--no-package-lock` flag is not needed.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Removes `--no-package-lock` from build scripts.
- Here is an example test run of a dev build succeeding without the
`--no-package-lock` flag:
https://github.com/ionic-team/ionic-framework/actions/runs/4801503002

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-25 20:42:45 +00:00
Sean Perkins
e501ac001c chore: angular test apps serve in dev mode (#27270)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

When adding the Angular 16 test infrastructure, I accidentally regressed
ng14/ng15 test apps to run in production mode when serving locally.

This resulted in slower serve time and the vendor code being code split,
making it difficult to debug locally.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Angular test apps run in dev mode when served locally
- Angular test apps run in prod mode when built with `npm run build`

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

We can share the same `angular.json` across all the major versions of
Angular we currently support.
2023-04-25 16:16:20 +00:00
Imre Bekker
01e028b789 fix(breadcumb): set background when focused on md (#27274)
Issue number: resolves #27273

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
When breadcrumb is focused in md mode, background is not set.

## What is the new behavior?
A slight background should have applied on breadcrumb when focused.


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-25 15:45:15 +00:00
Liam DeBeasi
0ac451998c test(many): do not await page.locator (#27267)
Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

`page.locator` is synchronous, but we were `await`ing the calls:
https://playwright.dev/docs/api/class-page#page-locator

We were also doing `page.locator(...).click()` when we can just do
`page.click([selector])` directly,

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Removes `await` usage from `page.locator`
- Removes `page.locator().click()` usage in favor of `page.click()`

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-25 12:26:17 +00:00
Maria Hutt
c267b43396 fix(modal): set default text color (#27207)
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Occurs only when using modal with datetime: text does not update
appropriately based on light or dark mode. For example, when using Ionic
dark theme, the calendar days does not switch to white.


<!-- Issues are required for both bug fixes and features. -->
Issue URL: resolves #26060 


## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Text (days and time) changes to the text color set via light (default)
or dark mode. The color change applies to days and time that are not
selected: not the current day.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Recommendation:
- Test both `datetime` and `datetime-button`

The bug originates when modal's content is not wrapped by `ion-content`
and because the modal renders outside of `<main />`. Text color is
passed to components properly inside `main` because `main` is rendered
inside another `ion-content`. `ion-content` provides the correct
text-color based on light or dark mode.

Example of text color working for modal when wrapped by `ion-content`:

```html
<ion-modal trigger="open-modal">
    ...
  <ion-content class="ion-padding">
    <div>Hello world</div>
  </ion-content>
</ion-modal>
```

However, there are times that the modal does not require this wrap:

```html
<ion-modal>
  <ion-datetime id="datetime"></ion-datetime>
</ion-modal>
```

The same bug would have occurred on `popover` if it wasn't for the fact
that the component provides the [text
color](https://github.com/ionic-team/ionic-framework/blob/main/core/src/components/popover/popover.scss#L42).

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2023-04-24 21:03:05 +00:00
Lars Mikkelsen
d425e6d4f3 chore(ci): enable npm package provenance (#27263)
See https://github.blog/2023-04-19-introducing-npm-package-provenance/
2023-04-24 13:04:10 +00:00
Liam DeBeasi
ad02058ef3 test(datetime): skip flaky tests (#27256)
Issue number: N/A

---------

These tests are flaky on CI:
https://github.com/ionic-team/ionic-framework/actions/runs/4757321510/jobs/8454046190?pr=27247

Looks like we are not waiting long enough for scrolling to finish.
2023-04-20 18:45:11 +00:00
Shawn Taylor
5a2b87cbcc fix(select): adjust label alignment when in a card (#27202)
Issue URL: resolves #27086

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
When an `ion-select` is inside a card, the label is slightly lower than
it should be, making it out of alignment with the label of an
`ion-input`.


<!-- Issues are required for both bug fixes and features. -->


## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- When inside a card, the labels of `ion-input` and `ion-select` are in
line with each other.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
This bug was occurring because the label of ion-select is in the shadow
DOM. [As
recommended](https://github.com/ionic-team/ionic-framework/issues/27086#issuecomment-1494427311),
this fix was also added to ion-input and ion-textarea in case those
labels are also later moved to the shadow DOM.


Before:
<img width="534" alt="Screenshot 2023-04-13 at 4 35 44 PM"
src="https://user-images.githubusercontent.com/14926794/231877123-02f8e381-2137-4d3c-8dab-ae9051ad3591.png">

After:
<img width="535" alt="Screenshot 2023-04-13 at 4 36 02 PM"
src="https://user-images.githubusercontent.com/14926794/231877151-bd49b87b-762a-4d20-b6b7-57c1ab3bb368.png">

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2023-04-20 17:53:43 +00:00
Liam DeBeasi
a8749929e0 fix(ios): scroll assist sizes input correctly (#27253)
Issue number: resolves #27249

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The cloned input/textarea for scroll assist is not sized correctly. For
legacy inputs, this causes the clone to be off by ~1px because it does
not have the correct height. For modern inputs, this causes the same bug
as the legacy inputs plus cloned inputs overlap any floating/stacked
labels. This was not a concern for legacy inputs because those inputs
did not contain the label element where modern inputs do.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Sets `bottom: 0` for cloned inputs so they have the correct height
- Sets `position: relative` on the `.native-wrapper` so the cloned input
does not flow outside of the parent container.

**Before**

| Modern Input | Legacy Input |
| - | - |
| <video
src="https://user-images.githubusercontent.com/2721089/233385644-3c15f98e-2646-41e1-b206-34c505791bde.MP4"></video>
| <video
src="https://user-images.githubusercontent.com/2721089/233385681-8d682222-44b4-4cdc-b0de-96ed3fd38792.MP4"></video>
|


(Note: The legacy input bug is subtle -- the input only shifts by ~1px)

**After**

| Modern Input | Legacy Input |
| - | - |
| <video
src="https://user-images.githubusercontent.com/2721089/233385911-243dea95-39b4-4d81-bfe9-26e52382a702.mp4"></video>
| <video
src="https://user-images.githubusercontent.com/2721089/233386237-2c9eede3-ca91-429b-8a35-15428529a883.mp4"></video>
|


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-20 15:57:56 +00:00
Sean Perkins
550e166d9c test(picker-internal): enable overlay tests (#27128)
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Picker internal overlay tests are disabled.

<!-- Issues are required for both bug fixes and features. -->
Issue URL: Internal


## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Enables picker internal overlay tests
- Fixes issue with screenshot captures

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2023-04-20 12:57:58 +00:00
Sean Perkins
beb46bf9de fix(react): nav will remove components from the DOM (#25763)
Issue #: resolves #25753

----------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

## Pull request checklist

Please check if your PR fulfills the following requirements:
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been reviewed and added / updated if needed (for bug
fixes / features)
- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See the [contributing
guide](https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation)
for details.
- [x] Build (`npm run build`) was run locally and any changes were
pushed
- [x] Lint (`npm run lint`) has passed locally and any fixes were made
for failures


## Pull request type

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type, submit multiple
pull requests if needed. -->

Please check the type of change your PR introduces:
- [x] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] Documentation content changes
- [ ] Other (please describe): 


## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

When `IonNav` performs a pop operation (navigating to root, back, etc.)
the views are not removed from the DOM.

<!-- Issues are required for both bug fixes and features. -->


## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- `IonNav` removes pages from the DOM when they are popped (navigate
back, navigate to root, etc.)
- Memoized constructing React delegate (was reconstructing on each
render)

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2023-04-19 17:03:24 +00:00
Sean Perkins
6f910576e2 chore: add angular 16 test infrastructure (#27209)
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->


<!-- Issues are required for both bug fixes and features. -->
Issue URL: Internal


## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Adds Angular 16 test app
- Introduces version test to validate which major version of Angular is
being tested

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2023-04-19 15:27:04 +00:00
Liam DeBeasi
678da3db36 merge release-7.0.3
Release 7.0.3
2023-04-19 10:14:25 -04:00
Liam DeBeasi
29bef31e0f chore(): clean up changelog 2023-04-19 09:35:25 -04:00
ionitron
3dc319e6e9 chore(): update package lock files 2023-04-19 13:30:07 +00:00
2531 changed files with 42428 additions and 9745 deletions

View File

@@ -270,6 +270,8 @@ npm install file:/~/ionic-vue-router-7.0.1.tgz
3. If a new test is needed, the easiest way is to copy the `basic/` directory from the component's `test/` directory, rename it, and edit the content in both the `index.html` and `e2e.ts` file (see [Screenshot Tests](#screenshot-tests) for more information on this file).
4. The `preview/` directory is used in the documentation as a demo. Only update this test if there is a bug in the test or if the API has a change that hasn't been updated in the test.
See [Ionic's E2E testing guide](../core/src/utils/test/playwright/docs/README.md) for information regarding the tools you can use to test Ionic.
##### Screenshot Tests
1. If the test exists in screenshot, there will be a file named `e2e.ts` in the directory of the test.

View File

@@ -2,7 +2,7 @@
<!-- Please make sure you are posting an issue pertaining to the Ionic Framework. If you are having an issue with the Ionic Appflow services (Ionic View, Ionic Deploy, etc.) please consult the Ionic Appflow support portal (https://ionic.zendesk.com/hc/en-us) -->
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/ -->
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or https://ionic.link/discord/ -->
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
@@ -17,7 +17,7 @@
[ ] bug report
[ ] feature request
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/ -->
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or https://ionic.link/discord -->
**Current behavior:**
<!-- Describe how the bug manifests. -->

View File

@@ -2,13 +2,9 @@ Issue number: #
---------
<!-- Please refer to our contributing documentation for any questions on submitting a pull request, or let us know here if you need any help: https://ionicframework.com/docs/building/contributing -->
<!-- Please do not submit updates to dependencies unless it fixes an issue. -->
<!-- Some docs updates need to be made in the `ionic-docs` repo, in a separate PR. See https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation for details. -->
<!-- Please do not submit updates to dependencies unless it fixes an issue. -->
<!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. -->
<!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. -->
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

View File

@@ -22,6 +22,9 @@ runs:
- uses: actions/setup-node@v3
with:
node-version: 16.x
- name: Install latest npm
run: npm install -g npm@latest
shell: bash
- name: Install Dependencies
run: lerna bootstrap --include-dependencies --scope ${{ inputs.scope }} --ignore-scripts -- --legacy-peer-deps
shell: bash
@@ -41,6 +44,6 @@ runs:
env:
NPM_TOKEN: ${{ inputs.token }}
- name: Publish to NPM
run: npm publish ${{ inputs.folder }} --tag ${{ inputs.tag }}
run: npm publish ${{ inputs.folder }} --tag ${{ inputs.tag }} --provenance
shell: bash
working-directory: ${{ inputs.working-directory }}

View File

@@ -29,7 +29,7 @@ runs:
shell: bash
working-directory: ./angular/test
- name: Install Dependencies
run: npm install
run: npm install --legacy-peer-deps
shell: bash
working-directory: ./angular/test/build/${{ inputs.app }}
- name: Sync Built Changes

View File

@@ -7,6 +7,9 @@ inputs:
description: 'Playwright total number of test shards (ex: 4)'
update:
description: 'Whether or not to update the reference snapshots'
commandModifier:
description: 'Command modifier to run. This is should only be used to temporarily run legacy E2E tests as we migrate to the generator infrastructure.'
runs:
using: 'composite'
steps:
@@ -24,7 +27,7 @@ runs:
working-directory: ./core
- name: Test
if: inputs.update != 'true'
run: npm run test.e2e -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
run: npm run test.e2e${{ inputs.commandModifier }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
shell: bash
working-directory: ./core
- name: Test and Update
@@ -46,14 +49,14 @@ 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${{ inputs.commandModifier }} -- --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
if [ -d core/updated-screenshots/core ]; then
echo "::set-output name=hasUpdatedScreenshots::$(echo 'true')"
echo "hasUpdatedScreenshots=$(echo 'true')" >> $GITHUB_OUTPUT
cd core/updated-screenshots
zip -q -r ../../UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip core
zip -q -r ../../UpdatedScreenshots${{ inputs.commandModifier }}-${{ inputs.shard }}-${{ inputs.totalShards }}.zip core
fi
shell: bash
working-directory: ./core
@@ -61,8 +64,8 @@ runs:
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
uses: actions/upload-artifact@v3
with:
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
name: updated-screenshots${{ inputs.commandModifier }}-${{ inputs.shard }}-${{ inputs.totalShards }}
path: UpdatedScreenshots${{ inputs.commandModifier }}-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
- name: Archive Test Results
# The always() ensures that this step
# runs even if the previous step fails.
@@ -73,6 +76,6 @@ runs:
if: always()
uses: ./.github/workflows/actions/upload-archive
with:
name: test-results-${{ inputs.shard }}-${{ inputs.totalShards }}
output: core/TestResults-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
name: test-results${{ inputs.commandModifier }}-${{ inputs.shard }}-${{ inputs.totalShards }}
output: core/TestResults${{ inputs.commandModifier }}-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
paths: core/playwright-report

View File

@@ -81,6 +81,45 @@ jobs:
if: ${{ needs.test-core-screenshot.result != 'success' }}
run: exit 1
test-core-screenshot-legacy:
strategy:
matrix:
# Divide the tests into n buckets
# and run those buckets in parallel.
# To increase the number of shards,
# add new items to the shard array
# and change the value of totalShards
# to be the length of the shard array.
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
totalShards: [20]
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
totalShards: ${{ matrix.totalShards }}
commandModifier: '.legacy'
# Screenshots are required to pass
# in order for the branch to be merge
# eligible. However, the screenshot tests
# are run on n runners where n can change
# over time. The verify-screenshots step allows
# us to have a required status check for screenshot
# results without having to manually add each
# matrix run in the branch protection rules
# Source: https://github.community/t/status-check-for-a-matrix-jobs/127354
verify-screenshots-legacy:
if: ${{ always() }}
needs: test-core-screenshot-legacy
runs-on: ubuntu-latest
steps:
- name: Check build matrix status
if: ${{ needs.test-core-screenshot-legacy.result != 'success' }}
run: exit 1
build-vue:
needs: [build-core]
runs-on: ubuntu-latest
@@ -135,7 +174,7 @@ jobs:
strategy:
fail-fast: false
matrix:
apps: [ng14, ng15]
apps: [ng14, ng15, ng16]
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:

View File

@@ -14,7 +14,7 @@ jobs:
# as lerna will fail when there is a leading 0
# See https://github.com/lerna/lerna/issues/2840
- name: Install Dependencies
run: npm ci --no-package-lock
run: npm ci
shell: bash
- id: create-dev-hash
name: Create Dev Hash
@@ -24,6 +24,8 @@ jobs:
release-ionic:
needs: [create-dev-hash]
permissions:
id-token: write
uses: ./.github/workflows/release-ionic.yml
with:
tag: dev

View File

@@ -17,7 +17,7 @@ jobs:
# as lerna will fail when there is a leading 0
# See https://github.com/lerna/lerna/issues/2840
- name: Install Dependencies
run: npm ci --no-package-lock
run: npm ci
shell: bash
- id: create-nightly-hash
name: Create Nightly Hash
@@ -29,6 +29,8 @@ jobs:
release-ionic:
needs: [create-nightly-hash]
permissions:
id-token: write
uses: ./.github/workflows/release-ionic.yml
with:
tag: nightly

View File

@@ -36,6 +36,8 @@ on:
jobs:
release-ionic:
permissions:
id-token: write
uses: ./.github/workflows/release-ionic.yml
with:
tag: ${{ inputs.tag }}

View File

@@ -87,6 +87,45 @@ jobs:
if: ${{ needs.test-core-screenshot.result != 'success' }}
run: exit 1
test-core-screenshot-legacy:
strategy:
matrix:
# Divide the tests into n buckets
# and run those buckets in parallel.
# To increase the number of shards,
# add new items to the shard array
# and change the value of totalShards
# to be the length of the shard array.
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
totalShards: [20]
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
totalShards: ${{ matrix.totalShards }}
commandModifier: '.legacy'
# Screenshots are required to pass
# in order for the branch to be merge
# eligible. However, the screenshot tests
# are run on n runners where n can change
# over time. The verify-screenshots step allows
# us to have a required status check for screenshot
# results without having to manually add each
# matrix run in the branch protection rules
# Source: https://github.community/t/status-check-for-a-matrix-jobs/127354
verify-screenshots-legacy:
if: ${{ always() }}
needs: test-core-screenshot-legacy
runs-on: ubuntu-latest
steps:
- name: Check build matrix status
if: ${{ needs.test-core-screenshot-legacy.result != 'success' }}
run: exit 1
build-vue:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest

View File

@@ -3,7 +3,35 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.0.3](https://github.com/ionic-team/ionic-framework/compare/v7.0.1...v7.0.3) (2023-04-19)
## [7.0.5](https://github.com/ionic-team/ionic-framework/compare/v7.0.4...v7.0.5) (2023-05-03)
### Bug Fixes
* **many:** form components do not take up full width in slot ([#27306](https://github.com/ionic-team/ionic-framework/issues/27306)) ([bfe7b38](https://github.com/ionic-team/ionic-framework/commit/bfe7b388318aca98014a0748f678e41a0f3910ae)), closes [#27305](https://github.com/ionic-team/ionic-framework/issues/27305)
* **scroll-assist:** set correct scroll padding ([#27261](https://github.com/ionic-team/ionic-framework/issues/27261)) ([7e1f996](https://github.com/ionic-team/ionic-framework/commit/7e1f996dc63cd414b30b22aebbfc09b0b6b4f6fc)), closes [#27257](https://github.com/ionic-team/ionic-framework/issues/27257)
* **toggle:** swipe gesture applies to knob ([#27255](https://github.com/ionic-team/ionic-framework/issues/27255)) ([6524582](https://github.com/ionic-team/ionic-framework/commit/65245826e3a775bcb8a5d6cfd05230f53470fc66)), closes [#27254](https://github.com/ionic-team/ionic-framework/issues/27254)
## [7.0.4](https://github.com/ionic-team/ionic-framework/compare/v7.0.3...v7.0.4) (2023-04-26)
### Bug Fixes
* **breadcumb:** set background when focused on md ([#27274](https://github.com/ionic-team/ionic-framework/issues/27274)) ([01e028b](https://github.com/ionic-team/ionic-framework/commit/01e028b789f84e80f20ce2be7be7f8519f925211)), closes [#27273](https://github.com/ionic-team/ionic-framework/issues/27273)
* **ios:** scroll assist sizes input correctly ([#27253](https://github.com/ionic-team/ionic-framework/issues/27253)) ([a874992](https://github.com/ionic-team/ionic-framework/commit/a8749929e01b07043631fbc8c522d39cbc3ae798)), closes [#27249](https://github.com/ionic-team/ionic-framework/issues/27249)
* **modal:** set default text color ([#27207](https://github.com/ionic-team/ionic-framework/issues/27207)) ([c267b43](https://github.com/ionic-team/ionic-framework/commit/c267b43396057d9fab344a30bd83d00523911dc1)), closes [#26060](https://github.com/ionic-team/ionic-framework/issues/26060) [/github.com/ionic-team/ionic-framework/blob/main/core/src/components/popover/popover.scss#L42](https://github.com//github.com/ionic-team/ionic-framework/blob/main/core/src/components/popover/popover.scss/issues/L42)
* **react:** nav will remove components from the DOM ([#25763](https://github.com/ionic-team/ionic-framework/issues/25763)) ([beb46bf](https://github.com/ionic-team/ionic-framework/commit/beb46bf9def466c4bf54aeed2b5ccdcfcf5cd579)), closes [#25753](https://github.com/ionic-team/ionic-framework/issues/25753)
* **select:** adjust label alignment when in a card ([#27202](https://github.com/ionic-team/ionic-framework/issues/27202)) ([5a2b87c](https://github.com/ionic-team/ionic-framework/commit/5a2b87cbcc5c789d02b29e776e2b9768d7ad5631)), closes [#27086](https://github.com/ionic-team/ionic-framework/issues/27086)
## [7.0.3](https://github.com/ionic-team/ionic-framework/compare/v7.0.2...v7.0.3) (2023-04-19)
### Bug Fixes
@@ -11,13 +39,9 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
* **accordion:** inset style respects animated property ([#27173](https://github.com/ionic-team/ionic-framework/issues/27173)) ([114fe28](https://github.com/ionic-team/ionic-framework/commit/114fe28f3cc9ee52bc5eefa569353f490ab01023)), closes [#27047](https://github.com/ionic-team/ionic-framework/issues/27047)
* **datetime:** clamp date between min and max when using month picker ([#27185](https://github.com/ionic-team/ionic-framework/issues/27185)) ([0385c08](https://github.com/ionic-team/ionic-framework/commit/0385c0862c98c9387b38d3a4416d74a2cc132ddd)), closes [#27027](https://github.com/ionic-team/ionic-framework/issues/27027)
* **input:** string values are emitted ([#27226](https://github.com/ionic-team/ionic-framework/issues/27226)) ([cdb0627](https://github.com/ionic-team/ionic-framework/commit/cdb0627c87299ba36da670c81f9d4e3446bb500d))
* **item:** ios active state has correct contrast ([#27134](https://github.com/ionic-team/ionic-framework/issues/27134)) ([bbdb0ca](https://github.com/ionic-team/ionic-framework/commit/bbdb0ca480d7cd46c030d1947ced712653cf122b)), closes [#000](https://github.com/ionic-team/ionic-framework/issues/000) [#000](https://github.com/ionic-team/ionic-framework/issues/000)
* **many:** dynamic label support for modern form controls ([#27156](https://github.com/ionic-team/ionic-framework/issues/27156)) ([30b548b](https://github.com/ionic-team/ionic-framework/commit/30b548b167883f0a657b0410d3bcf76dbb6895e0)), closes [#27085](https://github.com/ionic-team/ionic-framework/issues/27085)
* **menu:** export menu interfaces ([#27227](https://github.com/ionic-team/ionic-framework/issues/27227)) ([80d8c66](https://github.com/ionic-team/ionic-framework/commit/80d8c667666ffdb6b8e668ef94cc58a93045bd0e))
* **menu:** refs are not destroyed on unmount ([#27141](https://github.com/ionic-team/ionic-framework/issues/27141)) ([b81b0d1](https://github.com/ionic-team/ionic-framework/commit/b81b0d14258d7b8caf028e6cfe81772ed2f5f119)), closes [/github.com/ionic-team/ionic-framework/blob/687b37ad3e3237b874473817bb7b59143ac113ce/packages/core/src/components/menu/menu.tsx#L136-L137](https://github.com//github.com/ionic-team/ionic-framework/blob/687b37ad3e3237b874473817bb7b59143ac113ce/packages/core/src/components/menu/menu.tsx/issues/L136-L137)
* **radio:** takes up full height in item ([#27168](https://github.com/ionic-team/ionic-framework/issues/27168)) ([987c79f](https://github.com/ionic-team/ionic-framework/commit/987c79f05b6791084c4526d80c8c28a28047dd58)), closes [/github.com/ionic-team/ionic-framework/blob/cb8f07c5530ffc222580a3e3bae8dc85f62c73e5/core/src/components/checkbox/checkbox.scss#L42](https://github.com//github.com/ionic-team/ionic-framework/blob/cb8f07c5530ffc222580a3e3bae8dc85f62c73e5/core/src/components/checkbox/checkbox.scss/issues/L42) [/github.com/ionic-team/ionic-framework/blob/cb8f07c5530ffc222580a3e3bae8dc85f62c73e5/core/src/components/toggle/toggle.scss#L43](https://github.com//github.com/ionic-team/ionic-framework/blob/cb8f07c5530ffc222580a3e3bae8dc85f62c73e5/core/src/components/toggle/toggle.scss/issues/L43)
* **segment-button:** update checked state on render ([#26970](https://github.com/ionic-team/ionic-framework/issues/26970)) ([16aa977](https://github.com/ionic-team/ionic-framework/commit/16aa9770bba983705d807ad363498693a0e7969b)), closes [#26830](https://github.com/ionic-team/ionic-framework/issues/26830)
* **segment:** segment disables segment buttons created asyncronously ([#27155](https://github.com/ionic-team/ionic-framework/issues/27155)) ([ad6b130](https://github.com/ionic-team/ionic-framework/commit/ad6b1301cf8528f7c9ad3c52730f01861117b380))
* **select:** respect --border-radius with modern template ([#27213](https://github.com/ionic-team/ionic-framework/issues/27213)) ([6ffbdbb](https://github.com/ionic-team/ionic-framework/commit/6ffbdbb3b2b69290cf25753d535bc7483bd7c6e8)), closes [#27208](https://github.com/ionic-team/ionic-framework/issues/27208)
* **select:** text does not overlap icon ([#27125](https://github.com/ionic-team/ionic-framework/issues/27125)) ([6fc0024](https://github.com/ionic-team/ionic-framework/commit/6fc002458ad23b129a214fd34d3a2fdc33800373)), closes [#27081](https://github.com/ionic-team/ionic-framework/issues/27081)
* **textarea:** legacy textarea respects padding ([#27219](https://github.com/ionic-team/ionic-framework/issues/27219)) ([742d429](https://github.com/ionic-team/ionic-framework/commit/742d4295ddfe40c643d9dd21ffc6d9fb3eb6f717)), closes [#27218](https://github.com/ionic-team/ionic-framework/issues/27218)

View File

@@ -3,7 +3,23 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.0.3](https://github.com/ionic-team/ionic/compare/v7.0.1...v7.0.3) (2023-04-19)
## [7.0.5](https://github.com/ionic-team/ionic-framework/compare/v7.0.4...v7.0.5) (2023-05-03)
**Note:** Version bump only for package @ionic/angular
## [7.0.4](https://github.com/ionic-team/ionic-framework/compare/v7.0.3...v7.0.4) (2023-04-26)
**Note:** Version bump only for package @ionic/angular
## [7.0.3](https://github.com/ionic-team/ionic/compare/v7.0.2...v7.0.3) (2023-04-19)
**Note:** Version bump only for package @ionic/angular

View File

@@ -10,7 +10,7 @@ Ionic Angular specific building blocks on top of [@ionic/core](https://www.npmjs
* [Ionic Forum](https://forum.ionicframework.com/)
* [Ionicons](http://ionicons.com/)
* [Stencil](https://stenciljs.com/)
* [Stencil Worldwide Slack](https://stencil-worldwide.herokuapp.com/)
* [Stencil Worldwide Slack](https://stencil-worldwide.slack.com/)
* [Capacitor](https://capacitor.ionicframework.com/)

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular",
"version": "7.0.3",
"version": "7.0.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular",
"version": "7.0.3",
"version": "7.0.5",
"license": "MIT",
"dependencies": {
"@ionic/core": "^7.0.3",
"@ionic/core": "^7.0.5",
"ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0",
"tslib": "^2.3.0"
@@ -1227,19 +1227,19 @@
"dev": true
},
"node_modules/@ionic/core": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.0.2.tgz",
"integrity": "sha512-GxQsMmsyBGeK9khIPNR3zw3WvDZj3I0inKtPcd/s9hEnfndAlFFI9gckB7/zrp55xoknCRwqAYT8sGWze3sn2w==",
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.0.5.tgz",
"integrity": "sha512-dcuE/PEF+GHsPEsLppUASSwWnzVcxFZE7uPMDzTwUPMOFTTaRgWbPxIly/4/VRbV6GSL6MEcuVVxhEdWjSODTg==",
"dependencies": {
"@stencil/core": "^3.2.1",
"@stencil/core": "^3.2.2",
"ionicons": "^7.1.0",
"tslib": "^2.1.0"
}
},
"node_modules/@ionic/core/node_modules/@stencil/core": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.1.tgz",
"integrity": "sha512-Ybm4NteQBScLq3H0JML/uqo4nWjNpZw1HAAURtR5LlRm7ptzNKO5S8EnHp3m05/uyTzeh9yLpUFHY7bxGNdYLg==",
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.2.tgz",
"integrity": "sha512-wXb9cVWL0T3cTwYLveekdTFCRGx6+9hpVDEXna+N8K8OPoW6xtFAHRLv+LjOM7k59PkA8MG3IinAfV7Y+xa0Hw==",
"bin": {
"stencil": "bin/stencil"
},
@@ -8104,19 +8104,19 @@
"dev": true
},
"@ionic/core": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.0.2.tgz",
"integrity": "sha512-GxQsMmsyBGeK9khIPNR3zw3WvDZj3I0inKtPcd/s9hEnfndAlFFI9gckB7/zrp55xoknCRwqAYT8sGWze3sn2w==",
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.0.5.tgz",
"integrity": "sha512-dcuE/PEF+GHsPEsLppUASSwWnzVcxFZE7uPMDzTwUPMOFTTaRgWbPxIly/4/VRbV6GSL6MEcuVVxhEdWjSODTg==",
"requires": {
"@stencil/core": "^3.2.1",
"@stencil/core": "^3.2.2",
"ionicons": "^7.1.0",
"tslib": "^2.1.0"
},
"dependencies": {
"@stencil/core": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.1.tgz",
"integrity": "sha512-Ybm4NteQBScLq3H0JML/uqo4nWjNpZw1HAAURtR5LlRm7ptzNKO5S8EnHp3m05/uyTzeh9yLpUFHY7bxGNdYLg=="
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.2.tgz",
"integrity": "sha512-wXb9cVWL0T3cTwYLveekdTFCRGx6+9hpVDEXna+N8K8OPoW6xtFAHRLv+LjOM7k59PkA8MG3IinAfV7Y+xa0Hw=="
}
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "7.0.3",
"version": "7.0.5",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@@ -17,7 +17,7 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic.git"
"url": "git+https://github.com/ionic-team/ionic-framework.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic/issues"
@@ -47,7 +47,7 @@
}
},
"dependencies": {
"@ionic/core": "^7.0.3",
"@ionic/core": "^7.0.5",
"ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0",
"tslib": "^2.3.0"

View File

@@ -5,7 +5,7 @@
"keywords": [],
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic.git"
"url": "git+https://github.com/ionic-team/ionic-framework.git"
},
"license": "MIT",
"main": "umd/index.js",

View File

@@ -116,7 +116,7 @@ export class IonModal {
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
this.el = r.nativeElement;
this.el.addEventListener('willPresent', () => {
this.el.addEventListener('ionMount', () => {
this.isCmpOpen = true;
c.detectChanges();
});
@@ -124,7 +124,6 @@ export class IonModal {
this.isCmpOpen = false;
c.detectChanges();
});
proxyOutputs(this, this.el, [
'ionModalDidPresent',
'ionModalWillPresent',

View File

@@ -977,7 +977,7 @@ export declare interface IonInfiniteScrollContent extends Components.IonInfinite
@ProxyCmp({
inputs: ['accept', 'autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'legacy', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'size', 'spellcheck', 'step', 'type', 'value'],
inputs: ['accept', 'autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'legacy', 'mask', 'maskPlaceholder', 'maskVisibility', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'size', 'spellcheck', 'step', 'type', 'value'],
methods: ['setFocus', 'getInputElement']
})
@Component({
@@ -985,7 +985,7 @@ export declare interface IonInfiniteScrollContent extends Components.IonInfinite
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['accept', 'autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'legacy', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'size', 'spellcheck', 'step', 'type', 'value'],
inputs: ['accept', 'autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearOnEdit', 'color', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'helperText', 'inputmode', 'label', 'labelPlacement', 'legacy', 'mask', 'maskPlaceholder', 'maskVisibility', 'max', 'maxlength', 'min', 'minlength', 'mode', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'size', 'spellcheck', 'step', 'type', 'value'],
})
export class IonInput {
protected el: HTMLElement;

View File

@@ -0,0 +1,5 @@
it("should be on Angular 14", () => {
cy.visit('/');
cy.get('ion-title').contains('Angular 14');
});

View File

@@ -1,3 +0,0 @@
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>

View File

@@ -1,8 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }

View File

@@ -0,0 +1,5 @@
it("should be on Angular 15", () => {
cy.visit('/');
cy.get('ion-title').contains('Angular 15');
});

View File

@@ -1,3 +0,0 @@
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>

View File

@@ -1,8 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }

View File

View File

@@ -0,0 +1,5 @@
it("should be on Angular 16", () => {
cy.visit('/');
cy.get('ion-title').contains('Angular 16');
});

28260
angular/test/apps/ng16/package-lock.json generated Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
{
"name": "ionic-angular-test-app",
"version": "0.0.0",
"private": true,
"scripts": {
"ng": "ng",
"start": "ng serve",
"sync:build": "sh scripts/build-ionic.sh",
"sync": "sh scripts/sync.sh",
"build": "ng build --configuration production --no-progress",
"lint": "ng lint",
"serve:ssr": "node dist/test-app/server/main.js",
"build:ssr": "ng build --prod && ng run test-app:server:production",
"dev:ssr": "ng run test-app:serve-ssr",
"prerender": "ng run test-app:prerender",
"cy.open": "cypress open",
"cy.run": "cypress run",
"test": "concurrently \"npm run start -- --configuration production\" \"wait-on http-get://localhost:4200 && npm run cy.run\" --kill-others --success first",
"test.watch": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.open\" --kill-others --success first"
},
"dependencies": {
"@angular/animations": "^16.0.0-rc.0",
"@angular/common": "^16.0.0-rc.0",
"@angular/compiler": "^16.0.0-rc.0",
"@angular/core": "^16.0.0-rc.0",
"@angular/forms": "^16.0.0-rc.0",
"@angular/platform-browser": "^16.0.0-rc.0",
"@angular/platform-browser-dynamic": "^16.0.0-rc.0",
"@angular/platform-server": "^16.0.0-rc.0",
"@angular/router": "^16.0.0-rc.0",
"@ionic/angular": "^7.0.0",
"@ionic/angular-server": "^7.0.0",
"@nguniversal/express-engine": "^15.0.0",
"core-js": "^2.6.11",
"express": "^4.15.2",
"ionicons": "^6.0.4",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"typescript-eslint-language-service": "^4.1.5",
"zone.js": "~0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^16.0.0-rc.0",
"@angular-eslint/builder": "^15.0.0",
"@angular-eslint/eslint-plugin": "^15.0.0",
"@angular-eslint/eslint-plugin-template": "^15.0.0",
"@angular-eslint/schematics": "^15.0.0",
"@angular-eslint/template-parser": "^15.0.0",
"@angular/cli": "^16.0.0-rc.0",
"@angular/compiler-cli": "^16.0.0-rc.0",
"@angular/language-service": "^16.0.0-rc.0",
"@nguniversal/builders": "^15.0.0",
"@types/express": "^4.17.7",
"@types/node": "^12.12.54",
"@typescript-eslint/eslint-plugin": "4.28.2",
"@typescript-eslint/parser": "4.28.2",
"concurrently": "^6.0.0",
"cypress": "^10.2.0",
"eslint": "^7.26.0",
"ts-loader": "^6.2.2",
"ts-node": "^8.3.0",
"typescript": "~5.0.2",
"wait-on": "^5.2.1",
"webpack": "^5.61.0",
"webpack-cli": "^4.9.2"
},
"engines": {
"node": ">= 16"
}
}

View File

@@ -0,0 +1,10 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
@NgModule({
imports: [
RouterModule.forChild([])
],
exports: [RouterModule]
})
export class VersionTestRoutingModule { }

View File

@@ -0,0 +1,35 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": false,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"emitDecoratorMetadata": true,
"typeRoots": ["node_modules/@types"],
"lib": ["ES2022", "dom"],
"plugins": [
{
"name": "typescript-eslint-language-service"
}
],
"useDefineForClassFields": false
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

View File

@@ -13,7 +13,6 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"aot": true,
"outputPath": "dist/test-app/browser",
"index": "src/index.html",
"main": "src/main.ts",
@@ -64,8 +63,17 @@
"maximumWarning": "6kb"
}
]
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
@@ -75,8 +83,12 @@
"configurations": {
"production": {
"browserTarget": "test-app:build:production"
},
"development": {
"browserTarget": "test-app:build:development"
}
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
@@ -136,9 +148,7 @@
}
},
"cli": {
"schematicCollections": [
"@angular-eslint/schematics"
],
"schematicCollections": ["@angular-eslint/schematics"],
"cache": {
"enabled": false
}

View File

@@ -121,4 +121,4 @@ describe('when in a modal', () => {
cy.get('#set-to-null').click();
cy.get('#inputWithFloatingLabel').should('not.have.class', 'item-has-value');
});
});
});

View File

@@ -15,7 +15,7 @@ npm pack ../../../dist
npm pack ../../../../packages/angular-server/dist
# Install Dependencies
npm install *.tgz --no-save
npm install *.tgz --no-save --legacy-peer-deps
# Delete Angular cache directory
rm -rf .angular/

View File

@@ -1,7 +1,7 @@
<ion-header>
<ion-toolbar>
<ion-title>
Test App
Test App - Angular {{ angularVersion.major }}
</ion-title>
</ion-toolbar>
</ion-header>

View File

@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, VERSION } from '@angular/core';
import { AnimationBuilder, AnimationController } from '@ionic/angular';
@Component({
@@ -6,6 +6,9 @@ import { AnimationBuilder, AnimationController } from '@ionic/angular';
templateUrl: './home-page.component.html',
})
export class HomePageComponent {
angularVersion = VERSION;
routerAnimation: AnimationBuilder = (_, opts) => {
const { direction, enteringEl, leavingEl } = opts;
const animation = this.animationCtrl.create().duration(500).easing('ease-out');

View File

@@ -17,4 +17,4 @@
</ion-list>
</ion-content>
</ng-template>
</ion-modal>
</ion-modal>

View File

@@ -24,4 +24,5 @@ export class ModalInlineComponent implements AfterViewInit {
onBreakpointDidChange() {
this.breakpointDidChangeCounter++;
}
}

View File

@@ -25,7 +25,7 @@
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
* import './zone-flags';
*
* The flags allowed in zone-flags.ts are listed here.
*
@@ -42,7 +42,7 @@
*
*/
import './zone-flags.ts';
import './zone-flags';
/***************************************************************************************************
* Zone JS is required by default for Angular itself.

View File

@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.0.5](https://github.com/ionic-team/ionic-framework/compare/v7.0.4...v7.0.5) (2023-05-03)
### Bug Fixes
* **many:** form components do not take up full width in slot ([#27306](https://github.com/ionic-team/ionic-framework/issues/27306)) ([bfe7b38](https://github.com/ionic-team/ionic-framework/commit/bfe7b388318aca98014a0748f678e41a0f3910ae)), closes [#27305](https://github.com/ionic-team/ionic-framework/issues/27305)
* **scroll-assist:** set correct scroll padding ([#27261](https://github.com/ionic-team/ionic-framework/issues/27261)) ([7e1f996](https://github.com/ionic-team/ionic-framework/commit/7e1f996dc63cd414b30b22aebbfc09b0b6b4f6fc)), closes [#27257](https://github.com/ionic-team/ionic-framework/issues/27257)
* **toggle:** swipe gesture applies to knob ([#27255](https://github.com/ionic-team/ionic-framework/issues/27255)) ([6524582](https://github.com/ionic-team/ionic-framework/commit/65245826e3a775bcb8a5d6cfd05230f53470fc66)), closes [#27254](https://github.com/ionic-team/ionic-framework/issues/27254)
## [7.0.4](https://github.com/ionic-team/ionic-framework/compare/v7.0.3...v7.0.4) (2023-04-26)
### Bug Fixes
* **breadcumb:** set background when focused on md ([#27274](https://github.com/ionic-team/ionic-framework/issues/27274)) ([01e028b](https://github.com/ionic-team/ionic-framework/commit/01e028b789f84e80f20ce2be7be7f8519f925211)), closes [#27273](https://github.com/ionic-team/ionic-framework/issues/27273)
* **ios:** scroll assist sizes input correctly ([#27253](https://github.com/ionic-team/ionic-framework/issues/27253)) ([a874992](https://github.com/ionic-team/ionic-framework/commit/a8749929e01b07043631fbc8c522d39cbc3ae798)), closes [#27249](https://github.com/ionic-team/ionic-framework/issues/27249)
* **modal:** set default text color ([#27207](https://github.com/ionic-team/ionic-framework/issues/27207)) ([c267b43](https://github.com/ionic-team/ionic-framework/commit/c267b43396057d9fab344a30bd83d00523911dc1)), closes [#26060](https://github.com/ionic-team/ionic-framework/issues/26060) [/github.com/ionic-team/ionic-framework/blob/main/core/src/components/popover/popover.scss#L42](https://github.com//github.com/ionic-team/ionic-framework/blob/main/core/src/components/popover/popover.scss/issues/L42)
* **select:** adjust label alignment when in a card ([#27202](https://github.com/ionic-team/ionic-framework/issues/27202)) ([5a2b87c](https://github.com/ionic-team/ionic-framework/commit/5a2b87cbcc5c789d02b29e776e2b9768d7ad5631)), closes [#27086](https://github.com/ionic-team/ionic-framework/issues/27086)
## [7.0.3](https://github.com/ionic-team/ionic/compare/v7.0.1...v7.0.3) (2023-04-19)

View File

@@ -104,7 +104,7 @@ const showModal = async () => {
* [Ionic Forum](https://forum.ionicframework.com/)
* [Ionicons](http://ionicons.com/)
* [Stencil](https://stenciljs.com/)
* [Stencil Worldwide Slack](https://stencil-worldwide.herokuapp.com/)
* [Stencil Worldwide Slack](https://stencil-worldwide.slack.com/)
* [Capacitor](https://capacitor.ionicframework.com/)

View File

@@ -553,6 +553,9 @@ ion-input,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "
ion-input,prop,label,string | undefined,undefined,false,false
ion-input,prop,labelPlacement,"end" | "fixed" | "floating" | "stacked" | "start",'start',false,false
ion-input,prop,legacy,boolean | undefined,undefined,false,false
ion-input,prop,mask,(string | RegExp)[] | RegExp | undefined,undefined,false,false
ion-input,prop,maskPlaceholder,null | string | undefined,'_',false,false
ion-input,prop,maskVisibility,"always" | "focus" | "never" | undefined,'always',false,false
ion-input,prop,max,number | string | undefined,undefined,false,false
ion-input,prop,maxlength,number | undefined,undefined,false,false
ion-input,prop,min,number | string | undefined,undefined,false,false

18
core/package-lock.json generated
View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/core",
"version": "7.0.3",
"version": "7.0.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
"version": "7.0.3",
"version": "7.0.5",
"license": "MIT",
"dependencies": {
"@stencil/core": "^3.2.1",
"@stencil/core": "^3.2.2",
"ionicons": "^7.1.0",
"tslib": "^2.1.0"
},
@@ -1594,9 +1594,9 @@
}
},
"node_modules/@stencil/core": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.1.tgz",
"integrity": "sha512-Ybm4NteQBScLq3H0JML/uqo4nWjNpZw1HAAURtR5LlRm7ptzNKO5S8EnHp3m05/uyTzeh9yLpUFHY7bxGNdYLg==",
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.2.tgz",
"integrity": "sha512-wXb9cVWL0T3cTwYLveekdTFCRGx6+9hpVDEXna+N8K8OPoW6xtFAHRLv+LjOM7k59PkA8MG3IinAfV7Y+xa0Hw==",
"bin": {
"stencil": "bin/stencil"
},
@@ -11467,9 +11467,9 @@
"requires": {}
},
"@stencil/core": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.1.tgz",
"integrity": "sha512-Ybm4NteQBScLq3H0JML/uqo4nWjNpZw1HAAURtR5LlRm7ptzNKO5S8EnHp3m05/uyTzeh9yLpUFHY7bxGNdYLg=="
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.2.tgz",
"integrity": "sha512-wXb9cVWL0T3cTwYLveekdTFCRGx6+9hpVDEXna+N8K8OPoW6xtFAHRLv+LjOM7k59PkA8MG3IinAfV7Y+xa0Hw=="
},
"@stencil/react-output-target": {
"version": "0.5.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "7.0.3",
"version": "7.0.5",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -31,7 +31,7 @@
"loader/"
],
"dependencies": {
"@stencil/core": "^3.2.1",
"@stencil/core": "^3.2.2",
"ionicons": "^7.1.0",
"tslib": "^2.1.0"
},
@@ -90,7 +90,8 @@
"test": "npm run test.spec && npm run test.e2e",
"test.spec": "stencil test --spec --max-workers=2",
"test.spec.debug": "npx --node-arg=\"--inspect-brk\" stencil test --spec",
"test.e2e": "npx playwright test",
"test.e2e": "npx playwright test --config playwright.config.ts",
"test.e2e.legacy": "npx playwright test --config playwright.config-legacy.ts",
"test.watch": "jest --watch --no-cache",
"test.treeshake": "node scripts/treeshaking.js dist/index.js",
"validate": "npm run lint && npm run test && npm run build && npm run test.treeshake"
@@ -99,7 +100,7 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/ionic-team/ionic.git"
"url": "git+https://github.com/ionic-team/ionic-framework.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic/issues"

View File

@@ -0,0 +1,119 @@
import type { PlaywrightTestConfig, PlaywrightTestOptions, PlaywrightWorkerOptions, Project } from '@playwright/test';
import { devices, expect } from '@playwright/test';
import { matchers } from './src/utils/test/playwright';
expect.extend(matchers);
const projects: Project<PlaywrightTestOptions, PlaywrightWorkerOptions>[] = [
{
/**
* This is really just desktop Firefox
* but with a mobile viewport.
*/
name: 'Mobile Firefox',
use: {
browserName: 'firefox',
/**
* This is the Pixel 5 configuration.
* We can't use devices['Pixel 5']
* because the "isMobile" option is
* not supported on Firefox.
*/
viewport: {
width: 393,
height: 727
},
},
},
{
name: 'Mobile Chrome',
use: {
browserName: 'chromium',
...devices['Pixel 5']
}
},
{
name: 'Mobile Safari',
use: {
browserName: 'webkit',
...devices['iPhone 12']
}
}
];
const modes = ['ios', 'md'];
const generateProjects = () => {
const projectsWithMetadata: Project<PlaywrightTestOptions, PlaywrightWorkerOptions>[] = [];
modes.forEach(mode => {
projects.forEach(project => {
projectsWithMetadata.push({
...project,
metadata: {
mode,
rtl: false,
_testing: true
}
});
projectsWithMetadata.push({
...project,
metadata: {
mode,
rtl: true,
_testing: true
}
});
});
});
return projectsWithMetadata;
}
/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testMatch: '*.e2e-legacy.ts',
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000
},
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Fail fast on CI */
maxFailures: process.env.CI ? 1 : 0,
/* Flaky test should be either addressed or disabled until we can address them */
retries: 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/**
* All failed tests should create
* a trace file for easier debugging.
*
* See https://playwright.dev/docs/trace-viewer
*/
trace: 'retain-on-failure',
baseURL: 'http://localhost:3333',
},
/* Configure projects for major browsers */
projects: generateProjects(),
webServer: {
command: 'serve -p 3333',
port: 3333,
reuseExistingServer: !process.env.CI
}
};
export default config;

View File

@@ -42,35 +42,6 @@ const projects: Project<PlaywrightTestOptions, PlaywrightWorkerOptions>[] = [
}
];
const modes = ['ios', 'md'];
const generateProjects = () => {
const projectsWithMetadata: Project<PlaywrightTestOptions, PlaywrightWorkerOptions>[] = [];
modes.forEach(mode => {
projects.forEach(project => {
projectsWithMetadata.push({
...project,
metadata: {
mode,
rtl: false,
_testing: true
}
});
projectsWithMetadata.push({
...project,
metadata: {
mode,
rtl: true,
_testing: true
}
});
});
});
return projectsWithMetadata;
}
/**
* See https://playwright.dev/docs/test-configuration.
*/
@@ -108,7 +79,7 @@ const config: PlaywrightTestConfig = {
},
/* Configure projects for major browsers */
projects: generateProjects(),
projects,
webServer: {
command: 'serve -p 3333',
port: 3333,

View File

@@ -17,6 +17,7 @@ import { CheckboxChangeEventDetail } from "./components/checkbox/checkbox-interf
import { ScrollBaseDetail, ScrollDetail } from "./components/content/content-interface";
import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
import { SpinnerTypes } from "./components/spinner/spinner-configs";
import { MaskExpression, MaskPlaceholder, MaskVisibility } from "./utils/input-masking/public-api";
import { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
import { CounterFormatter } from "./components/item/item-interface";
import { MenuChangeEventDetail, Side } from "./components/menu/menu-interface";
@@ -53,6 +54,7 @@ export { CheckboxChangeEventDetail } from "./components/checkbox/checkbox-interf
export { ScrollBaseDetail, ScrollDetail } from "./components/content/content-interface";
export { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
export { SpinnerTypes } from "./components/spinner/spinner-configs";
export { MaskExpression, MaskPlaceholder, MaskVisibility } from "./utils/input-masking/public-api";
export { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
export { CounterFormatter } from "./components/item/item-interface";
export { MenuChangeEventDetail, Side } from "./components/menu/menu-interface";
@@ -1225,6 +1227,18 @@ export namespace Components {
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the `label` property. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
"legacy"?: boolean;
/**
* The predefined format of the user's input. For example, you can set a mask that only accepts digits, or you can configure a more complex pattern like a phone number or credit card number. The mask supports two formats: 1. A valid [regular expression pattern](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) 2. An array containing regular expression and fixed character patterns The fixed characters in the mask cannot be erased or replaced by the user. For example in a phone number mask, the `(`, `)` and `-` are examples of fixed characters.
*/
"mask"?: MaskExpression;
/**
* Character or string to cover unfilled parts of the mask. The default character is `_`. If set to `null`, `undefined` or an empty string, unfilled parts will be empty as in a regular input.
*/
"maskPlaceholder"?: MaskPlaceholder;
/**
* The visibility of the mask placeholder. With `always`, the placeholder will be visible even when the control does not have focus. With `focus`, the placeholder will only be visible when the control has focus. With `never`, the placeholder will never be visibly displayed.
*/
"maskVisibility"?: MaskVisibility;
/**
* The maximum value, which must not be less than its minimum (min attribute) value.
*/
@@ -2888,16 +2902,16 @@ export namespace Components {
interface IonTabs {
"getRouteId": () => Promise<RouteID | undefined>;
/**
* Get the currently selected tab.
* Get the currently selected tab. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
*/
"getSelected": () => Promise<string | undefined>;
/**
* Get a specific tab by the value of its `tab` property or an element reference.
* Get a specific tab by the value of its `tab` property or an element reference. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
* @param tab The tab instance to select. If passed a string, it should be the value of the tab's `tab` property.
*/
"getTab": (tab: string | HTMLIonTabElement) => Promise<HTMLIonTabElement | undefined>;
/**
* Select a tab by the value of its `tab` property or an element reference.
* Select a tab by the value of its `tab` property or an element reference. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
* @param tab The tab instance to select. If passed a string, it should be the value of the tab's `tab` property.
*/
"select": (tab: string | HTMLIonTabElement) => Promise<boolean>;
@@ -5255,6 +5269,18 @@ declare namespace LocalJSX {
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the `label` property. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
"legacy"?: boolean;
/**
* The predefined format of the user's input. For example, you can set a mask that only accepts digits, or you can configure a more complex pattern like a phone number or credit card number. The mask supports two formats: 1. A valid [regular expression pattern](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) 2. An array containing regular expression and fixed character patterns The fixed characters in the mask cannot be erased or replaced by the user. For example in a phone number mask, the `(`, `)` and `-` are examples of fixed characters.
*/
"mask"?: MaskExpression;
/**
* Character or string to cover unfilled parts of the mask. The default character is `_`. If set to `null`, `undefined` or an empty string, unfilled parts will be empty as in a regular input.
*/
"maskPlaceholder"?: MaskPlaceholder;
/**
* The visibility of the mask placeholder. With `always`, the placeholder will be visible even when the control does not have focus. With `focus`, the placeholder will only be visible when the control has focus. With `never`, the placeholder will never be visibly displayed.
*/
"maskVisibility"?: MaskVisibility;
/**
* The maximum value, which must not be less than its minimum (min attribute) value.
*/
@@ -5830,6 +5856,10 @@ declare namespace LocalJSX {
* Emitted before the modal has presented.
*/
"onIonModalWillPresent"?: (event: IonModalCustomEvent<void>) => void;
/**
* Emitted before the modal has presented, but after the component has been mounted in the DOM. This event exists so iOS can run the entering transition properly
*/
"onIonMount"?: (event: IonModalCustomEvent<void>) => void;
/**
* Emitted before the modal has dismissed. Shorthand for ionModalWillDismiss.
*/

View File

@@ -1,44 +1,46 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('accordion: a11y', () => {
test('accordions should be keyboard navigable', async ({ page, skip, browserName }) => {
// TODO(FW-1764): remove skip once issue is resolved
skip.browser('firefox', 'https://github.com/ionic-team/ionic-framework/issues/25070');
// TODO (FW-2979)
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
configs().forEach(({ config, title }) => {
test.describe(title('accordion: a11y'), () => {
test('accordions should be keyboard navigable', async ({ page, skip, browserName }) => {
// TODO(FW-1764): remove skip once issue is resolved
skip.browser('firefox', 'https://github.com/ionic-team/ionic-framework/issues/25070');
// TODO (FW-2979)
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
await page.goto(`/src/components/accordion/test/a11y`);
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
await page.goto(`/src/components/accordion/test/a11y`, config);
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
const personalInfoHeader = page.locator('ion-accordion:first-child > ion-item');
const billingAddressHeader = page.locator('ion-accordion:nth-child(2) > ion-item');
const shippingAddressHeader = page.locator('ion-accordion:nth-child(3) > ion-item');
const addressInput = page.locator('#address1 input');
const personalInfoHeader = page.locator('ion-accordion:first-child > ion-item');
const billingAddressHeader = page.locator('ion-accordion:nth-child(2) > ion-item');
const shippingAddressHeader = page.locator('ion-accordion:nth-child(3) > ion-item');
const addressInput = page.locator('#address1 input');
await page.keyboard.press(tabKey);
await expect(personalInfoHeader).toBeFocused();
await page.keyboard.press(tabKey);
await expect(personalInfoHeader).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(billingAddressHeader).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(billingAddressHeader).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(shippingAddressHeader).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(shippingAddressHeader).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(personalInfoHeader).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(personalInfoHeader).toBeFocused();
await page.keyboard.press('ArrowUp');
await expect(shippingAddressHeader).toBeFocused();
await page.keyboard.press('ArrowUp');
await expect(shippingAddressHeader).toBeFocused();
// open Shipping Address accordion and move focus to the input inside it
await page.keyboard.press('Enter');
await page.waitForChanges();
await page.keyboard.press(tabKey);
await expect(addressInput).toBeFocused();
// open Shipping Address accordion and move focus to the input inside it
await page.keyboard.press('Enter');
await page.waitForChanges();
await page.keyboard.press(tabKey);
await expect(addressInput).toBeFocused();
// ensure keyboard interaction doesn't move focus from body
await page.keyboard.press('ArrowDown');
await expect(addressInput).toBeFocused();
// ensure keyboard interaction doesn't move focus from body
await page.keyboard.press('ArrowDown');
await expect(addressInput).toBeFocused();
});
});
});

View File

@@ -1,56 +1,49 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('accordion: states', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
skip.mode('ios');
});
test('should properly set readonly on child accordions', async ({ page }) => {
await page.setContent(`
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');
const accordionGroup = page.locator('ion-accordion-group');
const accordion = page.locator('ion-accordion');
await expect(accordion).toHaveJSProperty('readonly', false);
await expect(accordion).toHaveJSProperty('readonly', false);
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
el.readonly = true;
});
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
el.readonly = true;
await page.waitForChanges();
await expect(accordion).toHaveJSProperty('readonly', true);
});
await page.waitForChanges();
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('readonly', true);
});
await expect(accordion).toHaveJSProperty('disabled', false);
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>
`);
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
el.disabled = true;
});
const accordionGroup = page.locator('ion-accordion-group');
const accordion = page.locator('ion-accordion');
await page.waitForChanges();
await expect(accordion).toHaveJSProperty('disabled', false);
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => {
el.disabled = true;
await expect(accordion).toHaveJSProperty('disabled', true);
});
await page.waitForChanges();
await expect(accordion).toHaveJSProperty('disabled', true);
});
});

View File

@@ -1,53 +1,22 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('accordion: basic', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/accordion/test/basic`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('accordion: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/accordion/test/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`accordion-basic-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot('accordion-basic'));
});
});
});
test.describe('accordion: ionChange', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should fire ionChange when interacting with accordions', async ({ page }) => {
await page.setContent(`
<ion-accordion-group value="second">
<ion-accordion value="first">
<button slot="header">Header</button>
<div slot="content">First Content</div>
</ion-accordion>
<ion-accordion value="second">
<button slot="header">Header</button>
<div slot="content">Second Content</div>
</ion-accordion>
<ion-accordion value="third">
<button slot="header">Header</button>
<div slot="content">Third Content</div>
</ion-accordion>
</ion-accordion-group>
`);
const ionChange = await page.spyOnEvent('ionChange');
const accordionHeaders = page.locator('button[slot="header"]');
await accordionHeaders.nth(0).click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'first' });
await accordionHeaders.nth(1).click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'second' });
await accordionHeaders.nth(2).click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'third' });
});
test('should not fire when programmatically setting a valid value', async ({ page }) => {
await page.setContent(`
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('accordion: ionChange'), () => {
test.beforeEach(async ({ page }) => {
await page.setContent(
`
<ion-accordion-group>
<ion-accordion value="first">
<button slot="header">Header</button>
@@ -62,13 +31,30 @@ test.describe('accordion: ionChange', () => {
<div slot="content">Third Content</div>
</ion-accordion>
</ion-accordion-group>
`,
config
);
});
test('should fire ionChange when interacting with accordions', async ({ page }) => {
const ionChange = await page.spyOnEvent('ionChange');
const accordionHeaders = page.locator('button[slot="header"]');
`);
await accordionHeaders.nth(0).click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'first' });
const ionChange = await page.spyOnEvent('ionChange');
const accordionGroup = page.locator('ion-accordion-group');
await accordionHeaders.nth(1).click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'second' });
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => (el.value = 'second'));
await expect(ionChange).not.toHaveReceivedEvent();
await accordionHeaders.nth(2).click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'third' });
});
test('should not fire when programmatically setting a valid value', async ({ page }) => {
const ionChange = await page.spyOnEvent('ionChange');
const accordionGroup = page.locator('ion-accordion-group');
await accordionGroup.evaluate((el: HTMLIonAccordionGroupElement) => (el.value = 'second'));
await expect(ionChange).not.toHaveReceivedEvent();
});
});
});

View File

@@ -1,32 +1,32 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('accordion: multiple', () => {
test('should update value and visually expand items', async ({ page, skip }) => {
skip.rtl();
configs({ directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('accordion: multiple'), () => {
test('should update value and visually expand items', async ({ page }) => {
await page.goto(`/src/components/accordion/test/multiple`, config);
const accordionGroup = page.locator('ion-accordion-group');
const diningHeader = page.locator('ion-accordion[value="dining"] ion-item[slot="header"]');
const attractionsHeader = page.locator('ion-accordion[value="attractions"] ion-item[slot="header"]');
await page.goto(`/src/components/accordion/test/multiple`);
const accordionGroup = page.locator('ion-accordion-group');
const diningHeader = page.locator('ion-accordion[value="dining"] ion-item[slot="header"]');
const attractionsHeader = page.locator('ion-accordion[value="attractions"] ion-item[slot="header"]');
await expect(accordionGroup).toHaveJSProperty('value', 'attractions');
await expect(accordionGroup).toHaveJSProperty('value', 'attractions');
await expect(accordionGroup).toHaveScreenshot(screenshot('accordion-one-open'));
await expect(accordionGroup).toHaveScreenshot(`accordion-one-open-${page.getSnapshotSettings()}.png`);
await diningHeader.click();
await page.waitForChanges();
await diningHeader.click();
await page.waitForChanges();
await expect(accordionGroup).toHaveJSProperty('value', ['attractions', 'dining']);
await expect(accordionGroup).toHaveJSProperty('value', ['attractions', 'dining']);
await expect(accordionGroup).toHaveScreenshot(screenshot('accordion-two-open'));
await expect(accordionGroup).toHaveScreenshot(`accordion-two-open-${page.getSnapshotSettings()}.png`);
await diningHeader.click();
await attractionsHeader.click();
await page.waitForChanges();
await diningHeader.click();
await attractionsHeader.click();
await page.waitForChanges();
await expect(accordionGroup).toHaveJSProperty('value', []);
await expect(accordionGroup).toHaveJSProperty('value', []);
await expect(accordionGroup).toHaveScreenshot(`accordion-zero-open-${page.getSnapshotSettings()}.png`);
await expect(accordionGroup).toHaveScreenshot(screenshot('accordion-zero-open'));
});
});
});

View File

@@ -1,28 +1,30 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('accordion: nested', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl();
configs({ directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('accordion: nested'), () => {
test('parent and child should not be disabled', async ({ page }) => {
await page.goto(`/src/components/accordion/test/nested`, config);
await page.goto(`/src/components/accordion/test/nested`);
});
const enabledGroup = page.locator('ion-accordion-group#enabled');
test('parent and child should not be disabled', async ({ page }) => {
const enabledGroup = page.locator('ion-accordion-group#enabled');
await expect(enabledGroup).toHaveScreenshot(screenshot('accordion-nested-enabled'));
});
await expect(enabledGroup).toHaveScreenshot(`accordion-nested-enabled-${page.getSnapshotSettings()}.png`);
});
test('parent should not be disabled when only child is disabled', async ({ page }) => {
await page.goto(`/src/components/accordion/test/nested`, config);
test('parent should not be disabled when only child is disabled', async ({ page }) => {
const nestedDisabledGroup = page.locator('ion-accordion-group#nested-disabled');
const nestedDisabledGroup = page.locator('ion-accordion-group#nested-disabled');
await expect(nestedDisabledGroup).toHaveScreenshot(`accordion-child-disabled-${page.getSnapshotSettings()}.png`);
});
await expect(nestedDisabledGroup).toHaveScreenshot(screenshot('accordion-child-disabled'));
});
test('parent and child should be disabled when parent is disabled', async ({ page }) => {
const parentDisabledGroup = page.locator('ion-accordion-group#parent-disabled');
test('parent and child should be disabled when parent is disabled', async ({ page }) => {
await page.goto(`/src/components/accordion/test/nested`, config);
await expect(parentDisabledGroup).toHaveScreenshot(`accordion-parent-disabled-${page.getSnapshotSettings()}.png`);
const parentDisabledGroup = page.locator('ion-accordion-group#parent-disabled');
await expect(parentDisabledGroup).toHaveScreenshot(screenshot('accordion-parent-disabled'));
});
});
});

View File

@@ -1,13 +1,15 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('accordion: standalone', () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/accordion/test/standalone`);
configs().forEach(({ config, title }) => {
test.describe(title('accordion: standalone'), () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/accordion/test/standalone`, config);
const results = await new AxeBuilder({ page }).analyze();
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
expect(results.violations).toEqual([]);
});
});
});

View File

@@ -15,6 +15,7 @@ import {
prepareOverlay,
present,
safeCall,
setOverlayId,
} from '../../utils/overlays';
import type { OverlayEventDetail } from '../../utils/overlays-interface';
import { getClassMap } from '../../utils/theme';
@@ -311,6 +312,10 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
this.triggerController.removeClickListener();
}
componentWillLoad() {
setOverlayId(this.el);
}
componentDidLoad() {
/**
* Do not create gesture if:

View File

@@ -1,7 +1,7 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import type { E2EPage } from '@utils/test/playwright';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
const testAria = async (page: E2EPage, buttonID: string, expectedAriaLabelledBy: string | null) => {
const didPresent = await page.spyOnEvent('ionActionSheetDidPresent');
@@ -20,38 +20,37 @@ const testAria = async (page: E2EPage, buttonID: string, expectedAriaLabelledBy:
expect(ariaLabelledBy).toBe(expectedAriaLabelledBy);
};
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action-sheet: a11y'), () => {
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/action-sheet/test/a11y`, config);
});
test('should not have accessibility violations when header is defined', async ({ page }) => {
const button = page.locator('#bothHeaders');
const didPresent = await page.spyOnEvent('ionActionSheetDidPresent');
test.describe('action-sheet: a11y', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl();
await page.goto(`/src/components/action-sheet/test/a11y`);
});
await button.click();
await didPresent.next();
test('should not have accessibility violations when header is defined', async ({ page }) => {
const button = page.locator('#bothHeaders');
const didPresent = await page.spyOnEvent('ionActionSheetDidPresent');
/**
* action-sheet overlays the entire screen, so
* Axe will be unable to verify color contrast
* on elements under the backdrop.
*/
const results = await new AxeBuilder({ page }).disableRules('color-contrast').analyze();
expect(results.violations).toEqual([]);
});
await button.click();
await didPresent.next();
test('should have aria-labelledby when header is set', async ({ page }) => {
await testAria(page, 'bothHeaders', 'action-sheet-1-header');
});
/**
* action-sheet overlays the entire screen, so
* Axe will be unable to verify color contrast
* on elements under the backdrop.
*/
const results = await new AxeBuilder({ page }).disableRules('color-contrast').analyze();
expect(results.violations).toEqual([]);
});
test('should not have aria-labelledby when header is not set', async ({ page }) => {
await testAria(page, 'noHeaders', null);
});
test('should have aria-labelledby when header is set', async ({ page }) => {
await testAria(page, 'bothHeaders', 'action-sheet-1-header');
});
test('should not have aria-labelledby when header is not set', async ({ page }) => {
await testAria(page, 'noHeaders', null);
});
test('should allow for manually specifying aria attributes', async ({ page }) => {
await testAria(page, 'customAria', 'Custom title');
test('should allow for manually specifying aria attributes', async ({ page }) => {
await testAria(page, 'customAria', 'Custom title');
});
});
});

View File

@@ -0,0 +1,41 @@
import { newSpecPage } from '@stencil/core/testing';
import { ActionSheet } from '../action-sheet';
it('action sheet should be assigned an incrementing id', async () => {
const page = await newSpecPage({
components: [ActionSheet],
html: `<ion-action-sheet is-open="true"></ion-action-sheet>`,
});
let actionSheet: HTMLIonActionSheetElement;
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet).not.toBe(null);
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-1');
// Remove the action sheet from the DOM
actionSheet.remove();
await page.waitForChanges();
// Create a new action sheet to verify the id is incremented
actionSheet = document.createElement('ion-action-sheet');
actionSheet.isOpen = true;
page.body.appendChild(actionSheet);
await page.waitForChanges();
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-2');
// Presenting the same action sheet again should reuse the existing id
actionSheet.isOpen = false;
await page.waitForChanges();
actionSheet.isOpen = true;
await page.waitForChanges();
actionSheet = page.body.querySelector('ion-action-sheet')!;
expect(actionSheet.getAttribute('id')).toBe('ion-overlay-2');
});

View File

@@ -1,17 +1,17 @@
import { expect } from '@playwright/test';
import type { Locator } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
import type { E2EPage } from '@utils/test/playwright';
test.describe('action sheet: basic', () => {
let actionSheetFixture: ActionSheetFixture;
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/action-sheet/test/basic`);
actionSheetFixture = new ActionSheetFixture(page);
});
test.describe('action sheet: data', () => {
test('should return data', async ({ page, skip }) => {
skip.rtl();
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: data'), () => {
let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => {
actionSheetFixture = new ActionSheetFixture(page);
await page.goto(`/src/components/action-sheet/test/basic`, config);
});
test('should return data', async ({ page }) => {
const ionActionSheetDidDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
await actionSheetFixture.open('#buttonData');
@@ -22,8 +22,7 @@ test.describe('action sheet: basic', () => {
await ionActionSheetDidDismiss.next();
expect(ionActionSheetDidDismiss).toHaveReceivedEventDetail({ data: { type: '1' }, role: undefined });
});
test('should return cancel button data', async ({ page, skip }) => {
skip.rtl();
test('should return cancel button data', async ({ page }) => {
const ionActionSheetDidDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
await actionSheetFixture.open('#buttonData');
@@ -35,16 +34,28 @@ test.describe('action sheet: basic', () => {
expect(ionActionSheetDidDismiss).toHaveReceivedEventDetail({ data: { type: 'cancel' }, role: 'cancel' });
});
});
test.describe('action sheet: attributes', () => {
test('should set htmlAttributes', async ({ page, skip }) => {
skip.rtl();
});
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: attributes'), () => {
test('should set htmlAttributes', async ({ page }) => {
await page.goto(`/src/components/action-sheet/test/basic`, config);
const actionSheetFixture = new ActionSheetFixture(page);
await actionSheetFixture.open('#basic');
const actionSheet = page.locator('ion-action-sheet');
await expect(actionSheet).toHaveAttribute('data-testid', 'basic-action-sheet');
});
});
test.describe('action sheet: variants', () => {
});
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('action sheet: variant rendering'), () => {
let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => {
actionSheetFixture = new ActionSheetFixture(page, screenshot);
await page.goto(`/src/components/action-sheet/test/basic`, config);
});
test('should open basic action sheet', async () => {
await actionSheetFixture.open('#basic');
await actionSheetFixture.screenshot('basic');
@@ -73,24 +84,31 @@ test.describe('action sheet: basic', () => {
await actionSheetFixture.open('#scrollWithoutCancel');
await actionSheetFixture.screenshot('scroll-without-cancel');
});
test('should open custom backdrop action sheet', async ({ page, skip }) => {
skip.rtl();
});
});
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: variant functionality'), () => {
let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => {
actionSheetFixture = new ActionSheetFixture(page);
await page.goto(`/src/components/action-sheet/test/basic`, config);
});
test('should open custom backdrop action sheet', async ({ page }) => {
await actionSheetFixture.open('#customBackdrop');
const backdrop = page.locator('ion-action-sheet ion-backdrop');
await expect(backdrop).toHaveCSS('opacity', '1');
});
test('should open alert from action sheet', async ({ page, skip }) => {
skip.rtl();
test('should open alert from action sheet', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
await actionSheetFixture.open('#alertFromActionSheet');
await page.locator('#open-alert').click();
await page.click('#open-alert');
await ionAlertDidPresent.next();
});
test('should not dismiss action sheet when backdropDismiss: false', async ({ page, skip }) => {
skip.rtl();
test('should not dismiss action sheet when backdropDismiss: false', async ({ page }) => {
await actionSheetFixture.open('#noBackdropDismiss');
const actionSheet = page.locator('ion-action-sheet');
@@ -99,9 +117,13 @@ test.describe('action sheet: basic', () => {
await expect(actionSheet).toBeVisible();
});
});
test.describe('action sheet: focus trap', () => {
test('it should trap focus in action sheet', async ({ page, skip, browserName }) => {
skip.rtl();
});
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: focus trap'), () => {
test('it should trap focus in action sheet', async ({ page, browserName }) => {
await page.goto(`/src/components/action-sheet/test/basic`, config);
const actionSheetFixture = new ActionSheetFixture(page);
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
await actionSheetFixture.open('#basic');
@@ -121,11 +143,13 @@ test.describe('action sheet: basic', () => {
class ActionSheetFixture {
readonly page: E2EPage;
readonly screenshotFn?: (file: string) => string;
private actionSheet!: Locator;
constructor(page: E2EPage) {
constructor(page: E2EPage, screenshot?: (file: string) => string) {
this.page = page;
this.screenshotFn = screenshot;
}
async open(selector: string) {
@@ -144,8 +168,14 @@ class ActionSheetFixture {
}
async screenshot(modifier: string) {
await expect(this.actionSheet).toHaveScreenshot(
`action-sheet-${modifier}-diff-${this.page.getSnapshotSettings()}.png`
);
const { screenshotFn } = this;
if (!screenshotFn) {
throw new Error(
'A screenshot function is required to take a screenshot. Pass one in when creating ActionSheetFixture.'
);
}
await expect(this.actionSheet).toHaveScreenshot(screenshotFn(`action-sheet-${modifier}-diff`));
}
}

View File

@@ -1,35 +1,34 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('action sheet: isOpen', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl('isOpen does not behave differently in RTL');
skip.mode('md', 'isOpen does not behave differently in MD');
await page.goto('/src/components/action-sheet/test/is-open');
});
configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: isOpen'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/action-sheet/test/is-open', config);
});
test('should open the action sheet', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const actionSheet = page.locator('ion-action-sheet');
test('should open the action sheet', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const actionSheet = page.locator('ion-action-sheet');
await page.click('#default');
await page.click('#default');
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
});
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
});
test('should open the action sheet then close after a timeout', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const ionActionSheetDidDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
const actionSheet = page.locator('ion-action-sheet');
test('should open the action sheet then close after a timeout', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const ionActionSheetDidDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
const actionSheet = page.locator('ion-action-sheet');
await page.click('#timeout');
await page.click('#timeout');
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
await ionActionSheetDidDismiss.next();
await ionActionSheetDidDismiss.next();
await expect(actionSheet).toBeHidden();
await expect(actionSheet).toBeHidden();
});
});
});

View File

@@ -1,21 +1,20 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('action sheet: translucent', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.mode('md', 'Translucent effect is only active on iOS mode');
skip.rtl('This tests how the component is painted, not layout. RTL tests are not needed here');
configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('action sheet: translucent'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/action-sheet/test/translucent`, config);
await page.goto(`/src/components/action-sheet/test/translucent`);
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const basic = page.locator('#basic');
await basic.click();
const basic = page.locator('#basic');
await basic.click();
await ionActionSheetDidPresent.next();
await ionActionSheetDidPresent.next();
const actionSheet = page.locator('ion-action-sheet');
await expect(actionSheet).toHaveScreenshot(`action-sheet-translucent-${page.getSnapshotSettings()}.png`);
const actionSheet = page.locator('ion-action-sheet');
await expect(actionSheet).toHaveScreenshot(screenshot('action-sheet-translucent'));
});
});
});

View File

@@ -1,35 +1,34 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('action sheet: trigger', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl('trigger does not behave differently in RTL');
skip.mode('md');
await page.goto('/src/components/action-sheet/test/trigger');
});
configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: trigger'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/action-sheet/test/trigger', config);
});
test('should open the action sheet', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const actionSheet = page.locator('#default-action-sheet');
test('should open the action sheet', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const actionSheet = page.locator('#default-action-sheet');
await page.click('#default');
await page.click('#default');
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
});
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
});
test('should present a previously presented action sheet', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const ionActionSheetDidDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
const actionSheet = page.locator('#timeout-action-sheet');
test('should present a previously presented action sheet', async ({ page }) => {
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const ionActionSheetDidDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
const actionSheet = page.locator('#timeout-action-sheet');
await page.click('#timeout');
await page.click('#timeout');
await ionActionSheetDidDismiss.next();
await ionActionSheetDidDismiss.next();
await page.click('#timeout');
await page.click('#timeout');
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
await ionActionSheetDidPresent.next();
await expect(actionSheet).toBeVisible();
});
});
});

View File

@@ -17,6 +17,7 @@ import {
prepareOverlay,
present,
safeCall,
setOverlayId,
} from '../../utils/overlays';
import type { OverlayEventDetail } from '../../utils/overlays-interface';
import type { IonicSafeString } from '../../utils/sanitization';
@@ -329,6 +330,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
}
componentWillLoad() {
setOverlayId(this.el);
this.inputsChanged();
this.buttonsChanged();
}

View File

@@ -1,7 +1,7 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import type { E2EPage } from '@utils/test/playwright';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
const testAria = async (
page: E2EPage,
@@ -28,36 +28,36 @@ const testAria = async (
expect(ariaDescribedBy).toBe(expectedAriaDescribedBy);
};
test.describe('alert: a11y', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl();
await page.goto(`/src/components/alert/test/a11y`);
});
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('alert: a11y'), () => {
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/alert/test/a11y`, config);
});
test('should not have accessibility violations when header and message are defined', async ({ page }) => {
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
const button = page.locator('#bothHeaders');
await button.click();
test('should not have accessibility violations when header and message are defined', async ({ page }) => {
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
const button = page.locator('#bothHeaders');
await button.click();
await didPresent.next();
await didPresent.next();
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
test('should have aria-labelledby when header is set', async ({ page }) => {
await testAria(page, 'noMessage', 'alert-1-hdr', null);
});
test('should have aria-labelledby when header is set', async ({ page }) => {
await testAria(page, 'noMessage', 'alert-1-hdr', null);
});
test('should have aria-describedby when message is set', async ({ page }) => {
await testAria(page, 'noHeaders', null, 'alert-1-msg');
});
test('should have aria-describedby when message is set', async ({ page }) => {
await testAria(page, 'noHeaders', null, 'alert-1-msg');
});
test('should fall back to subHeader for aria-labelledby if header is not defined', async ({ page }) => {
await testAria(page, 'subHeaderOnly', 'alert-1-sub-hdr', 'alert-1-msg');
});
test('should fall back to subHeader for aria-labelledby if header is not defined', async ({ page }) => {
await testAria(page, 'subHeaderOnly', 'alert-1-sub-hdr', 'alert-1-msg');
});
test('should allow for manually specifying aria attributes', async ({ page }) => {
await testAria(page, 'customAria', 'Custom title', 'Custom description');
test('should allow for manually specifying aria attributes', async ({ page }) => {
await testAria(page, 'customAria', 'Custom title', 'Custom description');
});
});
});

View File

@@ -0,0 +1,41 @@
import { newSpecPage } from '@stencil/core/testing';
import { Alert } from '../alert';
it('alert should be assigned an incrementing id', async () => {
const page = await newSpecPage({
components: [Alert],
html: `<ion-alert is-open="true"></ion-alert>`,
});
let alert: HTMLIonAlertElement;
alert = page.body.querySelector('ion-alert')!;
expect(alert).not.toBe(null);
expect(alert.getAttribute('id')).toBe('ion-overlay-1');
// Remove the alert from the DOM
alert.remove();
await page.waitForChanges();
// Create a new alert to verify the id is incremented
alert = document.createElement('ion-alert');
alert.isOpen = true;
page.body.appendChild(alert);
await page.waitForChanges();
alert = page.body.querySelector('ion-alert')!;
expect(alert.getAttribute('id')).toBe('ion-overlay-2');
// Presenting the same alert again should reuse the existing id
alert.isOpen = false;
await page.waitForChanges();
alert.isOpen = true;
await page.waitForChanges();
alert = page.body.querySelector('ion-alert')!;
expect(alert.getAttribute('id')).toBe('ion-overlay-2');
});

View File

@@ -1,113 +1,147 @@
import { expect } from '@playwright/test';
import type { Locator } from '@playwright/test';
import type { E2EPage } from '@utils/test/playwright';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
const openAlert = async (page: E2EPage, buttonID: string) => {
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
configs({ directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('alert: basic'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/alert/test/basic', config);
});
test('focus trap should work correctly', async ({ page, browserName }) => {
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
await page.click(`#${buttonID}`);
await didPresent.next();
const alertFixture = new AlertFixture(page, screenshot);
return page.locator('ion-alert');
};
const alert = await alertFixture.open('#multipleButtons');
const alertBtns = alert.locator('button');
const testAlert = async (page: E2EPage, buttonID: string) => {
await page.goto(`/src/components/alert/test/basic`);
await page.keyboard.press(tabKey);
await expect(alertBtns.nth(0)).toBeFocused();
const didDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const alert = await openAlert(page, buttonID);
await page.keyboard.press(`Shift+${tabKey}`);
await expect(alertBtns.nth(2)).toBeFocused();
await expect(alert).toBeVisible();
await expect(alert).toHaveScreenshot(`alert-${buttonID}-${page.getSnapshotSettings()}.png`);
await alert.evaluate((el: HTMLIonAlertElement) => el.dismiss());
await didDismiss.next();
await expect(alert).toHaveCount(0);
};
test.describe('alert: basic', () => {
test('focus trap should work correctly', async ({ page, skip, browserName }) => {
skip.rtl();
await page.goto(`/src/components/alert/test/basic`);
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
const alert = await openAlert(page, 'multipleButtons');
const alertBtns = alert.locator('button');
await page.keyboard.press(tabKey);
await expect(alertBtns.nth(0)).toBeFocused();
await page.keyboard.press(`Shift+${tabKey}`);
await expect(alertBtns.nth(2)).toBeFocused();
await page.keyboard.press(tabKey);
await expect(alertBtns.nth(0)).toBeFocused();
});
test('should set custom attributes', async ({ page, skip }) => {
skip.rtl();
await page.goto(`/src/components/alert/test/basic`);
const alert = await openAlert(page, 'basic');
await expect(alert).toHaveAttribute('data-testid', 'basic-alert');
});
test('should dismiss when async handler resolves', async ({ page, skip }) => {
skip.rtl();
await page.goto(`/src/components/alert/test/basic`);
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const ionLoadingDidDismiss = await page.spyOnEvent('ionLoadingDidDismiss');
const alert = page.locator('ion-alert');
await page.click('#asyncHandler');
await ionAlertDidPresent.next();
await page.click('.alert-button');
await expect(alert).toBeVisible();
await ionLoadingDidDismiss.next();
await ionAlertDidDismiss.next();
await expect(alert).toBeHidden();
});
test.describe('should not have visual regressions', () => {
test('header, subheader, message', async ({ page }) => {
await testAlert(page, 'basic');
await page.keyboard.press(tabKey);
await expect(alertBtns.nth(0)).toBeFocused();
});
test('long message', async ({ page }) => {
await testAlert(page, 'longMessage');
test('should set custom attributes', async ({ page }) => {
const alertFixture = new AlertFixture(page, screenshot);
const alert = await alertFixture.open('#basic');
await expect(alert).toHaveAttribute('data-testid', 'basic-alert');
});
test('more than two buttons', async ({ page }) => {
await testAlert(page, 'multipleButtons');
});
test('should dismiss when async handler resolves', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const ionLoadingDidDismiss = await page.spyOnEvent('ionLoadingDidDismiss');
test('no message', async ({ page }) => {
await testAlert(page, 'noMessage');
});
const alert = page.locator('ion-alert');
test('two buttons', async ({ page }) => {
await testAlert(page, 'confirm');
});
await page.click('#asyncHandler');
await ionAlertDidPresent.next();
test('form prompt', async ({ page }) => {
await testAlert(page, 'prompt');
});
await page.click('.alert-button');
test('radios', async ({ page }) => {
await testAlert(page, 'radio');
});
await expect(alert).toBeVisible();
test('checkboxes', async ({ page }) => {
await testAlert(page, 'checkbox');
await ionLoadingDidDismiss.next();
await ionAlertDidDismiss.next();
await expect(alert).toBeHidden();
});
});
});
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('should not have visual regressions'), () => {
let alertFixture!: AlertFixture;
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/alert/test/basic', config);
alertFixture = new AlertFixture(page, screenshot);
});
test('header, subheader, message', async () => {
await alertFixture.open('#basic');
await alertFixture.screenshot('basic');
});
test('long message', async () => {
await alertFixture.open('#longMessage');
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');
});
test('two buttons', async () => {
await alertFixture.open('#confirm');
await alertFixture.screenshot('confirm');
});
test('form prompt', async () => {
await alertFixture.open('#prompt');
await alertFixture.screenshot('prompt');
});
test('radios', async () => {
await alertFixture.open('#radio');
await alertFixture.screenshot('radio');
});
test('checkboxes', async () => {
await alertFixture.open('#checkbox');
await alertFixture.screenshot('checkbox');
});
});
});
class AlertFixture {
readonly page: E2EPage;
readonly screenshotFn?: (file: string) => string;
private alert!: Locator;
constructor(page: E2EPage, screenshot?: (file: string) => string) {
this.page = page;
this.screenshotFn = screenshot;
}
async open(selector: string) {
const ionAlertDidPresent = await this.page.spyOnEvent('ionAlertDidPresent');
await this.page.locator(selector).click();
await ionAlertDidPresent.next();
this.alert = this.page.locator('ion-alert');
await expect(this.alert).toBeVisible();
return this.alert;
}
async dismiss() {
const ionAlertDidDismiss = await this.page.spyOnEvent('ionAlertDidDismiss');
await this.alert.evaluate((el: HTMLIonAlertElement) => el.dismiss());
await ionAlertDidDismiss.next();
await expect(this.alert).not.toBeVisible();
}
async screenshot(modifier: string) {
const { screenshotFn } = this;
if (!screenshotFn) {
throw new Error(
'A screenshot function is required to take a screenshot. Pass one in when creating ActionSheetFixture.'
);
}
await expect(this.alert).toHaveScreenshot(screenshotFn(`alert-${modifier}`));
}
}

View File

@@ -1,34 +1,33 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('alert: isOpen', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl('isOpen does not behave differently in RTL');
skip.mode('md', 'isOpen does not behave differently in MD');
await page.goto('/src/components/alert/test/is-open');
});
configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) => {
test.describe(title('alert: isOpen'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/alert/test/is-open', config);
});
test('should open the alert', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const alert = page.locator('ion-alert');
test('should open the alert', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const alert = page.locator('ion-alert');
await page.click('#default');
await page.click('#default');
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
});
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
});
test('should open the alert then close after a timeout', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const alert = page.locator('ion-alert');
test('should open the alert then close after a timeout', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const alert = page.locator('ion-alert');
await page.click('#timeout');
await page.click('#timeout');
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
await ionAlertDidDismiss.next();
await expect(alert).toBeHidden();
await ionAlertDidDismiss.next();
await expect(alert).toBeHidden();
});
});
});

View File

@@ -1,16 +1,18 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('alert: standalone', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/alert/test/standalone`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('alert: standalone'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/alert/test/standalone`, config);
const alert = page.locator('ion-alert');
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
const alert = page.locator('ion-alert');
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
await page.click('#basic');
await didPresent.next();
await page.click('#basic');
await didPresent.next();
await expect(alert).toHaveScreenshot(`alert-standalone-${page.getSnapshotSettings()}.png`);
await expect(alert).toHaveScreenshot(screenshot('alert-standalone'));
});
});
});

View File

@@ -1,35 +1,34 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('alert: trigger', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl('trigger does not behave differently in RTL');
skip.mode('md');
await page.goto('/src/components/alert/test/trigger');
});
configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ config, title }) => {
test.describe(title('alert: trigger'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/alert/test/trigger', config);
});
test('should open the alert', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const alert = page.locator('#default-alert');
test('should open the alert', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const alert = page.locator('#default-alert');
await page.click('#default');
await page.click('#default');
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
});
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
});
test('should present a previously presented alert', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const alert = page.locator('#timeout-alert');
test('should present a previously presented alert', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const alert = page.locator('#timeout-alert');
await page.click('#timeout');
await page.click('#timeout');
await ionAlertDidDismiss.next();
await ionAlertDidDismiss.next();
await page.click('#timeout');
await page.click('#timeout');
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
await ionAlertDidPresent.next();
await expect(alert).toBeVisible();
});
});
});

View File

@@ -1,34 +1,37 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
import type { E2EPage } from '@utils/test/playwright';
test.describe('app: safe-area', () => {
const testOverlay = async (page: E2EPage, trigger: string, event: string, screenshotModifier: string) => {
const presentEvent = await page.spyOnEvent(event);
/**
* Safe area tests only check top and bottom edges. RTL checks are not required here.
*/
configs({ directions: ['ltr'] }).forEach(({ config, title, screenshot }) => {
test.describe(title('app: safe-area'), () => {
const testOverlay = async (page: E2EPage, trigger: string, event: string, screenshotModifier: string) => {
const presentEvent = await page.spyOnEvent(event);
await page.click(trigger);
await presentEvent.next();
await page.click(trigger);
await presentEvent.next();
// Sometimes the inner content takes a frame or two to render
await page.waitForChanges();
// Sometimes the inner content takes a frame or two to render
await page.waitForChanges();
await expect(page).toHaveScreenshot(`app-${screenshotModifier}-diff-${page.getSnapshotSettings()}.png`);
};
test.beforeEach(async ({ page, skip }) => {
skip.rtl('Safe area tests only check top and bottom edges. RTL checks are not required here.');
await page.goto(`/src/components/app/test/safe-area`);
});
test('should not have visual regressions with action sheet', async ({ page }) => {
await testOverlay(page, '#show-action-sheet', 'ionActionSheetDidPresent', 'action-sheet');
});
test('should not have visual regressions with menu', async ({ page }) => {
await testOverlay(page, '#show-menu', 'ionDidOpen', 'menu');
});
test('should not have visual regressions with picker', async ({ page }) => {
await testOverlay(page, '#show-picker', 'ionPickerDidPresent', 'picker');
});
test('should not have visual regressions with toast', async ({ page }) => {
await testOverlay(page, '#show-toast', 'ionToastDidPresent', 'toast');
await expect(page).toHaveScreenshot(screenshot(`app-${screenshotModifier}-diff`));
};
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/app/test/safe-area`, config);
});
test('should not have visual regressions with action sheet', async ({ page }) => {
await testOverlay(page, '#show-action-sheet', 'ionActionSheetDidPresent', 'action-sheet');
});
test('should not have visual regressions with menu', async ({ page }) => {
await testOverlay(page, '#show-menu', 'ionDidOpen', 'menu');
});
test('should not have visual regressions with picker', async ({ page }) => {
await testOverlay(page, '#show-picker', 'ionPickerDidPresent', 'picker');
});
test('should not have visual regressions with toast', async ({ page }) => {
await testOverlay(page, '#show-toast', 'ionToastDidPresent', 'toast');
});
});
});

View File

@@ -1,20 +1,24 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('avatar: basic', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.rtl('Avatar does not test RTL behaviors. Usages of Avatar in slots are tested in components that use Avatar.');
/**
* Avatar does not test RTL behaviors.
* Usages of Avatar in slots are tested in components that use Avatar.
*/
configs({ directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('avatar: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/avatar/test/basic`, config);
await page.goto(`/src/components/avatar/test/basic`);
const avatar = page.locator('#avatar');
const avatarChip = page.locator('#avatar-chip');
const avatarItemStart = page.locator('#avatar-item-start');
const avatarItemEnd = page.locator('#avatar-item-end');
const avatar = page.locator('#avatar');
const avatarChip = page.locator('#avatar-chip');
const avatarItemStart = page.locator('#avatar-item-start');
const avatarItemEnd = page.locator('#avatar-item-end');
await expect(avatar).toHaveScreenshot(`avatar-diff-${page.getSnapshotSettings()}.png`);
await expect(avatarChip).toHaveScreenshot(`avatar-chip-diff-${page.getSnapshotSettings()}.png`);
await expect(avatarItemStart).toHaveScreenshot(`avatar-item-start-diff-${page.getSnapshotSettings()}.png`);
await expect(avatarItemEnd).toHaveScreenshot(`avatar-item-end-diff-${page.getSnapshotSettings()}.png`);
await expect(avatar).toHaveScreenshot(screenshot(`avatar-diff`));
await expect(avatarChip).toHaveScreenshot(screenshot(`avatar-chip-diff`));
await expect(avatarItemStart).toHaveScreenshot(screenshot(`avatar-item-start-diff`));
await expect(avatarItemEnd).toHaveScreenshot(screenshot(`avatar-item-end-diff`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('back-button: basic', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/back-button/test/basic`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('back-button: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/back-button/test/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`back-button-basic-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`back-button-basic`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('back-button: toolbar', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/back-button/test/toolbar`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('back-button: toolbar'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/back-button/test/toolbar`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`back-button-toolbar-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`back-button-toolbar`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('badge: rendering', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/badge/test/basic');
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('badge: rendering'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/badge/test/basic', config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`badge-basic-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`badge-basic`));
});
});
});

View File

@@ -9,7 +9,7 @@
--color-active: #{$breadcrumb-md-color-active};
--color-hover: #{$breadcrumb-md-color-active};
--color-focused: #{$breadcrumb-md-color-focused};
--background-focused: $breadcrumb-md-background-focused;
--background-focused: #{$breadcrumb-md-background-focused};
}
:host(.breadcrumb-active) {

View File

@@ -1,12 +1,14 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('breadcrumbs: axe', () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/a11y`);
configs().forEach(({ config, title }) => {
test.describe(title('breadcrumbs: axe'), () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/a11y`, config);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('breadcrumbs: basic', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/basic`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('breadcrumbs: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`breadcrumb-diff-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`breadcrumb-diff`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('breadcrumbs: collapsed', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/collapsed`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('breadcrumbs: collapsed'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/collapsed`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`breadcrumb-collapsed-diff-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`breadcrumb-collapsed-diff`));
});
});
});

View File

@@ -1,71 +1,70 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('breadcrumbs: reactive', () => {
test.beforeEach(async ({ page, skip }) => {
skip.rtl();
skip.mode('ios');
await page.goto(`/src/components/breadcrumbs/test/reactive`);
});
test.describe('adding a breadcrumb item', () => {
test('should update the active item', async ({ page }) => {
const breadcrumbItems = page.locator('ion-breadcrumb');
const addItemButton = page.locator('ion-button#add-btn');
await expect(breadcrumbItems).toHaveCount(4);
await addItemButton.click();
await page.waitForChanges();
await expect(breadcrumbItems).toHaveCount(5);
const previousActiveItem = breadcrumbItems.nth(3);
const lastBreadcrumbItem = breadcrumbItems.nth(4);
await expect(previousActiveItem).not.toHaveClass(/breadcrumb-active/);
await expect(lastBreadcrumbItem).toHaveClass(/breadcrumb-active/);
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('breadcrumbs: reactive'), () => {
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/breadcrumbs/test/reactive`, config);
});
test('should not have visual regressions', async ({ page }) => {
await page.setIonViewport();
test.describe('adding a breadcrumb item', () => {
test('should update the active item', async ({ page }) => {
const breadcrumbItems = page.locator('ion-breadcrumb');
const breadcrumbs = page.locator('ion-breadcrumbs');
const addItemButton = page.locator('ion-button#add-btn');
await page.click('#add-btn');
await page.waitForChanges();
await expect(breadcrumbItems).toHaveCount(4);
await expect(breadcrumbs).toHaveScreenshot(`breadcrumbs-reactive-add-diff-${page.getSnapshotSettings()}.png`);
});
});
await addItemButton.click();
await page.waitForChanges();
test.describe('removing a breadcrumb item', () => {
test('should update the active item', async ({ page }) => {
const breadcrumbItems = page.locator('ion-breadcrumb');
await expect(breadcrumbItems).toHaveCount(5);
await expect(breadcrumbItems).toHaveCount(4);
const previousActiveItem = breadcrumbItems.nth(3);
const lastBreadcrumbItem = breadcrumbItems.nth(4);
await page.click('#remove-btn');
await page.waitForChanges();
await expect(previousActiveItem).not.toHaveClass(/breadcrumb-active/);
await expect(lastBreadcrumbItem).toHaveClass(/breadcrumb-active/);
});
await expect(breadcrumbItems).toHaveCount(3);
test('should not have visual regressions', async ({ page }) => {
await page.setIonViewport();
const lastBreadcrumbItem = breadcrumbItems.nth(2);
const breadcrumbs = page.locator('ion-breadcrumbs');
await expect(lastBreadcrumbItem).toHaveClass(/breadcrumb-active/);
await page.click('#add-btn');
await page.waitForChanges();
await expect(breadcrumbs).toHaveScreenshot(screenshot(`breadcrumbs-reactive-add-diff`));
});
});
test('should not have visual regressions', async ({ page }) => {
await page.setIonViewport();
test.describe('removing a breadcrumb item', () => {
test('should update the active item', async ({ page }) => {
const breadcrumbItems = page.locator('ion-breadcrumb');
const breadcrumbs = page.locator('ion-breadcrumbs');
await expect(breadcrumbItems).toHaveCount(4);
await page.click('#remove-btn');
await page.waitForChanges();
await page.click('#remove-btn');
await page.waitForChanges();
await expect(breadcrumbs).toHaveScreenshot(`breadcrumbs-reactive-remove-diff-${page.getSnapshotSettings()}.png`);
await expect(breadcrumbItems).toHaveCount(3);
const lastBreadcrumbItem = breadcrumbItems.nth(2);
await expect(lastBreadcrumbItem).toHaveClass(/breadcrumb-active/);
});
test('should not have visual regressions', async ({ page }) => {
await page.setIonViewport();
const breadcrumbs = page.locator('ion-breadcrumbs');
await page.click('#remove-btn');
await page.waitForChanges();
await expect(breadcrumbs).toHaveScreenshot(screenshot(`breadcrumbs-reactive-remove-diff`));
});
});
});
});

View File

@@ -1,56 +1,65 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: basic', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/basic`);
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('button: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`button-diff-${page.getSnapshotSettings()}.png`);
});
test('should correctly set fill to undefined', async ({ page, skip }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/25886',
});
skip.rtl();
skip.mode('ios', 'This behavior does not differ across modes');
await page.setContent(`
<ion-button fill="outline"></ion-button>
`);
const button = page.locator('ion-button');
await expect(button).toHaveClass(/button-outline/);
await button.evaluate((el: HTMLIonButtonElement) => (el.fill = undefined));
await page.waitForChanges();
await expect(button).toHaveClass(/button-solid/);
});
});
test.describe('button: ripple effect', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.mode('ios', 'Ripple effect is only available in MD mode.');
await page.goto(`/src/components/button/test/basic?ionic:_testing=false`);
const button = page.locator('#default');
await button.scrollIntoViewIfNeeded();
const boundingBox = await button.boundingBox();
if (boundingBox) {
await page.mouse.move(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2);
await page.mouse.down();
}
await page.waitForSelector('#default.ion-activated');
await expect(button).toHaveScreenshot(`button-ripple-effect-${page.getSnapshotSettings()}.png`, {
animations: 'disabled',
await expect(page).toHaveScreenshot(screenshot(`button-diff`));
});
});
});
configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ config, title }) => {
test.describe(title('button: basic'), () => {
test('should correctly set fill to undefined', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/25886',
});
await page.setContent(
`
<ion-button fill="outline"></ion-button>
`,
config
);
const button = page.locator('ion-button');
await expect(button).toHaveClass(/button-outline/);
await button.evaluate((el: HTMLIonButtonElement) => (el.fill = undefined));
await page.waitForChanges();
await expect(button).toHaveClass(/button-solid/);
});
});
});
/**
* Ripple effect is only available in MD mode.
*/
configs({ modes: ['md'] }).forEach(({ config, screenshot, title }) => {
test.describe(title('button: ripple effect'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/basic?ionic:_testing=false`, config);
const button = page.locator('#default');
await button.scrollIntoViewIfNeeded();
const boundingBox = await button.boundingBox();
if (boundingBox) {
await page.mouse.move(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2);
await page.mouse.down();
}
await page.waitForSelector('#default.ion-activated');
await expect(button).toHaveScreenshot(screenshot(`button-ripple-effect`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: clear', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/clear`);
configs().forEach(({ title, config, screenshot }) => {
test.describe(title('button: clear'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/clear`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`button-clear-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`button-clear`));
});
});
});

View File

@@ -1,13 +1,17 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: expand', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.rtl('All content takes up the full width, so RTL has no effect.');
await page.goto(`/src/components/button/test/expand`);
/**
* All content takes up the full width, so RTL has no effect.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: expand'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/expand`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`button-expand-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`button-expand`));
});
});
});

View File

@@ -1,55 +1,66 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: form', () => {
test('should submit the form by id', async ({ page }) => {
await page.setContent(`
<form id="myForm"></form>
<ion-button form="myForm" type="submit">Submit</ion-button>
`);
configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) => {
test.describe(title('button: form'), () => {
test('should submit the form by id', async ({ page }) => {
await page.setContent(
`
<form id="myForm"></form>
<ion-button form="myForm" type="submit">Submit</ion-button>
`,
config
);
const submitEvent = await page.spyOnEvent('submit');
const submitEvent = await page.spyOnEvent('submit');
await page.click('ion-button');
await page.click('ion-button');
expect(submitEvent).toHaveReceivedEvent();
expect(submitEvent).toHaveReceivedEvent();
});
test('should submit the form by reference', async ({ page }) => {
await page.setContent(
`
<form></form>
<ion-button type="submit">Submit</ion-button>
<script>
const form = document.querySelector('form');
const button = document.querySelector('ion-button');
button.form = form;
</script>
`,
config
);
const submitEvent = await page.spyOnEvent('submit');
await page.click('ion-button');
expect(submitEvent).toHaveReceivedEvent();
});
test('should submit the closest form', async ({ page }) => {
await page.setContent(
`
<form>
<ion-button type="submit">Submit</ion-button>
</form>
`,
config
);
const submitEvent = await page.spyOnEvent('submit');
await page.click('ion-button');
expect(submitEvent).toHaveReceivedEvent();
});
});
test('should submit the form by reference', async ({ page }) => {
await page.setContent(`
<form></form>
<ion-button type="submit">Submit</ion-button>
<script>
const form = document.querySelector('form');
const button = document.querySelector('ion-button');
button.form = form;
</script>
`);
const submitEvent = await page.spyOnEvent('submit');
await page.click('ion-button');
expect(submitEvent).toHaveReceivedEvent();
});
test('should submit the closest form', async ({ page }) => {
await page.setContent(`
<form>
<ion-button type="submit">Submit</ion-button>
</form>
`);
const submitEvent = await page.spyOnEvent('submit');
await page.click('ion-button');
expect(submitEvent).toHaveReceivedEvent();
});
test.describe('should throw a warning if the form cannot be found', () => {
test.describe(title('should throw a warning if the form cannot be found'), () => {
test('form is a string selector', async ({ page }) => {
await page.setContent(`<ion-button type="submit" form="missingForm">Submit</ion-button>`);
await page.setContent(`<ion-button type="submit" form="missingForm">Submit</ion-button>`, config);
const logs: string[] = [];
@@ -66,7 +77,8 @@ test.describe('button: form', () => {
});
test('form is an element reference', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-button type="submit">Submit</ion-button>
<script>
const form = document.querySelector('form');
@@ -74,7 +86,9 @@ test.describe('button: form', () => {
button.form = form;
</script>
`);
`,
config
);
const logs: string[] = [];

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: icon', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/icon`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('button: icon'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/icon`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`button-icon-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`button-icon`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: outline', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/outline`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('button: outline'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/outline`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`button-outline-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`button-outline`));
});
});
});

View File

@@ -1,13 +1,17 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: round', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.rtl('All content takes up the full width, so RTL has no effect.');
await page.goto(`/src/components/button/test/round`);
/**
* All content takes up the full width, so RTL has no effect.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: round'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/round`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`button-round-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`button-round`));
});
});
});

View File

@@ -1,50 +1,62 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('button: size', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should render small buttons', async ({ page }) => {
await page.setContent(`
<ion-button size="small" fill="solid">Small Button</ion-button>
`);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-size-small-${page.getSnapshotSettings()}.png`);
});
test('should render large buttons', async ({ page }) => {
await page.setContent(`
<ion-button size="large" fill="solid">Large Button</ion-button>
`);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-size-large-${page.getSnapshotSettings()}.png`);
});
test.describe('in ion-buttons', () => {
test('should render small button', async ({ page }) => {
await page.setContent(`
<ion-buttons>
<ion-button size="small" fill="solid">Small Button</ion-button>
</ion-buttons>
`);
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: size'), () => {
test('should render small buttons', async ({ page }) => {
await page.setContent(
`
<ion-button size="small" fill="solid">Small Button</ion-button>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-size-small-in-buttons-${page.getSnapshotSettings()}.png`);
await expect(wrapper).toHaveScreenshot(screenshot(`button-size-small`));
});
test('should render large buttons', async ({ page }) => {
await page.setContent(
`
<ion-button size="large" fill="solid">Large Button</ion-button>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(screenshot(`button-size-large`));
});
});
test.describe(title('in ion-buttons'), () => {
test('should render small button', async ({ page }) => {
await page.setContent(
`
<ion-buttons>
<ion-button size="small" fill="solid">Small Button</ion-button>
</ion-buttons>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(screenshot(`button-size-small-in-buttons`));
});
test('should render large button', async ({ page }) => {
await page.setContent(`
<ion-buttons>
<ion-button size="large" fill="solid">Large Button</ion-button>
</ion-buttons>
`);
await page.setContent(
`
<ion-buttons>
<ion-button size="large" fill="solid">Large Button</ion-button>
</ion-buttons>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-size-large-in-buttons-${page.getSnapshotSettings()}.png`);
await expect(wrapper).toHaveScreenshot(screenshot(`button-size-large-in-buttons`));
});
});
});

View File

@@ -1,55 +1,66 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
/**
* Clear buttons have special font-weight
* styles which is why we make sure
* to capture the clear button here.
*/
test.describe('button: strong', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should render strong button', async ({ page }) => {
await page.setContent(`
<ion-button fill="solid" strong="true">Button</ion-button>
`);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-strong-${page.getSnapshotSettings()}.png`);
});
test('should render strong clear button', async ({ page }) => {
await page.setContent(`
<ion-button fill="clear" strong="true">Button</ion-button>
`);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-clear-strong-${page.getSnapshotSettings()}.png`);
});
test.describe('in ion-buttons', () => {
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: strong'), () => {
test('should render strong button', async ({ page }) => {
await page.setContent(`
<ion-buttons>
<ion-button strong="true" fill="solid">Button</ion-button>
</ion-buttons>
`);
await page.setContent(
`
<ion-button fill="solid" strong="true">Button</ion-button>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-strong-in-buttons-${page.getSnapshotSettings()}.png`);
await expect(wrapper).toHaveScreenshot(screenshot(`button-strong`));
});
test('should render strong clear button', async ({ page }) => {
await page.setContent(`
<ion-buttons>
<ion-button strong="true" fill="clear">Button</ion-button>
</ion-buttons>
`);
await page.setContent(
`
<ion-button fill="clear" strong="true">Button</ion-button>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(`button-clear-strong-in-buttons-${page.getSnapshotSettings()}.png`);
await expect(wrapper).toHaveScreenshot(screenshot(`button-clear-strong`));
});
});
test.describe(title('in ion-buttons'), () => {
test('should render strong button', async ({ page }) => {
await page.setContent(
`
<ion-buttons>
<ion-button strong="true" fill="solid">Button</ion-button>
</ion-buttons>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(screenshot(`button-strong-in-buttons`));
});
test('should render strong clear button', async ({ page }) => {
await page.setContent(
`
<ion-buttons>
<ion-button strong="true" fill="clear">Button</ion-button>
</ion-buttons>
`,
config
);
const wrapper = page.locator('ion-button');
await expect(wrapper).toHaveScreenshot(screenshot(`button-clear-strong-in-buttons`));
});
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('card-header: basic', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/card-header/test/basic`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('card-header: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/card-header/test/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`card-header-diff-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`card-header-diff`));
});
});
});

View File

@@ -1,10 +1,11 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('card: basic', () => {
test.describe('card: rendering', () => {
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('card: rendering'), () => {
test('should not have visual regressions with basic card', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-card>
<ion-card-header>
<ion-card-title>Card Title</ion-card-title>
@@ -16,20 +17,20 @@ test.describe('card: basic', () => {
in the woods. Wash your spirit clean.
</ion-card-content>
</ion-card>
`);
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-diff-${page.getSnapshotSettings()}.png`);
await expect(card).toHaveScreenshot(screenshot(`card-diff`));
});
});
test.describe('card: feature rendering', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
});
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('card: feature rendering'), () => {
test('should not have visual regressions with button cards', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-card button="true">
<ion-card-header>
<ion-card-title>Card Title</ion-card-title>
@@ -40,35 +41,17 @@ test.describe('card: basic', () => {
in the woods. Wash your spirit clean.
</ion-card-content>
</ion-card>
`);
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-button-${page.getSnapshotSettings()}.png`);
});
test('should not have visual regressions with translucent cards', async ({ page, skip }) => {
skip.mode('md', 'Translucent effect is only available in iOS mode.');
await page.setContent(`
<ion-card>
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0">
<img style="transform: rotate(145deg) scale(1.5)" src="/src/components/card/test/img.jpg" />
</div>
<ion-card-header translucent="true">
<ion-card-title> Title </ion-card-title>
<ion-card-subtitle> Subtitle </ion-card-subtitle>
</ion-card-header>
<ion-card-content style="min-height: 20px"></ion-card-content>
</ion-card>
`);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-translucent-${page.getSnapshotSettings()}.png`);
await expect(card).toHaveScreenshot(screenshot(`card-button`));
});
test('should not have visual regressions with disabled card', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-card disabled="true">
<ion-card-header>
<ion-card-title>Card Title</ion-card-title>
@@ -80,13 +63,16 @@ test.describe('card: basic', () => {
in the woods. Wash your spirit clean.
</ion-card-content>
</ion-card>
`);
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-disabled-${page.getSnapshotSettings()}.png`);
await expect(card).toHaveScreenshot(screenshot(`card-disabled`));
});
test('should not have visual regressions with color', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-card color="danger">
<ion-card-header>
<ion-card-title>Card Title</ion-card-title>
@@ -98,13 +84,16 @@ test.describe('card: basic', () => {
in the woods. Wash your spirit clean.
</ion-card-content>
</ion-card>
`);
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-color-${page.getSnapshotSettings()}.png`);
await expect(card).toHaveScreenshot(screenshot(`card-color`));
});
test('headings should have correct size in card', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-card>
<ion-card-content>
<h1>Heading 1</h1>
@@ -116,13 +105,16 @@ test.describe('card: basic', () => {
<p>Paragraph</p>
</ion-card-content>
</ion-card>
`);
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-headings-${page.getSnapshotSettings()}.png`);
await expect(card).toHaveScreenshot(screenshot(`card-headings`));
});
test('should render even without header or content elements', async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-card>
<ion-list lines="none">
<ion-item href="#" class="ion-activated">
@@ -150,10 +142,38 @@ test.describe('card: basic', () => {
</ion-item>
</ion-list>
</ion-card>
`);
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(`card-no-content-or-header-${page.getSnapshotSettings()}.png`);
await expect(card).toHaveScreenshot(screenshot(`card-no-content-or-header`));
});
});
});
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('card: translucent'), () => {
test('should not have visual regressions with translucent cards', async ({ page }) => {
await page.setContent(
`
<ion-card>
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0">
<img style="transform: rotate(145deg) scale(1.5)" src="/src/components/card/test/img.jpg" />
</div>
<ion-card-header translucent="true">
<ion-card-title> Title </ion-card-title>
<ion-card-subtitle> Subtitle </ion-card-subtitle>
</ion-card-header>
<ion-card-content style="min-height: 20px"></ion-card-content>
</ion-card>
`,
config
);
const card = page.locator('ion-card');
await expect(card).toHaveScreenshot(screenshot(`card-translucent`));
});
});
});

View File

@@ -42,8 +42,14 @@
height: 100%;
}
:host(.in-item[slot="start"]:not(.legacy-checkbox)),
:host(.in-item[slot="end"]:not(.legacy-checkbox)) {
/**
* Checkbox can be slotted
* in components such as item and
* toolbar which is why we do not
* limit the below behavior to just ion-item.
*/
:host([slot="start"]:not(.legacy-checkbox)),
:host([slot="end"]:not(.legacy-checkbox)) {
width: auto;
}

View File

@@ -1,17 +1,14 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: a11y', () => {
test.beforeEach(async ({ skip }) => {
skip.rtl();
skip.mode('md');
});
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('checkbox: a11y'), () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/a11y`, config);
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/a11y`);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});
});

View File

@@ -1,100 +1,123 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: basic visual tests', () => {
test('should render unchecked checkbox correctly', async ({ page }) => {
await page.setContent(`
<ion-checkbox>Unchecked</ion-checkbox>
`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: basic visual tests'), () => {
test('should render unchecked checkbox correctly', async ({ page }) => {
await page.setContent(
`
<ion-checkbox>Unchecked</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(`checkbox-unchecked-${page.getSnapshotSettings()}.png`);
});
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-unchecked`));
});
test('should render checked checkbox correctly', async ({ page }) => {
await page.setContent(`
<ion-checkbox checked>Checked</ion-checkbox>
`);
test('should render checked checkbox correctly', async ({ page }) => {
await page.setContent(
`
<ion-checkbox checked>Checked</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(`checkbox-checked-${page.getSnapshotSettings()}.png`);
});
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-checked`));
});
test('should render disabled checkbox correctly', async ({ page }) => {
await page.setContent(`
<ion-checkbox checked disabled>Disabled</ion-checkbox>
`);
test('should render disabled checkbox correctly', async ({ page }) => {
await page.setContent(
`
<ion-checkbox checked disabled>Disabled</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(`checkbox-disabled-${page.getSnapshotSettings()}.png`);
});
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-disabled`));
});
test('should render custom checkmark-width correctly', async ({ page }) => {
await page.setContent(`
<ion-checkbox checked style="--checkmark-width: 7">Checkmark Width</ion-checkbox>
`);
test('should render custom checkmark-width correctly', async ({ page }) => {
await page.setContent(
`
<ion-checkbox checked style="--checkmark-width: 7">Checkmark Width</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(`checkbox-checkmark-width-${page.getSnapshotSettings()}.png`);
});
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-checkmark-width`));
});
test('should render custom size correctly', async ({ page }) => {
await page.setContent(`
<ion-checkbox checked style="--size: 100px">Size</ion-checkbox>
`);
test('should render custom size correctly', async ({ page }) => {
await page.setContent(
`
<ion-checkbox checked style="--size: 100px">Size</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(`checkbox-size-${page.getSnapshotSettings()}.png`);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-size`));
});
});
});
test.describe('checkbox: ionChange', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
skip.mode('ios');
});
test('should fire ionChange when interacting with checkbox', async ({ page }) => {
await page.setContent(`
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
`);
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
await checkbox.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await checkbox.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
test('should fire ionChange when interacting with checkbox in item', async ({ page }) => {
await page.setContent(`
<ion-item>
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('checkbox: ionChange'), () => {
test('should fire ionChange when interacting with checkbox', async ({ page }) => {
await page.setContent(
`
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
</ion-item>
`);
`,
config
);
const ionChange = await page.spyOnEvent('ionChange');
const item = page.locator('ion-item');
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
await item.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await checkbox.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await item.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
await checkbox.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
test('should not fire when programmatically setting a value', async ({ page }) => {
await page.setContent(`
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
`);
test('should fire ionChange when interacting with checkbox in item', async ({ page }) => {
await page.setContent(
`
<ion-item>
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
</ion-item>
`,
config
);
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
const ionChange = await page.spyOnEvent('ionChange');
const item = page.locator('ion-item');
await checkbox.evaluate((el: HTMLIonCheckboxElement) => (el.checked = true));
expect(ionChange).not.toHaveReceivedEvent();
await item.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await item.click();
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
test('should not fire when programmatically setting a value', async ({ page }) => {
await page.setContent(
`
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
`,
config
);
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
await checkbox.evaluate((el: HTMLIonCheckboxElement) => (el.checked = true));
expect(ionChange).not.toHaveReceivedEvent();
});
});
});

View File

@@ -1,26 +1,30 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: color', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: color'), () => {
test('should apply color when checked', async ({ page }) => {
await page.setContent(
`
<ion-checkbox color="danger" checked="true">Label</ion-checkbox>
`,
config
);
test('should apply color when checked', async ({ page }) => {
await page.setContent(`
<ion-checkbox color="danger" checked="true">Label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-color-checked`));
});
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-color-checked-${page.getSnapshotSettings()}.png`);
});
test('should not apply color when unchecked', async ({ page }) => {
await page.setContent(
`
<ion-checkbox color="danger">Label</ion-checkbox>
`,
config
);
test('should not apply color when unchecked', async ({ page }) => {
await page.setContent(`
<ion-checkbox color="danger">Label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-color-unchecked-${page.getSnapshotSettings()}.png`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-color-unchecked`));
});
});
});

View File

@@ -1,13 +1,13 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: indeterminate', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.rtl();
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: indeterminate'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/indeterminate`, config);
await page.goto(`/src/components/checkbox/test/indeterminate`);
const checkbox = page.locator('ion-checkbox:first-child');
await expect(checkbox).toHaveScreenshot(`checkbox-indeterminate-${page.getSnapshotSettings()}.png`);
const checkbox = page.locator('ion-checkbox:first-child');
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-indeterminate`));
});
});
});

View File

@@ -1,37 +1,52 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: item', () => {
test('should render correctly in list', async ({ page }) => {
await page.setContent(`
<ion-list>
<ion-item>
<ion-checkbox>Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
`);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(`checkbox-list-${page.getSnapshotSettings()}.png`);
});
test('should render correctly in inset list', async ({ page }) => {
await page.setContent(`
<ion-list inset="true">
<ion-item>
<ion-checkbox>Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
`);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(`checkbox-inset-list-${page.getSnapshotSettings()}.png`);
});
test('label should have correct contrast when used in an item', async ({ page, skip }) => {
skip.rtl();
await page.setContent(`
<ion-item color="primary">
<ion-checkbox>Enable Notifications</ion-checkbox>
</ion-item>
`);
const item = page.locator('ion-item');
expect(await item.screenshot()).toMatchSnapshot(`checkbox-item-color-${page.getSnapshotSettings()}.png`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: item with list'), () => {
test('should render correctly in list', async ({ page }) => {
await page.setContent(
`
<ion-list>
<ion-item>
<ion-checkbox>Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
`,
config
);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(screenshot(`checkbox-list`));
});
test('should render correctly in inset list', async ({ page }) => {
await page.setContent(
`
<ion-list inset="true">
<ion-item>
<ion-checkbox>Enable Notifications</ion-checkbox>
</ion-item>
</ion-list>
`,
config
);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(screenshot(`checkbox-inset-list`));
});
});
});
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: label in item'), () => {
test('label should have correct contrast when used in an item', async ({ page }) => {
await page.setContent(
`
<ion-item color="primary">
<ion-checkbox>Enable Notifications</ion-checkbox>
</ion-item>
`,
config
);
const item = page.locator('ion-item');
expect(await item.screenshot()).toMatchSnapshot(screenshot(`checkbox-item-color`));
});
});
});

View File

@@ -1,5 +1,5 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
/**
* By default ion-checkbox only takes up
@@ -9,120 +9,134 @@ import { test } from '@utils/test/playwright';
* we set the width of the checkbox so we can
* see the justification results.
*/
test.describe('checkbox: label', () => {
test.describe('checkbox: start placement', () => {
test('should render a start justification with label in the start position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="start" justify="start" style="width: 200px">Label</ion-checkbox>
`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: label'), () => {
test.describe('checkbox: start placement', () => {
test('should render a start justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="start" justify="start" style="width: 200px">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-start-justify-start-${page.getSnapshotSettings()}.png`
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-start-justify-start`));
});
test('should render an end justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="start" justify="end" style="width: 200px">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-start-justify-end`));
});
test('should render a space between justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="start" justify="space-between" style="width: 200px">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-start-justify-space-between`));
});
test('should truncate long labels with ellipses', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="start" justify="start" style="width: 200px">
Long Label Long Label Long Label Long Label Long Label Long Label
</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-long-label`));
});
});
test('should render an end justification with label in the start position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="start" justify="end" style="width: 200px">Label</ion-checkbox>
`);
test.describe('checkbox: end placement', () => {
test('should render a start justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="end" justify="start" style="width: 200px">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-start-justify-end-${page.getSnapshotSettings()}.png`
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-end-justify-start`));
});
test('should render an end justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="end" justify="end" style="width: 200px">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-end-justify-end`));
});
test('should render a space between justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="end" justify="space-between" style="width: 200px">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-end-justify-space-between`));
});
});
test('should render a space between justification with label in the start position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="start" justify="space-between" style="width: 200px">Label</ion-checkbox>
`);
test.describe('checkbox: fixed placement', () => {
test('should render a start justification with label in the fixed position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="fixed" justify="start" style="width: 200px">This is a long label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-start-justify-space-between-${page.getSnapshotSettings()}.png`
);
});
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-fixed-justify-start`));
});
test('should truncate long labels with ellipses', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="start" justify="start" style="width: 200px">
Long Label Long Label Long Label Long Label Long Label Long Label
</ion-checkbox>
`);
test('should render an end justification with label in the fixed position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="fixed" justify="end" style="width: 200px">This is a long label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-long-label-${page.getSnapshotSettings()}.png`);
});
});
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-fixed-justify-end`));
});
test.describe('checkbox: end placement', () => {
test('should render a start justification with label in the end position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="end" justify="start" style="width: 200px">Label</ion-checkbox>
`);
test('should render a space between justification with label in the fixed position', async ({ page }) => {
await page.setContent(
`
<ion-checkbox label-placement="fixed" justify="space-between" style="width: 200px">This is a long label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-end-justify-start-${page.getSnapshotSettings()}.png`
);
});
test('should render an end justification with label in the end position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="end" justify="end" style="width: 200px">Label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-end-justify-end-${page.getSnapshotSettings()}.png`
);
});
test('should render a space between justification with label in the end position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="end" justify="space-between" style="width: 200px">Label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-end-justify-space-between-${page.getSnapshotSettings()}.png`
);
});
});
test.describe('checkbox: fixed placement', () => {
test('should render a start justification with label in the fixed position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="fixed" justify="start" style="width: 200px">This is a long label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-fixed-justify-start-${page.getSnapshotSettings()}.png`
);
});
test('should render an end justification with label in the fixed position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="fixed" justify="end" style="width: 200px">This is a long label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-fixed-justify-end-${page.getSnapshotSettings()}.png`
);
});
test('should render a space between justification with label in the fixed position', async ({ page }) => {
await page.setContent(`
<ion-checkbox label-placement="fixed" justify="space-between" style="width: 200px">This is a long label</ion-checkbox>
`);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(
`checkbox-label-fixed-justify-space-between-${page.getSnapshotSettings()}.png`
);
const checkbox = page.locator('ion-checkbox');
expect(await checkbox.screenshot()).toMatchSnapshot(screenshot(`checkbox-label-fixed-justify-space-between`));
});
});
});
});

View File

@@ -1,61 +1,71 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: basic (legacy)', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/legacy/basic`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: basic (legacy)'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/legacy/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
expect(await page.screenshot()).toMatchSnapshot(`checkbox-legacy-basic-${page.getSnapshotSettings()}.png`);
expect(await page.screenshot()).toMatchSnapshot(screenshot(`checkbox-legacy-basic`));
});
});
});
test.describe('checkbox: ionChange', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should fire ionChange when interacting with checkbox', async ({ page }) => {
await page.setContent(`
<ion-checkbox value="my-checkbox"></ion-checkbox>
`);
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
await checkbox.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await checkbox.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
test('should fire ionChange when interacting with checkbox in item', async ({ page }) => {
await page.setContent(`
<ion-item>
configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('checkbox: ionChange'), () => {
test('should fire ionChange when interacting with checkbox', async ({ page }) => {
await page.setContent(
`
<ion-checkbox value="my-checkbox"></ion-checkbox>
</ion-item>
`);
`,
config
);
const ionChange = await page.spyOnEvent('ionChange');
const item = page.locator('ion-item');
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
await item.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await checkbox.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await item.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
await checkbox.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
test('should not fire when programmatically setting a value', async ({ page }) => {
await page.setContent(`
<ion-checkbox value="my-checkbox"></ion-checkbox>
`);
test('should fire ionChange when interacting with checkbox in item', async ({ page }) => {
await page.setContent(
`
<ion-item>
<ion-checkbox value="my-checkbox"></ion-checkbox>
</ion-item>
`,
config
);
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
const ionChange = await page.spyOnEvent('ionChange');
const item = page.locator('ion-item');
await checkbox.evaluate((el: HTMLIonCheckboxElement) => (el.checked = true));
await expect(ionChange).not.toHaveReceivedEvent();
await item.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
await item.click();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
});
test('should not fire when programmatically setting a value', async ({ page }) => {
await page.setContent(
`
<ion-checkbox value="my-checkbox"></ion-checkbox>
`,
config
);
const ionChange = await page.spyOnEvent('ionChange');
const checkbox = page.locator('ion-checkbox');
await checkbox.evaluate((el: HTMLIonCheckboxElement) => (el.checked = true));
await expect(ionChange).not.toHaveReceivedEvent();
});
});
});

View File

@@ -1,13 +1,13 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('checkbox: indeterminate (legacy)', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/legacy/indeterminate`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: indeterminate (legacy)'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/checkbox/test/legacy/indeterminate`, config);
const content = page.locator('#checkboxes');
expect(await content.screenshot()).toMatchSnapshot(
`checkbox-legacy-indeterminate-${page.getSnapshotSettings()}.png`
);
const content = page.locator('#checkboxes');
expect(await content.screenshot()).toMatchSnapshot(screenshot(`checkbox-legacy-indeterminate`));
});
});
});

View File

@@ -1,36 +1,42 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('chip: rendering', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/chip/test/basic');
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('chip: rendering'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/chip/test/basic', config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`chip-basic-${page.getSnapshotSettings()}.png`);
});
test('should not clip descenders in item', async ({ page, skip }) => {
skip.rtl();
skip.mode('md');
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/18313',
await expect(page).toHaveScreenshot(screenshot(`chip-basic`));
});
});
});
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('chip: descenders'), () => {
test('should not clip descenders in item', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/18313',
});
await page.setContent(
`
<ion-list>
<ion-item>
<ion-chip>
<ion-label>Agreements</ion-label>
</ion-chip>
</ion-item>
</ion-list>
`,
config
);
const chip = page.locator('ion-chip');
await expect(chip).toHaveScreenshot(screenshot(`chip-descender`));
});
await page.setContent(`
<ion-list>
<ion-item>
<ion-chip>
<ion-label>Agreements</ion-label>
</ion-chip>
</ion-item>
</ion-list>
`);
const chip = page.locator('ion-chip');
await expect(chip).toHaveScreenshot(`chip-descender-${page.getSnapshotSettings()}.png`);
});
});

View File

@@ -1,12 +1,14 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('chip: states', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/chip/test/states');
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('chip: states'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto('/src/components/chip/test/states', config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`chip-states-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`chip-states`));
});
});
});

View File

@@ -1,15 +1,17 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('content: basic', () => {
test('should not have visual regressions', async ({ page, skip }) => {
skip.rtl();
skip.mode('ios', 'ion-content does not have mode-specific styling');
/**
* ion-content does not have mode-specific styling
*/
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('content: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/content/test/basic`, config);
await page.goto(`/src/components/content/test/basic`);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`content-diff-${page.getSnapshotSettings()}.png`);
await expect(page).toHaveScreenshot(screenshot(`content-diff`));
});
});
});

Some files were not shown because too many files have changed in this diff Show More