chore(): sync with main
@ -41,5 +41,13 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
"custom-rules/no-component-on-ready-method": "error"
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.e2e.ts"],
|
||||
"rules": {
|
||||
"custom-rules/await-playwright-promise-assertion": "error"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
70
core/custom-rules/await-playwright-promise-assertion.js
Normal file
@ -0,0 +1,70 @@
|
||||
module.exports = {
|
||||
meta: {
|
||||
messages: {
|
||||
awaitPlaywrightPromiseAssertion: 'This Playwright assertion returns a Promise. Add an "await" to avoid creating a flaky test.',
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
ExpressionStatement(node) {
|
||||
const expression = node.expression;
|
||||
|
||||
/**
|
||||
* The first expression of a properly awaited
|
||||
* Playwright assertion should be an AwaitExpression,
|
||||
* so if it goes directly to the CallExpression
|
||||
* then we potentially need to report this.
|
||||
*/
|
||||
if (expression.type === 'CallExpression') {
|
||||
const { object, property } = expression.callee;
|
||||
|
||||
/**
|
||||
* Check to see if the property name is
|
||||
* of a known Playwright async assertion.
|
||||
*/
|
||||
if (
|
||||
property !== undefined &&
|
||||
property.type === 'Identifier' &&
|
||||
hasPlaywrightAsyncAssertion(property.name)
|
||||
) {
|
||||
context.report({ node: node, messageId: 'awaitPlaywrightPromiseAssertion' });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns `true` if `property` is the name
|
||||
* of a known async Playwright assertion.
|
||||
*/
|
||||
const hasPlaywrightAsyncAssertion = (property) => {
|
||||
return ASYNC_PLAYWRIGHT_ASSERTS.includes(property);
|
||||
}
|
||||
|
||||
// https://playwright.dev/docs/test-assertions
|
||||
const ASYNC_PLAYWRIGHT_ASSERTS = [
|
||||
'toBeChecked',
|
||||
'toBeDisabled',
|
||||
'toBeEditable',
|
||||
'toBeEmpty',
|
||||
'toBeEnabled',
|
||||
'toBeFocused',
|
||||
'toBeHidden',
|
||||
'toBeVisible',
|
||||
'toContainText',
|
||||
'toHaveAttribute',
|
||||
'toHaveClass',
|
||||
'toHaveCount',
|
||||
'toHaveCSS',
|
||||
'toHaveId',
|
||||
'toHaveJSProperty',
|
||||
'toHaveScreenshot',
|
||||
'toHaveText',
|
||||
'toHaveValue',
|
||||
'toHaveValues',
|
||||
'toHaveTitle',
|
||||
'toHaveURL',
|
||||
'toBeOK',
|
||||
];
|
@ -1,5 +1,6 @@
|
||||
module.exports = {
|
||||
rules: {
|
||||
'no-component-on-ready-method': require('./no-component-on-ready-method.js')
|
||||
'no-component-on-ready-method': require('./no-component-on-ready-method.js'),
|
||||
'await-playwright-promise-assertion': require('./await-playwright-promise-assertion.js')
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
module.exports = {
|
||||
meta: {
|
||||
messages: {
|
||||
noComponentOnReadyMethod: 'Using the componentOnReady method is not allowed. Use the componentOnReady helper utility in src/utils/helpers.ts instead.',
|
||||
},
|
||||
meta: {
|
||||
messages: {
|
||||
noComponentOnReadyMethod: 'Using the componentOnReady method is not allowed. Use the componentOnReady helper utility in src/utils/helpers.ts instead.',
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
CallExpression(node) {
|
||||
/**
|
||||
* We only want to exclude usages of componentOnReady().
|
||||
* Checking for the existence of the componentOnReady method
|
||||
* is a way of determining if we are in a lazy loaded build
|
||||
* or custom elements build, so we want to allow that.
|
||||
*/
|
||||
const callee = node.callee;
|
||||
if (callee.type === 'MemberExpression' && callee.property.name === 'componentOnReady') {
|
||||
context.report({ node: node, messageId: 'noComponentOnReadyMethod' });
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
CallExpression(node) {
|
||||
/**
|
||||
* We only want to exclude usages of componentOnReady().
|
||||
* Checking for the existence of the componentOnReady method
|
||||
* is a way of determining if we are in a lazy loaded build
|
||||
* or custom elements build, so we want to allow that.
|
||||
*/
|
||||
const callee = node.callee;
|
||||
if (callee.type === 'MemberExpression' && callee.property.name === 'componentOnReady') {
|
||||
context.report({ node: node, messageId: 'noComponentOnReadyMethod' });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
30
core/package-lock.json
generated
@ -18,7 +18,7 @@
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@jest/core": "^27.5.1",
|
||||
"@playwright/test": "^1.23.3",
|
||||
"@playwright/test": "^1.29.0",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.4.0",
|
||||
@ -1513,13 +1513,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.23.3.tgz",
|
||||
"integrity": "sha512-kR4vo2UGHC84DGqE6EwvAeaehj3xCAK6LoC1P1eu6ZGdC79rlqRKf8cFDx6q6c9T8MQSL1O9eOlup0BpwqNF0w==",
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.29.0.tgz",
|
||||
"integrity": "sha512-gp5PVBenxTJsm2bATWDNc2CCnrL5OaA/MXQdJwwkGQtqTjmY+ZOqAdLqo49O9MLTDh2vYh+tHWDnmFsILnWaeA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.23.3"
|
||||
"playwright-core": "1.29.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@ -8351,9 +8351,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.23.3",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.23.3.tgz",
|
||||
"integrity": "sha512-x35yzsXDyo0BIXYimLnUFNyb42c//NadUNH6IPGOteZm96oTGA1kn4Hq6qJTI1/f9wEc1F9O1DsznXIgXMil7A==",
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.29.0.tgz",
|
||||
"integrity": "sha512-pboOm1m0RD6z1GtwAbEH60PYRfF87vKdzOSRw2RyO0Y0a7utrMyWN2Au1ojGvQr4umuBMODkKTv607YIRypDSQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@ -11913,13 +11913,13 @@
|
||||
}
|
||||
},
|
||||
"@playwright/test": {
|
||||
"version": "1.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.23.3.tgz",
|
||||
"integrity": "sha512-kR4vo2UGHC84DGqE6EwvAeaehj3xCAK6LoC1P1eu6ZGdC79rlqRKf8cFDx6q6c9T8MQSL1O9eOlup0BpwqNF0w==",
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.29.0.tgz",
|
||||
"integrity": "sha512-gp5PVBenxTJsm2bATWDNc2CCnrL5OaA/MXQdJwwkGQtqTjmY+ZOqAdLqo49O9MLTDh2vYh+tHWDnmFsILnWaeA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.23.3"
|
||||
"playwright-core": "1.29.0"
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-node-resolve": {
|
||||
@ -17008,9 +17008,9 @@
|
||||
}
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.23.3",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.23.3.tgz",
|
||||
"integrity": "sha512-x35yzsXDyo0BIXYimLnUFNyb42c//NadUNH6IPGOteZm96oTGA1kn4Hq6qJTI1/f9wEc1F9O1DsznXIgXMil7A==",
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.29.0.tgz",
|
||||
"integrity": "sha512-pboOm1m0RD6z1GtwAbEH60PYRfF87vKdzOSRw2RyO0Y0a7utrMyWN2Au1ojGvQr4umuBMODkKTv607YIRypDSQ==",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
|
@ -40,7 +40,7 @@
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@jest/core": "^27.5.1",
|
||||
"@playwright/test": "^1.23.3",
|
||||
"@playwright/test": "^1.29.0",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.4.0",
|
||||
|
2
core/src/components.d.ts
vendored
@ -1190,7 +1190,7 @@ export namespace Components {
|
||||
*/
|
||||
"required": boolean;
|
||||
/**
|
||||
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global `input.focus()`.
|
||||
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global `input.focus()`. Developers who wish to focus an input when a page enters should call `setFocus()` in the `ionViewDidEnter()` lifecycle method.
|
||||
*/
|
||||
"setFocus": () => Promise<void>;
|
||||
/**
|
||||
|
@ -5,6 +5,8 @@ test.describe('accordion: a11y', () => {
|
||||
test('accordions should be keyboard navigable', async ({ page, skip, browserName }) => {
|
||||
// TODO(FW-1764): remove skip once issue is resolved
|
||||
skip.browser('firefox', 'https://github.com/ionic-team/ionic-framework/issues/25070');
|
||||
// TODO (FW-2979)
|
||||
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
|
||||
|
||||
await page.goto(`/src/components/accordion/test/a11y`);
|
||||
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
|
||||
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 454 KiB After Width: | Height: | Size: 454 KiB |
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 442 KiB |
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 247 KiB |
Before Width: | Height: | Size: 246 KiB After Width: | Height: | Size: 246 KiB |
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 279 KiB |
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 278 KiB |
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 276 KiB |
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 276 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 290 KiB After Width: | Height: | Size: 290 KiB |
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 290 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 346 KiB After Width: | Height: | Size: 352 KiB |
Before Width: | Height: | Size: 346 KiB After Width: | Height: | Size: 352 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 202 KiB |
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@ -48,7 +48,6 @@ test.describe('card: basic', () => {
|
||||
|
||||
test('should not have visual regressions with translucent cards', async ({ page, skip }) => {
|
||||
skip.mode('md', 'Translucent effect is only available in iOS mode.');
|
||||
skip.browser('firefox', 'Firefox has some issues rendering translucent effects on Linux.');
|
||||
|
||||
await page.setContent(`
|
||||
<ion-card>
|
||||
|