Compare commits

..

1 Commits

Author SHA1 Message Date
Sean Perkins
395b14317f chore: use dev-build 2023-11-15 12:56:32 -05:00
137 changed files with 1653 additions and 6119 deletions

2
.github/CODEOWNERS vendored
View File

@@ -11,8 +11,6 @@
# In each subsection folders are ordered first by depth, then alphabetically.
# This should make it easy to add new rules without breaking existing ones.
* @ionic-team/framework
# Frameworks
## Angular

View File

@@ -3,32 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)
### Bug Fixes
* **alert:** date inputs render correctly in mobile safari ([#28495](https://github.com/ionic-team/ionic-framework/issues/28495)) ([b833f0e](https://github.com/ionic-team/ionic-framework/commit/b833f0e826ddd261230e2e29b70e2dc884d8cb04)), closes [#28494](https://github.com/ionic-team/ionic-framework/issues/28494)
* **datetime:** allow disabling datetime with prefer-wheel ([#28511](https://github.com/ionic-team/ionic-framework/issues/28511)) ([01130e1](https://github.com/ionic-team/ionic-framework/commit/01130e12e1d73bbf558da9d4dffd7122822ff39c))
## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21)
### Bug Fixes
* **alert:** match MD spec on tablet ([#28501](https://github.com/ionic-team/ionic-framework/issues/28501)) ([6a2be9f](https://github.com/ionic-team/ionic-framework/commit/6a2be9fa3c12a893d98dc139a1575a6e7e3c7c26)), closes [#23977](https://github.com/ionic-team/ionic-framework/issues/23977)
* **angular:** ng add @ionic/angular in standalone projects ([#28523](https://github.com/ionic-team/ionic-framework/issues/28523)) ([c07312e](https://github.com/ionic-team/ionic-framework/commit/c07312e5ed931f6f825ccf083c9dead9fa815843)), closes [#28514](https://github.com/ionic-team/ionic-framework/issues/28514)
* **angular:** overlays are defined when using standalone controllers ([#28560](https://github.com/ionic-team/ionic-framework/issues/28560)) ([9453132](https://github.com/ionic-team/ionic-framework/commit/9453132aa8952b4adfa1326e61138b329e254f76)), closes [#28385](https://github.com/ionic-team/ionic-framework/issues/28385)
* **datetime:** updating value with min scrolls to new value ([#28549](https://github.com/ionic-team/ionic-framework/issues/28549)) ([388d19e](https://github.com/ionic-team/ionic-framework/commit/388d19e04f83f85abd4602adb04cc71ac575764a)), closes [#28548](https://github.com/ionic-team/ionic-framework/issues/28548)
## [7.5.5](https://github.com/ionic-team/ionic-framework/compare/v7.5.4...v7.5.5) (2023-11-15)

View File

@@ -3,30 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)
### Bug Fixes
* **alert:** date inputs render correctly in mobile safari ([#28495](https://github.com/ionic-team/ionic-framework/issues/28495)) ([b833f0e](https://github.com/ionic-team/ionic-framework/commit/b833f0e826ddd261230e2e29b70e2dc884d8cb04)), closes [#28494](https://github.com/ionic-team/ionic-framework/issues/28494)
* **datetime:** allow disabling datetime with prefer-wheel ([#28511](https://github.com/ionic-team/ionic-framework/issues/28511)) ([01130e1](https://github.com/ionic-team/ionic-framework/commit/01130e12e1d73bbf558da9d4dffd7122822ff39c))
## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21)
### Bug Fixes
* **alert:** match MD spec on tablet ([#28501](https://github.com/ionic-team/ionic-framework/issues/28501)) ([6a2be9f](https://github.com/ionic-team/ionic-framework/commit/6a2be9fa3c12a893d98dc139a1575a6e7e3c7c26)), closes [#23977](https://github.com/ionic-team/ionic-framework/issues/23977)
* **datetime:** updating value with min scrolls to new value ([#28549](https://github.com/ionic-team/ionic-framework/issues/28549)) ([388d19e](https://github.com/ionic-team/ionic-framework/commit/388d19e04f83f85abd4602adb04cc71ac575764a)), closes [#28548](https://github.com/ionic-team/ionic-framework/issues/28548)
## [7.5.5](https://github.com/ionic-team/ionic-framework/compare/v7.5.4...v7.5.5) (2023-11-15)

1625
core/package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "7.5.7",
"version": "7.5.5",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -31,7 +31,7 @@
"loader/"
],
"dependencies": {
"@stencil/core": "^4.7.2",
"@stencil/core": "^4.6.0-dev.1698410852.c526078",
"ionicons": "^7.2.1",
"tslib": "^2.1.0"
},
@@ -64,7 +64,6 @@
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"prettier": "^2.6.1",
"puppeteer": "21.1.1",
"rollup": "^2.26.4",
"sass": "^1.33.0",
"serve": "^14.0.1",

View File

@@ -2043,10 +2043,6 @@ export namespace Components {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the picker.
*/
"disabled": boolean;
/**
* A list of options to be displayed in the picker
*/
@@ -6687,10 +6683,6 @@ declare namespace LocalJSX {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the picker.
*/
"disabled"?: boolean;
/**
* A list of options to be displayed in the picker
*/

View File

@@ -1,8 +1,8 @@
import { newSpecPage } from '@stencil/core/testing';
import { AccordionGroup } from '../../accordion-group/accordion-group';
import { Item } from '../../item/item';
import { Accordion } from '../accordion';
import { AccordionGroup } from '../../accordion-group/accordion-group.tsx';
import { Item } from '../../item/item.tsx';
import { Accordion } from '../accordion.tsx';
it('should open correct accordions when accordion group value is set', async () => {
const page = await newSpecPage({
@@ -25,7 +25,7 @@ it('should open correct accordions when accordion group value is set', async ()
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const accordionGroup = page.body.querySelector('ion-accordion-group');
const accordions = accordionGroup.querySelectorAll('ion-accordion');
accordions.forEach((accordion) => {
@@ -61,7 +61,7 @@ it('should open correct accordions when accordion value is set', async () => {
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const accordionGroup = page.body.querySelector('ion-accordion-group');
const accordions = accordionGroup.querySelectorAll('ion-accordion');
accordions.forEach((accordion) => {
@@ -97,7 +97,7 @@ it('should open more than one accordion when multiple="true"', async () => {
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const accordionGroup = page.body.querySelector('ion-accordion-group');
const accordions = accordionGroup.querySelectorAll('ion-accordion');
accordions.forEach((accordion) => {
@@ -133,7 +133,7 @@ it('should render with accordion open', async () => {
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const accordionGroup = page.body.querySelector('ion-accordion-group');
const accordions = accordionGroup.querySelectorAll('ion-accordion');
expect(accordions[0].classList.contains('accordion-collapsed')).toEqual(false);
@@ -162,7 +162,7 @@ it('should accept a string when multiple="true"', async () => {
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const accordionGroup = page.body.querySelector('ion-accordion-group');
const accordions = accordionGroup.querySelectorAll('ion-accordion');
expect(accordions[0].classList.contains('accordion-collapsed')).toEqual(false);
@@ -183,8 +183,8 @@ it('should set default values if not provided', async () => {
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const accordion = accordionGroup.querySelector('ion-accordion')!;
const accordionGroup = page.body.querySelector('ion-accordion-group');
const accordion = accordionGroup.querySelector('ion-accordion');
/**
* ID is determined via an auto incrementing counter

View File

@@ -7,17 +7,10 @@ describe('action sheet: htmlAttributes inheritance', () => {
it('should correctly inherit attributes on host', async () => {
const page = await newSpecPage({
components: [ActionSheet],
template: () => (
<ion-action-sheet
htmlAttributes={{
'data-testid': 'basic-action-sheet',
}}
overlayIndex={1}
></ion-action-sheet>
),
template: () => <ion-action-sheet htmlAttributes={{ 'data-testid': 'basic-action-sheet' }}></ion-action-sheet>,
});
const actionSheet = page.body.querySelector('ion-action-sheet')!;
const actionSheet = page.body.querySelector('ion-action-sheet');
await expect(actionSheet.getAttribute('data-testid')).toBe('basic-action-sheet');
});

View File

@@ -105,17 +105,6 @@
&::-ms-clear {
display: none;
}
&::-webkit-date-and-time-value {
/**
* The -webkit-date-and-time-value pseudo element is used
* to style the date/time input on iOS/Mobile Safari.
* To avoid layout shift between an empty state and a selected state,
* we set the height `18px` to match the native input height for
* date/time inputs on iOS/Mobile Safari.
*/
height: 18px;
}
}

View File

@@ -52,18 +52,9 @@
}
.alert-message {
font-size: $alert-md-message-font-size;
}
max-height: $alert-md-content-max-height;
/**
* MD Alerts on tablets can expand vertically up to
* a total maximum height. We only want to set a max-height
* on mobile phones.
*/
@include mobile-viewport() {
.alert-message {
max-height: $alert-md-content-max-height;
}
font-size: $alert-md-message-font-size;
}
.alert-message:empty {
@@ -111,24 +102,14 @@
.alert-checkbox-group {
position: relative;
max-height: $alert-md-content-max-height;
border-top: $alert-md-list-border-top;
border-bottom: $alert-md-list-border-bottom;
overflow: auto;
}
/**
* MD Alerts on tablets can expand vertically up to
* a total maximum height. We only want to set a max-height
* on mobile phones.
*/
@include mobile-viewport() {
.alert-radio-group,
.alert-checkbox-group {
max-height: $alert-md-content-max-height;
}
}
.alert-tappable {
position: relative;
@@ -301,14 +282,3 @@
.alert-button-inner {
justify-content: $alert-md-button-group-justify-content;
}
/**
* MD alerts should scale up to 560px x 560px
* on tablet dimensions.
*/
@include tablet-viewport() {
:host {
--max-width: #{$alert-md-max-width-tablet};
--max-height: #{$alert-md-max-height-tablet};
}
}

View File

@@ -10,20 +10,6 @@ $alert-md-font-size: dynamic-font(14px) !default;
/// @prop - Max width of the alert
$alert-md-max-width: 280px !default;
/// @prop - Max width of the alert on a tablet
/**
* Large display requirements for MD Alert:
* 1. Maintain a minimum of 48px distance from the leading and
* trailing edges of the screen. (48px * 2 = 96px)
* 2. The width can increase up to 560px.
* 3. The height can increase up to 560px.
* Source: https://m2.material.io/components/dialogs#behavior
*/
$alert-md-max-width-tablet: min(calc(100vw - 96px), 560px) !default;
/// @prop - Max width of the alert on a tablet
$alert-md-max-height-tablet: min(calc(100vh - 96px), 560px) !default;
/// @prop - Border radius of the alert
$alert-md-border-radius: 4px !default;

View File

@@ -84,15 +84,7 @@
font-weight: normal;
}
/**
* Alert has a maximum height in scenarios
* such as the MD alert on tablet devices.
* As a result, we need to make sure the inner
* containers can scroll otherwise content
* may be cut off.
*/
.alert-message,
.alert-input-group {
.alert-message {
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
overflow-y: auto;

View File

@@ -1,7 +1,6 @@
import { newSpecPage } from '@stencil/core/testing';
import { config } from '../../../global/config';
import { Alert } from '../alert';
import { config } from '../../../global/config';
describe('alert: custom html', () => {
it('should not allow for custom html by default', async () => {
@@ -10,7 +9,7 @@ describe('alert: custom html', () => {
html: `<ion-alert message="<button class='custom-html'>Custom Text</button>"></ion-alert>`,
});
const content = page.body.querySelector('.alert-message')!;
const content = page.body.querySelector('.alert-message');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).toBe(null);
});
@@ -22,7 +21,7 @@ describe('alert: custom html', () => {
html: `<ion-alert message="<button class='custom-html'>Custom Text</button>"></ion-alert>`,
});
const content = page.body.querySelector('.alert-message')!;
const content = page.body.querySelector('.alert-message');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null);
});
@@ -34,7 +33,7 @@ describe('alert: custom html', () => {
html: `<ion-alert message="<button class='custom-html'>Custom Text</button>"></ion-alert>`,
});
const content = page.body.querySelector('.alert-message')!;
const content = page.body.querySelector('.alert-message');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).toBe(null);
});

View File

@@ -1,47 +0,0 @@
import { expect } from '@playwright/test';
import { configs, test, Viewports } from '@utils/test/playwright';
/**
* This behavior does not vary across directions.
*/
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('alert: rendering - tablet'), () => {
test.beforeEach(async ({ page }) => {
await page.setViewportSize(Viewports.tablet.portrait);
await page.goto('/src/components/alert/test/basic', config);
});
test('should expand width and height on larger displays with text', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const button = page.locator('#longMessage');
const alert = page.locator('ion-alert');
await button.click();
await ionAlertDidPresent.next();
await expect(alert).toHaveScreenshot(screenshot('alert-tablet-text'));
});
test('should expand width and height on larger displays with checkboxes', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const button = page.locator('#checkbox');
const alert = page.locator('ion-alert');
await button.click();
await ionAlertDidPresent.next();
await expect(alert).toHaveScreenshot(screenshot('alert-tablet-checkboxes'));
});
test('should expand width and height on larger displays with radios', async ({ page }) => {
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const button = page.locator('#radio');
const alert = page.locator('ion-alert');
await button.click();
await ionAlertDidPresent.next();
await expect(alert).toHaveScreenshot(screenshot('alert-tablet-radios'));
});
});
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,7 +1,7 @@
import { newSpecPage } from '@stencil/core/testing';
import { Breadcrumb } from '../../breadcrumb/breadcrumb';
import { Breadcrumbs } from '../breadcrumbs';
import { Breadcrumb } from '../../breadcrumb/breadcrumb.tsx';
import { Breadcrumbs } from '../breadcrumbs.tsx';
it('should correctly provide the collapsed breadcrumbs in the event payload', async () => {
const page = await newSpecPage({
@@ -18,8 +18,8 @@ it('should correctly provide the collapsed breadcrumbs in the event payload', as
});
const onCollapsedClick = jest.fn((ev) => ev);
const breadcrumbs = page.body.querySelector('ion-breadcrumbs')!;
const breadcrumb = page.body.querySelectorAll('ion-breadcrumb')!;
const breadcrumbs = page.body.querySelector('ion-breadcrumbs');
const breadcrumb = page.body.querySelectorAll('ion-breadcrumb');
breadcrumbs.addEventListener('ionCollapsedClick', onCollapsedClick);
@@ -46,8 +46,8 @@ it('should exclude the separator from narrators', async () => {
`,
});
const firstBreadcrumb = page.body.querySelector('ion-breadcrumb:first-of-type')!;
const separator = firstBreadcrumb.shadowRoot!.querySelector('[part="separator"]')!;
const firstBreadcrumb = page.body.querySelector('ion-breadcrumb:first-of-type');
const separator = firstBreadcrumb.shadowRoot.querySelector('[part="separator"]');
expect(separator.getAttribute('aria-hidden')).toBe('true');
});
@@ -62,7 +62,7 @@ it('should have color attribute', async () => {
`,
});
const breadcrumbs = page.body.querySelector('ion-breadcrumbs')!;
const breadcrumbs = page.body.querySelector('ion-breadcrumbs');
expect(breadcrumbs.hasAttribute('color')).toBe(true);
});

View File

@@ -1,5 +1,4 @@
import { newSpecPage } from '@stencil/core/testing';
import { Button } from '../../button';
describe('Button: Hidden Form Button', () => {
@@ -16,7 +15,8 @@ describe('Button: Hidden Form Button', () => {
return page.body.querySelectorAll('form button');
};
const button = page.body.querySelector('ion-button')!;
const form = page.body.querySelectorAll('form');
const button = page.body.querySelector('ion-button');
await page.waitForChanges();

View File

@@ -11,7 +11,7 @@ describe('ion-checkbox: disabled', () => {
`,
});
const checkbox = page.body.querySelector('ion-checkbox')!;
const checkbox = page.body.querySelector('ion-checkbox');
expect(checkbox.checked).toBe(false);

View File

@@ -1132,7 +1132,7 @@ export class Datetime implements ComponentInterface {
* so we need to re-init behavior with the new elements.
*/
componentDidRender() {
const { presentation, prevPresentation, calendarBodyRef, minParts, preferWheel, forceRenderDate } = this;
const { presentation, prevPresentation, calendarBodyRef, minParts, preferWheel } = this;
/**
* TODO(FW-2165)
@@ -1150,20 +1150,7 @@ export class Datetime implements ComponentInterface {
const hasCalendarGrid = !preferWheel && ['date-time', 'time-date', 'date'].includes(presentation);
if (minParts !== undefined && hasCalendarGrid && calendarBodyRef) {
const workingMonth = calendarBodyRef.querySelector('.calendar-month:nth-of-type(1)');
/**
* We need to make sure the datetime is not in the process
* of scrolling to a new datetime value if the value
* is updated programmatically.
* Otherwise, the datetime will appear to not scroll at all because
* we are resetting the scroll position to the center of the view.
* Prior to the datetime's value being updated programmatically,
* the calendarBodyRef is scrolled such that the middle month is centered
* in the view. The below code updates the scroll position so the middle
* month is also centered in the view. Since the scroll position did not change,
* the scroll callback in this file does not fire,
* and the resolveForceDateScrolling promise never resolves.
*/
if (workingMonth && forceRenderDate === undefined) {
if (workingMonth) {
calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
}
}
@@ -1538,7 +1525,7 @@ export class Datetime implements ComponentInterface {
}
private renderCombinedDatePickerColumn() {
const { defaultParts, disabled, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
const { defaultParts, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
const activePart = this.getActivePartsWithFallback();
@@ -1617,7 +1604,6 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
class="date-column"
color={this.color}
disabled={disabled}
items={items}
value={todayString}
onIonChange={(ev: CustomEvent) => {
@@ -1729,7 +1715,7 @@ export class Datetime implements ComponentInterface {
return [];
}
const { disabled, workingParts } = this;
const { workingParts } = this;
const activePart = this.getActivePartsWithFallback();
@@ -1737,7 +1723,6 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
class="day-column"
color={this.color}
disabled={disabled}
items={days}
value={(workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined}
onIonChange={(ev: CustomEvent) => {
@@ -1774,7 +1759,7 @@ export class Datetime implements ComponentInterface {
return [];
}
const { disabled, workingParts } = this;
const { workingParts } = this;
const activePart = this.getActivePartsWithFallback();
@@ -1782,7 +1767,6 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
class="month-column"
color={this.color}
disabled={disabled}
items={months}
value={workingParts.month}
onIonChange={(ev: CustomEvent) => {
@@ -1818,7 +1802,7 @@ export class Datetime implements ComponentInterface {
return [];
}
const { disabled, workingParts } = this;
const { workingParts } = this;
const activePart = this.getActivePartsWithFallback();
@@ -1826,7 +1810,6 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
class="year-column"
color={this.color}
disabled={disabled}
items={years}
value={workingParts.year}
onIonChange={(ev: CustomEvent) => {
@@ -1892,7 +1875,7 @@ export class Datetime implements ComponentInterface {
}
private renderHourPickerColumn(hoursData: PickerColumnItem[]) {
const { disabled, workingParts } = this;
const { workingParts } = this;
if (hoursData.length === 0) return [];
const activePart = this.getActivePartsWithFallback();
@@ -1900,7 +1883,6 @@ export class Datetime implements ComponentInterface {
return (
<ion-picker-column-internal
color={this.color}
disabled={disabled}
value={activePart.hour}
items={hoursData}
numericInput
@@ -1921,7 +1903,7 @@ export class Datetime implements ComponentInterface {
);
}
private renderMinutePickerColumn(minutesData: PickerColumnItem[]) {
const { disabled, workingParts } = this;
const { workingParts } = this;
if (minutesData.length === 0) return [];
const activePart = this.getActivePartsWithFallback();
@@ -1929,7 +1911,6 @@ export class Datetime implements ComponentInterface {
return (
<ion-picker-column-internal
color={this.color}
disabled={disabled}
value={activePart.minute}
items={minutesData}
numericInput
@@ -1950,7 +1931,7 @@ export class Datetime implements ComponentInterface {
);
}
private renderDayPeriodPickerColumn(dayPeriodData: PickerColumnItem[]) {
const { disabled, workingParts } = this;
const { workingParts } = this;
if (dayPeriodData.length === 0) {
return [];
}
@@ -1962,7 +1943,6 @@ export class Datetime implements ComponentInterface {
<ion-picker-column-internal
style={isDayPeriodRTL ? { order: '-1' } : {}}
color={this.color}
disabled={disabled}
value={activePart.ampm}
items={dayPeriodData}
onIonChange={(ev: CustomEvent) => {

View File

@@ -1,22 +1,21 @@
import type { DatetimeParts } from '../datetime-interface';
import { isSameDay, isBefore, isAfter } from '../utils/comparison';
describe('isSameDay()', () => {
it('should return correct results for month, day, and year', () => {
const reference: DatetimeParts = { month: 1, day: 1, year: 2021 };
const reference = { month: 1, day: 1, year: 2021 };
expect(isSameDay(reference, { month: 1, day: 1, year: 2021 })).toEqual(true);
expect(isSameDay(reference, { month: 2, day: 1, year: 2021 })).toEqual(false);
expect(isSameDay(reference, { month: 1, day: 2, year: 2021 })).toEqual(false);
expect(isSameDay(reference, { month: 1, day: 1, year: 2022 })).toEqual(false);
expect(isSameDay(reference, { month: 0, day: 0, year: 0 })).toEqual(false);
expect(isSameDay(reference, { month: null, day: null, year: null } as any)).toEqual(false);
expect(isSameDay(reference, { month: null, day: null, year: null })).toEqual(false);
});
});
describe('isBefore()', () => {
it('should return correct results for month, day, and year', () => {
const reference: DatetimeParts = { month: 1, day: 1, year: 2021 };
const reference = { month: 1, day: 1, year: 2021 };
expect(isBefore(reference, { month: 1, day: 1, year: 2021 })).toEqual(false);
expect(isBefore(reference, { month: 2, day: 1, year: 2021 })).toEqual(true);
@@ -24,13 +23,13 @@ describe('isBefore()', () => {
expect(isBefore(reference, { month: 1, day: 1, year: 2022 })).toEqual(true);
expect(isBefore(reference, { month: 1, day: 1, year: 2020 })).toEqual(false);
expect(isBefore(reference, { month: 0, day: 0, year: 0 })).toEqual(false);
expect(isBefore(reference, { month: null, day: null, year: null } as any)).toEqual(false);
expect(isBefore(reference, { month: null, day: null, year: null })).toEqual(false);
});
});
describe('isAfter()', () => {
it('should return correct results for month, day, and year', () => {
const reference: DatetimeParts = { month: 2, day: 2, year: 2021 };
const reference = { month: 2, day: 2, year: 2021 };
expect(isAfter(reference, { month: 2, day: 2, year: 2021 })).toEqual(false);
expect(isAfter(reference, { month: 2, day: 1, year: 2021 })).toEqual(true);
@@ -43,6 +42,6 @@ describe('isAfter()', () => {
* 2021 > undefined === false
* 2021 > null === true
*/
expect(isAfter(reference, { month: null, day: null, year: null } as any)).toEqual(true);
expect(isAfter(reference, { month: null, day: null, year: null })).toEqual(true);
});
});

View File

@@ -1,4 +1,3 @@
import type { DatetimeParts } from '../datetime-interface';
import {
generateMonths,
getDaysOfWeek,
@@ -365,7 +364,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 19,
minute: 50,
} as unknown as DatetimeParts;
};
const minParts = {
day: undefined,
@@ -373,7 +372,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 19,
minute: 50,
} as unknown as DatetimeParts;
};
const { hours } = generateTime('en-US', refValue, 'h23', minParts);
@@ -388,7 +387,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 20,
minute: 22,
} as unknown as DatetimeParts;
};
const minParts = {
day: undefined,
@@ -396,7 +395,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 19,
minute: 30,
} as unknown as DatetimeParts;
};
const { hours, minutes } = generateTime('en-US', refValue, 'h23', minParts);
@@ -412,7 +411,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 20,
minute: 30,
} as unknown as DatetimeParts;
};
const minParts = {
day: undefined,
@@ -420,7 +419,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 19,
minute: 30,
} as unknown as DatetimeParts;
};
const maxParts = {
day: undefined,
@@ -428,7 +427,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 20,
minute: 40,
} as unknown as DatetimeParts;
};
const { hours } = generateTime('en-US', refValue, 'h23', minParts, maxParts);
@@ -442,7 +441,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 13,
minute: 0,
} as unknown as DatetimeParts;
};
const maxParts = {
day: undefined,
@@ -450,7 +449,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 13,
minute: 2,
} as unknown as DatetimeParts;
};
const { minutes } = generateTime('en-US', refValue, 'h23', undefined, maxParts);
@@ -464,7 +463,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 12,
minute: 0,
} as unknown as DatetimeParts;
};
const maxParts = {
day: undefined,
@@ -472,7 +471,7 @@ describe('generateTime()', () => {
year: undefined,
hour: 13,
minute: 2,
} as unknown as DatetimeParts;
};
const { minutes } = generateTime('en-US', refValue, 'h23', undefined, maxParts);
@@ -483,7 +482,7 @@ describe('generateTime()', () => {
describe('getToday', () => {
beforeAll(() => {
jest.useFakeTimers();
jest.useFakeTimers('modern');
// System time is zero based, 1 = February
jest.setSystemTime(new Date(2022, 1, 21, 18, 30));
});

View File

@@ -1,39 +0,0 @@
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { Datetime } from '../../../datetime/datetime';
import { PickerColumnInternal } from '../../../picker-column-internal/picker-column-internal';
import { PickerInternal } from '../../../picker-internal/picker-internal';
describe('ion-datetime disabled', () => {
beforeEach(() => {
// IntersectionObserver isn't available in test environment
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
global.IntersectionObserver = mockIntersectionObserver;
});
it('picker should be disabled in prefer wheel mode', async () => {
const page = await newSpecPage({
components: [Datetime, PickerColumnInternal, PickerInternal],
template: () => (
<ion-datetime id="inline-datetime-wheel" disabled prefer-wheel value="2022-04-21T00:00:00"></ion-datetime>
),
});
await page.waitForChanges();
const datetime = page.body.querySelector('ion-datetime')!;
const columns = datetime.shadowRoot!.querySelectorAll('ion-picker-column-internal');
await expect(columns.length).toEqual(4);
columns.forEach((column) => {
expect(column.disabled).toBe(true);
});
});
});

View File

@@ -66,11 +66,6 @@
<h2>Inline - No Default Value</h2>
<ion-datetime id="inline-datetime-no-value" disabled></ion-datetime>
</div>
<div class="grid-item">
<h2>Inline - Prefer Wheel</h2>
<ion-datetime id="inline-datetime-wheel" disabled prefer-wheel value="2022-04-21T00:00:00"></ion-datetime>
</div>
</div>
</ion-content>
<script>

View File

@@ -1,4 +1,3 @@
import type { DatetimeParts } from '../datetime-interface';
import {
generateDayAriaLabel,
getMonthAndDay,
@@ -110,7 +109,7 @@ describe('getLocalizedDayPeriod', () => {
describe('getLocalizedTime', () => {
it('should localize the time to PM', () => {
const datetimeParts: DatetimeParts = {
const datetimeParts = {
day: 1,
month: 1,
year: 2022,
@@ -122,7 +121,7 @@ describe('getLocalizedTime', () => {
});
it('should localize the time to AM', () => {
const datetimeParts: DatetimeParts = {
const datetimeParts = {
day: 1,
month: 1,
year: 2022,
@@ -134,7 +133,7 @@ describe('getLocalizedTime', () => {
});
it('should avoid Chromium bug when using 12 hour time in a 24 hour locale', () => {
const datetimeParts: DatetimeParts = {
const datetimeParts = {
day: 1,
month: 1,
year: 2022,
@@ -145,12 +144,12 @@ describe('getLocalizedTime', () => {
expect(getLocalizedTime('en-GB', datetimeParts, 'h12')).toEqual('12:00 am');
});
it('should parse time-only values correctly', () => {
const datetimeParts: Partial<DatetimeParts> = {
const datetimeParts = {
hour: 22,
minute: 40,
};
expect(getLocalizedTime('en-US', datetimeParts as DatetimeParts, 'h12')).toEqual('10:40 PM');
expect(getLocalizedTime('en-US', datetimeParts as DatetimeParts, 'h23')).toEqual('22:40');
expect(getLocalizedTime('en-US', datetimeParts, 'h12')).toEqual('10:40 PM');
expect(getLocalizedTime('en-US', datetimeParts, 'h23')).toEqual('22:40');
});
});

View File

@@ -1,4 +1,3 @@
import type { DatetimeParts } from '../datetime-interface';
import {
getPreviousYear,
getNextYear,
@@ -104,31 +103,31 @@ describe('getInternalHourValue()', () => {
describe('calculateHourFromAMPM()', () => {
it('should correctly convert from AM to PM', () => {
expect(calculateHourFromAMPM({ hour: 12, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(12);
expect(calculateHourFromAMPM({ hour: 1, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(13);
expect(calculateHourFromAMPM({ hour: 2, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(14);
expect(calculateHourFromAMPM({ hour: 3, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(15);
expect(calculateHourFromAMPM({ hour: 4, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(16);
expect(calculateHourFromAMPM({ hour: 5, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(17);
expect(calculateHourFromAMPM({ hour: 6, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(18);
expect(calculateHourFromAMPM({ hour: 7, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(19);
expect(calculateHourFromAMPM({ hour: 8, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(20);
expect(calculateHourFromAMPM({ hour: 9, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(21);
expect(calculateHourFromAMPM({ hour: 10, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(22);
expect(calculateHourFromAMPM({ hour: 11, ampm: 'am' } as DatetimeParts, 'pm')).toEqual(23);
expect(calculateHourFromAMPM({ hour: 12, ampm: 'am' }, 'pm')).toEqual(12);
expect(calculateHourFromAMPM({ hour: 1, ampm: 'am' }, 'pm')).toEqual(13);
expect(calculateHourFromAMPM({ hour: 2, ampm: 'am' }, 'pm')).toEqual(14);
expect(calculateHourFromAMPM({ hour: 3, ampm: 'am' }, 'pm')).toEqual(15);
expect(calculateHourFromAMPM({ hour: 4, ampm: 'am' }, 'pm')).toEqual(16);
expect(calculateHourFromAMPM({ hour: 5, ampm: 'am' }, 'pm')).toEqual(17);
expect(calculateHourFromAMPM({ hour: 6, ampm: 'am' }, 'pm')).toEqual(18);
expect(calculateHourFromAMPM({ hour: 7, ampm: 'am' }, 'pm')).toEqual(19);
expect(calculateHourFromAMPM({ hour: 8, ampm: 'am' }, 'pm')).toEqual(20);
expect(calculateHourFromAMPM({ hour: 9, ampm: 'am' }, 'pm')).toEqual(21);
expect(calculateHourFromAMPM({ hour: 10, ampm: 'am' }, 'pm')).toEqual(22);
expect(calculateHourFromAMPM({ hour: 11, ampm: 'am' }, 'pm')).toEqual(23);
expect(calculateHourFromAMPM({ hour: 13, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(1);
expect(calculateHourFromAMPM({ hour: 14, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(2);
expect(calculateHourFromAMPM({ hour: 15, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(3);
expect(calculateHourFromAMPM({ hour: 16, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(4);
expect(calculateHourFromAMPM({ hour: 17, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(5);
expect(calculateHourFromAMPM({ hour: 18, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(6);
expect(calculateHourFromAMPM({ hour: 19, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(7);
expect(calculateHourFromAMPM({ hour: 20, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(8);
expect(calculateHourFromAMPM({ hour: 21, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(9);
expect(calculateHourFromAMPM({ hour: 22, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(10);
expect(calculateHourFromAMPM({ hour: 23, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(11);
expect(calculateHourFromAMPM({ hour: 0, ampm: 'pm' } as DatetimeParts, 'am')).toEqual(12);
expect(calculateHourFromAMPM({ hour: 13, ampm: 'pm' }, 'am')).toEqual(1);
expect(calculateHourFromAMPM({ hour: 14, ampm: 'pm' }, 'am')).toEqual(2);
expect(calculateHourFromAMPM({ hour: 15, ampm: 'pm' }, 'am')).toEqual(3);
expect(calculateHourFromAMPM({ hour: 16, ampm: 'pm' }, 'am')).toEqual(4);
expect(calculateHourFromAMPM({ hour: 17, ampm: 'pm' }, 'am')).toEqual(5);
expect(calculateHourFromAMPM({ hour: 18, ampm: 'pm' }, 'am')).toEqual(6);
expect(calculateHourFromAMPM({ hour: 19, ampm: 'pm' }, 'am')).toEqual(7);
expect(calculateHourFromAMPM({ hour: 20, ampm: 'pm' }, 'am')).toEqual(8);
expect(calculateHourFromAMPM({ hour: 21, ampm: 'pm' }, 'am')).toEqual(9);
expect(calculateHourFromAMPM({ hour: 22, ampm: 'pm' }, 'am')).toEqual(10);
expect(calculateHourFromAMPM({ hour: 23, ampm: 'pm' }, 'am')).toEqual(11);
expect(calculateHourFromAMPM({ hour: 0, ampm: 'pm' }, 'am')).toEqual(12);
});
});

View File

@@ -42,8 +42,7 @@ describe('parseDate()', () => {
* See https://github.com/ionic-team/ionic-framework/commit/3fb4caf21ffac12f765c4c80bf1850e05d211c6a
*/
it('should return the correct time zone offset', () => {
// Casting as any since `tzOffset` does not exist on DatetimeParts
expect((parseDate('2022-12-15T13:47:30-02:00') as any)?.tzOffset).toEqual(undefined);
expect(parseDate('2022-12-15T13:47:30-02:00').tzOffset).toEqual(undefined);
});
it('should parse an array of dates', () => {
@@ -163,8 +162,8 @@ describe('parseMinParts()', () => {
minute: 4,
hour: 2,
};
expect(parseMinParts(undefined as any, today)).toEqual(undefined);
expect(parseMinParts(null as any, today)).toEqual(undefined);
expect(parseMinParts(undefined, today)).toEqual(undefined);
expect(parseMinParts(null, today)).toEqual(undefined);
expect(parseMinParts('foo', today)).toEqual(undefined);
});
});
@@ -226,8 +225,8 @@ describe('parseMaxParts()', () => {
minute: 4,
hour: 2,
};
expect(parseMaxParts(undefined as any, today)).toEqual(undefined);
expect(parseMaxParts(null as any, today)).toEqual(undefined);
expect(parseMaxParts(undefined, today)).toEqual(undefined);
expect(parseMaxParts(null, today)).toEqual(undefined);
expect(parseMaxParts('foo', today)).toEqual(undefined);
});
});

View File

@@ -84,13 +84,13 @@ describe('isPrevMonthDisabled()', () => {
// Date month and year is the same as min month and year
expect(isPrevMonthDisabled({ month: 1, year: 2021, day: null }, { month: 1, year: 2021, day: null })).toEqual(true);
// Date year is the same as min year (month not provided)
expect(
isPrevMonthDisabled({ month: 1, year: 2021, day: null }, { year: 2021, month: null, day: null } as any)
).toEqual(true);
expect(isPrevMonthDisabled({ month: 1, year: 2021, day: null }, { year: 2021, month: null, day: null })).toEqual(
true
);
// Date year is less than the min year (month not provided)
expect(
isPrevMonthDisabled({ month: 5, year: 2021, day: null }, { year: 2022, month: null, day: null } as any)
).toEqual(true);
expect(isPrevMonthDisabled({ month: 5, year: 2021, day: null }, { year: 2022, month: null, day: null })).toEqual(
true
);
// Date is above the maximum bounds and the previous month does not does not fall within the
// min-max range.
@@ -118,12 +118,12 @@ describe('isPrevMonthDisabled()', () => {
expect(isPrevMonthDisabled({ month: 12, year: 2021, day: null })).toEqual(false);
// Date year is the same as min year,
// but can navigate to a previous month without reducing the year.
expect(
isPrevMonthDisabled({ month: 12, year: 2021, day: null }, { year: 2021, month: null, day: null } as any)
).toEqual(false);
expect(
isPrevMonthDisabled({ month: 2, year: 2021, day: null }, { year: 2021, month: null, day: null } as any)
).toEqual(false);
expect(isPrevMonthDisabled({ month: 12, year: 2021, day: null }, { year: 2021, month: null, day: null })).toEqual(
false
);
expect(isPrevMonthDisabled({ month: 2, year: 2021, day: null }, { year: 2021, month: null, day: null })).toEqual(
false
);
});
});

View File

@@ -1,7 +1,6 @@
import { newSpecPage } from '@stencil/core/testing';
import { config } from '../../../global/config';
import { InfiniteScrollContent } from '../infinite-scroll-content';
import { config } from '../../../global/config';
describe('infinite-scroll-content: custom html', () => {
it('should not allow for custom html by default', async () => {
@@ -10,7 +9,7 @@ describe('infinite-scroll-content: custom html', () => {
html: `<ion-infinite-scroll-content loading-text="<button class='custom-html'>Custom Text</button>"></ion-infinite-scroll-content>`,
});
const content = page.body.querySelector('.infinite-loading-text')!;
const content = page.body.querySelector('.infinite-loading-text');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).toBe(null);
});
@@ -22,7 +21,7 @@ describe('infinite-scroll-content: custom html', () => {
html: `<ion-infinite-scroll-content loading-text="<button class='custom-html'>Custom Text</button>"></ion-infinite-scroll-content>`,
});
const content = page.body.querySelector('.infinite-loading-text')!;
const content = page.body.querySelector('.infinite-loading-text');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null);
});
@@ -34,7 +33,7 @@ describe('infinite-scroll-content: custom html', () => {
html: `<ion-infinite-scroll-content loading-text="<button class='custom-html'>Custom Text2</button>"></ion-infinite-scroll-content>`,
});
const content = page.body.querySelector('.infinite-loading-text')!;
const content = page.body.querySelector('.infinite-loading-text');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).toBe(null);
});

View File

@@ -1,5 +1,4 @@
import { newSpecPage } from '@stencil/core/testing';
import { Input } from '../input';
describe('input: rendering', () => {
@@ -9,7 +8,7 @@ describe('input: rendering', () => {
html: '<ion-input title="my title" tabindex="-1" data-form-type="password"></ion-input>',
});
const nativeEl = page.body.querySelector('ion-input input')!;
const nativeEl = page.body.querySelector('ion-input input');
expect(nativeEl.getAttribute('title')).toBe('my title');
expect(nativeEl.getAttribute('tabindex')).toBe('-1');
expect(nativeEl.getAttribute('data-form-type')).toBe('password');
@@ -64,9 +63,9 @@ describe('input: label rendering', () => {
`,
});
const input = page.body.querySelector('ion-input')!;
const input = page.body.querySelector('ion-input');
const labelText = input.querySelector('.label-text-wrapper')!;
const labelText = input.querySelector('.label-text-wrapper');
expect(labelText.textContent).toBe('Label Prop Text');
});
@@ -78,9 +77,9 @@ describe('input: label rendering', () => {
`,
});
const input = page.body.querySelector('ion-input')!;
const input = page.body.querySelector('ion-input');
const labelText = input.querySelector('.label-text-wrapper')!;
const labelText = input.querySelector('.label-text-wrapper');
expect(labelText.textContent).toBe('Label Slot Text');
});
@@ -92,9 +91,9 @@ describe('input: label rendering', () => {
`,
});
const input = page.body.querySelector('ion-input')!;
const input = page.body.querySelector('ion-input');
const labelText = input.querySelector('.label-text-wrapper')!;
const labelText = input.querySelector('.label-text-wrapper');
expect(labelText.textContent).toBe('Label Prop Text');
});

View File

@@ -1,7 +1,6 @@
import { newSpecPage } from '@stencil/core/testing';
import { Item } from '../../../item/item';
import { Input } from '../../input';
import { Item } from '../../../item/item';
it('should render as modern when label is set asynchronously', async () => {
const page = await newSpecPage({
@@ -13,7 +12,7 @@ it('should render as modern when label is set asynchronously', async () => {
`,
});
const input = page.body.querySelector('ion-input')!;
const input = page.body.querySelector('ion-input');
// Template should be modern
expect(input.classList.contains('legacy-input')).toBe(false);

View File

@@ -1,10 +1,9 @@
import { Radio } from '../../../radio/radio.tsx';
import { RadioGroup } from '../../../radio-group/radio-group.tsx';
import { Item } from '../../item.tsx';
import { List } from '../../../list/list.tsx';
import { newSpecPage } from '@stencil/core/testing';
import { List } from '../../../list/list';
import { RadioGroup } from '../../../radio-group/radio-group';
import { Radio } from '../../../radio/radio';
import { Item } from '../../item';
describe('ion-item', () => {
it('should not have a role when used without list', async () => {
const page = await newSpecPage({
@@ -12,7 +11,7 @@ describe('ion-item', () => {
html: `<ion-item>Hello World</ion-item>`,
});
const item = page.body.querySelector('ion-item')!;
const item = page.body.querySelector('ion-item');
expect(item.getAttribute('role')).toBe(null);
});
@@ -28,7 +27,7 @@ describe('ion-item', () => {
`,
});
const item = page.body.querySelector('ion-item')!;
const item = page.body.querySelector('ion-item');
expect(item.getAttribute('role')).toBe('listitem');
});
@@ -46,7 +45,7 @@ describe('ion-item', () => {
`,
});
const item = page.body.querySelector('ion-item')!;
const item = page.body.querySelector('ion-item');
expect(item.getAttribute('role')).toBe(null);
});
});

View File

@@ -7,10 +7,10 @@ describe('loading: htmlAttributes inheritance', () => {
it('should correctly inherit attributes on host', async () => {
const page = await newSpecPage({
components: [Loading],
template: () => <ion-loading overlayIndex={1} htmlAttributes={{ 'data-testid': 'basic-loading' }}></ion-loading>,
template: () => <ion-loading htmlAttributes={{ 'data-testid': 'basic-loading' }}></ion-loading>,
});
const loading = page.body.querySelector('ion-loading')!;
const loading = page.body.querySelector('ion-loading');
await expect(loading.getAttribute('data-testid')).toBe('basic-loading');
});

View File

@@ -27,7 +27,7 @@
// iOS Card Modal
// --------------------------------------------------
@include mobile-viewport() {
@media screen and (max-width: 767px) {
@supports (width: max(0px, 1px)) {
:host(.modal-card) {
--height: calc(100% - max(30px, var(--ion-safe-area-top)) - 10px);
@@ -60,7 +60,7 @@
}
}
@include tablet-viewport() {
@media screen and (min-width: 768px) {
:host(.modal-card) {
--width: calc(100% - 120px);
--height: calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));

View File

@@ -15,8 +15,8 @@ describe('modal: a11y', () => {
`,
});
const modal = page.body.querySelector('ion-modal')!;
const modalWrapper = modal.shadowRoot!.querySelector('.modal-wrapper')!;
const modal = page.body.querySelector('ion-modal');
const modalWrapper = modal.shadowRoot.querySelector('.modal-wrapper');
await expect(modalWrapper.getAttribute('role')).toBe('alertdialog');
});

View File

@@ -7,10 +7,10 @@ describe('modal: htmlAttributes inheritance', () => {
it('should correctly inherit attributes on host', async () => {
const page = await newSpecPage({
components: [Modal],
template: () => <ion-modal htmlAttributes={{ 'data-testid': 'basic-modal' }} overlayIndex={1}></ion-modal>,
template: () => <ion-modal htmlAttributes={{ 'data-testid': 'basic-modal' }}></ion-modal>,
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await expect(modal.getAttribute('data-testid')).toBe('basic-modal');
});

View File

@@ -1,18 +1,19 @@
import { h, setMode } from '@stencil/core';
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { setMode } from '@stencil/core';
import { Content } from '../../../content/content';
import { Modal } from '../../modal';
import { Content } from '../../../content/content';
describe('modal: canDismiss', () => {
describe('modal: regular modal', () => {
it('should dismiss when canDismiss is true', async () => {
const page = await newSpecPage({
components: [Modal],
template: () => <ion-modal overlayIndex={1} animated={false} canDismiss={true}></ion-modal>,
template: () => <ion-modal animated={false} canDismiss={true}></ion-modal>,
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -25,10 +26,10 @@ describe('modal: canDismiss', () => {
it('should not dismiss when canDismiss is false', async () => {
const page = await newSpecPage({
components: [Modal],
template: () => <ion-modal overlayIndex={1} animated={false} canDismiss={false}></ion-modal>,
template: () => <ion-modal animated={false} canDismiss={false}></ion-modal>,
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -43,7 +44,6 @@ describe('modal: canDismiss', () => {
components: [Modal],
template: () => (
<ion-modal
overlayIndex={1}
animated={false}
canDismiss={() => {
return new Promise((resolve) => {
@@ -54,7 +54,7 @@ describe('modal: canDismiss', () => {
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -69,7 +69,6 @@ describe('modal: canDismiss', () => {
components: [Modal],
template: () => (
<ion-modal
overlayIndex={1}
animated={false}
canDismiss={() => {
return new Promise((resolve) => {
@@ -80,7 +79,7 @@ describe('modal: canDismiss', () => {
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -95,24 +94,19 @@ describe('modal: canDismiss', () => {
/**
* Card modal is only available on iOS
*/
setMode(() => 'ios');
setMode((elm) => 'ios');
});
it('should dismiss when canDismiss is true', async () => {
const page = await newSpecPage({
components: [Content, Modal],
template: () => (
<ion-modal
overlayIndex={1}
presentingElement={document.createElement('div')}
animated={false}
canDismiss={true}
>
<ion-modal presentingElement={document.createElement('div')} animated={false} canDismiss={true}>
<ion-content>Test Content</ion-content>
</ion-modal>
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -126,18 +120,13 @@ describe('modal: canDismiss', () => {
const page = await newSpecPage({
components: [Content, Modal],
template: () => (
<ion-modal
overlayIndex={1}
presentingElement={document.createElement('div')}
animated={false}
canDismiss={false}
>
<ion-modal presentingElement={document.createElement('div')} animated={false} canDismiss={false}>
<ion-content>Test Content</ion-content>
</ion-modal>
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -152,7 +141,6 @@ describe('modal: canDismiss', () => {
components: [Content, Modal],
template: () => (
<ion-modal
overlayIndex={1}
presentingElement={document.createElement('div')}
animated={false}
canDismiss={() => {
@@ -166,7 +154,7 @@ describe('modal: canDismiss', () => {
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -181,7 +169,6 @@ describe('modal: canDismiss', () => {
components: [Content, Modal],
template: () => (
<ion-modal
overlayIndex={1}
presentingElement={document.createElement('div')}
animated={false}
canDismiss={() => {
@@ -195,7 +182,7 @@ describe('modal: canDismiss', () => {
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -210,17 +197,11 @@ describe('modal: canDismiss', () => {
const page = await newSpecPage({
components: [Modal],
template: () => (
<ion-modal
overlayIndex={1}
breakpoints={[0, 1]}
initialBreakpoint={1}
animated={false}
canDismiss={true}
></ion-modal>
<ion-modal breakpoints={[0, 1]} initialBreakpoint={1} animated={false} canDismiss={true}></ion-modal>
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -234,17 +215,11 @@ describe('modal: canDismiss', () => {
const page = await newSpecPage({
components: [Modal],
template: () => (
<ion-modal
overlayIndex={1}
breakpoints={[0, 1]}
initialBreakpoint={1}
animated={false}
canDismiss={false}
></ion-modal>
<ion-modal breakpoints={[0, 1]} initialBreakpoint={1} animated={false} canDismiss={false}></ion-modal>
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -259,7 +234,6 @@ describe('modal: canDismiss', () => {
components: [Modal],
template: () => (
<ion-modal
overlayIndex={1}
breakpoints={[0, 1]}
initialBreakpoint={1}
animated={false}
@@ -272,7 +246,7 @@ describe('modal: canDismiss', () => {
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -287,7 +261,6 @@ describe('modal: canDismiss', () => {
components: [Modal],
template: () => (
<ion-modal
overlayIndex={1}
breakpoints={[0, 1]}
initialBreakpoint={1}
animated={false}
@@ -300,7 +273,7 @@ describe('modal: canDismiss', () => {
),
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
@@ -315,15 +288,15 @@ describe('modal: canDismiss', () => {
const canDismiss = jest.fn();
const page = await newSpecPage({
components: [Modal],
template: () => <ion-modal overlayIndex={1} animated={false} canDismiss={canDismiss}></ion-modal>,
template: () => <ion-modal animated={false} canDismiss={canDismiss}></ion-modal>,
});
const modal = page.body.querySelector('ion-modal')!;
const modal = page.body.querySelector('ion-modal');
await modal.present();
await page.waitForChanges();
await modal.dismiss('my data', 'my role');
const returnValue = await modal.dismiss('my data', 'my role');
expect(canDismiss).toHaveBeenCalledWith('my data', 'my role');
});

View File

@@ -1,5 +1,6 @@
import { newSpecPage } from '@stencil/core/testing';
import { Config } from '../../../global/config';
import type { ComponentProps } from '../../../interface';
import { Nav } from '../nav';
import type { NavOptions } from '../nav-interface';
@@ -196,6 +197,7 @@ describe('NavController', () => {
.insert(-1, null as any, null, null, trnsDone)
.then(() => {
fail('it should not succeed');
done();
})
.catch((err: Error) => {
const hasCompleted = false;
@@ -250,6 +252,7 @@ describe('NavController', () => {
.pop(null, trnsDone)
.then(() => {
fail('it should not succeed');
done();
})
.catch((err: any) => {
const hasCompleted = false;
@@ -816,10 +819,15 @@ describe('NavController', () => {
beforeEach(async () => {
trnsDone = jest.fn();
const config = new Config();
config.reset({ animated: false });
const page = await newSpecPage({
components: [Nav],
html: `<ion-nav></ion-nav>`,
autoApplyChanges: true,
context: {
config,
},
});
nav = page.rootInstance;
});
@@ -840,7 +848,7 @@ describe('NavController', () => {
pause: jest.fn(),
cancel: jest.fn(),
onfinish: undefined,
} as any;
};
animation.play = () => {
if (animation.onfinish) {

View File

@@ -71,20 +71,13 @@
}
:host .picker-item-empty,
:host .picker-item[disabled] {
:host .picker-item.picker-item-disabled {
scroll-snap-align: none;
cursor: default;
}
:host .picker-item-empty,
:host(:not([disabled])) .picker-item[disabled] {
scroll-snap-align: none;
}
:host([disabled]) {
overflow-y: hidden;
}
:host .picker-item[disabled] {
:host .picker-item.picker-item-disabled {
opacity: 0.4;
}

View File

@@ -35,11 +35,6 @@ export class PickerColumnInternal implements ComponentInterface {
@Element() el!: HTMLIonPickerColumnInternalElement;
/**
* If `true`, the user cannot interact with the picker.
*/
@Prop() disabled = false;
/**
* A list of options to be displayed in the picker
*/
@@ -413,15 +408,13 @@ export class PickerColumnInternal implements ComponentInterface {
};
get activeItem() {
// If the whole picker column is disabled, the current value should appear active
// If the current value item is specifically disabled, it should not appear active
const selector = `.picker-item[data-value="${this.value}"]${this.disabled ? '' : ':not([disabled])'}`;
return getElementRoot(this.el).querySelector(selector) as HTMLElement | null;
return getElementRoot(this.el).querySelector(
`.picker-item[data-value="${this.value}"]:not([disabled])`
) as HTMLElement | null;
}
render() {
const { items, color, disabled: pickerDisabled, isActive, numericInput } = this;
const { items, color, isActive, numericInput } = this;
const mode = getIonMode(this);
/**
@@ -430,12 +423,10 @@ export class PickerColumnInternal implements ComponentInterface {
* the attribute can be moved to datetime.tsx and set on every
* instance of ion-picker-column-internal there instead.
*/
return (
<Host
exportparts={`${PICKER_ITEM_PART}, ${PICKER_ITEM_ACTIVE_PART}`}
disabled={pickerDisabled}
tabindex={pickerDisabled ? null : 0}
tabindex={0}
class={createColorClasses(color, {
[mode]: true,
['picker-column-active']: isActive,
@@ -452,8 +443,6 @@ export class PickerColumnInternal implements ComponentInterface {
&nbsp;
</div>
{items.map((item, index) => {
const isItemDisabled = pickerDisabled || item.disabled || false;
{
/*
Users should be able to tab
@@ -469,13 +458,14 @@ export class PickerColumnInternal implements ComponentInterface {
tabindex="-1"
class={{
'picker-item': true,
'picker-item-disabled': item.disabled || false,
}}
data-value={item.value}
data-index={index}
onClick={(ev: Event) => {
this.centerPickerItemInView(ev.target as HTMLElement, true);
}}
disabled={isItemDisabled}
disabled={item.disabled}
part={PICKER_ITEM_PART}
>
{item.text}

View File

@@ -45,39 +45,26 @@
<ion-content class="ion-padding">
<div class="grid">
<div class="grid-item">
<h2>Even items disabled</h2>
<h2>Default</h2>
<ion-picker-internal>
<ion-picker-column-internal id="half-disabled"></ion-picker-column-internal>
</ion-picker-internal>
</div>
<div class="grid-item">
<h2>Column disabled</h2>
<ion-picker-internal>
<ion-picker-column-internal id="column-disabled" value="11" disabled></ion-picker-column-internal>
<ion-picker-column-internal id="default"></ion-picker-column-internal>
</ion-picker-internal>
</div>
</div>
</ion-content>
<script>
const halfDisabledPicker = document.getElementById('half-disabled');
const halfDisabledItems = Array(24)
const defaultPickerColumn = document.getElementById('default');
const items = Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
disabled: i % 2 === 0,
}));
halfDisabledPicker.items = halfDisabledItems;
halfDisabledPicker.value = 12;
const fullDisabledPicker = document.getElementById('column-disabled');
const items = Array(24)
.fill()
.map((_, i) => ({
text: `${i}`,
value: i,
}));
fullDisabledPicker.items = items;
defaultPickerColumn.items = items;
defaultPickerColumn.value = 12;
</script>
</ion-app>
</body>

View File

@@ -35,7 +35,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('picker-column-internal: disabled items'), () => {
test.describe(title('picker-column-internal: disabled'), () => {
test('all picker items should be enabled by default', async ({ page }) => {
await page.setContent(
`
@@ -55,7 +55,9 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
config
);
const pickerItems = page.locator('ion-picker-column-internal .picker-item:not(.picker-item-empty, [disabled])');
const pickerItems = page.locator(
'ion-picker-column-internal .picker-item:not(.picker-item-empty, .picker-item-disabled)'
);
expect(await pickerItems.count()).toBe(3);
});
@@ -78,7 +80,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
config
);
const disabledItem = page.locator('ion-picker-column-internal .picker-item[disabled]');
const disabledItem = page.locator('ion-picker-column-internal .picker-item.picker-item-disabled');
await expect(disabledItem).not.toBeEnabled();
});
test('disabled picker item should not be considered active', async ({ page }) => {
@@ -128,7 +130,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await page.waitForChanges();
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).toBeDisabled();
await expect(disabledItem).toHaveClass(/picker-item-disabled/);
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
test('defaulting the value to a disabled item should not cause that item to be active', async ({ page }) => {
@@ -152,42 +154,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
);
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).toBeDisabled();
await expect(disabledItem).toHaveClass(/picker-item-disabled/);
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
});
});
/**
* This behavior does not vary across directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('picker-column-internal: disabled column rendering'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/picker-column-internal/test/disabled', config);
});
test('disabled column should not have visual regressions', async ({ page }) => {
const disabledColumn = page.locator('#column-disabled');
await page.waitForChanges();
await expect(disabledColumn).toHaveScreenshot(screenshot('picker-internal-disabled-column'));
});
});
});
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('picker-column-internal: disabled column'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/picker-column-internal/test/disabled', config);
});
test('item in disabled column should not be interactive', async ({ page }) => {
const secondItem = page.locator('#column-disabled .picker-item:not(.picker-item-empty)').nth(1);
await expect(secondItem).toBeDisabled();
});
});
});

View File

@@ -19,7 +19,6 @@ describe('picker-column', () => {
text: 'Java',
},
],
name: 'programmingLanguages',
};
const page = await newSpecPage({
@@ -27,8 +26,8 @@ describe('picker-column', () => {
template: () => <ion-picker-column col={col}></ion-picker-column>,
});
const firstOption = page.body.querySelector('ion-picker-column .picker-opt:nth-child(1)')!;
const secondOption = page.body.querySelector('ion-picker-column .picker-opt:nth-child(2)')!;
const firstOption = page.body.querySelector('ion-picker-column .picker-opt:nth-child(1)');
const secondOption = page.body.querySelector('ion-picker-column .picker-opt:nth-child(2)');
expect(firstOption.getAttribute('aria-label')).toBe('C Sharp');
expect(secondOption.getAttribute('aria-label')).toBe(null);

View File

@@ -15,19 +15,18 @@ describe('picker-column: dynamic options', () => {
const page = await newSpecPage({
components: [PickerColumnCmp],
template: () => <ion-picker-column col={{ options: defaultOptions, name: 'animals' }}></ion-picker-column>,
template: () => <ion-picker-column col={{ options: defaultOptions }}></ion-picker-column>,
});
const pickerCol = page.body.querySelector('ion-picker-column')!;
const pickerCol = page.body.querySelector('ion-picker-column');
pickerCol.col = {
options: [...defaultOptions, { text: 'Carrot', value: 'carrot' }],
name: 'vegetables',
};
await page.waitForChanges();
const pickerOpt = pickerCol.querySelector('.picker-opt:nth(2)')!;
const pickerOpt = pickerCol.querySelector('.picker-opt:nth(2)');
expect(pickerOpt.getAttribute('style')).toContain('transform');
});
});

View File

@@ -5,14 +5,14 @@ import { PickerColumnCmp } from '../picker-column';
describe('picker-column', () => {
it('should add class to host of component', async () => {
const col = { cssClass: 'test-class', options: [], name: 'col' };
const col = { cssClass: 'test-class', options: [] };
const page = await newSpecPage({
components: [PickerColumnCmp],
template: () => <ion-picker-column col={col}></ion-picker-column>,
});
const pickerCol = page.body.querySelector('ion-picker-column')!;
const pickerCol = page.body.querySelector('ion-picker-column');
expect(pickerCol.classList.contains('test-class')).toBe(true);
});
});

View File

@@ -7,10 +7,10 @@ describe('popover: htmlAttributes inheritance', () => {
it('should correctly inherit attributes on host', async () => {
const page = await newSpecPage({
components: [Popover],
template: () => <ion-popover overlayIndex={1} htmlAttributes={{ 'data-testid': 'basic-popover' }}></ion-popover>,
template: () => <ion-popover htmlAttributes={{ 'data-testid': 'basic-popover' }}></ion-popover>,
});
const popover = page.body.querySelector('ion-popover')!;
const popover = page.body.querySelector('ion-popover');
await expect(popover.getAttribute('data-testid')).toBe('basic-popover');
});

View File

@@ -17,20 +17,20 @@ describe('isTriggerElement', () => {
describe('getIndexOfItem', () => {
it('should return the correct index in an array of ion-items', () => {
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']);
expect(getIndexOfItem(array, array[1])).toEqual(1);
});
it('should return -1 when ion-item not found', () => {
const el = document.createElement('ion-item');
const array = createArrayOfElements(['ion-item', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'ion-item']);
expect(getIndexOfItem(array, el)).toEqual(-1);
});
it('should return -1 if a non-ion-item is passed in', () => {
const array = createArrayOfElements(['ion-item', 'div', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'div', 'ion-item']);
expect(getIndexOfItem(array, array[1])).toEqual(-1);
});
@@ -38,24 +38,24 @@ describe('getIndexOfItem', () => {
describe('getNextItem', () => {
it('should get the next item in an array of ion-items', () => {
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']);
expect(getNextItem(array, array[1])).toEqual(array[2]);
});
it('should return undefined if there is no next item', () => {
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']);
expect(getNextItem(array, array[2])).toEqual(undefined);
});
});
describe('getPrevItem', () => {
it('should get the previous item in an array of ion-items', () => {
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']);
expect(getPrevItem(array, array[1])).toEqual(array[0]);
});
it('should return undefined if there is no previous item', () => {
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']) as HTMLIonItemElement[];
const array = createArrayOfElements(['ion-item', 'ion-item', 'ion-item']);
expect(getPrevItem(array, array[0])).toEqual(undefined);
});
});

View File

@@ -1,8 +1,7 @@
import { Radio } from '../radio.tsx';
import { RadioGroup } from '../../radio-group/radio-group.tsx';
import { newSpecPage } from '@stencil/core/testing';
import { RadioGroup } from '../../radio-group/radio-group';
import { Radio } from '../radio';
describe('ion-radio', () => {
it('should set a default value', async () => {
const radio = new Radio();
@@ -22,7 +21,7 @@ describe('ion-radio', () => {
`,
});
const radio = page.body.querySelector('ion-radio')!;
const radio = page.root.querySelector('ion-radio');
expect(radio.classList.contains('radio-checked')).toBe(false);
radio.value = 'a';
@@ -44,8 +43,8 @@ describe('ion-radio: disabled', () => {
`,
});
const radio = page.body.querySelector('ion-radio')!;
const radioGroup = page.body.querySelector('ion-radio-group')!;
const radio = page.body.querySelector('ion-radio');
const radioGroup = page.body.querySelector('ion-radio-group');
expect(radioGroup.value).toBe(undefined);

View File

@@ -1,10 +1,8 @@
import { newSpecPage } from '@stencil/core/testing';
import { Item } from '../../item/item';
import { Range } from '../range';
import { Item } from '../../item/item';
let sharedRange: Range;
let sharedRange;
describe('Range', () => {
beforeEach(() => {
sharedRange = new Range();
@@ -23,8 +21,7 @@ describe('Range', () => {
];
valueTests.forEach((test) => {
// Casting as any since we are accessing a private API on the range component
expect((sharedRange as any).ensureValueInBounds(test[0])).toBe(test[1]);
expect(sharedRange.ensureValueInBounds(test[0])).toBe(test[1]);
});
});
@@ -61,8 +58,7 @@ describe('Range', () => {
];
valueTests.forEach((test) => {
// Casting as any since we are accessing a private API on the range component
expect((sharedRange as any).ensureValueInBounds(test[0])).toEqual(test[1]);
expect(sharedRange.ensureValueInBounds(test[0])).toEqual(test[1]);
});
});
});
@@ -77,7 +73,7 @@ describe('range id', () => {
</ion-range>`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.getAttribute('id')).toBe('my-custom-range');
});
});
@@ -93,7 +89,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(true);
expect(range.classList.contains('range-item-end-adjustment')).toBe(true);
});
@@ -108,7 +104,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(true);
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});
@@ -123,7 +119,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(true);
});
@@ -138,7 +134,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(true);
});
@@ -153,7 +149,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(true);
expect(range.classList.contains('range-item-end-adjustment')).toBe(true);
});
@@ -168,7 +164,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(true);
expect(range.classList.contains('range-item-end-adjustment')).toBe(true);
});
@@ -181,7 +177,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});
@@ -195,7 +191,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});
@@ -210,7 +206,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});
@@ -225,7 +221,7 @@ describe('range: item adjustments', () => {
`,
});
const range = page.body.querySelector('ion-range')!;
const range = page.body.querySelector('ion-range');
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});

View File

@@ -1,7 +1,6 @@
import { newSpecPage } from '@stencil/core/testing';
import { config } from '../../../global/config';
import { RefresherContent } from '../refresher-content';
import { config } from '../../../global/config';
describe('refresher-content: custom html', () => {
it('should not allow for custom html by default', async () => {
@@ -10,11 +9,11 @@ describe('refresher-content: custom html', () => {
html: `<ion-refresher-content pulling-text="<button class='custom-pulling-html'>Custom Pulling Text</button>" refreshing-text="<button class='custom-refreshing-html'>Custom Refreshing Text</button>"></ion-refresher-content>`,
});
const pullingContent = page.body.querySelector('.refresher-pulling-text')!;
const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text')!;
const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).toBe(null);
});
@@ -26,11 +25,11 @@ describe('refresher-content: custom html', () => {
html: `<ion-refresher-content pulling-text="<button class='custom-pulling-html'>Custom Pulling Text</button>" refreshing-text="<button class='custom-refreshing-html'>Custom Refreshing Text</button>"></ion-refresher-content>`,
});
const pullingContent = page.body.querySelector('.refresher-pulling-text')!;
const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).not.toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text')!;
const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).not.toBe(null);
});
@@ -42,11 +41,11 @@ describe('refresher-content: custom html', () => {
html: `<ion-refresher-content pulling-text="<button class='custom-pulling-html'>Custom Pulling Text</button>" refreshing-text="<button class='custom-html'>Custom Refreshing Text</button>"></ion-refresher-content>`,
});
const pullingContent = page.body.querySelector('.refresher-pulling-text')!;
const pullingContent = page.body.querySelector('.refresher-pulling-text');
expect(pullingContent.textContent).toContain('Custom Pulling Text');
expect(pullingContent.querySelector('button.custom-pulling-html')).toBe(null);
const refreshingContent = page.body.querySelector('.refresher-refreshing-text')!;
const refreshingContent = page.body.querySelector('.refresher-refreshing-text');
expect(refreshingContent.textContent).toContain('Custom Refreshing Text');
expect(refreshingContent.querySelector('button.custom-refreshing-html')).toBe(null);
});

View File

@@ -203,17 +203,17 @@ describe('findChainForSegments', () => {
describe('mergeParams', () => {
it('should merge undefined', () => {
expect(mergeParams(undefined, undefined)).toBeUndefined();
expect(mergeParams(null as any, undefined)).toBeUndefined();
expect(mergeParams(undefined, null as any)).toBeUndefined();
expect(mergeParams(null as any, null as any)).toBeUndefined();
expect(mergeParams(null, undefined)).toBeUndefined();
expect(mergeParams(undefined, null)).toBeUndefined();
expect(mergeParams(null, null)).toBeUndefined();
});
it('should merge undefined with params', () => {
const params = { data: '1' };
expect(mergeParams(undefined, params)).toEqual(params);
expect(mergeParams(null as any, params)).toEqual(params);
expect(mergeParams(null, params)).toEqual(params);
expect(mergeParams(params, undefined)).toEqual(params);
expect(mergeParams(params, null as any)).toEqual(params);
expect(mergeParams(params, null)).toEqual(params);
});
it('should merge params with params', () => {
@@ -253,44 +253,36 @@ describe('RouterSegments', () => {
describe('matchesRedirect', () => {
it('should match empty redirect', () => {
expect(matchesRedirect([''], { from: [''], to: { segments: [''] } })).toBeTruthy();
expect(matchesRedirect([''], { from: ['*'], to: { segments: [''] } })).toBeTruthy();
expect(matchesRedirect([''], { from: [''], to: [''] })).toBeTruthy();
expect(matchesRedirect([''], { from: ['*'], to: [''] })).toBeTruthy();
expect(matchesRedirect([''], { from: ['hola'], to: { segments: [] } })).toBeFalsy();
expect(matchesRedirect([''], { from: ['hola', '*'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect([''], { from: ['hola'], to: [''] })).toBeFalsy();
expect(matchesRedirect([''], { from: ['hola', '*'], to: [''] })).toBeFalsy();
});
it('should match simple segment redirect', () => {
expect(matchesRedirect(['workouts'], { from: ['workouts'], to: { segments: [''] } })).toBeTruthy();
expect(matchesRedirect(['workouts'], { from: ['*'], to: { segments: [''] } })).toBeTruthy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts', '*'], to: { segments: [''] } })).toBeTruthy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts', 'hola'], to: { segments: [''] } })).toBeTruthy();
expect(matchesRedirect(['workouts'], { from: ['workouts'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts'], { from: ['*'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts', '*'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts', 'hola'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts'], { from: ['workouts', '*'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts', 'adios'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect(['workouts'], { from: ['workouts', '*'], to: [''] })).toBeFalsy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts'], to: [''] })).toBeFalsy();
expect(matchesRedirect(['workouts', 'hola'], { from: ['workouts', 'adios'], to: [''] })).toBeFalsy();
});
it('should match long route', () => {
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['*'], to: { segments: [''] } })).toBeTruthy();
expect(
matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', '*'], to: { segments: [''] } })
).toBeTruthy();
expect(
matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path', '*'], to: { segments: [''] } })
).toBeTruthy();
expect(
matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path', 'to'], to: { segments: [''] } })
).toBeTruthy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['*'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', '*'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path', '*'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path', 'to'], to: [''] })).toBeTruthy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['login'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['login', '*'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts'], to: { segments: [''] } })).toBeFalsy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['login'], to: [''] })).toBeFalsy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['login', '*'], to: [''] })).toBeFalsy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts'], to: [''] })).toBeFalsy();
expect(matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path'], to: [''] })).toBeFalsy();
expect(
matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path'], to: { segments: [''] } })
).toBeFalsy();
expect(
matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path', 'to', '*'], to: { segments: [''] } })
matchesRedirect(['workouts', 'path', 'to'], { from: ['workouts', 'path', 'to', '*'], to: [''] })
).toBeFalsy();
});

View File

@@ -18,21 +18,19 @@ describe('ionic-conference-app', () => {
expect(getRouteIDs('/about', routes)).toEqual(['page-tabs', 'page-about']);
expect(getRouteIDs('/tutorial', routes)).toEqual(['page-tutorial']);
expect(
getRoutePath([{ id: 'PAGE-TABS' }, { id: 'tab-schedule' }, { id: 'page-schedule' }] as RouteID[], routes)
).toEqual('/');
expect(getRoutePath([{ id: 'PAGE-TABS' }, { id: 'tab-schedule' }, { id: 'page-schedule' }], routes)).toEqual('/');
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'TAB-SPEAKER' }] as RouteID[], routes)).toEqual('/speaker');
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'TAB-SPEAKER' }], routes)).toEqual('/speaker');
expect(
getRoutePath([{ id: 'page-tabs' }, { id: 'TAB-SPEAKER' }, { id: 'page-speaker-list' }] as RouteID[], routes)
).toEqual('/speaker');
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'TAB-SPEAKER' }, { id: 'page-speaker-list' }], routes)).toEqual(
'/speaker'
);
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'PAGE-MAP' }] as RouteID[], routes)).toEqual('/map');
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'PAGE-MAP' }], routes)).toEqual('/map');
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'page-about' }] as RouteID[], routes)).toEqual('/about');
expect(getRoutePath([{ id: 'page-tabs' }, { id: 'page-about' }], routes)).toEqual('/about');
expect(getRoutePath([{ id: 'page-tutorial' }] as RouteID[], routes)).toEqual('/tutorial');
expect(getRoutePath([{ id: 'page-tutorial' }], routes)).toEqual('/tutorial');
});
let win: Window;

View File

@@ -9,7 +9,7 @@ describe('searchbar: rendering', () => {
html: '<ion-searchbar name="search"></ion-searchbar>',
});
const nativeEl = page.body.querySelector('ion-searchbar input')!;
const nativeEl = page.body.querySelector('ion-searchbar input');
expect(nativeEl.getAttribute('name')).toBe('search');
});
});

View File

@@ -9,14 +9,14 @@ it('should disable segment buttons added to disabled segment async', async () =>
html: `<ion-segment disabled="true"></ion-segment>`,
});
const segment = page.body.querySelector('ion-segment')!;
const segment = page.body.querySelector('ion-segment');
segment.innerHTML = `
<ion-segment-button>
<ion-label>Segment Button</ion-label>
</ion-segment-button>`;
await page.waitForChanges();
const segmentButton = page.body.querySelector('ion-segment-button')!;
const segmentButton = page.body.querySelector('ion-segment-button');
expect(segmentButton.disabled).toBe(true);
});
@@ -32,7 +32,7 @@ it('should set checked state when value is set asynchronously', async () => {
`,
});
const segmentButton = page.body.querySelector('ion-segment-button')!;
const segmentButton = page.root.querySelector('ion-segment-button');
expect(segmentButton.classList.contains('segment-button-checked')).toBe(false);

View File

@@ -10,9 +10,9 @@ describe('ion-select', () => {
template: () => <ion-select value="my value" name="my name" disabled={true}></ion-select>,
});
const select = page.body.querySelector('ion-select')!;
const select = page.body.querySelector('ion-select');
const hiddenInput = select.querySelector<HTMLInputElement>('input[type="hidden"]')!;
const hiddenInput = select.querySelector('input[type="hidden"]');
expect(hiddenInput).not.toBe(null);
expect(hiddenInput.value).toBe('my value');
@@ -28,10 +28,10 @@ describe('ion-select', () => {
`,
});
const select = page.body.querySelector('ion-select')!;
const select = page.body.querySelector('ion-select');
const propEl = select.shadowRoot!.querySelector('.label-text');
const slotEl = select.shadowRoot!.querySelector('slot[name="label"]');
const propEl = select.shadowRoot.querySelector('.label-text');
const slotEl = select.shadowRoot.querySelector('slot[name="label"]');
expect(propEl).not.toBe(null);
expect(slotEl).toBe(null);
@@ -44,10 +44,10 @@ describe('ion-select', () => {
`,
});
const select = page.body.querySelector('ion-select')!;
const select = page.body.querySelector('ion-select');
const propEl = select.shadowRoot!.querySelector('.label-text');
const slotEl = select.shadowRoot!.querySelector('slot[name="label"]');
const propEl = select.shadowRoot.querySelector('.label-text');
const slotEl = select.shadowRoot.querySelector('slot[name="label"]');
expect(propEl).toBe(null);
expect(slotEl).not.toBe(null);
@@ -60,10 +60,10 @@ describe('ion-select', () => {
`,
});
const select = page.body.querySelector('ion-select')!;
const select = page.body.querySelector('ion-select');
const propEl = select.shadowRoot!.querySelector('.label-text');
const slotEl = select.shadowRoot!.querySelector('slot[name="label"]');
const propEl = select.shadowRoot.querySelector('.label-text');
const slotEl = select.shadowRoot.querySelector('slot[name="label"]');
expect(propEl).not.toBe(null);
expect(slotEl).toBe(null);

View File

@@ -1,5 +1,4 @@
import { newSpecPage } from '@stencil/core/testing';
import { Textarea } from '../textarea';
it('should inherit attributes', async () => {
@@ -8,7 +7,7 @@ it('should inherit attributes', async () => {
html: '<ion-textarea title="my title" tabindex="-1" data-form-type="password"></ion-textarea>',
});
const nativeEl = page.body.querySelector('ion-textarea textarea')!;
const nativeEl = page.body.querySelector('ion-textarea textarea');
expect(nativeEl.getAttribute('title')).toBe('my title');
expect(nativeEl.getAttribute('tabindex')).toBe('-1');
expect(nativeEl.getAttribute('data-form-type')).toBe('password');
@@ -32,9 +31,9 @@ describe('textarea: label rendering', () => {
`,
});
const textarea = page.body.querySelector('ion-textarea')!;
const textarea = page.body.querySelector('ion-textarea');
const labelText = textarea.querySelector('.label-text-wrapper')!;
const labelText = textarea.querySelector('.label-text-wrapper');
expect(labelText.textContent).toBe('Label Prop Text');
});
@@ -46,9 +45,9 @@ describe('textarea: label rendering', () => {
`,
});
const textarea = page.body.querySelector('ion-textarea')!;
const textarea = page.body.querySelector('ion-textarea');
const labelText = textarea.querySelector('.label-text-wrapper')!;
const labelText = textarea.querySelector('.label-text-wrapper');
expect(labelText.textContent).toBe('Label Prop Slot');
});
@@ -60,9 +59,9 @@ describe('textarea: label rendering', () => {
`,
});
const textarea = page.body.querySelector('ion-textarea')!;
const textarea = page.body.querySelector('ion-textarea');
const labelText = textarea.querySelector('.label-text-wrapper')!;
const labelText = textarea.querySelector('.label-text-wrapper');
expect(labelText.textContent).toBe('Label Prop Text');
});

View File

@@ -1,8 +1,8 @@
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { config } from '../../../global/config';
import { Toast } from '../toast';
import { config } from '../../../global/config';
import { toastController } from '../../../utils/overlays';
describe('toast: custom html', () => {
it('should not allow for custom html by default', async () => {
@@ -11,8 +11,8 @@ describe('toast: custom html', () => {
html: `<ion-toast message="<button class='custom-html'>Custom Text</button>"></ion-toast>`,
});
const toast = page.body.querySelector('ion-toast')!;
const content = toast.shadowRoot!.querySelector('.toast-message')!;
const toast = page.body.querySelector('ion-toast');
const content = toast.shadowRoot.querySelector('.toast-message');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).toBe(null);
});
@@ -24,8 +24,8 @@ describe('toast: custom html', () => {
html: `<ion-toast message="<button class='custom-html'>Custom Text</button>"></ion-toast>`,
});
const toast = page.body.querySelector('ion-toast')!;
const content = toast.shadowRoot!.querySelector('.toast-message')!;
const toast = page.body.querySelector('ion-toast');
const content = toast.shadowRoot.querySelector('.toast-message');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).not.toBe(null);
});
@@ -37,8 +37,8 @@ describe('toast: custom html', () => {
html: `<ion-toast message="<button class='custom-html'>Custom Text</button>"></ion-toast>`,
});
const toast = page.body.querySelector('ion-toast')!;
const content = toast.shadowRoot!.querySelector('.toast-message')!;
const toast = page.body.querySelector('ion-toast');
const content = toast.shadowRoot.querySelector('.toast-message');
expect(content.textContent).toContain('Custom Text');
expect(content.querySelector('button.custom-html')).toBe(null);
});
@@ -56,9 +56,9 @@ describe('toast: a11y smoke test', () => {
html: `<ion-toast message="Message" header="Header"></ion-toast>`,
});
const toast = page.body.querySelector('ion-toast')!;
const header = toast.shadowRoot!.querySelector('.toast-header')!;
const message = toast.shadowRoot!.querySelector('.toast-message')!;
const toast = page.body.querySelector('ion-toast');
const header = toast.shadowRoot.querySelector('.toast-header');
const message = toast.shadowRoot.querySelector('.toast-message');
expect(header.getAttribute('aria-hidden')).toBe('true');
expect(message.getAttribute('aria-hidden')).toBe('true');
@@ -74,7 +74,7 @@ describe('toast: a11y smoke test', () => {
`,
});
const toast = page.body.querySelector('ion-toast')!;
const toast = page.body.querySelector('ion-toast');
/**
* Wait for present method to resolve
@@ -83,8 +83,8 @@ describe('toast: a11y smoke test', () => {
await toast.present();
await page.waitForChanges();
const header = toast.shadowRoot!.querySelector('.toast-header')!;
const message = toast.shadowRoot!.querySelector('.toast-message')!;
const header = toast.shadowRoot.querySelector('.toast-header');
const message = toast.shadowRoot.querySelector('.toast-message');
expect(header.getAttribute('aria-hidden')).toBe(null);
expect(message.getAttribute('aria-hidden')).toBe(null);
@@ -98,7 +98,7 @@ describe('toast: duration config', () => {
html: `<ion-toast></ion-toast>`,
});
const toast = page.body.querySelector('ion-toast')!;
const toast = page.body.querySelector('ion-toast');
expect(toast.duration).toBe(0);
});
@@ -111,7 +111,7 @@ describe('toast: duration config', () => {
html: `<ion-toast></ion-toast>`,
});
const toast = page.body.querySelector('ion-toast')!;
const toast = page.body.querySelector('ion-toast');
expect(toast.duration).toBe(5000);
});
@@ -121,10 +121,10 @@ describe('toast: htmlAttributes', () => {
it('should correctly inherit attributes on host', async () => {
const page = await newSpecPage({
components: [Toast],
template: () => <ion-toast overlayIndex={1} htmlAttributes={{ 'data-testid': 'basic-toast' }}></ion-toast>,
template: () => <ion-toast htmlAttributes={{ 'data-testid': 'basic-toast' }}></ion-toast>,
});
const toast = page.body.querySelector('ion-toast')!;
const toast = page.body.querySelector('ion-toast');
await expect(toast.getAttribute('data-testid')).toBe('basic-toast');
});
@@ -134,12 +134,12 @@ describe('toast: button cancel', () => {
it('should render the cancel button with part button-cancel', async () => {
const page = await newSpecPage({
components: [Toast],
template: () => <ion-toast overlayIndex={1} buttons={[{ text: 'Cancel', role: 'cancel' }]}></ion-toast>,
template: () => <ion-toast buttons={[{ text: 'Cancel', role: 'cancel' }]}></ion-toast>,
});
const toast = page.body.querySelector('ion-toast')!;
const toast = page.body.querySelector('ion-toast');
const buttonCancel = toast.shadowRoot!.querySelector('.toast-button-cancel')!;
const buttonCancel = toast?.shadowRoot?.querySelector('.toast-button-cancel');
expect(buttonCancel.getAttribute('part')).toBe('button cancel');
});

View File

@@ -51,7 +51,7 @@ describe('ion-toggle: disabled', () => {
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const toggle = page.body.querySelector('ion-toggle');
expect(toggle.checked).toBe(false);

View File

@@ -1,12 +1,11 @@
import type { IonicConfig } from '../../interface';
import { Config } from '../config';
describe('Config', () => {
it('should get a value from the config', () => {
const config = new Config();
config.reset({ mode: 'ios' } as IonicConfig);
expect(config.get('mode')).toEqual('ios');
expect(config.getBoolean('mode')).toBe(false);
config.reset({ name: 'Doc Brown' });
expect(config.get('name')).toEqual('Doc Brown');
expect(config.getBoolean('name')).toBe(false);
});
it('should get a boolean value', () => {
@@ -19,14 +18,14 @@ describe('Config', () => {
bool4: 'hola',
bool5: 0,
bool6: 1,
} as any);
expect(config.getBoolean('bool0' as any)).toEqual(false);
expect(config.getBoolean('bool1' as any)).toEqual(false);
expect(config.getBoolean('bool2' as any)).toEqual(true);
expect(config.getBoolean('bool3' as any)).toEqual(true);
expect(config.getBoolean('bool4' as any)).toEqual(false);
expect(config.getBoolean('bool5' as any)).toEqual(false);
expect(config.getBoolean('bool6' as any)).toEqual(true);
});
expect(config.getBoolean('bool0')).toEqual(false);
expect(config.getBoolean('bool1')).toEqual(false);
expect(config.getBoolean('bool2')).toEqual(true);
expect(config.getBoolean('bool3')).toEqual(true);
expect(config.getBoolean('bool4')).toEqual(false);
expect(config.getBoolean('bool5')).toEqual(false);
expect(config.getBoolean('bool6')).toEqual(true);
});
it('should get a number value', () => {
@@ -37,12 +36,12 @@ describe('Config', () => {
nu2: '200',
nu3: '2.3',
nu4: -100.2,
} as any);
expect(config.getNumber('nu0' as any)).toEqual(0);
expect(config.getNumber('nu1' as any)).toEqual(-1);
expect(config.getNumber('nu2' as any)).toEqual(200);
expect(config.getNumber('nu3' as any)).toEqual(2.3);
expect(config.getNumber('nu4' as any)).toEqual(-100.2);
});
expect(config.getNumber('nu0')).toEqual(0);
expect(config.getNumber('nu1')).toEqual(-1);
expect(config.getNumber('nu2')).toEqual(200);
expect(config.getNumber('nu3')).toEqual(2.3);
expect(config.getNumber('nu4')).toEqual(-100.2);
});
it('should not get fallback', () => {
@@ -57,29 +56,29 @@ describe('Config', () => {
nu0: '0',
nu1: 0,
nu2: 10,
} as any);
expect(config.get('text0' as any, 'HEY')).toEqual('');
expect(config.get('text1' as any, 'HEY')).toEqual('hola');
});
expect(config.get('text0', 'HEY')).toEqual('');
expect(config.get('text1', 'HEY')).toEqual('hola');
expect(config.getBoolean('bool0' as any, true)).toEqual(false);
expect(config.getBoolean('bool1' as any, true)).toEqual(false);
expect(config.getBoolean('bool0', true)).toEqual(false);
expect(config.getBoolean('bool1', true)).toEqual(false);
expect(config.getNumber('nu0' as any, 100)).toEqual(0);
expect(config.getNumber('nu1' as any, 100)).toEqual(0);
expect(config.getNumber('nu2' as any, 100)).toEqual(10);
expect(config.getNumber('nu0', 100)).toEqual(0);
expect(config.getNumber('nu1', 100)).toEqual(0);
expect(config.getNumber('nu2', 100)).toEqual(10);
});
it('should get fallback', () => {
const config = new Config();
expect(config.get('text0' as any, 'HEY')).toEqual('HEY');
expect(config.getBoolean('bool0' as any, true)).toEqual(true);
expect(config.getNumber('nu0' as any, 100)).toEqual(100);
expect(config.get('text0', 'HEY')).toEqual('HEY');
expect(config.getBoolean('bool0', true)).toEqual(true);
expect(config.getNumber('nu0', 100)).toEqual(100);
});
it('should set value', () => {
const config = new Config();
expect(config.get('text0' as any, 'HEY')).toEqual('HEY');
config.set('text0' as any, 'hola');
expect(config.get('text0' as any, 'HEY')).toEqual('hola');
expect(config.get('text0', 'HEY')).toEqual('HEY');
config.set('text0', 'hola');
expect(config.get('text0', 'HEY')).toEqual('hola');
});
});

View File

@@ -1,38 +1,3 @@
/**
* A heuristic that applies CSS to tablet
* viewports.
*
* Usage:
* @include tablet-viewport() {
* :host {
* background-color: green;
* }
* }
*/
@mixin tablet-viewport() {
@media screen and (min-width: 768px) {
@content;
}
}
/**
* A heuristic that applies CSS to mobile
* viewports (i.e. phones, not tablets).
*
* Usage:
* @include mobile-viewport() {
* :host {
* background-color: blue;
* }
* }
*/
@mixin mobile-viewport() {
@media screen and (max-width: 767px) {
@content;
}
}
@mixin input-cover() {
@include position(0, null, null, 0);
@include margin(0);
@@ -252,7 +217,7 @@
$restSelectors: append($restSelectors, $selector, comma);
}
}
// Supported by Chrome.
@if length($hostContextSelectors) > 0 {
@at-root #{$hostContextSelectors} {

View File

@@ -108,7 +108,7 @@ describe('Animation Class', () => {
animation.play();
animation.progressStart();
animation.progressEnd(1, 0);
animation.progressEnd(1);
expect(animation.isRunning()).toEqual(true);
});
@@ -125,9 +125,9 @@ describe('Animation Class', () => {
await animation.play();
animation.progressStart();
animation.progressEnd(0, 0);
animation.progressEnd(0);
await new Promise<void>((resolve) => {
await new Promise((resolve) => {
animation.onFinish(() => {
expect(animation.isRunning()).toEqual(false);
resolve();
@@ -161,8 +161,8 @@ describe('Animation Class', () => {
const el = document.createElement('p');
animation.addElement(el);
animation.addElement(null as any);
animation.addElement(undefined as any);
animation.addElement(null);
animation.addElement(undefined);
expect(animation.elements.length).toEqual(1);
});
@@ -188,8 +188,8 @@ describe('Animation Class', () => {
});
it('should not error when trying to add null or undefined', () => {
animation.addAnimation(null as any);
animation.addAnimation(undefined as any);
animation.addAnimation(null);
animation.addAnimation(undefined);
expect(animation.childAnimations.length).toEqual(0);
});
@@ -312,7 +312,7 @@ describe('Animation Class', () => {
animation.progressStart(true);
expect(animation.getEasing()).toEqual('linear');
animation.progressEnd(0, 0);
animation.progressEnd();
expect(animation.getEasing()).toEqual('ease-in-out');
});
@@ -428,15 +428,9 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.5), [
0.16,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.97), [
0.56,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.33), [
0.11,
]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.5), [0.16]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.97), [0.56]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.33), [0.11]);
});
it('cubic-bezier(1, 0, 0.68, 0.28)', () => {
@@ -447,15 +441,9 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.08), [
0.6,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.5), [
0.84,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.94), [
0.98,
]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.08), [0.6]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.5), [0.84]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.94), [0.98]);
});
it('cubic-bezier(0.4, 0, 0.6, 1)', () => {
@@ -466,15 +454,9 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.39), [
0.43,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.03), [
0.11,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.89), [
0.78,
]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.39), [0.43]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.03), [0.11]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.89), [0.78]);
});
it('cubic-bezier(0, 0, 0.2, 1)', () => {
@@ -485,15 +467,9 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.95), [
0.71,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.1), [
0.03,
]);
shouldApproximatelyEqual(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 0.7), [
0.35,
]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.95), [0.71]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.1), [0.03]);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 0.7), [0.35]);
});
it('cubic-bezier(0.32, 0.72, 0, 1) (with out of bounds progression)', () => {
@@ -504,8 +480,8 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 1.32)[0]).toBeUndefined();
expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], -0.32)[0]).toBeUndefined();
expect(getTimeGivenProgression(...equation, 1.32)[0]).toBeUndefined();
expect(getTimeGivenProgression(...equation, -0.32)[0]).toBeUndefined();
});
it('cubic-bezier(0.21, 1.71, 0.88, 0.9) (multiple solutions)', () => {
@@ -516,10 +492,7 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
shouldApproximatelyEqual(
getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 1.02),
[0.35, 0.87]
);
shouldApproximatelyEqual(getTimeGivenProgression(...equation, 1.02), [0.35, 0.87]);
});
it('cubic-bezier(0.32, 0.72, 0, 1) (with out of bounds progression)', () => {
@@ -530,8 +503,8 @@ describe('cubic-bezier conversion', () => {
[1, 1],
];
expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], 1.32)).toEqual([]);
expect(getTimeGivenProgression(equation[0], equation[1], equation[2], equation[3], -0.32)).toEqual([]);
expect(getTimeGivenProgression(...equation, 1.32)).toEqual([]);
expect(getTimeGivenProgression(...equation, -0.32)).toEqual([]);
});
});
});

View File

@@ -16,8 +16,8 @@ const mockVisualViewport = (
win: Window,
visualViewport: any = { width: 320, height: 568 },
layoutViewport = { innerWidth: 320, innerHeight: 568 }
) => {
(win as any).visualViewport = {
): any => {
win.visualViewport = {
width: 320,
height: 568,
offsetTop: 0,
@@ -29,32 +29,26 @@ const mockVisualViewport = (
onscroll: undefined,
};
(win as any).visualViewport = Object.assign(win.visualViewport!, visualViewport);
win.visualViewport = Object.assign(win.visualViewport, visualViewport);
win = Object.assign(win, layoutViewport);
const mockDispatchEvent = jest.fn();
win.dispatchEvent = mockDispatchEvent;
win.dispatchEvent = jest.fn();
trackViewportChanges(win);
return {
win,
mockDispatchEvent,
};
return win;
};
const mockCapacitor = (win: Window) => {
(win as any).Capacitor = {
win.Capacitor = {
isPluginAvailable: () => false,
};
};
const resizeVisualViewport = (win: Window, visualViewport: any = {}) => {
(win as any).visualViewport = Object.assign((win as any).visualViewport, visualViewport);
win.visualViewport = Object.assign(win.visualViewport, visualViewport);
if (win.visualViewport!.onresize) {
win.visualViewport!.onresize({} as any);
if (win.visualViewport.onresize) {
win.visualViewport.onresize();
} else {
trackViewportChanges(win);
}
@@ -93,64 +87,62 @@ describe('Keyboard Assist Tests', () => {
describe('setKeyboardOpen()', () => {
it('should dispatch the keyboard open event on the window', () => {
const mockDispatchEvent = jest.fn();
window.dispatchEvent = mockDispatchEvent;
window.dispatchEvent = jest.fn();
setKeyboardOpen(window);
expect(mockDispatchEvent.mock.calls.length).toEqual(1);
expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
expect(window.dispatchEvent.mock.calls.length).toEqual(1);
expect(window.dispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
});
});
describe('setKeyboardClose()', () => {
it('should dispatch the keyboard close event on the window', () => {
const mockDispatchEvent = jest.fn();
window.dispatchEvent = mockDispatchEvent;
window.dispatchEvent = jest.fn();
setKeyboardClose(window);
expect(mockDispatchEvent.mock.calls.length).toEqual(1);
expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_CLOSE);
expect(window.dispatchEvent.mock.calls.length).toEqual(1);
expect(window.dispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_CLOSE);
});
});
describe('keyboardDidOpen()', () => {
beforeEach(() => {
resetKeyboardAssist();
resetKeyboardAssist(window);
mockVisualViewport(window);
});
it('should return true when visual viewport height < layout viewport height and meets or exceeds the keyboard threshold', () => {
resizeVisualViewport(window, { height: 200 });
expect(keyboardDidOpen()).toEqual(true);
expect(keyboardDidOpen(window)).toEqual(true);
});
it('should return true if the layout and visual viewports resize', () => {
resizeLayoutViewport(window, { width: 320, height: 300 });
resizeVisualViewport(window, { width: 320, height: 300 });
expect(keyboardDidOpen()).toEqual(true);
expect(keyboardDidOpen(window)).toEqual(true);
});
it('should return false when visual viewport height < layout viewport heigh but does not meet the keyboard threshold', () => {
resizeVisualViewport(window, { height: 500 });
expect(keyboardDidOpen()).toEqual(false);
expect(keyboardDidOpen(window)).toEqual(false);
});
it('should return false on orientation change', () => {
resizeVisualViewport(window, { width: 320, height: 250 });
resizeVisualViewport(window, { width: 250, height: 320 });
expect(keyboardDidOpen()).toEqual(false);
expect(keyboardDidOpen(window)).toEqual(false);
});
it('should return false when both the visual and layout viewports change', () => {
resizeVisualViewport(window, { width: 250, height: 320 });
resizeVisualViewport(window, { width: 250, height: 320 }, { innerWidth: 250, innerHeight: 320 });
expect(keyboardDidOpen()).toEqual(false);
expect(keyboardDidOpen(window)).toEqual(false);
});
it('should return true when the keyboard shows even if the user is zoomed in', () => {
@@ -160,13 +152,13 @@ describe('Keyboard Assist Tests', () => {
// User taps input and keyboard appears
resizeVisualViewport(window, { width: 160, height: 184, scale: 2 });
expect(keyboardDidOpen()).toEqual(true);
expect(keyboardDidOpen(window)).toEqual(true);
});
});
describe('keyboardDidClose()', () => {
beforeEach(() => {
resetKeyboardAssist();
resetKeyboardAssist(window);
mockVisualViewport(window);
});
@@ -230,66 +222,54 @@ describe('Keyboard Assist Tests', () => {
});
describe('Keyboard Assist Integration', () => {
let mockDispatchEvent: jest.Mock<any, any>;
beforeEach(() => {
resetKeyboardAssist();
mockDispatchEvent = mockVisualViewport(window).mockDispatchEvent;
resetKeyboardAssist(window);
mockVisualViewport(window);
startKeyboardAssist(window);
});
afterEach(() => {
mockDispatchEvent.mockReset();
});
it('should properly set the keyboard to be open', () => {
resizeVisualViewport(window, { width: 320, height: 350 });
expect(mockDispatchEvent.mock.calls.length).toEqual(1);
expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
expect(window.dispatchEvent.mock.calls.length).toEqual(1);
expect(window.dispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
});
it('should properly set the keyboard to be closed', () => {
resizeVisualViewport(window, { width: 320, height: 350 });
resizeVisualViewport(window, { width: 320, height: 568 });
expect(mockDispatchEvent.mock.calls.length).toEqual(2);
expect(mockDispatchEvent.mock.calls[1][0].type).toEqual(KEYBOARD_DID_CLOSE);
expect(window.dispatchEvent.mock.calls.length).toEqual(2);
expect(window.dispatchEvent.mock.calls[1][0].type).toEqual(KEYBOARD_DID_CLOSE);
});
it('should properly set the keyboard to be resized', () => {
resizeVisualViewport(window, { width: 320, height: 350 });
resizeVisualViewport(window, { width: 320, height: 360 });
expect(mockDispatchEvent.mock.calls.length).toEqual(2);
expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
expect(mockDispatchEvent.mock.calls[1][0].type).toEqual(KEYBOARD_DID_OPEN);
expect(window.dispatchEvent.mock.calls.length).toEqual(2);
expect(window.dispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
expect(window.dispatchEvent.mock.calls[1][0].type).toEqual(KEYBOARD_DID_OPEN);
});
it('should not set keyboard open on orientation change', () => {
resizeVisualViewport(window, { width: 568, height: 320 });
expect(mockDispatchEvent.mock.calls.length).toEqual(0);
expect(window.dispatchEvent.mock.calls.length).toEqual(0);
});
});
describe('Keyboard Assist with Capacitor', () => {
let mockDispatchEvent: jest.Mock<any, any>;
beforeEach(() => {
resetKeyboardAssist();
resetKeyboardAssist(window);
mockCapacitor(window);
mockDispatchEvent = mockVisualViewport(window).mockDispatchEvent;
mockVisualViewport(window);
startKeyboardAssist(window);
});
afterEach(() => {
mockDispatchEvent.mockReset();
});
it('should attach visual viewport listeners when Capacitor is available but the Keyboard plugin is not', () => {
resizeVisualViewport(window, { width: 320, height: 350 });
expect(mockDispatchEvent.mock.calls.length).toEqual(1);
expect(mockDispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
expect(window.dispatchEvent.mock.calls.length).toEqual(1);
expect(window.dispatchEvent.mock.calls[0][0].type).toEqual(KEYBOARD_DID_OPEN);
});
});

View File

@@ -65,7 +65,7 @@ describe('sanitizeDOMString', () => {
});
const enableSanitizer = (enable = true) => {
(window as any).Ionic = {};
(window as any).Ionic.config = {};
(window as any).Ionic.config.sanitizerEnabled = enable;
window.Ionic = {};
window.Ionic.config = {};
window.Ionic.config.sanitizerEnabled = enable;
};

View File

@@ -1,8 +1,8 @@
import { newSpecPage } from '@stencil/core/testing';
import { Item } from '../../components/item/item';
import { Label } from '../../components/label/label';
import { Toggle } from '../../components/toggle/toggle';
import { Item } from '../../components/item/item.tsx';
import { Label } from '../../components/label/label.tsx';
import { Toggle } from '../../components/toggle/toggle.tsx';
import { getAriaLabel } from '../helpers';
describe('getAriaLabel()', () => {
@@ -17,7 +17,7 @@ describe('getAriaLabel()', () => {
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const toggle = page.body.querySelector('ion-toggle');
const { label, labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
@@ -35,7 +35,7 @@ describe('getAriaLabel()', () => {
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const toggle = page.body.querySelector('ion-toggle');
const { label, labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
@@ -53,7 +53,7 @@ describe('getAriaLabel()', () => {
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const toggle = page.body.querySelector('ion-toggle');
const { labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
@@ -70,7 +70,7 @@ describe('getAriaLabel()', () => {
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const toggle = page.body.querySelector('ion-toggle');
const { labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
@@ -87,7 +87,7 @@ describe('getAriaLabel()', () => {
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const toggle = page.body.querySelector('ion-toggle');
const { labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');

View File

@@ -1,4 +1,3 @@
import type { BackButtonEvent } from '../../../src/interface';
import { startHardwareBackButton } from '../hardware-back-button';
describe('Hardware Back Button', () => {
@@ -6,7 +5,7 @@ describe('Hardware Back Button', () => {
it('should call handler', () => {
const cbSpy = jest.fn();
document.addEventListener('ionBackButton', (ev) => {
(ev as BackButtonEvent).detail.register(0, cbSpy);
ev.detail.register(0, cbSpy);
});
dispatchBackButtonEvent();
@@ -17,8 +16,8 @@ describe('Hardware Back Button', () => {
const cbSpy = jest.fn();
const cbSpyTwo = jest.fn();
document.addEventListener('ionBackButton', (ev) => {
(ev as BackButtonEvent).detail.register(100, cbSpy);
(ev as BackButtonEvent).detail.register(99, cbSpyTwo);
ev.detail.register(100, cbSpy);
ev.detail.register(99, cbSpyTwo);
});
dispatchBackButtonEvent();
@@ -30,8 +29,8 @@ describe('Hardware Back Button', () => {
const cbSpy = jest.fn();
const cbSpyTwo = jest.fn();
document.addEventListener('ionBackButton', (ev) => {
(ev as BackButtonEvent).detail.register(100, cbSpy);
(ev as BackButtonEvent).detail.register(100, cbSpyTwo);
ev.detail.register(100, cbSpy);
ev.detail.register(100, cbSpyTwo);
});
dispatchBackButtonEvent();
@@ -40,13 +39,13 @@ describe('Hardware Back Button', () => {
});
it('should call multiple callbacks', () => {
const cbSpy = (processNextHandler: () => void) => {
const cbSpy = (processNextHandler) => {
processNextHandler();
};
const cbSpyTwo = jest.fn();
document.addEventListener('ionBackButton', (ev) => {
(ev as BackButtonEvent).detail.register(100, cbSpy);
(ev as BackButtonEvent).detail.register(99, cbSpyTwo);
ev.detail.register(100, cbSpy);
ev.detail.register(99, cbSpyTwo);
});
dispatchBackButtonEvent();

View File

@@ -1,8 +1,9 @@
import { newSpecPage } from '@stencil/core/testing';
import { Modal } from '../../../components/modal/modal';
import { Nav } from '../../../components/nav/nav';
import { RouterOutlet } from '../../../components/router-outlet/router-outlet';
import { Modal } from '../../../components/modal/modal';
import { setRootAriaHidden } from '../../overlays';
describe('setRootAriaHidden()', () => {
@@ -14,7 +15,7 @@ describe('setRootAriaHidden()', () => {
`,
});
const routerOutlet = page.body.querySelector('ion-router-outlet')!;
const routerOutlet = page.body.querySelector('ion-router-outlet');
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(false);
@@ -33,7 +34,7 @@ describe('setRootAriaHidden()', () => {
`,
});
const nav = page.body.querySelector('ion-nav')!;
const nav = page.body.querySelector('ion-nav');
expect(nav.hasAttribute('aria-hidden')).toEqual(false);
@@ -53,8 +54,8 @@ describe('setRootAriaHidden()', () => {
`,
});
const containerRoot = page.body.querySelector('#ion-view-container-root')!;
const notContainerRoot = page.body.querySelector('#not-container-root')!;
const containerRoot = page.body.querySelector('#ion-view-container-root');
const notContainerRoot = page.body.querySelector('#not-container-root');
expect(containerRoot.hasAttribute('aria-hidden')).toEqual(false);
expect(notContainerRoot.hasAttribute('aria-hidden')).toEqual(false);
@@ -89,8 +90,8 @@ describe('setRootAriaHidden()', () => {
`,
});
const routerOutlet = page.body.querySelector('ion-router-outlet')!;
const modal = page.body.querySelector('ion-modal')!;
const routerOutlet = page.body.querySelector('ion-router-outlet');
const modal = page.body.querySelector('ion-modal');
await modal.present();
@@ -108,9 +109,9 @@ describe('setRootAriaHidden()', () => {
`,
});
const routerOutlet = page.body.querySelector('ion-router-outlet')!;
const modalOne = page.body.querySelector<HTMLIonModalElement>('ion-modal#one')!;
const modalTwo = page.body.querySelector<HTMLIonModalElement>('ion-modal#two')!;
const routerOutlet = page.body.querySelector('ion-router-outlet');
const modalOne = page.body.querySelector('ion-modal#one');
const modalTwo = page.body.querySelector('ion-modal#two');
await modalOne.present();

View File

@@ -32,9 +32,8 @@ export const setContent = async (page: Page, html: string, testInfo: TestInfo, o
const output = `
<!DOCTYPE html>
<html dir="${direction}" lang="en">
<html dir="${direction}">
<head>
<title>Ionic Playwright Test</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
<link href="${baseUrl}/css/ionic.bundle.css" rel="stylesheet" />

View File

@@ -12,7 +12,7 @@ describe('componentOnReady()', () => {
);
const component = document.createElement('hello-world');
componentOnReady(component, (el: HTMLElement) => {
componentOnReady(component, (el) => {
expect(el).toBe(component);
done();
});
@@ -39,7 +39,7 @@ describe('componentOnReady()', () => {
);
const component = document.createElement('hello-world');
componentOnReady(component, (el: HTMLElement) => {
componentOnReady(component, (el) => {
expect(el).toBe(component);
expect(cb).toHaveBeenCalledTimes(1);
done();

View File

@@ -37,6 +37,9 @@
"src",
],
"exclude": [
"node_modules"
"node_modules",
"**/test/**/*.spec.ts",
"**/test/**/*.spec.tsx",
"**/test/**/e2e.ts"
]
}

View File

@@ -3,22 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)
**Note:** Version bump only for package @ionic/docs
## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21)
**Note:** Version bump only for package @ionic/docs
## [7.5.5](https://github.com/ionic-team/ionic-framework/compare/v7.5.4...v7.5.5) (2023-11-15)
**Note:** Version bump only for package @ionic/docs

View File

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

View File

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

View File

@@ -4,5 +4,5 @@
"docs",
"packages/*"
],
"version": "7.5.7"
"version": "7.5.5"
}

View File

@@ -3,22 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)
**Note:** Version bump only for package @ionic/angular-server
## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21)
**Note:** Version bump only for package @ionic/angular-server
## [7.5.5](https://github.com/ionic-team/ionic-framework/compare/v7.5.4...v7.5.5) (2023-11-15)
**Note:** Version bump only for package @ionic/angular-server

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular-server",
"version": "7.5.7",
"version": "7.5.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular-server",
"version": "7.5.7",
"version": "7.5.5",
"license": "MIT",
"dependencies": {
"@ionic/core": "^7.5.7"
"@ionic/core": "^7.5.5"
},
"devDependencies": {
"@angular-eslint/eslint-plugin": "^14.0.0",
@@ -1060,9 +1060,9 @@
"dev": true
},
"node_modules/@ionic/core": {
"version": "7.5.6",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.6.tgz",
"integrity": "sha512-bYQp2twwm61uA0Q31ToVIpQWsiQ9so1dRoWZPD+l+y4fVuFmOCLYeS6XTLTm73jVBq40JfEcsac7eYC4DxoemQ==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.5.tgz",
"integrity": "sha512-7Rn3OUz8QCob7yMuCLs5dVLpChscNCm+OqH8lqTzy3N/8VSKHLNPHIHTIa4DQm9HwjtpOB+XCTeIqbdWHkLgnA==",
"dependencies": {
"@stencil/core": "^4.7.2",
"ionicons": "^7.2.1",
@@ -7330,9 +7330,9 @@
"dev": true
},
"@ionic/core": {
"version": "7.5.6",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.6.tgz",
"integrity": "sha512-bYQp2twwm61uA0Q31ToVIpQWsiQ9so1dRoWZPD+l+y4fVuFmOCLYeS6XTLTm73jVBq40JfEcsac7eYC4DxoemQ==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.5.tgz",
"integrity": "sha512-7Rn3OUz8QCob7yMuCLs5dVLpChscNCm+OqH8lqTzy3N/8VSKHLNPHIHTIa4DQm9HwjtpOB+XCTeIqbdWHkLgnA==",
"requires": {
"@stencil/core": "^4.7.2",
"ionicons": "^7.2.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular-server",
"version": "7.5.7",
"version": "7.5.5",
"description": "Angular SSR Module for Ionic",
"keywords": [
"ionic",
@@ -62,6 +62,6 @@
},
"prettier": "@ionic/prettier-config",
"dependencies": {
"@ionic/core": "^7.5.7"
"@ionic/core": "^7.5.5"
}
}

View File

@@ -3,26 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.5.7](https://github.com/ionic-team/ionic-framework/compare/v7.5.6...v7.5.7) (2023-11-29)
**Note:** Version bump only for package @ionic/angular
## [7.5.6](https://github.com/ionic-team/ionic-framework/compare/v7.5.5...v7.5.6) (2023-11-21)
### Bug Fixes
* **angular:** ng add @ionic/angular in standalone projects ([#28523](https://github.com/ionic-team/ionic-framework/issues/28523)) ([c07312e](https://github.com/ionic-team/ionic-framework/commit/c07312e5ed931f6f825ccf083c9dead9fa815843)), closes [#28514](https://github.com/ionic-team/ionic-framework/issues/28514)
* **angular:** overlays are defined when using standalone controllers ([#28560](https://github.com/ionic-team/ionic-framework/issues/28560)) ([9453132](https://github.com/ionic-team/ionic-framework/commit/9453132aa8952b4adfa1326e61138b329e254f76)), closes [#28385](https://github.com/ionic-team/ionic-framework/issues/28385)
## [7.5.5](https://github.com/ionic-team/ionic-framework/compare/v7.5.4...v7.5.5) (2023-11-15)
**Note:** Version bump only for package @ionic/angular

View File

@@ -1,4 +1,7 @@
export { AlertController } from './providers/alert-controller';
export { LoadingController } from './providers/loading-controller';
export { MenuController } from './providers/menu-controller';
export { PickerController } from './providers/picker-controller';
export { DomController } from './providers/dom-controller';
export { NavController } from './providers/nav-controller';

View File

@@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { OverlayBaseController } from '@ionic/angular/common';
import type { AlertOptions } from '@ionic/core/components';
import { alertController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-alert.js';
import { OverlayBaseController } from '../utils/overlay';
@Injectable({
providedIn: 'root',
@@ -10,6 +10,5 @@ import { defineCustomElement } from '@ionic/core/components/ion-alert.js';
export class AlertController extends OverlayBaseController<AlertOptions, HTMLIonAlertElement> {
constructor() {
super(alertController);
defineCustomElement();
}
}

View File

@@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { OverlayBaseController } from '@ionic/angular/common';
import type { LoadingOptions } from '@ionic/core/components';
import { loadingController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-loading.js';
import { OverlayBaseController } from '../utils/overlay';
@Injectable({
providedIn: 'root',
@@ -10,6 +10,5 @@ import { defineCustomElement } from '@ionic/core/components/ion-loading.js';
export class LoadingController extends OverlayBaseController<LoadingOptions, HTMLIonLoadingElement> {
constructor() {
super(loadingController);
defineCustomElement();
}
}

View File

@@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { OverlayBaseController } from '@ionic/angular/common';
import type { PickerOptions } from '@ionic/core/components';
import { pickerController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-picker.js';
import { OverlayBaseController } from '../utils/overlay';
@Injectable({
providedIn: 'root',
@@ -10,6 +10,5 @@ import { defineCustomElement } from '@ionic/core/components/ion-picker.js';
export class PickerController extends OverlayBaseController<PickerOptions, HTMLIonPickerElement> {
constructor() {
super(pickerController);
defineCustomElement();
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "7.5.7",
"version": "7.5.5",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@@ -48,7 +48,7 @@
}
},
"dependencies": {
"@ionic/core": "^7.5.7",
"@ionic/core": "^7.5.5",
"ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0",
"tslib": "^2.3.0"
@@ -61,12 +61,11 @@
"zone.js": ">=0.11.0"
},
"devDependencies": {
"@angular-devkit/core": "^17.0.0",
"@angular-devkit/schematics": "^17.0.0",
"@angular-devkit/core": "^14.0.0",
"@angular-devkit/schematics": "^14.0.0",
"@angular-eslint/eslint-plugin": "^14.0.0",
"@angular-eslint/eslint-plugin-template": "^14.0.0",
"@angular-eslint/template-parser": "^14.0.0",
"@angular/cli": "^14.0.0",
"@angular/common": "^14.0.0",
"@angular/compiler": "^14.0.0",
"@angular/compiler-cli": "^14.0.0",
@@ -77,7 +76,7 @@
"@angular/router": "^14.0.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@schematics/angular": "^17.0.0",
"@schematics/angular": "^14.0.0",
"@types/node": "12.12.5",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",

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