@ionic/core 7.5.6-dev.11700168085.18cb70d3 → 7.5.6-dev.11700492285.1581ed02
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ion-datetime.js +2 -2
- package/dist/cjs/ion-datetime_3.cjs.entry.js +2 -2
- package/dist/collection/collection-manifest.json +4 -4
- package/dist/collection/components/accordion/test/accordion.spec.js +195 -0
- package/dist/collection/components/action-sheet/test/action-sheet-id.spec.js +32 -0
- package/dist/collection/components/action-sheet/test/basic/action-sheet.spec.js +18 -0
- package/dist/collection/components/alert/test/alert-id.spec.js +32 -0
- package/dist/collection/components/alert/test/alert.spec.js +37 -0
- package/dist/collection/components/back-button/test/back-button.spec.js +86 -0
- package/dist/collection/components/breadcrumb/test/aria.spec.js +22 -0
- package/dist/collection/components/breadcrumbs/test/breadcrumbs.spec.js +58 -0
- package/dist/collection/components/button/test/form-reference/button.spec.js +26 -0
- package/dist/collection/components/card/test/aria.spec.js +16 -0
- package/dist/collection/components/checkbox/test/checkbox.spec.js +20 -0
- package/dist/collection/components/datetime/datetime.js +2 -2
- package/dist/collection/components/datetime/test/a11y/datetime.spec.js +43 -0
- package/dist/collection/components/datetime/test/comparison.spec.js +43 -0
- package/dist/collection/components/datetime/test/data.spec.js +456 -0
- package/dist/collection/components/datetime/test/format.spec.js +124 -0
- package/dist/collection/components/datetime/test/helpers.spec.js +72 -0
- package/dist/collection/components/datetime/test/manipulation.spec.js +433 -0
- package/dist/collection/components/datetime/test/parse.spec.js +222 -0
- package/dist/collection/components/datetime/test/state.spec.js +114 -0
- package/dist/collection/components/infinite-scroll-content/test/infinite-scroll-content.spec.js +37 -0
- package/dist/collection/components/input/test/input.spec.js +85 -0
- package/dist/collection/components/input/test/item/input.spec.js +24 -0
- package/dist/collection/components/item/test/a11y/item.spec.js +48 -0
- package/dist/collection/components/loading/test/basic/loading.spec.js +16 -0
- package/dist/collection/components/loading/test/loading-id.spec.js +32 -0
- package/dist/collection/components/loading/test/loading.spec.js +37 -0
- package/dist/collection/components/modal/test/a11y/modal.spec.js +22 -0
- package/dist/collection/components/modal/test/basic/modal.spec.js +16 -0
- package/dist/collection/components/modal/test/can-dismiss/modal.spec.js +191 -0
- package/dist/collection/components/modal/test/modal-id.spec.js +32 -0
- package/dist/collection/components/nav/test/nav-controller.spec.js +749 -0
- package/dist/collection/components/picker/test/picker-id.spec.js +32 -0
- package/dist/collection/components/picker-column/test/picker-column-aria.spec.js +35 -0
- package/dist/collection/components/picker-column/test/picker-column-dynamic.spec.js +29 -0
- package/dist/collection/components/picker-column/test/picker-column.spec.js +17 -0
- package/dist/collection/components/popover/test/basic/popover.spec.js +16 -0
- package/dist/collection/components/popover/test/popover-id.spec.js +32 -0
- package/dist/collection/components/popover/test/util.spec.js +53 -0
- package/dist/collection/components/radio/test/radio.spec.js +46 -0
- package/dist/collection/components/range/test/label/range.spec.js +23 -0
- package/dist/collection/components/range/test/range.spec.js +205 -0
- package/dist/collection/components/refresher-content/test/refresher-content.spec.js +46 -0
- package/dist/collection/components/router/test/matching.spec.js +250 -0
- package/dist/collection/components/router/test/parser.spec.js +133 -0
- package/dist/collection/components/router/test/path.spec.js +218 -0
- package/dist/collection/components/router/test/router.spec.js +55 -0
- package/dist/collection/components/searchbar/test/searchbar.spec.js +15 -0
- package/dist/collection/components/segment/test/segment.spec.js +37 -0
- package/dist/collection/components/select/test/select.spec.js +59 -0
- package/dist/collection/components/textarea/test/textarea.spec.js +59 -0
- package/dist/collection/components/toast/test/toast-id.spec.js +32 -0
- package/dist/collection/components/toast/test/toast.spec.js +120 -0
- package/dist/collection/components/toggle/test/toggle.spec.js +55 -0
- package/dist/collection/global/test/config-controller.spec.js +77 -0
- package/dist/collection/utils/animation/test/animation.spec.js +431 -0
- package/dist/collection/utils/keyboard/test/keyboard-controller.spec.js +21 -0
- package/dist/collection/utils/keyboard/test/keyboard.spec.js +214 -0
- package/dist/collection/utils/sanitization/test/sanitization.spec.js +43 -0
- package/dist/collection/utils/test/aria.spec.js +79 -0
- package/dist/collection/utils/test/attributes.spec.js +53 -0
- package/dist/collection/utils/test/hardware-back-button.spec.js +53 -0
- package/dist/collection/utils/test/overlays/overlays.spec.js +102 -0
- package/dist/collection/utils/test/platform.spec.js +132 -0
- package/dist/collection/utils/test/ready.spec.js +39 -0
- package/dist/collection/utils/test/theme.spec.js +56 -0
- package/dist/docs.json +21 -21
- package/dist/esm/ion-datetime_3.entry.js +2 -2
- package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-40903d34.system.js +1 -1
- package/dist/ionic/p-ad61e508.entry.js +4 -0
- package/dist/ionic/p-d91e93ac.system.entry.js +4 -0
- package/hydrate/index.js +2 -2
- package/package.json +2 -1
- package/dist/ionic/p-b76c6241.system.entry.js +0 -4
- package/dist/ionic/p-b781d6b2.entry.js +0 -4
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { IonicSafeString, sanitizeDOMString } from "..";
|
|
5
|
+
describe('sanitizeDOMString', () => {
|
|
6
|
+
it('disable sanitizer', () => {
|
|
7
|
+
enableSanitizer(false);
|
|
8
|
+
expect(sanitizeDOMString('<img src="x" onerror="alert(document.cookie);">')).toEqual('<img src="x" onerror="alert(document.cookie);">');
|
|
9
|
+
});
|
|
10
|
+
it('bypass sanitizer', () => {
|
|
11
|
+
expect(sanitizeDOMString(new IonicSafeString('<img src="x" onerror="alert(document.cookie);">'))).toEqual('<img src="x" onerror="alert(document.cookie);">');
|
|
12
|
+
});
|
|
13
|
+
it('filter onerror', () => {
|
|
14
|
+
expect(sanitizeDOMString('<img src="x" onerror="alert(document.cookie);">')).toEqual('<img src="x">');
|
|
15
|
+
});
|
|
16
|
+
it('filter onclick', () => {
|
|
17
|
+
expect(sanitizeDOMString('<button id="myButton" name="myButton" onclick="alert(document.cookie);">harmless button</button>')).toEqual('<button id="myButton" name="myButton">harmless button</button>');
|
|
18
|
+
});
|
|
19
|
+
it('filter <a> href JS', () => {
|
|
20
|
+
expect(sanitizeDOMString('<a href="javascript:alert(document.cookie)">harmless link</a>')).toEqual('<a>harmless link</a>');
|
|
21
|
+
expect(sanitizeDOMString('<a href="javascr	ipt:alert(document.cookie)">harmless link</a>')).toEqual('<a>harmless link</a>');
|
|
22
|
+
});
|
|
23
|
+
it('filter <a> href JS + class attribute', () => {
|
|
24
|
+
expect(sanitizeDOMString('<a class="link" href="Javascript:alert(document.cookie)">harmless link</a>')).toEqual('<a class="link">harmless link</a>');
|
|
25
|
+
});
|
|
26
|
+
it('filter <iframe>', () => {
|
|
27
|
+
expect(sanitizeDOMString('<iframe src="javascript:alert(document.cookie)"></iframe>')).toEqual('');
|
|
28
|
+
});
|
|
29
|
+
it('filter href + javascript ', () => {
|
|
30
|
+
expect(sanitizeDOMString('<div><button><a href="javascript:alert(document.cookie)">click me</a></button></div>')).toEqual('<div><button><a>click me</a></button></div>');
|
|
31
|
+
});
|
|
32
|
+
it('filter <object>', () => {
|
|
33
|
+
expect(sanitizeDOMString('<object><img src="x" onerror="alert(document.cookie);"></object>')).toEqual('');
|
|
34
|
+
});
|
|
35
|
+
it('sanitizeDOMString', () => {
|
|
36
|
+
expect(sanitizeDOMString('<ion-item><ion-label>Hello!</ion-label><ion-button onclick="alert(document.cookie);">Click me</ion-button>')).toEqual('<ion-item><ion-label>Hello!</ion-label><ion-button>Click me</ion-button></ion-item>');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
const enableSanitizer = (enable = true) => {
|
|
40
|
+
window.Ionic = {};
|
|
41
|
+
window.Ionic.config = {};
|
|
42
|
+
window.Ionic.config.sanitizerEnabled = enable;
|
|
43
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { newSpecPage } from "@stencil/core/testing";
|
|
5
|
+
import { Item } from "../../components/item/item";
|
|
6
|
+
import { Label } from "../../components/label/label";
|
|
7
|
+
import { Toggle } from "../../components/toggle/toggle";
|
|
8
|
+
import { getAriaLabel } from "../helpers";
|
|
9
|
+
describe('getAriaLabel()', () => {
|
|
10
|
+
it('should correctly link component to label', async () => {
|
|
11
|
+
const page = await newSpecPage({
|
|
12
|
+
components: [Item, Label, Toggle],
|
|
13
|
+
html: `
|
|
14
|
+
<ion-item>
|
|
15
|
+
<ion-label>My Label</ion-label>
|
|
16
|
+
<ion-toggle></ion-toggle>
|
|
17
|
+
</ion-item>
|
|
18
|
+
`,
|
|
19
|
+
});
|
|
20
|
+
const toggle = page.body.querySelector('ion-toggle');
|
|
21
|
+
const { label, labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
|
|
22
|
+
expect(labelText).toEqual('My Label');
|
|
23
|
+
expect(labelId).toEqual('ion-tg-0-lbl');
|
|
24
|
+
expect(label).toEqual(page.body.querySelector('ion-label'));
|
|
25
|
+
});
|
|
26
|
+
it('should correctly link component when using custom label', async () => {
|
|
27
|
+
const page = await newSpecPage({
|
|
28
|
+
components: [Toggle],
|
|
29
|
+
html: `
|
|
30
|
+
<div id="my-label">Hello World</div>
|
|
31
|
+
<ion-toggle legacy="true" aria-labelledby="my-label"></ion-toggle>
|
|
32
|
+
`,
|
|
33
|
+
});
|
|
34
|
+
const toggle = page.body.querySelector('ion-toggle');
|
|
35
|
+
const { label, labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
|
|
36
|
+
expect(labelText).toEqual('Hello World');
|
|
37
|
+
expect(labelId).toEqual('my-label');
|
|
38
|
+
expect(label).toEqual(page.body.querySelector('#my-label'));
|
|
39
|
+
});
|
|
40
|
+
it('should correctly link component when special characters are used', async () => {
|
|
41
|
+
const page = await newSpecPage({
|
|
42
|
+
components: [Toggle],
|
|
43
|
+
html: `
|
|
44
|
+
<div id="id.1">Hello World</div>
|
|
45
|
+
<ion-toggle legacy="true" aria-labelledby="id.1"></ion-toggle>
|
|
46
|
+
`,
|
|
47
|
+
});
|
|
48
|
+
const toggle = page.body.querySelector('ion-toggle');
|
|
49
|
+
const { labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
|
|
50
|
+
expect(labelText).toEqual('Hello World');
|
|
51
|
+
expect(labelId).toEqual('id.1');
|
|
52
|
+
});
|
|
53
|
+
it('should only set the label id if one was not set already', async () => {
|
|
54
|
+
const page = await newSpecPage({
|
|
55
|
+
components: [Toggle],
|
|
56
|
+
html: `
|
|
57
|
+
<label id="my-id" for="id.1">Hello World</label>
|
|
58
|
+
<ion-toggle legacy="true" id="id.1"></ion-toggle>
|
|
59
|
+
`,
|
|
60
|
+
});
|
|
61
|
+
const toggle = page.body.querySelector('ion-toggle');
|
|
62
|
+
const { labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
|
|
63
|
+
expect(labelText).toEqual('Hello World');
|
|
64
|
+
expect(labelId).toEqual('my-id');
|
|
65
|
+
});
|
|
66
|
+
it('should set label id', async () => {
|
|
67
|
+
const page = await newSpecPage({
|
|
68
|
+
components: [Toggle],
|
|
69
|
+
html: `
|
|
70
|
+
<label for="id.1">Hello World</label>
|
|
71
|
+
<ion-toggle legacy="true" id="id.1"></ion-toggle>
|
|
72
|
+
`,
|
|
73
|
+
});
|
|
74
|
+
const toggle = page.body.querySelector('ion-toggle');
|
|
75
|
+
const { labelId, labelText } = getAriaLabel(toggle, 'ion-tg-0');
|
|
76
|
+
expect(labelText).toEqual('Hello World');
|
|
77
|
+
expect(labelId).toEqual('id.1-lbl');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { inheritAttributes, inheritAriaAttributes } from "../helpers";
|
|
5
|
+
describe('inheritAttributes()', () => {
|
|
6
|
+
it('should create an attribute inheritance object', () => {
|
|
7
|
+
const el = document.createElement('div');
|
|
8
|
+
el.setAttribute('tabindex', '20');
|
|
9
|
+
el.setAttribute('title', 'myTitle');
|
|
10
|
+
const attributeObject = inheritAttributes(el, ['tabindex', 'title']);
|
|
11
|
+
expect(attributeObject).toEqual({
|
|
12
|
+
tabindex: '20',
|
|
13
|
+
title: 'myTitle',
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it('should not inherit attributes that are not defined on the element', () => {
|
|
17
|
+
const el = document.createElement('div');
|
|
18
|
+
el.setAttribute('tabindex', '20');
|
|
19
|
+
const attributeObject = inheritAttributes(el, ['tabindex', 'title']);
|
|
20
|
+
expect(attributeObject).toEqual({
|
|
21
|
+
tabindex: '20',
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it('should not inherit attributes that are not defined on the input array', () => {
|
|
25
|
+
const el = document.createElement('div');
|
|
26
|
+
el.setAttribute('tabindex', '20');
|
|
27
|
+
el.setAttribute('title', 'myTitle');
|
|
28
|
+
const attributeObject = inheritAttributes(el, ['title']);
|
|
29
|
+
expect(attributeObject).toEqual({
|
|
30
|
+
title: 'myTitle',
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('inheritAriaAttributes()', () => {
|
|
35
|
+
it('should inherit ARIA attributes defined on the HTML element', () => {
|
|
36
|
+
const el = document.createElement('div');
|
|
37
|
+
el.setAttribute('aria-label', 'myLabel');
|
|
38
|
+
el.setAttribute('aria-describedby', 'myDescription');
|
|
39
|
+
const attributeObject = inheritAriaAttributes(el);
|
|
40
|
+
expect(attributeObject).toEqual({
|
|
41
|
+
'aria-label': 'myLabel',
|
|
42
|
+
'aria-describedby': 'myDescription',
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it('should inherit the role attribute defined on the HTML element', () => {
|
|
46
|
+
const el = document.createElement('div');
|
|
47
|
+
el.setAttribute('role', 'button');
|
|
48
|
+
const attributeObject = inheritAriaAttributes(el);
|
|
49
|
+
expect(attributeObject).toEqual({
|
|
50
|
+
role: 'button',
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { startHardwareBackButton } from "../hardware-back-button";
|
|
5
|
+
describe('Hardware Back Button', () => {
|
|
6
|
+
beforeEach(() => startHardwareBackButton());
|
|
7
|
+
it('should call handler', () => {
|
|
8
|
+
const cbSpy = jest.fn();
|
|
9
|
+
document.addEventListener('ionBackButton', (ev) => {
|
|
10
|
+
ev.detail.register(0, cbSpy);
|
|
11
|
+
});
|
|
12
|
+
dispatchBackButtonEvent();
|
|
13
|
+
expect(cbSpy).toHaveBeenCalled();
|
|
14
|
+
});
|
|
15
|
+
it('should call handlers in order of priority', () => {
|
|
16
|
+
const cbSpy = jest.fn();
|
|
17
|
+
const cbSpyTwo = jest.fn();
|
|
18
|
+
document.addEventListener('ionBackButton', (ev) => {
|
|
19
|
+
ev.detail.register(100, cbSpy);
|
|
20
|
+
ev.detail.register(99, cbSpyTwo);
|
|
21
|
+
});
|
|
22
|
+
dispatchBackButtonEvent();
|
|
23
|
+
expect(cbSpy).toHaveBeenCalled();
|
|
24
|
+
expect(cbSpyTwo).not.toHaveBeenCalled();
|
|
25
|
+
});
|
|
26
|
+
it('should only call last handler to be added for handlers with same priority', () => {
|
|
27
|
+
const cbSpy = jest.fn();
|
|
28
|
+
const cbSpyTwo = jest.fn();
|
|
29
|
+
document.addEventListener('ionBackButton', (ev) => {
|
|
30
|
+
ev.detail.register(100, cbSpy);
|
|
31
|
+
ev.detail.register(100, cbSpyTwo);
|
|
32
|
+
});
|
|
33
|
+
dispatchBackButtonEvent();
|
|
34
|
+
expect(cbSpy).not.toHaveBeenCalled();
|
|
35
|
+
expect(cbSpyTwo).toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
it('should call multiple callbacks', () => {
|
|
38
|
+
const cbSpy = (processNextHandler) => {
|
|
39
|
+
processNextHandler();
|
|
40
|
+
};
|
|
41
|
+
const cbSpyTwo = jest.fn();
|
|
42
|
+
document.addEventListener('ionBackButton', (ev) => {
|
|
43
|
+
ev.detail.register(100, cbSpy);
|
|
44
|
+
ev.detail.register(99, cbSpyTwo);
|
|
45
|
+
});
|
|
46
|
+
dispatchBackButtonEvent();
|
|
47
|
+
expect(cbSpyTwo).toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
const dispatchBackButtonEvent = () => {
|
|
51
|
+
const ev = new Event('backbutton');
|
|
52
|
+
document.dispatchEvent(ev);
|
|
53
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { newSpecPage } from "@stencil/core/testing";
|
|
5
|
+
import { Modal } from "../../../components/modal/modal";
|
|
6
|
+
import { Nav } from "../../../components/nav/nav";
|
|
7
|
+
import { RouterOutlet } from "../../../components/router-outlet/router-outlet";
|
|
8
|
+
import { setRootAriaHidden } from "../../overlays";
|
|
9
|
+
describe('setRootAriaHidden()', () => {
|
|
10
|
+
it('should correctly remove and re-add router outlet from accessibility tree', async () => {
|
|
11
|
+
const page = await newSpecPage({
|
|
12
|
+
components: [RouterOutlet],
|
|
13
|
+
html: `
|
|
14
|
+
<ion-router-outlet></ion-router-outlet>
|
|
15
|
+
`,
|
|
16
|
+
});
|
|
17
|
+
const routerOutlet = page.body.querySelector('ion-router-outlet');
|
|
18
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(false);
|
|
19
|
+
setRootAriaHidden(true);
|
|
20
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(true);
|
|
21
|
+
setRootAriaHidden(false);
|
|
22
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(false);
|
|
23
|
+
});
|
|
24
|
+
it('should correctly remove and re-add nav from accessibility tree', async () => {
|
|
25
|
+
const page = await newSpecPage({
|
|
26
|
+
components: [Nav],
|
|
27
|
+
html: `
|
|
28
|
+
<ion-nav></ion-nav>
|
|
29
|
+
`,
|
|
30
|
+
});
|
|
31
|
+
const nav = page.body.querySelector('ion-nav');
|
|
32
|
+
expect(nav.hasAttribute('aria-hidden')).toEqual(false);
|
|
33
|
+
setRootAriaHidden(true);
|
|
34
|
+
expect(nav.hasAttribute('aria-hidden')).toEqual(true);
|
|
35
|
+
setRootAriaHidden(false);
|
|
36
|
+
expect(nav.hasAttribute('aria-hidden')).toEqual(false);
|
|
37
|
+
});
|
|
38
|
+
it('should correctly remove and re-add custom container from accessibility tree', async () => {
|
|
39
|
+
const page = await newSpecPage({
|
|
40
|
+
components: [],
|
|
41
|
+
html: `
|
|
42
|
+
<div id="ion-view-container-root"></div>
|
|
43
|
+
<div id="not-container-root"></div>
|
|
44
|
+
`,
|
|
45
|
+
});
|
|
46
|
+
const containerRoot = page.body.querySelector('#ion-view-container-root');
|
|
47
|
+
const notContainerRoot = page.body.querySelector('#not-container-root');
|
|
48
|
+
expect(containerRoot.hasAttribute('aria-hidden')).toEqual(false);
|
|
49
|
+
expect(notContainerRoot.hasAttribute('aria-hidden')).toEqual(false);
|
|
50
|
+
setRootAriaHidden(true);
|
|
51
|
+
expect(containerRoot.hasAttribute('aria-hidden')).toEqual(true);
|
|
52
|
+
expect(notContainerRoot.hasAttribute('aria-hidden')).toEqual(false);
|
|
53
|
+
setRootAriaHidden(false);
|
|
54
|
+
expect(containerRoot.hasAttribute('aria-hidden')).toEqual(false);
|
|
55
|
+
expect(notContainerRoot.hasAttribute('aria-hidden')).toEqual(false);
|
|
56
|
+
});
|
|
57
|
+
it('should not error if router outlet was not found', async () => {
|
|
58
|
+
await newSpecPage({
|
|
59
|
+
components: [],
|
|
60
|
+
html: `
|
|
61
|
+
<div></div>
|
|
62
|
+
`,
|
|
63
|
+
});
|
|
64
|
+
setRootAriaHidden(true);
|
|
65
|
+
});
|
|
66
|
+
it('should remove router-outlet from accessibility tree when overlay is presented', async () => {
|
|
67
|
+
const page = await newSpecPage({
|
|
68
|
+
components: [RouterOutlet, Modal],
|
|
69
|
+
html: `
|
|
70
|
+
<ion-router-outlet>
|
|
71
|
+
<ion-modal></ion-modal>
|
|
72
|
+
</ion-router-outlet>
|
|
73
|
+
`,
|
|
74
|
+
});
|
|
75
|
+
const routerOutlet = page.body.querySelector('ion-router-outlet');
|
|
76
|
+
const modal = page.body.querySelector('ion-modal');
|
|
77
|
+
await modal.present();
|
|
78
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(true);
|
|
79
|
+
});
|
|
80
|
+
it('should add router-outlet from accessibility tree when then final overlay is dismissed', async () => {
|
|
81
|
+
const page = await newSpecPage({
|
|
82
|
+
components: [RouterOutlet, Modal],
|
|
83
|
+
html: `
|
|
84
|
+
<ion-router-outlet>
|
|
85
|
+
<ion-modal id="one"></ion-modal>
|
|
86
|
+
<ion-modal id="two"></ion-modal>
|
|
87
|
+
</ion-router-outlet>
|
|
88
|
+
`,
|
|
89
|
+
});
|
|
90
|
+
const routerOutlet = page.body.querySelector('ion-router-outlet');
|
|
91
|
+
const modalOne = page.body.querySelector('ion-modal#one');
|
|
92
|
+
const modalTwo = page.body.querySelector('ion-modal#two');
|
|
93
|
+
await modalOne.present();
|
|
94
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(true);
|
|
95
|
+
await modalTwo.present();
|
|
96
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(true);
|
|
97
|
+
await modalOne.dismiss();
|
|
98
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(true);
|
|
99
|
+
await modalTwo.dismiss();
|
|
100
|
+
expect(routerOutlet.hasAttribute('aria-hidden')).toEqual(false);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import initialize from "../../global/ionic-global";
|
|
5
|
+
import { testUserAgent, getPlatforms, isPlatform } from "../platform";
|
|
6
|
+
import { PlatformConfiguration, configureBrowser } from "./platform.utils";
|
|
7
|
+
describe('Platform Tests', () => {
|
|
8
|
+
describe('testUserAgent()', () => {
|
|
9
|
+
it('should return true when testing if user agent is an iPhone', () => {
|
|
10
|
+
const win = configureBrowser(PlatformConfiguration.iPhone);
|
|
11
|
+
expect(testUserAgent(win, /iPhone/)).toEqual(true);
|
|
12
|
+
});
|
|
13
|
+
it('should return false when testing if user agent is an iPad', () => {
|
|
14
|
+
const win = configureBrowser(PlatformConfiguration.iPhone);
|
|
15
|
+
expect(testUserAgent(win, /iPad/)).toEqual(false);
|
|
16
|
+
});
|
|
17
|
+
it('should return false when testing if user agent is an Android', () => {
|
|
18
|
+
const win = configureBrowser(PlatformConfiguration.iPhone);
|
|
19
|
+
expect(testUserAgent(win, /android|sink/i)).toEqual(false);
|
|
20
|
+
});
|
|
21
|
+
it('should return true when testing if user agent is an Android', () => {
|
|
22
|
+
const win = configureBrowser(PlatformConfiguration.AndroidTablet);
|
|
23
|
+
expect(testUserAgent(win, /android|sink/i)).toEqual(true);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('getPlatforms()', () => {
|
|
27
|
+
it('should contain "desktop" platform', () => {
|
|
28
|
+
const win = configureBrowser(PlatformConfiguration.DesktopSafari);
|
|
29
|
+
expect(getPlatforms(win)).toContain('desktop');
|
|
30
|
+
});
|
|
31
|
+
it('should contain "android" and "tablet" platforms', () => {
|
|
32
|
+
const win = configureBrowser(PlatformConfiguration.AndroidTablet);
|
|
33
|
+
const platforms = getPlatforms(win);
|
|
34
|
+
expect(platforms).toContain('android');
|
|
35
|
+
expect(platforms).toContain('tablet');
|
|
36
|
+
});
|
|
37
|
+
it('should contain "capacitor" platform', () => {
|
|
38
|
+
const win = configureBrowser(PlatformConfiguration.Capacitor);
|
|
39
|
+
expect(getPlatforms(win)).toContain('capacitor');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('isPlatform()', () => {
|
|
43
|
+
it('should return true for "capacitor" and "hybrid" in a Capacitor app', () => {
|
|
44
|
+
const win = configureBrowser(PlatformConfiguration.Capacitor);
|
|
45
|
+
expect(isPlatform(win, 'capacitor')).toEqual(true);
|
|
46
|
+
expect(isPlatform(win, 'hybrid')).toEqual(true);
|
|
47
|
+
});
|
|
48
|
+
it('should work without win parameter', () => {
|
|
49
|
+
global.window = configureBrowser(PlatformConfiguration.DesktopSafari);
|
|
50
|
+
expect(isPlatform('capacitor')).toEqual(false);
|
|
51
|
+
expect(isPlatform('desktop')).toEqual(true);
|
|
52
|
+
});
|
|
53
|
+
it('should return false for "capacitor" and true for "desktop" on desktop safari', () => {
|
|
54
|
+
const win = configureBrowser(PlatformConfiguration.DesktopSafari);
|
|
55
|
+
expect(isPlatform(win, 'capacitor')).toEqual(false);
|
|
56
|
+
expect(isPlatform(win, 'desktop')).toEqual(true);
|
|
57
|
+
});
|
|
58
|
+
it('should return true for "android" and "tablet" and false for "ios" on an android tablet', () => {
|
|
59
|
+
const win = configureBrowser(PlatformConfiguration.AndroidTablet);
|
|
60
|
+
expect(isPlatform(win, 'android')).toEqual(true);
|
|
61
|
+
expect(isPlatform(win, 'tablet')).toEqual(true);
|
|
62
|
+
expect(isPlatform(win, 'ios')).toEqual(false);
|
|
63
|
+
});
|
|
64
|
+
it('should return true for "cordova" and "hybrid" in a Cordova app', () => {
|
|
65
|
+
const win = configureBrowser(PlatformConfiguration.Cordova);
|
|
66
|
+
expect(isPlatform(win, 'cordova')).toEqual(true);
|
|
67
|
+
expect(isPlatform(win, 'hybrid')).toEqual(true);
|
|
68
|
+
});
|
|
69
|
+
it('should return true for "ipad" and "tablet" on an iPad Pro', () => {
|
|
70
|
+
const win = configureBrowser(PlatformConfiguration.iPadPro);
|
|
71
|
+
expect(isPlatform(win, 'ipad')).toEqual(true);
|
|
72
|
+
expect(isPlatform(win, 'tablet')).toEqual(true);
|
|
73
|
+
});
|
|
74
|
+
it('should return true for "android", false for "tablet, and false for "desktop"" on a Pixel 2 XL', () => {
|
|
75
|
+
const win = configureBrowser(PlatformConfiguration.Pixel2XL);
|
|
76
|
+
expect(isPlatform(win, 'android')).toEqual(true);
|
|
77
|
+
expect(isPlatform(win, 'tablet')).toEqual(false);
|
|
78
|
+
expect(isPlatform(win, 'desktop')).toEqual(false);
|
|
79
|
+
});
|
|
80
|
+
it('should return true for "android" and "tablet" and false for "desktop" on a Galaxy View', () => {
|
|
81
|
+
const win = configureBrowser(PlatformConfiguration.GalaxyView);
|
|
82
|
+
expect(isPlatform(win, 'android')).toEqual(true);
|
|
83
|
+
expect(isPlatform(win, 'tablet')).toEqual(true);
|
|
84
|
+
expect(isPlatform(win, 'desktop')).toEqual(false);
|
|
85
|
+
});
|
|
86
|
+
it('should return false for "android", "tablet", and "ipad" on desktop Safari', () => {
|
|
87
|
+
const win = configureBrowser(PlatformConfiguration.DesktopSafari);
|
|
88
|
+
expect(isPlatform(win, 'android')).toEqual(false);
|
|
89
|
+
expect(isPlatform(win, 'tablet')).toEqual(false);
|
|
90
|
+
expect(isPlatform(win, 'ipad')).toEqual(false);
|
|
91
|
+
});
|
|
92
|
+
it('should return false for "android" and "tablet" and false for "desktop" on iPhone', () => {
|
|
93
|
+
const win = configureBrowser(PlatformConfiguration.iPhone);
|
|
94
|
+
expect(isPlatform(win, 'android')).toEqual(false);
|
|
95
|
+
expect(isPlatform(win, 'tablet')).toEqual(false);
|
|
96
|
+
expect(isPlatform(win, 'desktop')).toEqual(false);
|
|
97
|
+
});
|
|
98
|
+
it('should return true for "android", false for "tablet", and false for "desktop" on Galaxy S9 Plus', () => {
|
|
99
|
+
const win = configureBrowser(PlatformConfiguration.GalaxyS9Plus);
|
|
100
|
+
expect(isPlatform(win, 'android')).toEqual(true);
|
|
101
|
+
expect(isPlatform(win, 'tablet')).toEqual(false);
|
|
102
|
+
expect(isPlatform(win, 'desktop')).toEqual(false);
|
|
103
|
+
});
|
|
104
|
+
it('should return true for "pwa" and false for "cordova"', () => {
|
|
105
|
+
const win = configureBrowser(PlatformConfiguration.PWA);
|
|
106
|
+
expect(isPlatform(win, 'pwa')).toEqual(true);
|
|
107
|
+
expect(isPlatform(win, 'cordova')).toEqual(false);
|
|
108
|
+
});
|
|
109
|
+
it('should return true for "ios", "ipad", and "tablet" and false for "iphone" and "android"', () => {
|
|
110
|
+
const win = configureBrowser(PlatformConfiguration.iPadOS);
|
|
111
|
+
expect(isPlatform(win, 'ios')).toEqual(true);
|
|
112
|
+
expect(isPlatform(win, 'ipad')).toEqual(true);
|
|
113
|
+
expect(isPlatform(win, 'tablet')).toEqual(true);
|
|
114
|
+
expect(isPlatform(win, 'iphone')).toEqual(false);
|
|
115
|
+
expect(isPlatform(win, 'android')).toEqual(false);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('Custom Platform Config', () => {
|
|
119
|
+
it('should use custom platform detection methods', () => {
|
|
120
|
+
const win = configureBrowser(PlatformConfiguration.DesktopSafari);
|
|
121
|
+
initialize({
|
|
122
|
+
platform: {
|
|
123
|
+
desktop: () => false,
|
|
124
|
+
cordova: () => true,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
expect(isPlatform(win, 'desktop')).toEqual(false);
|
|
128
|
+
expect(isPlatform(win, 'cordova')).toEqual(true);
|
|
129
|
+
expect(getPlatforms(win).includes('cordova')).toEqual(true);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { componentOnReady } from "../helpers";
|
|
5
|
+
describe('componentOnReady()', () => {
|
|
6
|
+
it('should correctly call callback for a custom element', (done) => {
|
|
7
|
+
customElements.define('hello-world', class extends HTMLElement {
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const component = document.createElement('hello-world');
|
|
13
|
+
componentOnReady(component, (el) => {
|
|
14
|
+
expect(el).toBe(component);
|
|
15
|
+
done();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
it('should correctly call callback for a lazy loaded component', (done) => {
|
|
19
|
+
const cb = jest.fn((el) => {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
setTimeout(() => resolve(el), 250);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
customElements.define('hello-world', class extends HTMLElement {
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
}
|
|
28
|
+
componentOnReady() {
|
|
29
|
+
return cb(this);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const component = document.createElement('hello-world');
|
|
33
|
+
componentOnReady(component, (el) => {
|
|
34
|
+
expect(el).toBe(component);
|
|
35
|
+
expect(cb).toHaveBeenCalledTimes(1);
|
|
36
|
+
done();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { getClassList, getClassMap } from "../theme";
|
|
5
|
+
describe('getClassList()', () => {
|
|
6
|
+
it('should parse string', () => {
|
|
7
|
+
expect(getClassList(' class class-event THEME-ios-bar-button')).toEqual([
|
|
8
|
+
'class',
|
|
9
|
+
'class-event',
|
|
10
|
+
'THEME-ios-bar-button',
|
|
11
|
+
]);
|
|
12
|
+
expect(getClassList('')).toEqual([]);
|
|
13
|
+
expect(getClassList(' ')).toEqual([]);
|
|
14
|
+
});
|
|
15
|
+
it('should pass array', () => {
|
|
16
|
+
expect(getClassList(['class', 'class-event', 'THEME-ios-bar-button'])).toEqual([
|
|
17
|
+
'class',
|
|
18
|
+
'class-event',
|
|
19
|
+
'THEME-ios-bar-button',
|
|
20
|
+
]);
|
|
21
|
+
expect(getClassList(['class ', ' class-event', ' THEME-ios-bar-button '])).toEqual([
|
|
22
|
+
'class',
|
|
23
|
+
'class-event',
|
|
24
|
+
'THEME-ios-bar-button',
|
|
25
|
+
]);
|
|
26
|
+
expect(getClassList(['class ', null, undefined, '', ' class-event', ' ', ' THEME-ios-bar-button '])).toEqual(['class', 'class-event', 'THEME-ios-bar-button']);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('getClassMap()', () => {
|
|
30
|
+
it('should parse string', () => {
|
|
31
|
+
expect(getClassMap(' class class-event THEME-ios-bar-button')).toEqual({
|
|
32
|
+
class: true,
|
|
33
|
+
'class-event': true,
|
|
34
|
+
'THEME-ios-bar-button': true,
|
|
35
|
+
});
|
|
36
|
+
expect(getClassMap('')).toEqual({});
|
|
37
|
+
expect(getClassMap(' ')).toEqual({});
|
|
38
|
+
});
|
|
39
|
+
it('should pass array', () => {
|
|
40
|
+
expect(getClassMap(['class', 'class-event', 'THEME-ios-bar-button'])).toEqual({
|
|
41
|
+
class: true,
|
|
42
|
+
'class-event': true,
|
|
43
|
+
'THEME-ios-bar-button': true,
|
|
44
|
+
});
|
|
45
|
+
expect(getClassMap(['class ', ' class-event', ' THEME-ios-bar-button '])).toEqual({
|
|
46
|
+
class: true,
|
|
47
|
+
'class-event': true,
|
|
48
|
+
'THEME-ios-bar-button': true,
|
|
49
|
+
});
|
|
50
|
+
expect(getClassMap(['class ', null, undefined, '', ' class-event', ' ', ' THEME-ios-bar-button '])).toEqual({
|
|
51
|
+
class: true,
|
|
52
|
+
'class-event': true,
|
|
53
|
+
'THEME-ios-bar-button': true,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
package/dist/docs.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"timestamp": "2023-11-
|
|
2
|
+
"timestamp": "2023-11-20T14:59:59",
|
|
3
3
|
"compiler": {
|
|
4
4
|
"name": "@stencil/core",
|
|
5
5
|
"version": "4.7.2",
|
|
@@ -28953,8 +28953,8 @@
|
|
|
28953
28953
|
"docstring": "",
|
|
28954
28954
|
"path": "src/components/accordion-group/accordion-group-interface.ts"
|
|
28955
28955
|
},
|
|
28956
|
-
"src/interface.d.ts::
|
|
28957
|
-
"declaration": "export
|
|
28956
|
+
"src/interface.d.ts::Color": {
|
|
28957
|
+
"declaration": "export type Color = LiteralUnion<PredefinedColors, string>;",
|
|
28958
28958
|
"docstring": "",
|
|
28959
28959
|
"path": "src/interface.d.ts"
|
|
28960
28960
|
},
|
|
@@ -28963,6 +28963,21 @@
|
|
|
28963
28963
|
"docstring": "",
|
|
28964
28964
|
"path": "src/interface.d.ts"
|
|
28965
28965
|
},
|
|
28966
|
+
"src/components/router/utils/interface.ts::RouterDirection": {
|
|
28967
|
+
"declaration": "export type RouterDirection = 'forward' | 'back' | 'root';",
|
|
28968
|
+
"docstring": "",
|
|
28969
|
+
"path": "src/components/router/utils/interface.ts"
|
|
28970
|
+
},
|
|
28971
|
+
"src/components/item/item-interface.ts::CounterFormatter": {
|
|
28972
|
+
"declaration": "(inputLength: number, maxLength: number) => string",
|
|
28973
|
+
"docstring": "",
|
|
28974
|
+
"path": "src/components/item/item-interface.ts"
|
|
28975
|
+
},
|
|
28976
|
+
"src/interface.d.ts::FrameworkDelegate": {
|
|
28977
|
+
"declaration": "export interface FrameworkDelegate {\n attachViewToDom(container: any, component: any, propsOrDataObj?: any, cssClasses?: string[]): Promise<HTMLElement>;\n removeViewFromDom(container: any, component: any): Promise<void>;\n}",
|
|
28978
|
+
"docstring": "",
|
|
28979
|
+
"path": "src/interface.d.ts"
|
|
28980
|
+
},
|
|
28966
28981
|
"src/components/action-sheet/action-sheet-interface.ts::ActionSheetButton": {
|
|
28967
28982
|
"declaration": "export interface ActionSheetButton<T = any> {\n text?: string;\n role?: 'cancel' | 'destructive' | 'selected' | string;\n icon?: string;\n cssClass?: string | string[];\n id?: string;\n htmlAttributes?: { [key: string]: any };\n handler?: () => boolean | void | Promise<boolean | void>;\n data?: T;\n}",
|
|
28968
28983
|
"docstring": "",
|
|
@@ -28988,16 +29003,6 @@
|
|
|
28988
29003
|
"docstring": "",
|
|
28989
29004
|
"path": "src/components/alert/alert-interface.ts"
|
|
28990
29005
|
},
|
|
28991
|
-
"src/interface.d.ts::Color": {
|
|
28992
|
-
"declaration": "export type Color = LiteralUnion<PredefinedColors, string>;",
|
|
28993
|
-
"docstring": "",
|
|
28994
|
-
"path": "src/interface.d.ts"
|
|
28995
|
-
},
|
|
28996
|
-
"src/components/router/utils/interface.ts::RouterDirection": {
|
|
28997
|
-
"declaration": "export type RouterDirection = 'forward' | 'back' | 'root';",
|
|
28998
|
-
"docstring": "",
|
|
28999
|
-
"path": "src/components/router/utils/interface.ts"
|
|
29000
|
-
},
|
|
29001
29006
|
"src/components/breadcrumb/breadcrumb-interface.ts::BreadcrumbCollapsedClickEventDetail": {
|
|
29002
29007
|
"declaration": "export interface BreadcrumbCollapsedClickEventDetail {\n ionShadowTarget?: HTMLElement;\n collapsedBreadcrumbs?: HTMLIonBreadcrumbElement[];\n}",
|
|
29003
29008
|
"docstring": "",
|
|
@@ -29078,10 +29083,10 @@
|
|
|
29078
29083
|
"docstring": "Values are converted to strings when emitted which is\nwhy we do not have a `number` type here even though the\n`value` prop accepts a `number` type.",
|
|
29079
29084
|
"path": "src/components/input/input-interface.ts"
|
|
29080
29085
|
},
|
|
29081
|
-
"src/components/
|
|
29082
|
-
"declaration": "
|
|
29086
|
+
"src/components/radio-group/radio-group-interface.ts::RadioGroupChangeEventDetail": {
|
|
29087
|
+
"declaration": "export interface RadioGroupChangeEventDetail<T = any> {\n value: T;\n event?: Event;\n}",
|
|
29083
29088
|
"docstring": "",
|
|
29084
|
-
"path": "src/components/
|
|
29089
|
+
"path": "src/components/radio-group/radio-group-interface.ts"
|
|
29085
29090
|
},
|
|
29086
29091
|
"src/components/menu/menu-interface.ts::Side": {
|
|
29087
29092
|
"declaration": "export type Side = 'start' | 'end';",
|
|
@@ -29198,11 +29203,6 @@
|
|
|
29198
29203
|
"docstring": "",
|
|
29199
29204
|
"path": "src/components/popover/popover-interface.ts"
|
|
29200
29205
|
},
|
|
29201
|
-
"src/components/radio-group/radio-group-interface.ts::RadioGroupChangeEventDetail": {
|
|
29202
|
-
"declaration": "export interface RadioGroupChangeEventDetail<T = any> {\n value: T;\n event?: Event;\n}",
|
|
29203
|
-
"docstring": "",
|
|
29204
|
-
"path": "src/components/radio-group/radio-group-interface.ts"
|
|
29205
|
-
},
|
|
29206
29206
|
"src/components/range/range-interface.ts::PinFormatter": {
|
|
29207
29207
|
"declaration": "(value: number) => number | string",
|
|
29208
29208
|
"docstring": "",
|
|
@@ -995,7 +995,7 @@ const Datetime = class {
|
|
|
995
995
|
* so we need to re-init behavior with the new elements.
|
|
996
996
|
*/
|
|
997
997
|
componentDidRender() {
|
|
998
|
-
const { presentation, prevPresentation, calendarBodyRef, minParts, preferWheel,
|
|
998
|
+
const { presentation, prevPresentation, calendarBodyRef, minParts, preferWheel, forceRenderDate } = this;
|
|
999
999
|
/**
|
|
1000
1000
|
* TODO(FW-2165)
|
|
1001
1001
|
* Remove this when https://bugs.webkit.org/show_bug.cgi?id=235960 is fixed.
|
|
@@ -1025,7 +1025,7 @@ const Datetime = class {
|
|
|
1025
1025
|
* the scroll callback in this file does not fire,
|
|
1026
1026
|
* and the resolveForceDateScrolling promise never resolves.
|
|
1027
1027
|
*/
|
|
1028
|
-
if (workingMonth &&
|
|
1028
|
+
if (workingMonth && forceRenderDate === undefined) {
|
|
1029
1029
|
calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
|
|
1030
1030
|
}
|
|
1031
1031
|
}
|