merge release-6.2.2

Release 6.2.2
This commit is contained in:
Liam DeBeasi
2022-08-10 14:39:08 -05:00
committed by GitHub
86 changed files with 655 additions and 793 deletions

View File

@ -74,8 +74,8 @@ jobs:
"path": [
"/npm/@ionic/core@6/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@latest/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@6/css/ionic.bundle.css,
"/npm/@ionic/core@latest/css/ionic.bundle.css
"/npm/@ionic/core@6/css/ionic.bundle.css",
"/npm/@ionic/core@latest/css/ionic.bundle.css"
]}'

View File

@ -3,6 +3,21 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [6.2.2](https://github.com/ionic-team/ionic-framework/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **angular:** DatetimeButton is declared on IonicModule ([#25727](https://github.com/ionic-team/ionic-framework/issues/25727)) ([76ad1d1](https://github.com/ionic-team/ionic-framework/commit/76ad1d18c81272435db1994977aa9dd5d880504a))
* **datetime:** add correct null check when value changes ([#25716](https://github.com/ionic-team/ionic-framework/issues/25716)) ([36bea1c](https://github.com/ionic-team/ionic-framework/commit/36bea1ca2520c9eb9ee7705abb046607a52d198d)), closes [#25714](https://github.com/ionic-team/ionic-framework/issues/25714)
* **datetime:** preferWheel respects column ordering by locale ([#25726](https://github.com/ionic-team/ionic-framework/issues/25726)) ([dee0f51](https://github.com/ionic-team/ionic-framework/commit/dee0f513ee443c0c69ea8e38a292c900e9c70221)), closes [#25722](https://github.com/ionic-team/ionic-framework/issues/25722)
* **react:** outlet will not clear in react 18 with hot reload ([#25703](https://github.com/ionic-team/ionic-framework/issues/25703)) ([3878bf7](https://github.com/ionic-team/ionic-framework/commit/3878bf76523f2e1c26c147473fd7c07ee4d0e820)), closes [#25507](https://github.com/ionic-team/ionic-framework/issues/25507)
* **vue:** go back to correct view with memory history ([#25732](https://github.com/ionic-team/ionic-framework/issues/25732)) ([8327889](https://github.com/ionic-team/ionic-framework/commit/832788971a7098e52812f66563cbc0a63d3e5df7)), closes [#25705](https://github.com/ionic-team/ionic-framework/issues/25705)
## [6.2.1](https://github.com/ionic-team/ionic-framework/compare/v6.2.0...v6.2.1) (2022-08-03)

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **angular:** DatetimeButton is declared on IonicModule ([#25727](https://github.com/ionic-team/ionic/issues/25727)) ([76ad1d1](https://github.com/ionic-team/ionic/commit/76ad1d18c81272435db1994977aa9dd5d880504a))
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)
**Note:** Version bump only for package @ionic/angular

View File

@ -1,15 +1,15 @@
{
"name": "@ionic/angular",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"jsonc-parser": "^3.0.0",
"tslib": "^2.0.0"
},
@ -1023,9 +1023,9 @@
"dev": true
},
"node_modules/@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dependencies": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -7939,9 +7939,9 @@
"dev": true
},
"@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"requires": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "6.2.1",
"version": "6.2.2",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@ -44,7 +44,7 @@
"validate": "npm i && npm run lint && npm run test && npm run build"
},
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"jsonc-parser": "^3.0.0",
"tslib": "^2.0.0"
},

View File

@ -40,6 +40,7 @@ import {
IonCol,
IonContent,
IonDatetime,
IonDatetimeButton,
IonFab,
IonFabButton,
IonFabList,
@ -127,6 +128,7 @@ const DECLARATIONS = [
IonCol,
IonContent,
IonDatetime,
IonDatetimeButton,
IonFab,
IonFabButton,
IonFabList,

View File

@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **datetime:** add correct null check when value changes ([#25716](https://github.com/ionic-team/ionic/issues/25716)) ([36bea1c](https://github.com/ionic-team/ionic/commit/36bea1ca2520c9eb9ee7705abb046607a52d198d)), closes [#25714](https://github.com/ionic-team/ionic/issues/25714)
* **datetime:** preferWheel respects column ordering by locale ([#25726](https://github.com/ionic-team/ionic/issues/25726)) ([dee0f51](https://github.com/ionic-team/ionic/commit/dee0f513ee443c0c69ea8e38a292c900e9c70221)), closes [#25722](https://github.com/ionic-team/ionic/issues/25722)
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)

View File

@ -1,12 +1,12 @@
{
"name": "@ionic/core",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"dependencies": {
"@stencil/core": "^2.16.0",

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "6.2.1",
"version": "6.2.2",
"description": "Base components for Ionic",
"keywords": [
"ionic",

View File

@ -353,7 +353,7 @@ export class Datetime implements ComponentInterface {
this.activePartsClone = [...valueDateParts];
} else {
const { month, day, year, hour, minute } = valueDateParts;
const ampm = hour ? (hour >= 12 ? 'pm' : 'am') : undefined;
const ampm = hour != null ? (hour >= 12 ? 'pm' : 'am') : undefined;
this.activePartsClone = {
...this.activeParts,
@ -1522,7 +1522,27 @@ export class Datetime implements ComponentInterface {
? getYearColumnData(this.todayParts, this.minParts, this.maxParts, this.parsedYearValues)
: [];
return [this.renderMonthPickerColumn(months), this.renderDayPickerColumn(days), this.renderYearPickerColumn(years)];
/**
* Certain locales show the day before the month.
*/
const showMonthFirst = isMonthFirstLocale(this.locale, { month: 'numeric', day: 'numeric' });
let renderArray = [];
if (showMonthFirst) {
renderArray = [
this.renderMonthPickerColumn(months),
this.renderDayPickerColumn(days),
this.renderYearPickerColumn(years),
];
} else {
renderArray = [
this.renderDayPickerColumn(days),
this.renderMonthPickerColumn(months),
this.renderYearPickerColumn(years),
];
}
return renderArray;
}
private renderDayPickerColumn(days: PickerColumnItem[]) {

View File

@ -89,6 +89,7 @@ test.describe('datetime: prefer wheel', () => {
expect(await yearValues.count()).toBe(3);
expect(await dayValues.count()).toBe(5);
});
test.describe('datetime: date wheel localization', () => {
test('should correctly localize the date data', async ({ page }) => {
await page.setContent(`
<ion-datetime
@ -110,6 +111,43 @@ test.describe('datetime: prefer wheel', () => {
expect(monthValues).toHaveText(['1月', '2月', '3月']);
expect(dayValues).toHaveText(['1日', '2日', '3日']);
});
test('should render the columns according to locale - en-US', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="en-US"
value="2022-01-01"
></ion-datetime>
`);
await page.waitForSelector('.datetime-ready');
const columns = page.locator('ion-picker-column-internal');
await expect(columns.nth(0)).toHaveClass(/month-column/);
await expect(columns.nth(1)).toHaveClass(/day-column/);
await expect(columns.nth(2)).toHaveClass(/year-column/);
});
test('should render the columns according to locale - en-GB', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="en-GB"
value="2022-01-01"
></ion-datetime>
`);
await page.waitForSelector('.datetime-ready');
const columns = page.locator('ion-picker-column-internal');
await expect(columns.nth(0)).toHaveClass(/day-column/);
await expect(columns.nth(1)).toHaveClass(/month-column/);
await expect(columns.nth(2)).toHaveClass(/year-column/);
});
});
});
test.describe('datetime: date-time wheel rendering', () => {
test('should not have visual regressions', async ({ page }) => {

View File

@ -74,8 +74,19 @@ export const getNumDaysInMonth = (month: number, year: number) => {
* others display year then month.
* We can use Intl.DateTimeFormat to determine
* the ordering for each locale.
* The formatOptions param can be used to customize
* which pieces of a date to compare against the month
* with. For example, some locales render dd/mm/yyyy
* while others render mm/dd/yyyy. This function can be
* used for variations of the same "month first" check.
*/
export const isMonthFirstLocale = (locale: string) => {
export const isMonthFirstLocale = (
locale: string,
formatOptions: Intl.DateTimeFormatOptions = {
month: 'numeric',
year: 'numeric',
}
) => {
/**
* By setting month and year we guarantee that only
* month, year, and literal (slashes '/', for example)
@ -88,7 +99,7 @@ export const isMonthFirstLocale = (locale: string) => {
*
* This ordering can be controlled by customizing the locale property.
*/
const parts = new Intl.DateTimeFormat(locale, { month: 'numeric', year: 'numeric' }).formatToParts(new Date());
const parts = new Intl.DateTimeFormat(locale, formatOptions).formatToParts(new Date());
return parts[0].type === 'month';
};

View File

@ -22,161 +22,35 @@
</ion-toolbar>
</ion-header>
<ion-content class="outer-content">
<p class="ion-text-center">
<ion-button onClick="addRadio()">Add Radio</ion-button>
<ion-button onClick="addChecked()">Add Checked</ion-button>
<ion-button id="removeButton" onClick="removeRadio()">Remove Radio</ion-button>
</p>
<ion-content>
<ion-list>
<ion-radio-group id="dynamicDisabled" disabled name="tannen" id="group" value="biff">
<ion-radio-group name="items" id="group" value="1">
<ion-list-header>
<ion-label>Luckiest Man On Earth <span id="group-value"></span></ion-label>
<ion-label>Radio Group Header</ion-label>
</ion-list-header>
<ion-item>
<ion-label
>Biff
<span id="biff"></span>
</ion-label>
<ion-radio value="biff" slot="start"></ion-radio>
<ion-label>Item 1</ion-label>
<ion-radio value="1" slot="start"></ion-radio>
</ion-item>
<ion-item>
<ion-label
>Griff
<span id="griff"></span>
</ion-label>
<ion-radio value="griff" slot="start"></ion-radio>
<ion-label>Item 2</ion-label>
<ion-radio value="2" slot="start"></ion-radio>
</ion-item>
<ion-item>
<ion-label
>Buford
<span id="buford"></span>
</ion-label>
<ion-radio value="buford" slot="start"></ion-radio>
<ion-label>Item 3</ion-label>
<ion-radio value="3" slot="start"></ion-radio>
</ion-item>
<ion-item>
<ion-label>George</ion-label>
<ion-radio value="george" slot="start"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
<ion-list>
<ion-radio-group value="huey">
<ion-item>
<ion-label>Huey</ion-label>
<ion-radio slot="start" value="huey"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Dewey</ion-label>
<ion-radio slot="start" value="dewey"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Louie</ion-label>
<ion-radio slot="start" value="louie"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
<ion-list>
<ion-radio-group value="huey">
<ion-item-divider>
<ion-label> Maintenance Drone </ion-label>
</ion-item-divider>
<ion-item>
<ion-label>Huey</ion-label>
<ion-radio slot="start" value="huey"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Dewey</ion-label>
<ion-radio slot="start" value="dewey"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Louie</ion-label>
<ion-radio slot="start" value="louie"></ion-radio>
<ion-label>Item 4</ion-label>
<ion-radio value="4" slot="start"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
</ion-content>
<style>
.outer-content {
--background: #f2f2f2;
}
ion-list {
margin-bottom: 10px !important;
}
</style>
<script>
let count = 0;
const removeButton = document.querySelector('#removeButton');
const valueEl = document.querySelector('#group-value');
const group = document.querySelector('ion-radio-group');
group.addEventListener('ionChange', (ev) => {
valueEl.textContent = group.value;
});
customElements
.whenDefined('ion-radio-group')
.then(() => group.componentOnReady && group.componentOnReady())
.then(() => {
valueEl.textContent = group.value;
});
function addRadio() {
const item = document.createElement('ion-item');
item.innerHTML = `
<ion-label>Item ${count}</ion-label>
<ion-radio value="item-${count}" slot="start"></ion-radio>
`;
group.appendChild(item);
count++;
removeButton.disabled = false;
}
function addChecked() {
const item = document.createElement('ion-item');
item.innerHTML = `
<ion-label>Item ${count}</ion-label>
<ion-radio value="item-${count}" slot="start"></ion-radio>
`;
group.appendChild(item);
group.value = `item-${count}`;
count++;
removeButton.disabled = false;
}
function removeRadio() {
const removeEl = group.children[group.children.length - 1];
if (removeEl && removeEl.tagName === 'ION-ITEM') {
removeEl.remove();
// No more radios to remove, disable button
if (!group.querySelector('ion-item')) {
removeButton.disabled = true;
}
}
}
</script>
</ion-app>
</body>
</html>

View File

@ -0,0 +1,110 @@
import { expect } from '@playwright/test';
import type { Locator } from '@playwright/test';
import { test } from '@utils/test/playwright';
import type { E2EPage } from '@utils/test/playwright';
test.describe('radio-group: basic', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/radio-group/test/basic`);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(`radio-group-diff-${page.getSnapshotSettings()}.png`);
});
});
test.describe('radio-group: interaction', () => {
let radioFixture: RadioFixture;
test.beforeEach(({ page }, testInfo) => {
test.skip(testInfo.project.metadata.rtl === true, 'This does not test LTR vs RTL logic.');
radioFixture = new RadioFixture(page);
});
test('spacebar should not deselect without allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="false">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('keyboard');
await radioFixture.expectChecked(true);
});
test('spacebar should deselect with allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="true">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('keyboard');
await radioFixture.expectChecked(false);
});
test('click should not deselect without allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="false">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('mouse');
await radioFixture.expectChecked(true);
});
test('click should deselect with allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="true">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('mouse');
await radioFixture.expectChecked(false);
});
});
class RadioFixture {
readonly page: E2EPage;
private radio!: Locator;
constructor(page: E2EPage) {
this.page = page;
}
async checkRadio(method: 'keyboard' | 'mouse', selector = 'ion-radio') {
const { page } = this;
const radio = (this.radio = page.locator(selector));
if (method === 'keyboard') {
await radio.focus();
await page.keyboard.press('Space');
} else {
await radio.click();
}
await page.waitForChanges();
return radio;
}
async expectChecked(state: boolean) {
const { radio } = this;
await expect(radio.locator('input')).toHaveJSProperty('checked', state);
}
}

View File

@ -0,0 +1,34 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('radio-group: form', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/radio-group/test/form');
});
test('selecting an option should update the value', async ({ page }) => {
const radioGroup = page.locator('ion-radio-group');
const ionChange = await page.spyOnEvent('ionChange');
const griffRadio = page.locator('ion-radio[value="griff"]');
await expect(radioGroup).toHaveAttribute('value', 'biff');
await griffRadio.click();
await page.waitForChanges();
await expect(ionChange).toHaveReceivedEventDetail({ value: 'griff' });
});
test('selecting a disabled option should not update the value', async ({ page }) => {
const value = page.locator('#value');
const disabledRadio = page.locator('ion-radio[value="george"]');
await expect(value).toHaveText('');
await expect(disabledRadio).toHaveAttribute('disabled', '');
await disabledRadio.click({ force: true });
await page.waitForChanges();
await expect(value).toHaveText('');
});
});

View File

@ -1,133 +0,0 @@
import { expect } from '@playwright/test';
import type { Locator } from '@playwright/test';
import { test } from '@utils/test/playwright';
import type { E2EPage } from '@utils/test/playwright';
test.describe('radio-group', () => {
// eslint-disable-next-line no-empty-pattern
test.beforeEach(({}, testInfo) => {
test.skip(testInfo.project.metadata.rtl === true, 'This does not test LTR vs RTL logic.');
});
test.describe('radio-group: interaction', () => {
let radioFixture: RadioFixture;
test.beforeEach(({ page }) => {
radioFixture = new RadioFixture(page);
});
test('spacebar should not deselect without allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="false">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('keyboard');
await radioFixture.expectChecked(true);
});
test('spacebar should deselect with allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="true">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('keyboard');
await radioFixture.expectChecked(false);
});
test('click should not deselect without allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="false">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('mouse');
await radioFixture.expectChecked(true);
});
test('click should deselect with allowEmptySelection', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="one" allow-empty-selection="true">
<ion-item>
<ion-label>One</ion-label>
<ion-radio id="one" value="one"></ion-radio>
</ion-item>
</ion-radio-group>
`);
await radioFixture.checkRadio('mouse');
await radioFixture.expectChecked(false);
});
});
test.describe('radio-group: state', () => {
test('radio should remain checked after being removed/readded to the dom', async ({ page }) => {
await page.goto('/src/components/radio-group/test/search');
const radioGroup = page.locator('ion-radio-group');
const radio = page.locator('ion-radio[value=two]');
// select radio
await radio.click();
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
// filter radio so it is not in DOM
await page.fill('ion-searchbar input', 'zero');
await page.waitForChanges();
expect(radio).toBeHidden();
// ensure radio group has the same value
expect(radioGroup).toHaveJSProperty('value', 'two');
// clear the search so the radio appears
await page.fill('ion-searchbar input', '');
await page.waitForChanges();
// ensure that the new radio instance is still checked
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
});
});
});
class RadioFixture {
readonly page: E2EPage;
private radio!: Locator;
constructor(page: E2EPage) {
this.page = page;
}
async checkRadio(method: 'keyboard' | 'mouse', selector = 'ion-radio') {
const { page } = this;
const radio = (this.radio = page.locator(selector));
if (method === 'keyboard') {
await radio.focus();
await page.keyboard.press('Space');
} else {
await radio.click();
}
await page.waitForChanges();
return radio;
}
async expectChecked(state: boolean) {
const { radio } = this;
await expect(radio.locator('input')).toHaveJSProperty('checked', state);
}
}

View File

@ -0,0 +1,35 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('radio-group', () => {
test.beforeEach(async ({ page }, testInfo) => {
test.skip(testInfo.project.metadata.rtl === true, 'This does not test LTR vs RTL logic.');
await page.goto('/src/components/radio-group/test/search');
});
test.describe('radio-group: state', () => {
test('radio should remain checked after being removed/readded to the dom', async ({ page }) => {
const radioGroup = page.locator('ion-radio-group');
const radio = page.locator('ion-radio[value=two]');
// select radio
await radio.click();
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
// filter radio so it is not in DOM
await page.fill('ion-searchbar input', 'zero');
await page.waitForChanges();
expect(radio).toBeHidden();
// ensure radio group has the same value
expect(radioGroup).toHaveJSProperty('value', 'two');
// clear the search so the radio appears
await page.fill('ion-searchbar input', '');
await page.waitForChanges();
// ensure that the new radio instance is still checked
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
});
});
});

View File

@ -1,65 +0,0 @@
import { newE2EPage } from '@stencil/core/testing';
test('searchbar: basic', async () => {
const page = await newE2EPage({
url: '/src/components/searchbar/test/basic?ionic:_testing=true',
});
const compares = [];
compares.push(await page.compareScreenshot());
let searchbar = await page.find('#basic');
await searchbar.callMethod('setFocus');
await page.waitForTimeout(250);
searchbar = await page.find('#basic');
expect(searchbar).toHaveClass('searchbar-has-focus');
compares.push(await page.compareScreenshot('focused'));
// No Cancel Button Searchbar
searchbar = await page.find('#noCancel');
await searchbar.callMethod('setFocus');
await page.waitForTimeout(250);
searchbar = await page.find('#noCancel');
expect(searchbar).toHaveClass('searchbar-has-focus');
compares.push(await page.compareScreenshot('no cancel button, focused'));
for (const compare of compares) {
expect(compare).toMatchScreenshot();
}
});
test('searchbar:rtl: basic', async () => {
const page = await newE2EPage({
url: '/src/components/searchbar/test/basic?ionic:_testing=true&rtl=true',
});
const compares = [];
compares.push(await page.compareScreenshot());
let searchbar = await page.find('#basic');
await searchbar.callMethod('setFocus');
await page.waitForTimeout(250);
searchbar = await page.find('#basic');
expect(searchbar).toHaveClass('searchbar-has-focus');
compares.push(await page.compareScreenshot('focused'));
// No Cancel Button Searchbar
searchbar = await page.find('#noCancel');
await searchbar.callMethod('setFocus');
await page.waitForTimeout(250);
searchbar = await page.find('#noCancel');
expect(searchbar).toHaveClass('searchbar-has-focus');
compares.push(await page.compareScreenshot('no cancel button, focused'));
for (const compare of compares) {
expect(compare).toMatchScreenshot();
}
});

View File

@ -26,61 +26,25 @@
<h5 class="ion-padding-start ion-padding-top">Search - Default</h5>
<ion-searchbar id="basic" value="test" type="tel" show-cancel-button="focus" debounce="500"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - No Cancel Button</h5>
<ion-searchbar
class="red-box"
id="noCancel"
value="after view"
autocorrect="off"
autocomplete="off"
spellcheck="true"
type="text"
show-cancel-button="never"
>
</ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Always Show Cancel Button</h5>
<ion-searchbar id="noCancel" value="after view" animated="true" show-cancel-button="always"> </ion-searchbar>
<ion-searchbar id="alwaysCancel" value="after view" animated="true" show-cancel-button="always">
</ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Never Show Cancel Button</h5>
<ion-searchbar id="noCancel" value="after view" animated="true" show-cancel-button="never"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Show Cancel Button on Focus</h5>
<ion-searchbar id="noCancel" value="after view" animated="true" show-cancel-button="focus"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Cancel Button set to false</h5>
<ion-searchbar
id="noCancel"
value="after view"
autocorrect="off"
autocomplete="off"
spellcheck="true"
type="text"
show-cancel-button="never"
>
</ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Cancel Button set to true</h5>
<ion-searchbar
id="noCancel"
value="after view"
autocorrect="off"
autocomplete="off"
spellcheck="true"
type="text"
show-cancel-button="focus"
>
</ion-searchbar>
<ion-searchbar id="focusCancel" value="after view" animated="true" show-cancel-button="focus"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - No Clear Button</h5>
<ion-searchbar id="noCancel" value="after view" type="text" show-clear-button="never"> </ion-searchbar>
<ion-searchbar id="noClear" value="after view" type="text" show-clear-button="never"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Always Show Clear Button</h5>
<ion-searchbar id="noCancel" value="after view" type="text" show-clear-button="always"> </ion-searchbar>
<ion-searchbar id="alwaysClear" value="after view" type="text" show-clear-button="always"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Input mode set to numeric</h5>
<ion-searchbar
id="noCancel"
id="numericMode"
value="after view"
inputmode="numeric"
autocorrect="off"
@ -100,38 +64,22 @@
<h5 class="ion-padding-start ion-padding-top">Search - Custom Search Icon</h5>
<ion-searchbar search-icon="home" show-cancel-button="focus" debounce="500"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Animated</h5>
<ion-searchbar animated="true" show-cancel-button="focus" debounce="500"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Custom Placeholder</h5>
<ion-searchbar
id="dynamicProp"
value="33"
autocorrect="on"
show-cancel-button="focus"
autocomplete="on"
spellcheck="false"
type="number"
placeholder="Filter Schedules"
>
</ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Custom Cancel Button Danger</h5>
<ion-searchbar show-cancel-button="focus" cancel-button-text="Really Long Cancel" color="danger">
</ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Custom Cancel Button</h5>
<ion-searchbar show-cancel-button="always" cancel-button-text="Really Long Cancel"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Custom Cancel Button Icon through property</h5>
<ion-searchbar show-cancel-button="focus" cancel-button-icon="rewind"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Value passed</h5>
<ion-searchbar value="mysearch" cancel-button-text="Really Long Cancel" color="dark" show-cancel-button="focus">
</ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Mode iOS</h5>
<ion-searchbar mode="ios" animated="true" show-cancel-button="focus" placeholder="Search"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - Mode MD</h5>
<ion-searchbar mode="md" animated="true" show-cancel-button="focus" placeholder="Search"> </ion-searchbar>
<ion-searchbar show-cancel-button="always" cancel-button-icon="play-back"> </ion-searchbar>
<h5 class="ion-padding-start ion-padding-top">Search - DebounceTime</h5>
<ion-searchbar
@ -158,10 +106,6 @@
>
</ion-searchbar>
<p class="ion-padding">
<ion-button expand="block" (click)="changeValue()">Change Value</ion-button>
</p>
<div class="ion-padding-horizontal">
<ion-button expand="block" onClick="toggleProp()">Toggle Property</ion-button>
</div>
@ -173,13 +117,6 @@
<ion-button expand="block" color="secondary" onClick="toggleDisabled()">Toggle disabled</ion-button>
</div>
<style>
.red-box {
--box-shadow: 0 2px 2px 0 rgba(255, 0, 0, 0.14), 0 3px 1px -2px rgba(255, 0, 0, 0.2),
0 1px 5px 0 rgba(255, 0, 0, 0.12);
}
</style>
<script>
function toggleAttr() {
var dynamicAttr = document.getElementById('dynamicAttr');
@ -245,17 +182,6 @@
const propIsSpellcheck = dynamicProp.spellcheck === true ? false : true;
dynamicProp.spellcheck = propIsSpellcheck;
}
const content = document.querySelector('#content');
content.addEventListener('ionChange', (ev) => {
console.log(ev);
});
content.addEventListener('ionCancel', (ev) => {
console.log(ev);
});
content.addEventListener('ionClear', (ev) => {
console.log(ev);
});
</script>
</ion-content>
</ion-app>

View File

@ -0,0 +1,35 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('searchbar: basic', () => {
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/searchbar/test/basic`);
});
test('should not have visual regressions', async ({ page }) => {
await page.setIonViewport();
expect(await page.screenshot()).toMatchSnapshot(`searchbar-diff-${page.getSnapshotSettings()}.png`);
});
test('should show cancel button on focus if show-cancel-button=focus', async ({ page }) => {
const searchbar = page.locator('#basic');
const cancelButton = searchbar.locator('.searchbar-cancel-button');
await searchbar.evaluate((el: HTMLIonSearchbarElement) => el.setFocus());
await page.waitForChanges();
await expect(searchbar).toHaveClass(/searchbar-has-focus/);
await expect(cancelButton).toBeVisible();
});
test('should not show cancel button on focus if show-cancel-button=never', async ({ page }) => {
const searchbar = page.locator('#noCancel');
const cancelButton = searchbar.locator('.searchbar-cancel-button');
await searchbar.evaluate((el: HTMLIonSearchbarElement) => el.setFocus());
await page.waitForChanges();
await expect(searchbar).toHaveClass(/searchbar-has-focus/);
await expect(cancelButton).toHaveCount(0);
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

View File

@ -1,10 +0,0 @@
import { newE2EPage } from '@stencil/core/testing';
test('searchbar: rtl', async () => {
const page = await newE2EPage({
url: '/src/components/searchbar/test/rtl?ionic:_testing=true',
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -1,31 +0,0 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Searchbar - RTL</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Searchbar - RTL</ion-title>
</ion-toolbar>
</ion-header>
<ion-content id="content">
<h5 class="ion-padding-start ion-padding-top">Search - Default</h5>
<ion-searchbar dir="rtl" value="test" type="tel" show-cancel-button="focus" debounce="500"> </ion-searchbar>
</ion-content>
</ion-app>
</body>
</html>

View File

@ -1,14 +0,0 @@
import { newE2EPage } from '@stencil/core/testing';
test('searchbar: standalone', async () => {
const page = await newE2EPage({
url: '/src/components/searchbar/test/standalone?ionic:_testing=true',
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
const searchbar = await page.find('ion-searchbar');
await searchbar.callMethod('setFocus');
expect(await page.compareScreenshot('focused')).toMatchScreenshot();
});

View File

@ -43,26 +43,9 @@
<ion-searchbar show-cancel-button="focus" cancel-button-text="Really Long Cancel" color="danger"> </ion-searchbar>
<ion-searchbar value="mysearch" cancel-button-text="Really Long Cancel" color="dark" show-cancel-button="focus">
<ion-searchbar value="mysearch" cancel-button-text="Really Long Cancel" color="dark" show-cancel-button="always">
</ion-searchbar>
<ion-searchbar mode="ios" animated="true" show-cancel-button="focus" placeholder="Search"> </ion-searchbar>
<ion-searchbar mode="md" animated="true" show-cancel-button="focus" placeholder="Search"> </ion-searchbar>
<ion-searchbar
autocorrect="on"
show-cancel-button="focus"
autocomplete="on"
spellcheck="true"
type="text"
debounce="5000"
placeholder="Check the log"
>
</ion-searchbar>
<ion-searchbar id="dynamicAttr" placeholder="Search" animated="true" show-cancel-button="never"> </ion-searchbar>
<ion-searchbar class="custom" show-cancel-button="focus"> </ion-searchbar>
<style>

View File

@ -0,0 +1,12 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('searchbar: standalone', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/searchbar/test/standalone`);
expect(await page.screenshot({ fullPage: true })).toMatchSnapshot(
`searchbar-standalone-${page.getSnapshotSettings()}.png`
);
});
});

View File

@ -1,10 +0,0 @@
import { newE2EPage } from '@stencil/core/testing';
test('searchbar: toolbar', async () => {
const page = await newE2EPage({
url: '/src/components/searchbar/test/toolbar?ionic:_testing=true',
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -1,162 +0,0 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Ionic Searchbar Toolbar</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<ion-app>
<ion-header translucent>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button>Undo</ion-button>
</ion-buttons>
<ion-title>Searchbar - Toolbar</ion-title>
<ion-buttons slot="end">
<ion-button>Clear</ion-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button>Undo</ion-button>
</ion-buttons>
<ion-searchbar translucent></ion-searchbar>
<ion-buttons slot="end">
<ion-button>Clear</ion-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-back-button default-href="#" slot="start"></ion-back-button>
<ion-searchbar translucent></ion-searchbar>
<ion-chip slot="end" outline>Chip</ion-chip>
</ion-toolbar>
</ion-header>
<ion-content id="content" fullscreen>
<h5 class="ion-padding-start">Search - Transparent Toolbar</h5>
<ion-toolbar transparent>
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Default Toolbar</h5>
<ion-toolbar>
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Primary Toolbar</h5>
<ion-toolbar color="primary">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Secondary Toolbar</h5>
<ion-toolbar color="secondary">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Tertiary Toolbar</h5>
<ion-toolbar color="tertiary">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Success Toolbar</h5>
<ion-toolbar color="success">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Warning Toolbar</h5>
<ion-toolbar color="warning">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Danger Toolbar</h5>
<ion-toolbar color="danger">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Light Toolbar</h5>
<ion-toolbar color="light">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Medium Toolbar</h5>
<ion-toolbar color="medium">
<ion-searchbar show-cancel-button="focus"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Dark Toolbar</h5>
<ion-toolbar color="dark">
<ion-searchbar show-cancel-button="focus" placeholder="Filter Schedules"></ion-searchbar>
</ion-toolbar>
<h5 class="ion-padding-start">Search - Dark Toolbar, Primary Search</h5>
<ion-toolbar color="dark">
<ion-searchbar show-cancel-button="focus" color="primary" placeholder="Filter Schedules"></ion-searchbar>
</ion-toolbar>
<ion-grid>
<ion-row>
<ion-col size="6"><f class="red"></f></ion-col>
<ion-col size="6"><f class="green"></f></ion-col>
<ion-col size="6"><f class="blue"></f></ion-col>
<ion-col size="6"><f class="yellow"></f></ion-col>
<ion-col size="6"><f class="pink"></f></ion-col>
<ion-col size="6"><f class="purple"></f></ion-col>
<ion-col size="6"><f class="black"></f></ion-col>
<ion-col size="6"><f class="orange"></f></ion-col>
</ion-row>
</ion-grid>
</ion-content>
</ion-app>
<style>
f {
display: block;
width: 100%;
height: 200px;
margin: 20px auto;
}
.red {
background-color: #ea445a;
}
.green {
background-color: #76d672;
}
.blue {
background-color: #3478f6;
}
.yellow {
background-color: #ffff80;
}
.pink {
background-color: #ff6b86;
}
.purple {
background-color: #7e34f6;
}
.black {
background-color: #000;
}
.orange {
background-color: #f69234;
}
</style>
</body>
</html>

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic-docs/compare/v6.2.1...v6.2.2) (2022-08-10)
**Note:** Version bump only for package @ionic/docs
## [6.2.1](https://github.com/ionic-team/ionic-docs/compare/v6.2.0...v6.2.1) (2022-08-03)
**Note:** Version bump only for package @ionic/docs

View File

@ -1,12 +1,12 @@
{
"name": "@ionic/docs",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/docs",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/docs",
"version": "6.2.1",
"version": "6.2.2",
"description": "Pre-packaged API documentation for the Ionic docs.",
"main": "core.json",
"types": "core.d.ts",

View File

@ -5,5 +5,5 @@
"angular",
"packages/*"
],
"version": "6.2.1"
"version": "6.2.2"
}

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
**Note:** Version bump only for package @ionic/angular-server
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)
**Note:** Version bump only for package @ionic/angular-server

View File

@ -1,12 +1,12 @@
{
"name": "@ionic/angular-server",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular-server",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"devDependencies": {
"@angular-eslint/eslint-plugin": "^12.6.1",
@ -18,7 +18,7 @@
"@angular/platform-browser": "^12.0.0",
"@angular/platform-browser-dynamic": "^12.2.10",
"@angular/platform-server": "^12.0.0",
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^5.2.0",
@ -786,9 +786,9 @@
"license": "BSD-3-Clause"
},
"node_modules/@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dev": true,
"dependencies": {
"@stencil/core": "^2.16.0",
@ -7103,9 +7103,9 @@
"dev": true
},
"@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dev": true,
"requires": {
"@stencil/core": "^2.16.0",

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/angular-server",
"version": "6.2.1",
"version": "6.2.2",
"description": "Angular SSR Module for Ionic",
"keywords": [
"ionic",
@ -56,7 +56,7 @@
"@angular/platform-browser": "^12.0.0",
"@angular/platform-browser-dynamic": "^12.2.10",
"@angular/platform-server": "^12.0.0",
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^5.2.0",

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **react:** outlet will not clear in react 18 with hot reload ([#25703](https://github.com/ionic-team/ionic/issues/25703)) ([3878bf7](https://github.com/ionic-team/ionic/commit/3878bf76523f2e1c26c147473fd7c07ee4d0e820)), closes [#25507](https://github.com/ionic-team/ionic/issues/25507)
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)
**Note:** Version bump only for package @ionic/react-router

View File

@ -1,15 +1,15 @@
{
"name": "@ionic/react-router",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/react-router",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"dependencies": {
"@ionic/react": "^6.2.1",
"@ionic/react": "^6.2.2",
"tslib": "*"
},
"devDependencies": {
@ -147,9 +147,9 @@
}
},
"node_modules/@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dependencies": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -157,11 +157,11 @@
}
},
"node_modules/@ionic/react": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-6.2.1.tgz",
"integrity": "sha512-zHqoGeEm4QwzCijBvcYZQifrCvFXSRChh8ey5lsYUixxKwgl2j9y3kKLckLiipR/g+mbC5lVjno0UlIlBvsulQ==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-6.2.2.tgz",
"integrity": "sha512-CRuDJbNDn9bbDba37/5v9aZ2gd450XGklGqXmsxEfadh1iq7iWmqcgw14S0ZDAXQt0aE/J+TeKhTyjyutjsAww==",
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2",
"tslib": "*"
},
@ -1157,9 +1157,9 @@
}
},
"@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"requires": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -1167,11 +1167,11 @@
}
},
"@ionic/react": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-6.2.1.tgz",
"integrity": "sha512-zHqoGeEm4QwzCijBvcYZQifrCvFXSRChh8ey5lsYUixxKwgl2j9y3kKLckLiipR/g+mbC5lVjno0UlIlBvsulQ==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-6.2.2.tgz",
"integrity": "sha512-CRuDJbNDn9bbDba37/5v9aZ2gd450XGklGqXmsxEfadh1iq7iWmqcgw14S0ZDAXQt0aE/J+TeKhTyjyutjsAww==",
"requires": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2",
"tslib": "*"
}

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/react-router",
"version": "6.2.1",
"version": "6.2.2",
"description": "React Router wrapper for @ionic/react",
"keywords": [
"ionic",
@ -37,7 +37,7 @@
"dist/"
],
"dependencies": {
"@ionic/react": "^6.2.1",
"@ionic/react": "^6.2.2",
"tslib": "*"
},
"peerDependencies": {

View File

@ -18,7 +18,8 @@ interface StackManagerProps {
interface StackManagerState {}
const isViewVisible = (el: HTMLElement) => !el.classList.contains('ion-page-invisible') && !el.classList.contains('ion-page-hidden');
const isViewVisible = (el: HTMLElement) =>
!el.classList.contains('ion-page-invisible') && !el.classList.contains('ion-page-hidden');
export class StackManager extends React.PureComponent<StackManagerProps, StackManagerState> {
id: string;
@ -33,6 +34,7 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
isInOutlet: () => true,
};
private clearOutletTimeout: any;
private pendingPageTransition = false;
constructor(props: StackManagerProps) {
@ -46,9 +48,20 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
}
componentDidMount() {
if (this.clearOutletTimeout) {
/**
* The clearOutlet integration with React Router is a bit hacky.
* It uses a timeout to clear the outlet after a transition.
* In React v18, components are mounted and unmounted in development mode
* to check for side effects.
*
* This clearTimeout prevents the outlet from being cleared when the component is re-mounted,
* which should only happen in development mode and as a result of a hot reload.
*/
clearTimeout(this.clearOutletTimeout);
}
if (this.routerOutletElement) {
this.setupRouterOutlet(this.routerOutletElement);
// console.log(`SM Mount - ${this.routerOutletElement.id} (${this.id})`);
this.handlePageTransition(this.props.routeInfo);
}
}
@ -67,8 +80,7 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
}
componentWillUnmount() {
// console.log(`SM UNMount - ${(this.routerOutletElement?.id as any).id} (${this.id})`);
this.context.clearOutlet(this.id);
this.clearOutletTimeout = this.context.clearOutlet(this.id);
}
async handlePageTransition(routeInfo: RouteInfo) {
@ -142,13 +154,20 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
* to find the leaving view item to transition between.
*/
if (!leavingViewItem && this.props.routeInfo.prevRouteLastPathname) {
leavingViewItem = this.context.findViewItemByPathname(this.props.routeInfo.prevRouteLastPathname, this.id);
leavingViewItem = this.context.findViewItemByPathname(
this.props.routeInfo.prevRouteLastPathname,
this.id
);
}
/**
* If the entering view is already visible and the leaving view is not, the transition does not need to occur.
*/
if (isViewVisible(enteringViewItem.ionPageElement) && leavingViewItem !== undefined && !isViewVisible(leavingViewItem.ionPageElement!)) {
if (
isViewVisible(enteringViewItem.ionPageElement) &&
leavingViewItem !== undefined &&
!isViewVisible(leavingViewItem.ionPageElement!)
) {
return;
}
@ -197,11 +216,16 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
const canStart = () => {
const config = getConfig();
const swipeEnabled = config && config.get('swipeBackEnabled', routerOutlet.mode === 'ios');
if (!swipeEnabled) { return false; }
if (!swipeEnabled) {
return false;
}
const { routeInfo } = this.props;
const propsToUse = (this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute) ? this.prevProps.routeInfo : { pathname: routeInfo.pushedByRoute || '' } as any;
const propsToUse =
this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute
? this.prevProps.routeInfo
: ({ pathname: routeInfo.pushedByRoute || '' } as any);
const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);
return (
@ -213,7 +237,6 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
* root url.
*/
enteringViewItem.mount &&
/**
* When on the first page (whatever view
* you land on after the root url) it
@ -229,7 +252,10 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
const onStart = async () => {
const { routeInfo } = this.props;
const propsToUse = (this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute) ? this.prevProps.routeInfo : { pathname: routeInfo.pushedByRoute || '' } as any;
const propsToUse =
this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute
? this.prevProps.routeInfo
: ({ pathname: routeInfo.pushedByRoute || '' } as any);
const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);
const leavingViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id, false);
@ -257,7 +283,10 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
*/
const { routeInfo } = this.props;
const propsToUse = (this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute) ? this.prevProps.routeInfo : { pathname: routeInfo.pushedByRoute || '' } as any;
const propsToUse =
this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute
? this.prevProps.routeInfo
: ({ pathname: routeInfo.pushedByRoute || '' } as any);
const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);
const leavingViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id, false);
@ -279,12 +308,12 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
ionPageElement.classList.add('ion-page-hidden');
}
}
}
};
routerOutlet.swipeHandler = {
canStart,
onStart,
onEnd
onEnd,
};
}
@ -333,7 +362,7 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
progressAnimation,
animationBuilder: routeInfo.routeAnimation,
});
}
};
const routerOutlet = this.routerOutletElement!;

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **react:** outlet will not clear in react 18 with hot reload ([#25703](https://github.com/ionic-team/ionic/issues/25703)) ([3878bf7](https://github.com/ionic-team/ionic/commit/3878bf76523f2e1c26c147473fd7c07ee4d0e820)), closes [#25507](https://github.com/ionic-team/ionic/issues/25507)
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)

View File

@ -1,15 +1,15 @@
{
"name": "@ionic/react",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/react",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2",
"tslib": "*"
},
@ -607,9 +607,9 @@
}
},
"node_modules/@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dependencies": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -9522,9 +9522,9 @@
}
},
"@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"requires": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/react",
"version": "6.2.1",
"version": "6.2.2",
"description": "React specific wrapper for @ionic/core",
"keywords": [
"ionic",
@ -41,7 +41,7 @@
"css/"
],
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2",
"tslib": "*"
},

View File

@ -23,8 +23,7 @@ export abstract class ViewStacks {
clear(outletId: string) {
// Give some time for the leaving views to transition before removing
setTimeout(() => {
// console.log('Removing viewstack for outletID ' + outletId);
return setTimeout(() => {
delete this.viewStacks[outletId];
}, 500);
}

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **vue:** go back to correct view with memory history ([#25732](https://github.com/ionic-team/ionic/issues/25732)) ([8327889](https://github.com/ionic-team/ionic/commit/832788971a7098e52812f66563cbc0a63d3e5df7)), closes [#25705](https://github.com/ionic-team/ionic/issues/25705)
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)
**Note:** Version bump only for package @ionic/vue-router

View File

@ -1,15 +1,15 @@
{
"name": "@ionic/vue-router",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/vue-router",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"dependencies": {
"@ionic/vue": "^6.2.1"
"@ionic/vue": "^6.2.2"
},
"devDependencies": {
"@types/jest": "^28.1.1",
@ -578,9 +578,9 @@
"dev": true
},
"node_modules/@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dependencies": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -588,11 +588,11 @@
}
},
"node_modules/@ionic/vue": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-6.2.1.tgz",
"integrity": "sha512-buVKw5ZAeNCBa1PmSZWkUDaNJgRSjp2iBzYH6/8MQC/bniTRb1QV6LebTAw3xt+6QhHqCeiBedZtwYCSlr510Q==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-6.2.2.tgz",
"integrity": "sha512-jxFW/FFCW6PB5daOGrBlHzZiabS+1A2MUExLQmBoVvw8Dt5gypv1J6oMWKqdVlBDOU7wqozkFjqioeK3c5sPSA==",
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2"
}
},
@ -5233,9 +5233,9 @@
"dev": true
},
"@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"requires": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -5243,11 +5243,11 @@
}
},
"@ionic/vue": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-6.2.1.tgz",
"integrity": "sha512-buVKw5ZAeNCBa1PmSZWkUDaNJgRSjp2iBzYH6/8MQC/bniTRb1QV6LebTAw3xt+6QhHqCeiBedZtwYCSlr510Q==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-6.2.2.tgz",
"integrity": "sha512-jxFW/FFCW6PB5daOGrBlHzZiabS+1A2MUExLQmBoVvw8Dt5gypv1J6oMWKqdVlBDOU7wqozkFjqioeK3c5sPSA==",
"requires": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2"
}
},

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/vue-router",
"version": "6.2.1",
"version": "6.2.2",
"description": "Vue Router integration for @ionic/vue",
"scripts": {
"prepublishOnly": "npm run build",
@ -44,7 +44,7 @@
},
"homepage": "https://github.com/ionic-team/ionic#readme",
"dependencies": {
"@ionic/vue": "^6.2.1"
"@ionic/vue": "^6.2.2"
},
"devDependencies": {
"@types/jest": "^28.1.1",

View File

@ -120,7 +120,12 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
* will go back in a linear fashion.
*/
prevInfo.pathname === routeInfo.pushedByRoute &&
routeInfo.tab === '' && prevInfo.tab === ''
/**
* Tab info can be undefined or '' (empty string)
* both are false-y values, so we can just use !.
*/
!routeInfo.tab && !prevInfo.tab
)
) {
router.back();

View File

@ -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.
## [6.2.2](https://github.com/ionic-team/ionic/compare/v6.2.1...v6.2.2) (2022-08-10)
### Bug Fixes
* **vue:** go back to correct view with memory history ([#25732](https://github.com/ionic-team/ionic/issues/25732)) ([8327889](https://github.com/ionic-team/ionic/commit/832788971a7098e52812f66563cbc0a63d3e5df7)), closes [#25705](https://github.com/ionic-team/ionic/issues/25705)
## [6.2.1](https://github.com/ionic-team/ionic/compare/v6.2.0...v6.2.1) (2022-08-03)
**Note:** Version bump only for package @ionic/vue

View File

@ -1,15 +1,15 @@
{
"name": "@ionic/vue",
"version": "6.2.1",
"version": "6.2.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/vue",
"version": "6.2.1",
"version": "6.2.2",
"license": "MIT",
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2"
},
"devDependencies": {
@ -59,9 +59,9 @@
}
},
"node_modules/@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"dependencies": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -768,9 +768,9 @@
}
},
"@ionic/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.1.tgz",
"integrity": "sha512-bWlE2ZMR7tMyqcBhncc21zZPMZfCEoyGQP2bdu/ft1uov0ozw/wfETygd07C+0DOkbU6x1OYncIvo+1bzK4alA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.2.tgz",
"integrity": "sha512-neE+JhtQ7Kb4nGoKR3e55edHQot5BZTw+woV9+pbyCXP1jGeyFeWWPYBYYOkm05TSEkHgh0v6NkV9y31k8GTNw==",
"requires": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/vue",
"version": "6.2.1",
"version": "6.2.2",
"description": "Vue specific wrapper for @ionic/core",
"scripts": {
"prepublishOnly": "npm run build",
@ -61,7 +61,7 @@
"vue-router": "^4.0.16"
},
"dependencies": {
"@ionic/core": "^6.2.1",
"@ionic/core": "^6.2.2",
"ionicons": "^6.0.2"
},
"vetur": {

View File

@ -0,0 +1,76 @@
import { mount } from '@vue/test-utils';
import { createRouter, createMemoryHistory } from '@ionic/vue-router';
import {
IonContent,
IonHeader,
IonToolbar,
IonBackButton,
IonicVue,
IonApp,
IonRouterOutlet,
IonPage,
} from '@ionic/vue';
import { waitForRouter } from './utils';
const App = {
components: { IonApp, IonRouterOutlet },
template: '<ion-app><ion-router-outlet /></ion-app>',
}
describe('createMemoryHistory', () => {
beforeAll(() => {
(HTMLElement.prototype as HTMLIonRouterOutletElement).commit = jest.fn();
});
it('should not error when going back with memory router', async () => {
const PageTemplate = {
template: `
<ion-page>
<ion-header>
<ion-toolbar>
<ion-back-button></ion-back-button>
</ion-toolbar>
</ion-header>
<ion-content></ion-content>
</ion-page>
`,
components: { IonPage, IonContent, IonHeader, IonToolbar, IonBackButton }
}
const router = createRouter({
history: createMemoryHistory(process.env.BASE_URL),
routes: [
{ path: '/', component: PageTemplate },
{ path: '/page2', component: PageTemplate },
{ path: '/page3', component: PageTemplate }
]
});
const push = jest.spyOn(router, 'back')
router.push('/');
await router.isReady();
const wrapper = mount(App, {
global: {
plugins: [router, IonicVue]
}
});
router.push('/page2');
await waitForRouter();
router.push('/page3');
await waitForRouter();
const backButtons = wrapper.findAllComponents(IonBackButton);
const pageTwoButton = backButtons[1];
const pageThreeButton = backButtons[2];
await pageThreeButton.trigger('click');
await waitForRouter();
await pageTwoButton.trigger('click');
await waitForRouter();
expect(push).toHaveBeenCalledTimes(2);
});
})