fix flaky tests, fix menu

This commit is contained in:
Liam DeBeasi
2019-07-31 13:37:07 -04:00
parent 07c50c18ef
commit cf585f1d3f
6 changed files with 139 additions and 68 deletions

View File

@@ -1427,7 +1427,7 @@ export namespace Components {
* @param name The name of the animation to register.
* @param animation The animation function to register.
*/
'registerAnimation': (name: string, animation: ((menu: MenuI) => IonicAnimation) | AnimationBuilder) => Promise<void>;
'registerAnimation': (name: string, animation: AnimationBuilder | ((menu: MenuI) => IonicAnimation)) => Promise<void>;
/**
* Enable or disable the ability to swipe open the menu.
* @param enable If `true`, the menu swipe gesture should be enabled.

View File

@@ -314,10 +314,11 @@ export class Menu implements ComponentInterface, MenuI {
private async startAnimation(shouldOpen: boolean, animated: boolean): Promise<void> {
const isReversed = !shouldOpen;
console.log('play', isReversed);
const ani = this.animation!
.fill('both')
.direction((isReversed) ? 'reverse' : 'normal')
.easing((isReversed) ? 'cubic-bezier(0.4, 0.0, 0.6, 1)' : 'cubic-bezier(0.0, 0.0, 0.2, 1)');
.easing((isReversed) ? 'cubic-bezier(0.4, 0.0, 0.6, 1)' : 'cubic-bezier(0.0, 0.0, 0.2, 1)')
.update(true);
if (animated) {
await ani.playAsync();

View File

@@ -30,6 +30,7 @@ export interface Animation {
easing(easing: string): Animation;
delay(delay: number): Animation;
parent(animation: Animation): Animation;
update(deep: boolean): Animation;
getKeyframes(): any[];
getDirection(): AnimationDirection | undefined;

View File

@@ -35,6 +35,7 @@ export const createAnimation = () => {
let shouldForceSyncPlayback = false;
let shouldForceReverseDirection = false;
let willComplete = true;
let shouldCalculateNumAnimations = true;
let ani: Animation;
/**
@@ -534,6 +535,8 @@ export const createAnimation = () => {
onFinishCallbacks.forEach(callback => {
callback(didComplete, ani);
});
shouldCalculateNumAnimations = true;
};
const animationFinish = () => {
@@ -605,13 +608,12 @@ export const createAnimation = () => {
animationFinish();
};
}
};
const initializeAnimation = () => {
beforeAnimation();
numAnimationsRunning = childAnimations.length + 1;
if (getKeyframes().length > 0) {
if (supportsWebAnimations) {
initializeWebAnimation();
@@ -682,12 +684,23 @@ export const createAnimation = () => {
});
};
const updateAnimation = () => {
/**
* Updates any existing animations.
*/
const update = (deep = false) => {
if (deep) {
childAnimations.forEach(animation => {
animation.update(deep);
});
}
if (supportsWebAnimations) {
updateWebAnimation();
} else {
updateCSSAnimation();
}
return ani;
};
const progressStart = (forceLinearEasing = false) => {
@@ -713,7 +726,7 @@ export const createAnimation = () => {
if (!shouldComplete) {
shouldForceReverseDirection = true;
onFinish(() => { willComplete = true; shouldForceReverseDirection = false; });
updateAnimation();
update();
progressStep(1 - step);
}
@@ -783,6 +796,11 @@ export const createAnimation = () => {
initializeAnimation();
}
if (shouldCalculateNumAnimations) {
numAnimationsRunning = childAnimations.length + 1;
shouldCalculateNumAnimations = false;
}
childAnimations.forEach(animation => {
animation.play();
});
@@ -890,6 +908,7 @@ export const createAnimation = () => {
keyframes,
addAnimation,
addElement,
update,
fill,
direction,
iterations,

View File

@@ -1,25 +1,72 @@
import { newE2EPage } from '@stencil/core/testing';
import { listenForEvent, waitForFunctionTestContext } from '../../../test/utils';
const navChanged = () => new Promise(resolve => window.addEventListener('ionRouteDidChange', resolve));
const ROUTE_CHANGED = 'onRouteChanged';
test('animation:backwards-compatibility animationbuilder', async () => {
const page = await newE2EPage({ url: '/src/utils/animation/test/animationbuilder?ionic:_testing=true' });
const page = await newE2EPage({ url: '/src/utils/animation/test/animationbuilder?ionic:_testing=true&_forceAnimationBuilder=true' });
const screenshotCompares = [];
const body = await page.$('body');
await listenForEvent(page, 'ionRouteDidChange', body, ROUTE_CHANGED);
const routeChangedCount: any = { count: 0 };
await page.exposeFunction(ROUTE_CHANGED, () => {
routeChangedCount.count += 1;
});
screenshotCompares.push(await page.compareScreenshot());
page.click('page-root ion-button.next');
await page.waitFor(navChanged);
await waitForNavChange(page, routeChangedCount);
page.click('page-one ion-button.next');
await page.waitFor(navChanged);
await waitForNavChange(page, routeChangedCount);
page.click('page-two ion-button.next');
await page.waitFor(navChanged);
await waitForNavChange(page, routeChangedCount);
page.click('page-three ion-back-button');
await page.waitFor(navChanged);
await waitForNavChange(page, routeChangedCount);
page.click('page-two ion-back-button');
await page.waitFor(navChanged);
await waitForNavChange(page, routeChangedCount);
page.click('page-one ion-back-button');
await page.waitFor(navChanged);
await waitForNavChange(page, routeChangedCount);
screenshotCompares.push(await page.compareScreenshot());
});
test('animation:backwards-compatibility animation', async () => {
const page = await newE2EPage({ url: '/src/utils/animation/test/animationbuilder?ionic:_testing=true' });
const screenshotCompares = [];
const body = await page.$('body');
await listenForEvent(page, 'ionRouteDidChange', body, ROUTE_CHANGED);
const routeChangedCount: any = { count: 0 };
await page.exposeFunction(ROUTE_CHANGED, () => {
routeChangedCount.count += 1;
});
screenshotCompares.push(await page.compareScreenshot());
page.click('page-root ion-button.next');
await waitForNavChange(page, routeChangedCount);
page.click('page-one ion-button.next');
await waitForNavChange(page, routeChangedCount);
page.click('page-two ion-button.next');
await waitForNavChange(page, routeChangedCount);
page.click('page-three ion-back-button');
await waitForNavChange(page, routeChangedCount);
page.click('page-two ion-back-button');
await waitForNavChange(page, routeChangedCount);
page.click('page-one ion-back-button');
await waitForNavChange(page, routeChangedCount);
screenshotCompares.push(await page.compareScreenshot());
});
const waitForNavChange = async (page, routeChangedCount) => {
await waitForFunctionTestContext((payload: any) => {
return payload.routeChangedCount.count === 1;
}, { routeChangedCount });
routeChangedCount.count = 0;
};

View File

@@ -93,62 +93,65 @@
customElements.define('page-two', PageTwo);
customElements.define('page-three', PageThree);
window.Ionic.config.navAnimation = (AnimationC, navEl, opts) => {
const TRANSLATEY = 'translateY';
const OFF_BOTTOM = '40px';
const CENTER = '0px';
const backDirection = (opts.direction === 'back');
const enteringEl = opts.enteringEl;
const leavingEl = opts.leavingEl;
const ionPageElement = getIonPageElement(enteringEl);
const enteringToolbarEle = ionPageElement.querySelector('ion-toolbar');
const rootTransition = new AnimationC();
rootTransition
.addElement(ionPageElement)
.beforeRemoveClass('ion-page-invisible');
// animate the component itself
if (backDirection) {
const forceAnimationBuilder = new URLSearchParams(window.location.search).get('ionic:_forceAnimationBuilder');
if (forceAnimationBuilder) {
window.Ionic.config.navAnimation = (AnimationC, navEl, opts) => {
const TRANSLATEY = 'translateY';
const OFF_BOTTOM = '40px';
const CENTER = '0px';
const backDirection = (opts.direction === 'back');
const enteringEl = opts.enteringEl;
const leavingEl = opts.leavingEl;
const ionPageElement = getIonPageElement(enteringEl);
const enteringToolbarEle = ionPageElement.querySelector('ion-toolbar');
const rootTransition = new AnimationC();
rootTransition
.duration(opts.duration || 200)
.easing('cubic-bezier(0.47,0,0.745,0.715)');
.addElement(ionPageElement)
.beforeRemoveClass('ion-page-invisible');
// animate the component itself
if (backDirection) {
rootTransition
.duration(opts.duration || 200)
.easing('cubic-bezier(0.47,0,0.745,0.715)');
} else {
rootTransition
.duration(opts.duration || 280)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.fromTo(TRANSLATEY, OFF_BOTTOM, CENTER, true)
.fromTo('opacity', 0.01, 1, true);
}
// Animate toolbar if it's there
if (enteringToolbarEle) {
const enteringToolBar = new AnimationC();
enteringToolBar.addElement(enteringToolbarEle);
rootTransition.add(enteringToolBar);
}
// setup leaving view
if (leavingEl && backDirection) {
// leaving content
rootTransition
.duration(opts.duration || 200)
.easing('cubic-bezier(0.47,0,0.745,0.715)');
const leavingPage = new AnimationC();
leavingPage
.addElement(getIonPageElement(leavingEl))
.fromTo(TRANSLATEY, CENTER, OFF_BOTTOM)
.fromTo('opacity', 1, 0);
rootTransition.add(leavingPage);
}
return Promise.resolve(rootTransition);
};
}
} else {
rootTransition
.duration(opts.duration || 280)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.fromTo(TRANSLATEY, OFF_BOTTOM, CENTER, true)
.fromTo('opacity', 0.01, 1, true);
}
// Animate toolbar if it's there
if (enteringToolbarEle) {
const enteringToolBar = new AnimationC();
enteringToolBar.addElement(enteringToolbarEle);
rootTransition.add(enteringToolBar);
}
// setup leaving view
if (leavingEl && backDirection) {
// leaving content
rootTransition
.duration(opts.duration || 200)
.easing('cubic-bezier(0.47,0,0.745,0.715)');
const leavingPage = new AnimationC();
leavingPage
.addElement(getIonPageElement(leavingEl))
.fromTo(TRANSLATEY, CENTER, OFF_BOTTOM)
.fromTo('opacity', 1, 0);
rootTransition.add(leavingPage);
}
return Promise.resolve(rootTransition);
};
const getIonPageElement = (element) => {
if (element.classList.contains('ion-page')) {
return element;