mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(reorder-group): add ability to reorder items inside shadow (#17747)
- adds ability to reorder items from within a shadow dom component - adds interactive test fixes #17746
This commit is contained in:
committed by
Brandy Carney
parent
a8a48a4ca4
commit
352797e932
@@ -64,7 +64,7 @@ export class ReorderGroup implements ComponentInterface {
|
||||
}
|
||||
|
||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||
el: this.doc.body,
|
||||
el: this.el,
|
||||
queue: this.queue,
|
||||
gestureName: 'reorder',
|
||||
gesturePriority: 110,
|
||||
|
||||
60
core/src/components/reorder-group/test/interactive/e2e.ts
Normal file
60
core/src/components/reorder-group/test/interactive/e2e.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import * as pd from '@stencil/core/dist/testing/puppeteer/puppeteer-declarations';
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { getElementProperty, queryDeep } from '../../../../utils/test/utils';
|
||||
import { moveReorderItem } from '../test.utils';
|
||||
|
||||
test('reorder: interactive', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/reorder-group/test/interactive?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const compares = [];
|
||||
compares.push(await page.compareScreenshot('reorder: interactive before move'));
|
||||
|
||||
const items = await page.$$('ion-reorder');
|
||||
const getItemId = await getElementProperty(items[0], 'id');
|
||||
expect(getItemId).toEqual('item-0');
|
||||
|
||||
await moveItem(getItemId, page, 'down', 1);
|
||||
|
||||
const itemsAfterFirstMove = await page.$$('ion-reorder');
|
||||
expect(await getElementProperty(itemsAfterFirstMove[0], 'id')).toEqual('item-1');
|
||||
|
||||
await moveItem(getItemId, page, 'up', 1);
|
||||
|
||||
const itemsAfterSecondMove = await page.$$('ion-reorder');
|
||||
expect(await getElementProperty(itemsAfterSecondMove[0], 'id')).toEqual('item-0');
|
||||
|
||||
compares.push(await page.compareScreenshot('reorder: interactive after move; before shadow move'));
|
||||
|
||||
const shadowDomList = await queryDeep(page, 'test-reorder-list-shadow-dom', 'ion-list');
|
||||
|
||||
const itemsInShadowRoot = await shadowDomList.$$('ion-reorder');
|
||||
const getShadowItemId = await getElementProperty(itemsInShadowRoot[0], 'id');
|
||||
expect(getShadowItemId).toEqual('item-0');
|
||||
|
||||
await moveItem(getShadowItemId, page, 'down', 1, 'test-reorder-list-shadow-dom', 'ion-list');
|
||||
|
||||
const itemsInShadowRootAfterFirstMove = await shadowDomList.$$('ion-reorder');
|
||||
expect(await getElementProperty(itemsInShadowRootAfterFirstMove[0], 'id')).toEqual('item-1');
|
||||
|
||||
await moveItem(getShadowItemId, page, 'up', 1, 'test-reorder-list-shadow-dom', 'ion-list');
|
||||
|
||||
const itemsInShadowRootAfterSecondMove = await shadowDomList.$$('ion-reorder');
|
||||
expect(await getElementProperty(itemsInShadowRootAfterSecondMove[0], 'id')).toEqual('item-0');
|
||||
|
||||
compares.push(await page.compareScreenshot('reorder: interactive after shadow move'));
|
||||
|
||||
for (const compare of compares) {
|
||||
expect(compare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
async function moveItem(id: string, page: pd.E2EPage, direction: 'up' | 'down' = 'up', numberOfSpaces = 1, ...parentSelectors: string[]) {
|
||||
try {
|
||||
await moveReorderItem(`#${id}`, page, direction, numberOfSpaces, ...parentSelectors);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Reorder - Interactive</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<link href="../../../../../css/core.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script src="../../../../../dist/ionic.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-list><ion-reorder-group disabled="false"></ion-reorder-group></ion-list>
|
||||
|
||||
<script>
|
||||
class TestReorderListShadowDom extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
const shadow = this.attachShadow({mode: 'open'});
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = `<ion-list><ion-reorder-group disabled="false"></ion-reorder-group></ion-list>`;
|
||||
shadow.appendChild(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('test-reorder-list-shadow-dom', TestReorderListShadowDom);
|
||||
|
||||
function addReorderItem(list) {
|
||||
const reorderItem = document.createElement('ion-reorder');
|
||||
reorderItem.innerHTML = `<ion-item>
|
||||
<ion-label>
|
||||
<h2>Item ${list.childElementCount}</h2>
|
||||
</ion-label>
|
||||
</ion-item>`;
|
||||
|
||||
reorderItem.id = `item-${list.childElementCount}`;
|
||||
|
||||
list.appendChild(reorderItem);
|
||||
}
|
||||
|
||||
const testShadowDomEl = document.createElement('test-reorder-list-shadow-dom');
|
||||
document.body.appendChild(testShadowDomEl);
|
||||
|
||||
let lists = Array.from(document.getElementsByTagName('ion-reorder-group'));
|
||||
lists.push(testShadowDomEl.shadowRoot.querySelector('ion-reorder-group'));
|
||||
|
||||
for (var i = 0; i < lists.length; i++) {
|
||||
lists[i].addEventListener('ionItemReorder', ({detail}) => detail.complete(true));
|
||||
for (var j = 0; j < 3; j++) addReorderItem(lists[i]);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
22
core/src/components/reorder-group/test/test.utils.ts
Normal file
22
core/src/components/reorder-group/test/test.utils.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import * as pd from '@stencil/core/dist/testing/puppeteer/puppeteer-declarations';
|
||||
|
||||
import { dragElementBy, queryDeep } from '../../../utils/test/utils';
|
||||
|
||||
/**
|
||||
* Moves a reorder item by simulating a drag event
|
||||
*/
|
||||
export async function moveReorderItem(id: string, page: pd.E2EPage, direction: 'up' | 'down' = 'up', numberOfSpaces = 1, ...parentSelectors: string[]) {
|
||||
try {
|
||||
const reorderItem = parentSelectors && parentSelectors.length > 0 ? await (await queryDeep(page, ...parentSelectors)).$(id) : await page.$(id);
|
||||
|
||||
if (!reorderItem) { throw new Error('Reorder Item is undefined'); }
|
||||
|
||||
const boundingBox = await reorderItem.boundingBox();
|
||||
if (!boundingBox) { throw new Error('Reorder Item bounding box is undefined'); }
|
||||
|
||||
await dragElementBy(reorderItem, page, 0, (direction === 'up') ? -(boundingBox.height * numberOfSpaces) : (boundingBox.height * numberOfSpaces));
|
||||
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
import { E2EPage } from '@stencil/core/testing';
|
||||
import { ElementHandle } from 'puppeteer';
|
||||
|
||||
export function generateE2EUrl(component: string, type: string, rtl = false): string {
|
||||
let url = `/src/components/${component}/test/${type}?ionic:_testing=true`;
|
||||
if (rtl) {
|
||||
@@ -14,6 +17,16 @@ export function cleanScreenshotName(screenshotName: string): string {
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a property on an element
|
||||
*/
|
||||
export const getElementProperty = async (element: any, property: string): Promise<string> => {
|
||||
const getProperty = await element.getProperty(property);
|
||||
if (!getProperty) { return ''; }
|
||||
|
||||
return getProperty.jsonValue();
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for an event and fires a callback
|
||||
* @param page - The Puppeteer `page` object
|
||||
@@ -87,3 +100,22 @@ export const waitForFunctionTestContext = async (fn: any, params: any, interval
|
||||
}, interval);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Pierce through shadow roots
|
||||
* https://github.com/GoogleChrome/puppeteer/issues/858#issuecomment-359763824
|
||||
*/
|
||||
export async function queryDeep(page: E2EPage, ...selectors: string[]): Promise<ElementHandle> {
|
||||
const shadowSelectorFn = (el: Element, selector: string): Element | null => (el && el.shadowRoot) && el.shadowRoot.querySelector(selector);
|
||||
|
||||
return new Promise(async resolve => {
|
||||
const [ firstSelector, ...restSelectors ] = selectors;
|
||||
let parentElement = await page.$(firstSelector);
|
||||
|
||||
for (const selector of restSelectors) {
|
||||
parentElement = await page.evaluateHandle(shadowSelectorFn, parentElement, selector) as any;
|
||||
}
|
||||
|
||||
if (parentElement) { resolve(parentElement); }
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user