Merge branch 'main' into chore-update-from-main
@ -29,7 +29,7 @@ runs:
|
||||
shell: bash
|
||||
working-directory: ./packages/angular/test
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: npm install --legacy-peer-deps # TODO(FW-6227): Remove legacy-peer-deps flag
|
||||
shell: bash
|
||||
working-directory: ./packages/angular/test/build/${{ inputs.app }}
|
||||
- name: Sync Built Changes
|
||||
|
2
.github/workflows/assign-issues.yml
vendored
@ -13,6 +13,6 @@ jobs:
|
||||
- name: 'Auto-assign issue'
|
||||
uses: pozil/auto-assign-issue@65947009a243e6b3993edeef4e64df3ca85d760c # v1.14.0
|
||||
with:
|
||||
assignees: sean-perkins, brandyscarney, thetaPC
|
||||
assignees: brandyscarney, thetaPC
|
||||
numOfAssignee: 1
|
||||
allowSelfAssign: false
|
||||
|
2
.github/workflows/build.yml
vendored
@ -140,7 +140,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
apps: [ng16, ng17]
|
||||
apps: [ng16, ng17, ng18]
|
||||
needs: [build-angular, build-angular-server]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
6
.github/workflows/conventional-commit.yml
vendored
@ -24,3 +24,9 @@ jobs:
|
||||
# within the message.
|
||||
subjectPatternError: |
|
||||
The subject "{subject}" found in the pull request title "{title}" didn't match the configured pattern. Please ensure that the subject doesn't start with an uppercase character.
|
||||
# If the PR contains one of these newline-delimited labels, the
|
||||
# validation is skipped. If you want to rerun the validation when
|
||||
# labels change, you might want to use the `labeled` and `unlabeled`
|
||||
# event triggers in your workflow.
|
||||
ignoreLabels: |
|
||||
release
|
||||
|
2
.github/workflows/stencil-nightly.yml
vendored
@ -150,7 +150,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
apps: [ng16, ng17]
|
||||
apps: [ng16, ng17, ng18]
|
||||
needs: [build-angular, build-angular-server]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
14
CHANGELOG.md
@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.1.1](https://github.com/ionic-team/ionic-framework/compare/v8.1.0...v8.1.1) (2024-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** add formatOptions property to standalone datetime ([#29468](https://github.com/ionic-team/ionic-framework/issues/29468)) ([bb1db52](https://github.com/ionic-team/ionic-framework/commit/bb1db52567e0884a896f9ccd76c27540b52f5e48)), closes [#29464](https://github.com/ionic-team/ionic-framework/issues/29464)
|
||||
* **angular:** persist select disabled state in item ([#29448](https://github.com/ionic-team/ionic-framework/issues/29448)) ([dfb72d7](https://github.com/ionic-team/ionic-framework/commit/dfb72d7ea06e28d76069b23eb90c3426181b7c4c)), closes [#29234](https://github.com/ionic-team/ionic-framework/issues/29234)
|
||||
* **angular:** set active segment button when dynamically changing items ([#29418](https://github.com/ionic-team/ionic-framework/issues/29418)) ([ee83388](https://github.com/ionic-team/ionic-framework/commit/ee833881da3ecaa0a9153397f0c7e62c1923f19c)), closes [#29414](https://github.com/ionic-team/ionic-framework/issues/29414)
|
||||
* **radio:** persist checked state when items are updated in radio-group ([#29457](https://github.com/ionic-team/ionic-framework/issues/29457)) ([7ea14ae](https://github.com/ionic-team/ionic-framework/commit/7ea14ae41eb27f2a58952bd27d91ef4c77bb6a0c)), closes [#29442](https://github.com/ionic-team/ionic-framework/issues/29442)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.1.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.2...v8.1.0) (2024-05-01)
|
||||
|
||||
|
||||
|
@ -3,6 +3,19 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.1.1](https://github.com/ionic-team/ionic-framework/compare/v8.1.0...v8.1.1) (2024-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** persist select disabled state in item ([#29448](https://github.com/ionic-team/ionic-framework/issues/29448)) ([dfb72d7](https://github.com/ionic-team/ionic-framework/commit/dfb72d7ea06e28d76069b23eb90c3426181b7c4c)), closes [#29234](https://github.com/ionic-team/ionic-framework/issues/29234)
|
||||
* **angular:** set active segment button when dynamically changing items ([#29418](https://github.com/ionic-team/ionic-framework/issues/29418)) ([ee83388](https://github.com/ionic-team/ionic-framework/commit/ee833881da3ecaa0a9153397f0c7e62c1923f19c)), closes [#29414](https://github.com/ionic-team/ionic-framework/issues/29414)
|
||||
* **radio:** persist checked state when items are updated in radio-group ([#29457](https://github.com/ionic-team/ionic-framework/issues/29457)) ([7ea14ae](https://github.com/ionic-team/ionic-framework/commit/7ea14ae41eb27f2a58952bd27d91ef4c77bb6a0c)), closes [#29442](https://github.com/ionic-team/ionic-framework/issues/29442)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.1.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.2...v8.1.0) (2024-05-01)
|
||||
|
||||
|
||||
|
4
core/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.17.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
|
@ -53,4 +53,7 @@ if (requestHeaded && !hasHeadedConfigFiles) {
|
||||
console.warn(chalk.yellow.bold('\n⚠️ You are running tests in headed mode, but one or more of your headed config files was not found.\nPlease ensure that both docker-display.txt and docker-display-volume.txt have been created in the correct location.\n'));
|
||||
}
|
||||
|
||||
execa('docker', args, { shell: true, stdio: 'inherit' });
|
||||
const res = await execa('docker', args, { shell: true, stdio: 'inherit' });
|
||||
|
||||
// If underlying scripts failed this whole process should fail too
|
||||
process.exit(res.exitCode);
|
||||
|
@ -3,10 +3,11 @@ import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
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
|
||||
// TODO(ROU-8157): remove skip once the keyboard navigation is working again
|
||||
test.skip('accordions should be keyboard navigable', async ({ page, skip, browserName }) => {
|
||||
// TODO(ROU-5358): remove skip once issue is resolved
|
||||
skip.browser('firefox', 'https://github.com/ionic-team/ionic-framework/issues/25070');
|
||||
// TODO (FW-2979)
|
||||
// TODO (ROU-5437)
|
||||
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
|
||||
|
||||
await page.goto(`/src/components/accordion/test/a11y`, config);
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Accordion - Basic</title>
|
||||
<title>Accordion - Standalone</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
@ -119,6 +119,7 @@
|
||||
outline: none;
|
||||
text-align: left;
|
||||
padding: 20px 16px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.custom-accordion-content {
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@ -11,7 +11,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ config, screenshot, t
|
||||
test('should update the active item', async ({ page }) => {
|
||||
const breadcrumbItems = page.locator('ion-breadcrumb');
|
||||
|
||||
const addItemButton = page.locator('ion-button#add-btn');
|
||||
const addItemButton = page.locator('#add-btn');
|
||||
|
||||
await expect(breadcrumbItems).toHaveCount(4);
|
||||
|
||||
|
@ -7,7 +7,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
await page.goto('/src/components/datetime/test/position', config);
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
|
||||
const openDateTimeBtn = page.locator('ion-button#open-datetime');
|
||||
const openDateTimeBtn = page.locator('#open-datetime');
|
||||
await openDateTimeBtn.click();
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 48 KiB |
@ -74,7 +74,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
|
||||
|
||||
await ionLoadingDidPresent.next();
|
||||
|
||||
const button = page.locator('ion-loading ion-button');
|
||||
const button = page.locator('ion-loading button');
|
||||
|
||||
if (browserName === 'webkit') {
|
||||
await page.keyboard.down('Alt');
|
||||
|
@ -29,7 +29,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
test('should trap focus', async ({ page, skip, browserName }) => {
|
||||
skip.browser('firefox', 'Firefox incorrectly allows keyboard focus to move to ion-content');
|
||||
// TODO (FW-2979)
|
||||
// TODO (ROU-5437)
|
||||
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
|
||||
const ionDidOpen = await page.spyOnEvent('ionDidOpen');
|
||||
|
||||
|
@ -24,7 +24,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
|
||||
await modal.evaluate((modal: HTMLIonModalElement) => {
|
||||
modal.remove();
|
||||
document.querySelector('ion-button')?.insertAdjacentElement('afterend', modal);
|
||||
document.querySelector('button')?.insertAdjacentElement('afterend', modal);
|
||||
});
|
||||
await page.waitForChanges();
|
||||
|
||||
|
@ -18,7 +18,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
test.describe('pushing a new page', () => {
|
||||
test('should render the pushed component', async ({ page }) => {
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page Two")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page Two")');
|
||||
const pageOne = page.locator('page-one');
|
||||
const pageTwo = page.locator('page-two');
|
||||
|
||||
@ -32,7 +32,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
});
|
||||
|
||||
test('should render the back button', async ({ page }) => {
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page Two")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page Two")');
|
||||
const pageTwoBackButton = page.locator('page-two ion-back-button');
|
||||
|
||||
await pageTwoButton.click();
|
||||
@ -45,7 +45,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test('back button should pop to the previous page', async ({ page }) => {
|
||||
const pageOne = page.locator('page-one');
|
||||
const pageTwo = page.locator('page-two');
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page Two")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page Two")');
|
||||
const pageTwoBackButton = page.locator('page-two ion-back-button');
|
||||
|
||||
await pageTwoButton.click();
|
||||
@ -65,8 +65,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
const pageTwo = page.locator('page-two');
|
||||
const pageThree = page.locator('page-three');
|
||||
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page Two")');
|
||||
const pageThreeButton = page.locator('ion-button:has-text("Go to Page Three")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page Two")');
|
||||
const pageThreeButton = page.locator('button:has-text("Go to Page Three")');
|
||||
|
||||
await pageTwoButton.click();
|
||||
await page.waitForChanges();
|
||||
|
@ -16,8 +16,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
const pageOne = page.locator('page-one');
|
||||
const pageTwo = page.locator('page-two');
|
||||
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page 2")');
|
||||
const pageTwoTwoButton = page.locator('ion-button:has-text("Go to Page 2.2")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page 2")');
|
||||
const pageTwoTwoButton = page.locator('button:has-text("Go to Page 2.2")');
|
||||
|
||||
await pageTwoButton.click();
|
||||
await page.waitForChanges();
|
||||
@ -35,7 +35,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
await expect(pageTwoOne).toHaveCount(1);
|
||||
await expect(pageTwoTwo).toBeVisible();
|
||||
|
||||
const pageThreeButton = page.locator('ion-button:has-text("Go to Page 3")');
|
||||
const pageThreeButton = page.locator('button:has-text("Go to Page 3")');
|
||||
|
||||
await pageThreeButton.click();
|
||||
await page.waitForChanges();
|
||||
@ -49,8 +49,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
test.describe('back button', () => {
|
||||
test('should work with nested ion-nav', async ({ page }) => {
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page 2")');
|
||||
const pageTwoTwoButton = page.locator('ion-button:has-text("Go to Page 2.2")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page 2")');
|
||||
const pageTwoTwoButton = page.locator('button:has-text("Go to Page 2.2")');
|
||||
|
||||
await pageTwoButton.click();
|
||||
await page.waitForChanges();
|
||||
@ -61,7 +61,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
await pageTwoTwoButton.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
const pageThreeButton = page.locator('ion-button:has-text("Go to Page 3")');
|
||||
const pageThreeButton = page.locator('button:has-text("Go to Page 3")');
|
||||
const pageThreeBackButton = page.locator('page-three ion-back-button');
|
||||
|
||||
await pageThreeButton.click();
|
||||
|
@ -24,8 +24,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
const pageOne = page.locator('page-one');
|
||||
const pageTwo = page.locator('page-two');
|
||||
|
||||
const pageOneButton = page.locator('ion-button:has-text("Go to Page One")');
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page Two")');
|
||||
const pageOneButton = page.locator('button:has-text("Go to Page One")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page Two")');
|
||||
|
||||
await pageOneButton.click();
|
||||
await page.waitForChanges();
|
||||
@ -45,7 +45,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
});
|
||||
|
||||
test('should render the back button', async ({ page }) => {
|
||||
const pageOneButton = page.locator('ion-button:has-text("Go to Page One")');
|
||||
const pageOneButton = page.locator('button:has-text("Go to Page One")');
|
||||
const pageOneBackButton = page.locator('page-one ion-back-button');
|
||||
|
||||
await pageOneButton.click();
|
||||
@ -59,7 +59,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
const pageRoot = page.locator('page-root');
|
||||
const pageOne = page.locator('page-one');
|
||||
|
||||
const pageOneButton = page.locator('ion-button:has-text("Go to Page One")');
|
||||
const pageOneButton = page.locator('button:has-text("Go to Page One")');
|
||||
const pageOneBackButton = page.locator('page-one ion-back-button');
|
||||
|
||||
await pageOneButton.click();
|
||||
@ -80,9 +80,9 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
const pageTwo = page.locator('page-two');
|
||||
const pageThree = page.locator('page-three');
|
||||
|
||||
const pageOneButton = page.locator('ion-button:has-text("Go to Page One")');
|
||||
const pageTwoButton = page.locator('ion-button:has-text("Go to Page Two")');
|
||||
const pageThreeButton = page.locator('ion-button:has-text("Go to Page Three")');
|
||||
const pageOneButton = page.locator('button:has-text("Go to Page One")');
|
||||
const pageTwoButton = page.locator('button:has-text("Go to Page Two")');
|
||||
const pageThreeButton = page.locator('button:has-text("Go to Page Three")');
|
||||
|
||||
await pageOneButton.click();
|
||||
await page.waitForChanges();
|
||||
|
@ -105,7 +105,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
);
|
||||
});
|
||||
|
||||
test('tabbing should correctly move focus between columns', async ({ page }) => {
|
||||
// TODO(FW-6232): remove this skip when tabbing is working properly
|
||||
test.skip('tabbing should correctly move focus between columns', async ({ page }) => {
|
||||
const firstColumn = page.locator('ion-picker-column#first');
|
||||
const secondColumn = page.locator('ion-picker-column#second');
|
||||
|
||||
@ -120,7 +121,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
await expect(secondColumn).toBeFocused();
|
||||
});
|
||||
|
||||
test('tabbing should correctly move focus back', async ({ page }) => {
|
||||
// TODO(FW-6232): remove this skip when tabbing is working properly
|
||||
test.skip('tabbing should correctly move focus back', async ({ page }) => {
|
||||
const firstColumn = page.locator('ion-picker-column#first');
|
||||
const secondColumn = page.locator('ion-picker-column#second');
|
||||
|
||||
|
@ -7,7 +7,8 @@ import type { E2ELocator } from '@utils/test/playwright/page/utils/locator';
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('picker: keyboard entry'), () => {
|
||||
test('should scroll to and update the value prop for a single column', async ({ page }) => {
|
||||
// TODO(FW-6232): remove this skip when keyboard entry is working properly
|
||||
test.skip('should scroll to and update the value prop for a single column', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker>
|
||||
@ -122,7 +123,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
await expect(secondColumn).toHaveJSProperty('value', 24);
|
||||
});
|
||||
|
||||
test('should select 00', async ({ page }) => {
|
||||
// TODO(FW-6232): remove this skip when keyboard entry is working properly
|
||||
test.skip('should select 00', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker>
|
||||
|
@ -40,7 +40,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
|
||||
await popover.evaluate((popover: HTMLIonPopoverElement) => {
|
||||
popover.remove();
|
||||
document.querySelector('ion-button')?.insertAdjacentElement('afterend', popover);
|
||||
document.querySelector('button')?.insertAdjacentElement('afterend', popover);
|
||||
});
|
||||
await page.waitForChanges();
|
||||
|
||||
|
@ -112,6 +112,18 @@ export class Radio implements ComponentInterface {
|
||||
*/
|
||||
@Event() ionBlur!: EventEmitter<void>;
|
||||
|
||||
componentDidLoad() {
|
||||
/**
|
||||
* The value may be `undefined` if it
|
||||
* gets set before the radio is
|
||||
* rendered. This ensures that the radio
|
||||
* is checked if the value matches. This
|
||||
* happens most often when Angular is
|
||||
* rendering the radio.
|
||||
*/
|
||||
this.updateState();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@Method()
|
||||
async setFocus(ev: globalThis.Event) {
|
||||
|
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 58 KiB |
@ -20,7 +20,7 @@ const checkedOptions: SelectPopoverOption[] = [
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('select-popover: basic'), () => {
|
||||
test.beforeEach(({ browserName }) => {
|
||||
test.skip(browserName === 'webkit', 'https://ionic-cloud.atlassian.net/browse/FW-2979');
|
||||
test.skip(browserName === 'webkit', 'ROU-5437');
|
||||
});
|
||||
|
||||
test.describe('single selection', () => {
|
||||
@ -55,7 +55,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
});
|
||||
|
||||
test('pressing Space on a selected option should dismiss the popover', async ({ browserName }) => {
|
||||
test.skip(browserName === 'firefox', 'Same behavior as https://ionic-cloud.atlassian.net/browse/FW-2979');
|
||||
test.skip(browserName === 'firefox', 'Same behavior as ROU-5437');
|
||||
|
||||
await selectPopoverPage.setup(config, checkedOptions, false);
|
||||
|
||||
|
@ -244,10 +244,6 @@ export class Select implements ComponentInterface {
|
||||
this.ionChange.emit({ value });
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
const { el } = this;
|
||||
|
||||
@ -273,6 +269,24 @@ export class Select implements ComponentInterface {
|
||||
});
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
/**
|
||||
* If any of the conditions that trigger the styleChanged callback
|
||||
* are met on component load, it is possible the event emitted
|
||||
* prior to a parent web component registering an event listener.
|
||||
*
|
||||
* To ensure the parent web component receives the event, we
|
||||
* emit the style event again after the component has loaded.
|
||||
*
|
||||
* This is often seen in Angular with the `dist` output target.
|
||||
*/
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
if (this.mutationO) {
|
||||
this.mutationO.disconnect();
|
||||
|
@ -40,7 +40,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
|
||||
test.describe('select: popover', () => {
|
||||
test('it should open a popover select', async ({ page, skip }) => {
|
||||
// TODO (FW-2979)
|
||||
// TODO (ROU-5437)
|
||||
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
|
@ -4,7 +4,7 @@ import { configs, test } from '@utils/test/playwright';
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('select: disabled options'), () => {
|
||||
test('should not focus a disabled option when no value is set', async ({ page, skip }) => {
|
||||
// TODO (FW-2979)
|
||||
// TODO (ROU-5437)
|
||||
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
|
||||
|
||||
test.info().annotations.push({
|
||||
|
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 46 KiB |
@ -71,16 +71,16 @@ $alert-ios-radio-label-text-color-checked: $alert-ios-button-text-color !default
|
||||
|
||||
The abundance of Sass variables currently in Ionic Framework is a result of their historical usage, being used to rebuild the CSS and customize Ionic Framework components.
|
||||
|
||||
The comments for Sass variables are also still visible today in [v7.7.0](https://github.com/ionic-team/ionic-framework/blob/v7.7.0/core/src/components/alert/alert.ios.vars.scss), even though they are no longer used by any documentation generators:
|
||||
The comments for Sass variables are also still visible today in [v8.1.0](https://github.com/ionic-team/ionic-framework/blob/v8.1.0/core/src/components/alert/alert.ios.vars.scss), even though they are no longer used by any documentation generators:
|
||||
|
||||
```scss
|
||||
// alert.ios.vars.scss
|
||||
|
||||
/// @prop - Max width of the alert
|
||||
$alert-ios-max-width: dynamic-font-clamp(1, 270px, 1.2) !default;
|
||||
$alert-ios-max-width: dynamic-font-clamp(1, 270px, 1.2);
|
||||
|
||||
/// @prop - Border radius of the alert
|
||||
$alert-ios-border-radius: 13px !default;
|
||||
$alert-ios-border-radius: 13px;
|
||||
```
|
||||
|
||||
These comments aren't necessary when the naming describes its use thoroughly. The comments for the variables above do not need to be there, as it is fairly obvious what they are used for.
|
||||
@ -91,7 +91,7 @@ However, the comment for the following variable might be helpful in explaining w
|
||||
// action-sheet.ios.vars.scss
|
||||
|
||||
/// @prop - Font weight of the action sheet title when it has a sub title
|
||||
$action-sheet-ios-title-with-sub-title-font-weight: 600 !default;
|
||||
$action-sheet-ios-title-with-sub-title-font-weight: 600;
|
||||
```
|
||||
|
||||
It could be argued though that the comment doesn't really help, as seeing the variable in use will explain its purpose the best. Additionally, this is an example of a variable that isn't necessary, given it is only used in one place, which is why it is so specific in the first place.
|
||||
@ -105,22 +105,20 @@ There are two things that need to be outlined here: when we should use comments
|
||||
We should update the comments for Sass variables in one of the following ways:
|
||||
|
||||
1. If we don't intend to ever publicly document the Sass variables again, we should update the comments to remove the syntax that was added for documentation generation:
|
||||
|
||||
```diff
|
||||
// alert.ios.vars.scss
|
||||
|
||||
-/// @prop - Border radius of the alert
|
||||
+// Border radius of the alert
|
||||
$alert-ios-border-radius: 13px !default;
|
||||
$alert-ios-border-radius: 13px;
|
||||
```
|
||||
|
||||
2. If we don't find the comments to be helpful, and want to stick with keeping the variable names specific, we should remove the comments entirely:
|
||||
|
||||
```diff
|
||||
// alert.ios.vars.scss
|
||||
|
||||
-/// @prop - Border radius of the alert
|
||||
$alert-ios-border-radius: 13px !default;
|
||||
$alert-ios-border-radius: 13px;
|
||||
```
|
||||
|
||||
3. If we find the comments to be helpful for certain variables or situations, like when there are math calculations involved, we should keep only the comments that are necessary to explain what is going on:
|
||||
@ -135,7 +133,7 @@ We should update the comments for Sass variables in one of the following ways:
|
||||
* a hairline (<1px) width, this will cause subpixel rendering
|
||||
* differences across browsers.
|
||||
*/
|
||||
$alert-ios-button-height: dynamic-font-min(1, 44px) !default;
|
||||
$alert-ios-button-height: dynamic-font-min(1, 44px);
|
||||
```
|
||||
|
||||
### Variables
|
||||
@ -163,11 +161,11 @@ Example of global variables:
|
||||
```scss
|
||||
// ionic.globals.scss
|
||||
|
||||
$font-family-base: var(--ion-font-family, inherit) !default;
|
||||
$font-family-base: var(--ion-font-family, inherit);
|
||||
|
||||
$hairlines-width: 0.55px !default;
|
||||
$hairlines-width: 0.55px;
|
||||
|
||||
$placeholder-opacity: 0.6 !default;
|
||||
$placeholder-opacity: 0.6;
|
||||
```
|
||||
|
||||
#### ✅ Theming
|
||||
@ -179,32 +177,32 @@ Example of theme variables:
|
||||
```scss
|
||||
// ionic.theme.default.scss
|
||||
|
||||
$background-color-value: #fff !default;
|
||||
$background-color-rgb-value: 255, 255, 255 !default;
|
||||
$background-color-value: #fff;
|
||||
$background-color-rgb-value: 255, 255, 255;
|
||||
|
||||
$text-color-value: #000 !default;
|
||||
$text-color-rgb-value: 0, 0, 0 !default;
|
||||
$text-color-value: #000;
|
||||
$text-color-rgb-value: 0, 0, 0;
|
||||
|
||||
$background-color: var(
|
||||
--ion-background-color,
|
||||
$background-color-value
|
||||
) !default;
|
||||
);
|
||||
$background-color-rgb: var(
|
||||
--ion-background-color-rgb,
|
||||
$background-color-rgb-value
|
||||
) !default;
|
||||
$text-color: var(--ion-text-color, $text-color-value) !default;
|
||||
$text-color-rgb: var(--ion-text-color-rgb, $text-color-rgb-value) !default;
|
||||
);
|
||||
$text-color: var(--ion-text-color, $text-color-value);
|
||||
$text-color-rgb: var(--ion-text-color-rgb, $text-color-rgb-value);
|
||||
```
|
||||
|
||||
```scss
|
||||
// ionic.theme.default.ios.scss
|
||||
|
||||
$backdrop-ios-color: var(--ion-backdrop-color, #000) !default;
|
||||
$backdrop-ios-color: var(--ion-backdrop-color, #000);
|
||||
$overlay-ios-background-color: var(
|
||||
--ion-overlay-background-color,
|
||||
var(--ion-color-step-100, #f9f9f9)
|
||||
) !default;
|
||||
);
|
||||
```
|
||||
|
||||
#### ✅ Reusable values
|
||||
@ -227,10 +225,10 @@ Example of reusable values:
|
||||
// alert.ios.vars.scss
|
||||
|
||||
/// @prop - Padding end of the alert head
|
||||
$alert-ios-head-padding-end: 16px !default;
|
||||
$alert-ios-head-padding-end: 16px;
|
||||
|
||||
/// @prop - Padding start of the alert head
|
||||
$alert-ios-head-padding-start: $alert-ios-head-padding-end !default;
|
||||
$alert-ios-head-padding-start: $alert-ios-head-padding-end;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -259,10 +257,10 @@ $alert-ios-head-padding-start: $alert-ios-head-padding-end !default;
|
||||
// alert.ios.vars.scss
|
||||
|
||||
/// @prop - Padding top of the alert head
|
||||
$alert-ios-head-padding-top: 12px !default;
|
||||
$alert-ios-head-padding-top: 12px;
|
||||
|
||||
/// @prop - Padding bottom of the alert head
|
||||
$alert-ios-head-padding-bottom: 7px !default;
|
||||
$alert-ios-head-padding-bottom: 7px;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -303,10 +301,10 @@ $global-md-item-padding-start: $global-md-item-padding-end;
|
||||
@import "../../themes/native/native.globals.md";
|
||||
|
||||
/// @prop - Padding end for the item content
|
||||
$item-md-padding-end: $global-md-item-padding-end !default;
|
||||
$item-md-padding-end: $global-md-item-padding-end;
|
||||
|
||||
/// @prop - Padding start for the item content
|
||||
$item-md-padding-start: $global-md-item-padding-start !default;
|
||||
$item-md-padding-start: $global-md-item-padding-start;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -315,10 +313,10 @@ $item-md-padding-start: $global-md-item-padding-start !default;
|
||||
@import "../../themes/native/native.globals.md";
|
||||
|
||||
/// @prop - Padding start for the divider
|
||||
$item-divider-md-padding-start: $global-md-item-padding-start !default;
|
||||
$item-divider-md-padding-start: $global-md-item-padding-start;
|
||||
|
||||
/// @prop - Padding end for the divider
|
||||
$item-divider-md-padding-end: $global-md-item-padding-end !default;
|
||||
$item-divider-md-padding-end: $global-md-item-padding-end;
|
||||
```
|
||||
|
||||
</td>
|
||||
@ -338,10 +336,10 @@ $item-divider-md-padding-end: $global-md-item-padding-end !default;
|
||||
@import "../../themes/native/native.globals.md";
|
||||
|
||||
/// @prop - Padding end for the item content
|
||||
$item-md-padding-end: 16px !default;
|
||||
$item-md-padding-end: 16px;
|
||||
|
||||
/// @prop - Padding start for the item content
|
||||
$item-md-padding-start: 16px !default;
|
||||
$item-md-padding-start: 16px;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -351,10 +349,10 @@ $item-md-padding-start: 16px !default;
|
||||
@import "../item/item.md.vars";
|
||||
|
||||
/// @prop - Padding start for the divider
|
||||
$item-divider-md-padding-start: $item-md-padding-start !default;
|
||||
$item-divider-md-padding-start: $item-md-padding-start;
|
||||
|
||||
/// @prop - Padding end for the divider
|
||||
$item-divider-md-padding-end: $item-md-padding-end !default;
|
||||
$item-divider-md-padding-end: $item-md-padding-end;
|
||||
```
|
||||
|
||||
</td>
|
||||
@ -380,8 +378,8 @@ $screen-breakpoints: (
|
||||
sm: 576px,
|
||||
md: 768px,
|
||||
lg: 992px,
|
||||
xl: 1200px,
|
||||
) !default;
|
||||
xl: 1200px
|
||||
);
|
||||
```
|
||||
|
||||
#### ✅ Dynamic calculations
|
||||
@ -429,7 +427,7 @@ $chip-avatar-size: math.div(24em, $chip-base-font-size);
|
||||
// alert.vars.scss
|
||||
|
||||
/// @prop - Font size of the alert button
|
||||
$alert-button-font-size: dynamic-font(14px) !default;
|
||||
$alert-button-font-size: dynamic-font(14px);
|
||||
```
|
||||
|
||||
</td>
|
||||
@ -456,7 +454,7 @@ For example, the color of the label changes when focused in `md` mode. However,
|
||||
// label.md.vars.scss
|
||||
|
||||
/// @prop - Text color of the stacked/floating label when it is focused
|
||||
$label-md-text-color-focused: ion-color(primary, base) !default;
|
||||
$label-md-text-color-focused: ion-color(primary, base);
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -485,7 +483,7 @@ $label-md-text-color-focused: ion-color(primary, base) !default;
|
||||
// label.ios.vars.scss
|
||||
|
||||
/// @prop - Text color of the stacked/floating label when it is focused
|
||||
$label-ios-text-color-focused: null !default;
|
||||
$label-ios-text-color-focused: null;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -537,7 +535,7 @@ A text alignment property should not be stored in a Sass variable, even if it is
|
||||
// action-sheet.ios.vars.scss
|
||||
|
||||
/// @prop - Text align of the action sheet
|
||||
$action-sheet-ios-text-align: center !default;
|
||||
$action-sheet-ios-text-align: center;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -597,10 +595,10 @@ Variables should not be used when they are structural changes of an element. Thi
|
||||
// alert.ios.vars.scss
|
||||
|
||||
/// @prop - Flex wrap of the alert button group
|
||||
$alert-ios-button-group-flex-wrap: wrap !default;
|
||||
$alert-ios-button-group-flex-wrap: wrap;
|
||||
|
||||
/// @prop - Flex of the alert button
|
||||
$alert-ios-button-flex: 1 1 auto !default;
|
||||
$alert-ios-button-flex: 1 1 auto;
|
||||
```
|
||||
|
||||
```scss
|
||||
@ -662,13 +660,13 @@ We shouldn't use variables for changing things such as `font-size` or `font-weig
|
||||
// action-sheet.ios.vars.scss
|
||||
|
||||
/// @prop - Font size of the action sheet title
|
||||
$action-sheet-ios-title-font-size: dynamic-font-min(1, 13px) !default;
|
||||
$action-sheet-ios-title-font-size: dynamic-font-min(1, 13px);
|
||||
|
||||
/// @prop - Font weight of the action sheet title
|
||||
$action-sheet-ios-title-font-weight: 400 !default;
|
||||
$action-sheet-ios-title-font-weight: 400;
|
||||
|
||||
/// @prop - Font size of the action sheet sub title
|
||||
$action-sheet-ios-sub-title-font-size: dynamic-font-min(1, 13px) !default;
|
||||
$action-sheet-ios-sub-title-font-size: dynamic-font-min(1, 13px);
|
||||
```
|
||||
|
||||
```scss
|
||||
|
@ -3,5 +3,5 @@
|
||||
"core",
|
||||
"packages/*"
|
||||
],
|
||||
"version": "8.1.0"
|
||||
"version": "8.1.1"
|
||||
}
|
||||
|
@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.1.1](https://github.com/ionic-team/ionic-framework/compare/v8.1.0...v8.1.1) (2024-05-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.1.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.2...v8.1.0) (2024-05-01)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
18
packages/angular-server/package-lock.json
generated
@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.1.0"
|
||||
"@ionic/core": "^8.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-eslint/eslint-plugin": "^16.0.0",
|
||||
@ -1119,9 +1119,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-CTa0JZA7T0Je7HiAinj/kjpxChQYDvitFBqMtNv88nOJn1KerbUKmV2JfQ0quNFneN8z/bBdNOaKc8T++cyDyg==",
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.1.tgz",
|
||||
"integrity": "sha512-ooB8gZtBuLeoHlE1wUvrXI0nyt26f46rPuyNh2Q062QniR4Ur5kqBXqWjUtdVUZqZvaElCbZJk3up+MQavoIMA==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.17.2",
|
||||
"ionicons": "^7.2.2",
|
||||
@ -7011,9 +7011,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-CTa0JZA7T0Je7HiAinj/kjpxChQYDvitFBqMtNv88nOJn1KerbUKmV2JfQ0quNFneN8z/bBdNOaKc8T++cyDyg==",
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.1.tgz",
|
||||
"integrity": "sha512-ooB8gZtBuLeoHlE1wUvrXI0nyt26f46rPuyNh2Q062QniR4Ur5kqBXqWjUtdVUZqZvaElCbZJk3up+MQavoIMA==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.17.2",
|
||||
"ionicons": "^7.2.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"description": "Angular SSR Module for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@ -62,6 +62,6 @@
|
||||
},
|
||||
"prettier": "@ionic/prettier-config",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.1.0"
|
||||
"@ionic/core": "^8.1.1"
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.1.1](https://github.com/ionic-team/ionic-framework/compare/v8.1.0...v8.1.1) (2024-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** add formatOptions property to standalone datetime ([#29468](https://github.com/ionic-team/ionic-framework/issues/29468)) ([bb1db52](https://github.com/ionic-team/ionic-framework/commit/bb1db52567e0884a896f9ccd76c27540b52f5e48)), closes [#29464](https://github.com/ionic-team/ionic-framework/issues/29464)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.1.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.2...v8.1.0) (2024-05-01)
|
||||
|
||||
|
||||
|
18
packages/angular/package-lock.json
generated
@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.1.0",
|
||||
"@ionic/core": "^8.1.1",
|
||||
"ionicons": "^7.0.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.3.0"
|
||||
@ -1398,9 +1398,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-CTa0JZA7T0Je7HiAinj/kjpxChQYDvitFBqMtNv88nOJn1KerbUKmV2JfQ0quNFneN8z/bBdNOaKc8T++cyDyg==",
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.1.tgz",
|
||||
"integrity": "sha512-ooB8gZtBuLeoHlE1wUvrXI0nyt26f46rPuyNh2Q062QniR4Ur5kqBXqWjUtdVUZqZvaElCbZJk3up+MQavoIMA==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.17.2",
|
||||
"ionicons": "^7.2.2",
|
||||
@ -9820,9 +9820,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-CTa0JZA7T0Je7HiAinj/kjpxChQYDvitFBqMtNv88nOJn1KerbUKmV2JfQ0quNFneN8z/bBdNOaKc8T++cyDyg==",
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.1.1.tgz",
|
||||
"integrity": "sha512-ooB8gZtBuLeoHlE1wUvrXI0nyt26f46rPuyNh2Q062QniR4Ur5kqBXqWjUtdVUZqZvaElCbZJk3up+MQavoIMA==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.17.2",
|
||||
"ionicons": "^7.2.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "8.1.0",
|
||||
"version": "8.1.1",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@ -47,7 +47,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.1.0",
|
||||
"@ionic/core": "^8.1.1",
|
||||
"ionicons": "^7.0.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.3.0"
|
||||
|
@ -24,6 +24,7 @@ const DATETIME_INPUTS = [
|
||||
'disabled',
|
||||
'doneText',
|
||||
'firstDayOfWeek',
|
||||
'formatOptions',
|
||||
'highlightedDates',
|
||||
'hourCycle',
|
||||
'hourValues',
|
||||
|
156
packages/angular/test/apps/ng18/angular.json
Normal file
@ -0,0 +1,156 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"test-app": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/test-app/browser",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"buildOptimizer": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "src/assets",
|
||||
"output": "assets"
|
||||
},
|
||||
{
|
||||
"glob": "**/*.svg",
|
||||
"input": "node_modules/ionicons/dist/ionicons/svg",
|
||||
"output": "./svg"
|
||||
}
|
||||
],
|
||||
"styles": ["src/styles.css"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"progress": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"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",
|
||||
"options": {
|
||||
"buildTarget": "test-app:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "test-app:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "test-app:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "test-app:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
"builder": "@angular-devkit/build-angular:server",
|
||||
"options": {
|
||||
"outputPath": "dist/test-app/server",
|
||||
"main": "server.ts",
|
||||
"tsConfig": "tsconfig.server.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"outputHashing": "media",
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"sourceMap": false,
|
||||
"optimization": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-ssr": {
|
||||
"builder": "@angular-devkit/build-angular:ssr-dev-server",
|
||||
"options": {
|
||||
"browserTarget": "test-app:build",
|
||||
"serverTarget": "test-app:server"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "test-app:build:production",
|
||||
"serverTarget": "test-app:server:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"prerender": {
|
||||
"builder": "@angular-devkit/build-angular:prerender",
|
||||
"options": {
|
||||
"browserTarget": "test-app:build:production",
|
||||
"serverTarget": "test-app:server:production",
|
||||
"routes": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"schematicCollections": ["@angular-eslint/schematics"],
|
||||
"cache": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}
|
0
packages/angular/test/apps/ng18/e2e/src/.gitkeep
Normal file
@ -0,0 +1,5 @@
|
||||
it("should be on Angular 18", () => {
|
||||
cy.visit('/lazy');
|
||||
|
||||
cy.get('ion-title').contains('Angular 18');
|
||||
});
|
@ -0,0 +1,8 @@
|
||||
it("binding route data to inputs should work", () => {
|
||||
cy.visit('/lazy/version-test/bind-route/test?query=test');
|
||||
|
||||
cy.get('#route-params').contains('test');
|
||||
cy.get('#query-params').contains('test');
|
||||
cy.get('#data').contains('data:bindToComponentInputs');
|
||||
cy.get('#resolve').contains('resolve:bindToComponentInputs');
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
describe('Modal Nav Params', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('/lazy/version-test/modal-nav-params');
|
||||
});
|
||||
|
||||
it('should assign the rootParams when presented in a modal multiple times', () => {
|
||||
cy.contains('Open Modal').click();
|
||||
cy.get('ion-modal').should('exist').should('be.visible');
|
||||
cy.get('ion-modal').contains('OK');
|
||||
|
||||
cy.contains("Close").click();
|
||||
cy.get('ion-modal').should('not.be.visible');
|
||||
|
||||
cy.contains('Open Modal').click();
|
||||
cy.get('ion-modal').should('exist').should('be.visible');
|
||||
cy.get('ion-modal').contains('OK').should('exist');
|
||||
});
|
||||
|
||||
});
|
15983
packages/angular/test/apps/ng18/package-lock.json
generated
Normal file
69
packages/angular/test/apps/ng18/package.json
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"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": "^18.0.0-rc.0",
|
||||
"@angular/common": "^18.0.0-rc.0",
|
||||
"@angular/compiler": "^18.0.0-rc.0",
|
||||
"@angular/core": "^18.0.0-rc.0",
|
||||
"@angular/forms": "^18.0.0-rc.0",
|
||||
"@angular/platform-browser": "^18.0.0-rc.0",
|
||||
"@angular/platform-browser-dynamic": "^18.0.0-rc.0",
|
||||
"@angular/platform-server": "^18.0.0-rc.0",
|
||||
"@angular/router": "^18.0.0-rc.0",
|
||||
"@angular/ssr": "^18.0.0-rc.0",
|
||||
"@ionic/angular": "^8.0.0",
|
||||
"@ionic/angular-server": "^8.0.0",
|
||||
"core-js": "^3.33.2",
|
||||
"express": "^4.15.2",
|
||||
"ionicons": "^7.2.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript-eslint-language-service": "^4.1.5",
|
||||
"zone.js": "~0.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^18.0.0-rc.0",
|
||||
"@angular-eslint/builder": "^17.0.0",
|
||||
"@angular-eslint/eslint-plugin": "^17.0.0",
|
||||
"@angular-eslint/eslint-plugin-template": "^17.0.0",
|
||||
"@angular-eslint/schematics": "^17.0.0",
|
||||
"@angular-eslint/template-parser": "^17.0.0",
|
||||
"@angular/cli": "^17.0.0",
|
||||
"@angular/compiler-cli": "^18.0.0-rc.0",
|
||||
"@angular/language-service": "^18.0.0-rc.0",
|
||||
"@types/express": "^4.17.7",
|
||||
"@types/ws": "8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"concurrently": "^6.0.0",
|
||||
"cypress": "^13.2.0",
|
||||
"eslint": "^7.26.0",
|
||||
"ts-loader": "^6.2.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"typescript": "^5.4.0",
|
||||
"wait-on": "^5.2.1",
|
||||
"webpack": "^5.61.0",
|
||||
"webpack-cli": "^4.9.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
}
|
71
packages/angular/test/apps/ng18/server.ts
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
import 'zone.js/node';
|
||||
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { CommonEngine } from '@angular/ssr';
|
||||
import * as express from 'express';
|
||||
import { existsSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import bootstrap from './src/main.server';
|
||||
|
||||
// The Express app is exported so that it can be used by serverless Functions.
|
||||
export function app(): express.Express {
|
||||
const server = express();
|
||||
const distFolder = join(process.cwd(), 'dist/test-app/browser');
|
||||
const indexHtml = existsSync(join(distFolder, 'index.original.html'))
|
||||
? join(distFolder, 'index.original.html')
|
||||
: join(distFolder, 'index.html');
|
||||
|
||||
const commonEngine = new CommonEngine();
|
||||
|
||||
server.set('view engine', 'html');
|
||||
server.set('views', distFolder);
|
||||
|
||||
// Example Express Rest API endpoints
|
||||
// server.get('/api/**', (req, res) => { });
|
||||
// Serve static files from /browser
|
||||
server.get('*.*', express.static(distFolder, {
|
||||
maxAge: '1y'
|
||||
}));
|
||||
|
||||
// All regular routes use the Angular engine
|
||||
server.get('*', (req, res, next) => {
|
||||
const { protocol, originalUrl, baseUrl, headers } = req;
|
||||
|
||||
commonEngine
|
||||
.render({
|
||||
bootstrap,
|
||||
documentFilePath: indexHtml,
|
||||
url: `${protocol}://${headers.host}${originalUrl}`,
|
||||
publicPath: distFolder,
|
||||
providers: [
|
||||
{ provide: APP_BASE_HREF, useValue: baseUrl },],
|
||||
})
|
||||
.then((html) => res.send(html))
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
function run(): void {
|
||||
const port = process.env['PORT'] || 4000;
|
||||
|
||||
// Start up the Node server
|
||||
const server = app();
|
||||
server.listen(port, () => {
|
||||
console.log(`Node Express server listening on http://localhost:${port}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Webpack will replace 'require' with '__webpack_require__'
|
||||
// '__non_webpack_require__' is a proxy to Node 'require'
|
||||
// The below code is to ensure that the server is run only when not requiring the bundle.
|
||||
declare const __non_webpack_require__: NodeRequire;
|
||||
const mainModule = __non_webpack_require__.main;
|
||||
const moduleFilename = mainModule && mainModule.filename || '';
|
||||
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
|
||||
run();
|
||||
}
|
||||
|
||||
export default bootstrap;
|
@ -0,0 +1,10 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { routes } from './app.routes';
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, { bindToComponentInputs: true })],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
@ -0,0 +1,41 @@
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bind-route',
|
||||
template: `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>bindToComponentInputs</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<div>
|
||||
<h3>Bind Route</h3>
|
||||
<p id="route-params">Route params: id: {{id}}</p>
|
||||
<p id="query-params">Query params: query: {{query}}</p>
|
||||
<p id="data">Data: title: {{title}}</p>
|
||||
<p id="resolve">Resolve: name: {{name}}</p>
|
||||
</div>
|
||||
</ion-content>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [IonicModule]
|
||||
})
|
||||
export class BindComponentInputsComponent implements OnInit {
|
||||
|
||||
@Input() id?: string; // path parameter
|
||||
@Input() query?: string; // query parameter
|
||||
@Input() title?: string; // data property
|
||||
@Input() name?: string; // resolve property
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log('BindComponentInputsComponent.ngOnInit', {
|
||||
id: this.id,
|
||||
query: this.query,
|
||||
title: this.title,
|
||||
name: this.name
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
|
||||
import { NavRootComponent } from "./nav-root.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-modal-nav-params',
|
||||
template: `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Modal Nav Params</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-button id="open">Open Modal</ion-button>
|
||||
<ion-modal #modal trigger="open">
|
||||
<ng-template>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-button (click)="modal.dismiss()">Close</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-nav [root]="root" [rootParams]="rootParams"></ion-nav>
|
||||
</ion-content>
|
||||
</ng-template>
|
||||
</ion-modal>
|
||||
</ion-content>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [IonicModule, NavRootComponent]
|
||||
})
|
||||
export class ModalNavParamsComponent {
|
||||
|
||||
root = NavRootComponent;
|
||||
rootParams = {
|
||||
params: {
|
||||
id: 123
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
import { JsonPipe } from "@angular/common";
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
|
||||
/**
|
||||
* This is used to track if any occurences of
|
||||
* the ion-nav root component being attached to
|
||||
* the DOM result in the rootParams not being
|
||||
* assigned to the component instance.
|
||||
*
|
||||
* https://github.com/ionic-team/ionic-framework/issues/27146
|
||||
*/
|
||||
let rootParamsException = false;
|
||||
|
||||
@Component({
|
||||
selector: 'app-modal-content',
|
||||
template: `
|
||||
{{ hasException ? 'ERROR' : 'OK' }}
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [IonicModule, JsonPipe]
|
||||
})
|
||||
export class NavRootComponent {
|
||||
|
||||
params: any;
|
||||
|
||||
ngOnInit() {
|
||||
if (this.params === undefined) {
|
||||
rootParamsException = true;
|
||||
}
|
||||
}
|
||||
|
||||
get hasException() {
|
||||
return rootParamsException;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'modal-nav-params',
|
||||
loadComponent: () => import('./modal-nav-params/modal-nav-params.component').then(m => m.ModalNavParamsComponent),
|
||||
},
|
||||
{
|
||||
path: 'bind-route/:id',
|
||||
data: {
|
||||
title: 'data:bindToComponentInputs'
|
||||
},
|
||||
resolve: {
|
||||
name: () => 'resolve:bindToComponentInputs'
|
||||
},
|
||||
loadComponent: () => import('./bind-component-inputs/bind-component-inputs.component').then(c => c.BindComponentInputsComponent)
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class VersionTestRoutingModule { }
|
35
packages/angular/test/apps/ng18/tsconfig.json
Normal 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
|
||||
}
|
||||
}
|
@ -25,7 +25,8 @@ describe('Form Controls: Range', () => {
|
||||
|
||||
cy.get('ion-range').should('have.class', 'ion-valid');
|
||||
cy.get('ion-range').should('have.class', 'ion-dirty');
|
||||
cy.get('ion-range').should('have.class', 'ion-touched');
|
||||
// TODO(FW-6226): Investigate why this regresses in Angular 18
|
||||
// cy.get('ion-range').should('have.class', 'ion-touched');
|
||||
cy.get('ion-range').invoke('prop', 'value').should('eq', 10);
|
||||
});
|
||||
|
||||
|
@ -15,7 +15,8 @@ npm pack ../../../dist
|
||||
npm pack ../../../../angular-server/dist
|
||||
|
||||
# Install Dependencies
|
||||
npm install *.tgz --no-save
|
||||
# TODO(FW-6227): Remove --legacy-peer-deps once Angular 18 is released
|
||||
npm install *.tgz --no-save --legacy-peer-deps
|
||||
|
||||
# Delete Angular cache directory
|
||||
rm -rf .angular/
|
||||
|