From b3f6219e03cc173997905d8d9eafc5df4cfcc149 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 29 Jul 2019 12:45:27 -0400 Subject: [PATCH] fix issue with onFinish being called out of order. added tests --- core/src/utils/animation/animation.ts | 8 +- core/src/utils/animation/test/basic/e2e.ts | 4 - core/src/utils/animation/test/multiple/e2e.ts | 52 ++++------ .../utils/animation/test/multiple/index.html | 21 ++-- core/src/utils/transition/md.transition.ts | 97 +++++++++---------- 5 files changed, 79 insertions(+), 103 deletions(-) diff --git a/core/src/utils/animation/animation.ts b/core/src/utils/animation/animation.ts index e0812b1bc2..575b2bce18 100644 --- a/core/src/utils/animation/animation.ts +++ b/core/src/utils/animation/animation.ts @@ -50,7 +50,7 @@ export const createAnimation = () => { const _afterAddReadFunctions: any[] = []; const _afterAddWriteFunctions: any[] = []; - const supportsWebAnimations = !!(window as any).Animation && _forceCSSAnimations !== null; + const supportsWebAnimations = !!(window as any).Animation && _forceCSSAnimations === null; /** * Destroy this animation and all child animations. @@ -445,10 +445,10 @@ export const createAnimation = () => { if (numAnimationsRunning === 0) { afterAnimation(); - } - if (parentAnimation) { - parentAnimation.animationFinish(); + if (parentAnimation) { + parentAnimation.animationFinish(); + } } }; diff --git a/core/src/utils/animation/test/basic/e2e.ts b/core/src/utils/animation/test/basic/e2e.ts index ec1e879cd6..30f43d7c4c 100644 --- a/core/src/utils/animation/test/basic/e2e.ts +++ b/core/src/utils/animation/test/basic/e2e.ts @@ -11,7 +11,6 @@ test(`animation:web: basic`, async () => { const ANIMATION_FINISHED = 'onIonAnimationFinished'; const animationFinishedCount: any = { count: 0 }; await page.exposeFunction(ANIMATION_FINISHED, () => { - console.log('yay'); animationFinishedCount.count += 1; }); @@ -30,9 +29,6 @@ test(`animation:web: basic`, async () => { test(`animation:css: basic`, async () => { const page = await newE2EPage({ url: '/src/utils/animation/test/basic?ionic:_forceCSSAnimations=true' }); - - page.evaluate(() => window.Ionic.config._forceCSSAnimations = true); - const screenshotCompares = []; screenshotCompares.push(await page.compareScreenshot()); diff --git a/core/src/utils/animation/test/multiple/e2e.ts b/core/src/utils/animation/test/multiple/e2e.ts index 4fe1e3171d..b85021064c 100644 --- a/core/src/utils/animation/test/multiple/e2e.ts +++ b/core/src/utils/animation/test/multiple/e2e.ts @@ -9,63 +9,45 @@ test(`animation:web: multiple`, async () => { screenshotCompares.push(await page.compareScreenshot()); const ANIMATION_FINISHED = 'onIonAnimationFinished'; - const animationStatus: any = { - 'AnimationRootFinished': false, - 'AnimationAFinished': false, - 'AnimationBFinished': false, - 'AnimationCFinished': false, - 'AnimationCSubAFinished': false - }; + const animationStatus = []; await page.exposeFunction(ANIMATION_FINISHED, (ev: any) => { - console.log(ev.detail) - - // need to check state of animations for on each event - animationStatus[ev.detail] = true; - - console.log(animationStatus) + animationStatus.push(ev.detail); }); const squareA = await page.$('.square-a'); - await listenForEvent(page, 'ionAnimationFinished', squareA, ANIMATION_FINISHED) - + await listenForEvent(page, 'ionAnimationFinished', squareA, ANIMATION_FINISHED); + await page.click('.play'); await page.waitForSelector('.play'); - - await waitForFunctionTestContext((payload: any) => { - return payload.animationStatus['AnimationRootFinished'] === true; - }, { animationStatus }); - - // need to ensure all other animations resolved + await waitForFunctionTestContext((payload: any) => { + return payload.animationStatus.join(', ') === ['AnimationBFinished', 'AnimationCSubAFinished', 'AnimationCFinished', 'AnimationAFinished', 'AnimationRootFinished'].join(', '); + + }, { animationStatus }); screenshotCompares.push(await page.compareScreenshot()); }); -/* -test(`animation:css: basic`, async () => { - const page = await newE2EPage({ url: '/src/utils/animation/test/basic?ionic:_forceCSSAnimations=true' }); - - page.evaluate(() => window.Ionic.config._forceCSSAnimations = true); - +test(`animation:css: multiple`, async () => { + const page = await newE2EPage({ url: '/src/utils/animation/test/multiple?ionic:_forceCSSAnimations=true' }); const screenshotCompares = []; screenshotCompares.push(await page.compareScreenshot()); const ANIMATION_FINISHED = 'onIonAnimationFinished'; - const animationFinishedCount: any = { count: 0 }; - await page.exposeFunction(ANIMATION_FINISHED, () => { - animationFinishedCount.count += 1; + const animationStatus = []; + await page.exposeFunction(ANIMATION_FINISHED, (ev: any) => { + animationStatus.push(ev.detail); }); - const square = await page.$('.square-a'); - await listenForEvent(page, 'ionAnimationFinished', square, ANIMATION_FINISHED); + const squareA = await page.$('.square-a'); + await listenForEvent(page, 'ionAnimationFinished', squareA, ANIMATION_FINISHED); await page.click('.play'); await page.waitForSelector('.play'); await waitForFunctionTestContext((payload: any) => { - return payload.animationFinishedCount.count === 1; - }, { animationFinishedCount }); + return payload.animationStatus.join(', ') === ['AnimationBFinished', 'AnimationCSubAFinished', 'AnimationCFinished', 'AnimationAFinished', 'AnimationRootFinished'].join(', '); + }, { animationStatus }); screenshotCompares.push(await page.compareScreenshot()); }); -*/ diff --git a/core/src/utils/animation/test/multiple/index.html b/core/src/utils/animation/test/multiple/index.html index 6fced0a0c1..cb08559a4b 100644 --- a/core/src/utils/animation/test/multiple/index.html +++ b/core/src/utils/animation/test/multiple/index.html @@ -20,16 +20,15 @@ const squareCText = document.querySelectorAll('.square-c .text'); const rootAnimation = createAnimation(); - const animationA = createAnimation('animation-a'); - const animationB = createAnimation('animation-b'); - const animationC = createAnimation('animation-c'); - - const animationCSubA = createAnimation('animation-c-sub-a'); + const animationA = createAnimation(); + const animationB = createAnimation(); + const animationC = createAnimation(); + const animationCSubA = createAnimation(); animationA .addElement(squareA) - .duration(2000) - .delay(5000) + .duration(500) + .delay(3500) .easing('linear') .iterations(1) .keyframes([ @@ -51,7 +50,7 @@ animationB .addElement(squareB) .duration(500) - .delay(2000) + .delay(1000) .easing('ease-in-out') .iterations(1) .keyframes([ @@ -72,7 +71,7 @@ animationC .addElement(squareC) - .duration(2000) + .duration(1000) .delay(500) .easing('ease-in-out') .iterations(1) @@ -94,8 +93,8 @@ animationCSubA .addElement(squareCText) - .duration(1000) - .delay(3000) + .duration(500) + .delay(2000) .fromTo('color', 'red', 'blue') .onFinish(() => { const ev = new CustomEvent('ionAnimationFinished', { detail: 'AnimationCSubAFinished' }); diff --git a/core/src/utils/transition/md.transition.ts b/core/src/utils/transition/md.transition.ts index 907ea2137e..17d9d937cb 100644 --- a/core/src/utils/transition/md.transition.ts +++ b/core/src/utils/transition/md.transition.ts @@ -2,61 +2,60 @@ import { IonicAnimation } from '../../interface'; import { createAnimation } from '../animation/animation'; import { TransitionOptions } from '../transition'; -export const mdTransitionAnimation = (opts: TransitionOptions): IonicAnimation => { - try { - const OFF_BOTTOM = '40px'; - const CENTER = '0px'; +export const mdTransitionAnimation = (_: HTMLElement, opts: TransitionOptions): IonicAnimation => { + const OFF_BOTTOM = '40px'; + const CENTER = '0px'; - const rootAnimation = createAnimation(); + const backDirection = (opts.direction === 'back'); + const enteringEl = opts.enteringEl; + const leavingEl = opts.leavingEl; - const enteringEl = opts.enteringEl; - const leavingEl = opts.leavingEl; - const backDirection = (opts.direction === 'back'); + const ionPageElement = getIonPageElement(enteringEl); + const enteringToolbarEle = ionPageElement.querySelector('ion-toolbar'); + const rootTransition = createAnimation(); - const ionPageElement = getIonPageElement(enteringEl); - const enteringToolbarEle = ionPageElement.querySelector('ion-toolbar'); + rootTransition + .addElement(ionPageElement) + .beforeRemoveClass('ion-page-invisible'); - rootAnimation - .addElement(ionPageElement) - .beforeRemoveClass('ion-page-invisible') - .fill('both'); + // animate the component itself + if (backDirection) { + rootTransition + .duration(opts.duration || 200) + .easing('cubic-bezier(0.47,0,0.745,0.715)'); - if (backDirection) { - rootAnimation - .duration(opts.duration || 200) - .easing('cubic-bezier(0.47,0,0.745,0.715)'); - } else { - rootAnimation - .duration(opts.duration || 280) - .easing('cubic-bezier(0.36,0.66,0.04,1)') - .fromTo('transform', `translateY(${OFF_BOTTOM})`, `translateY(${CENTER})`) - .fromTo('opacity', 0.01, 1); - } - - if (enteringToolbarEle) { - const enteringToolBarAnimation = createAnimation(); - enteringToolBarAnimation.addElement(enteringToolbarEle); - rootAnimation.addAnimation(enteringToolBarAnimation); - } - - if (leavingEl && backDirection) { - rootAnimation - .duration(opts.duration || 200) - .easing('cubic-bezier(0.47,0,0.745,0.715)'); - - const leavingPageAnimation = createAnimation(); - leavingPageAnimation - .addElement(getIonPageElement(leavingEl)) - .fromTo('transform', `translateY(${CENTER})`, `translateY(${OFF_BOTTOM})`) - .fromTo('opacity', 1, 0); - - rootAnimation.addAnimation(leavingPageAnimation); - } - - return rootAnimation; - } catch (err) { - throw err; + } else { + rootTransition + .duration(opts.duration || 280) + .easing('cubic-bezier(0.36,0.66,0.04,1)') + .fromTo('transform', `translateY(${OFF_BOTTOM})`, `translateY(${CENTER})`) + .fromTo('opacity', 0.01, 1); } + + // Animate toolbar if it's there + if (enteringToolbarEle) { + const enteringToolBar = createAnimation(); + enteringToolBar.addElement(enteringToolbarEle); + rootTransition.addAnimation(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 = createAnimation(); + leavingPage + .addElement(getIonPageElement(leavingEl)) + .fromTo('transform', `translateY(${CENTER})`, `translateY(${OFF_BOTTOM})`) + .fromTo('opacity', 1, 0); + + rootTransition.addAnimation(leavingPage); + } + + return rootTransition; }; const getIonPageElement = (element: HTMLElement) => {