add base tests

This commit is contained in:
Liam DeBeasi
2019-07-26 16:39:28 -04:00
parent d8df74ef82
commit 085f5df0b7
11 changed files with 151 additions and 36 deletions

View File

@@ -24,8 +24,8 @@ export interface Animation {
addAnimation(animationToADd: Animation | Animation[] | undefined | null): Animation;
addElement(el: Element | Element[] | Node | Node[] | NodeList | undefined | null): Animation;
iterations(iterations: number): Animation;
fill(fill: 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined): Animation;
direction(direction: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined): Animation;
fill(fill: AnimationFill | undefined): Animation;
direction(direction: AnimationDirection | undefined): Animation;
duration(duration: number): Animation;
easing(easing: string): Animation;
delay(delay: number): Animation;
@@ -33,8 +33,8 @@ export interface Animation {
parent(animation: Animation): Animation;
getKeyframes(): any[];
getDirection(): 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined;
getFill(): 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined;
getDirection(): AnimationDirection | undefined;
getFill(): AnimationFill | undefined;
getDelay(): number | undefined;
getIterations(): number | undefined;
getEasing(): string | undefined;
@@ -56,3 +56,6 @@ export interface Animation {
onFinish(callback: any): Animation;
}
export type AnimationDirection = 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
export type AnimationFill = 'auto' | 'none' | 'forwards' | 'backwards' | 'both';

View File

@@ -1,8 +1,13 @@
import { Animation } from './animation-interface';
import { Animation, AnimationDirection, AnimationFill } from './animation-interface';
import { addClassToArray, animationEnd, createKeyframeStylesheet, generateKeyframeString } from './animation-utils';
let counter = 0;
/**
* HACKY
*/
const _forceCSSAnimations = new URLSearchParams(window.location.search).get('ionic:_forceCSSAnimations');
export const createAnimation = () => {
const elements: HTMLElement[] = [];
const childAnimations: Animation[] = [];
@@ -45,7 +50,7 @@ export const createAnimation = () => {
const _afterAddReadFunctions: any[] = [];
const _afterAddWriteFunctions: any[] = [];
const supportsWebAnimations = !!(window as any).Animation;
const supportsWebAnimations = !!(window as any).Animation && _forceCSSAnimations !== null;
/**
* Destroy this animation and all child animations.
@@ -213,14 +218,14 @@ export const createAnimation = () => {
return ani;
};
const getFill = (): 'auto' | 'none' | 'forwards' | 'backwards' | 'both' | undefined => {
const getFill = () => {
if (_fill !== undefined) { return _fill; }
if (parentAnimation) { return parentAnimation.getFill(); }
return undefined;
};
const getDirection = (): 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' | undefined => {
const getDirection = () => {
if (shouldForceReverseDirection) { return 'reverse'; }
if (_direction !== undefined) { return _direction; }
if (parentAnimation) { return parentAnimation.getDirection(); }
@@ -229,7 +234,7 @@ export const createAnimation = () => {
};
const getEasing = (): string | undefined => {
const getEasing = () => {
if (shouldForceLinearEasing) { return 'linear'; }
if (_easing !== undefined) { return _easing; }
if (parentAnimation) { return parentAnimation.getEasing(); }
@@ -237,7 +242,7 @@ export const createAnimation = () => {
return undefined;
};
const getDuration = (): number | undefined => {
const getDuration = () => {
if (shouldForceSyncPlayback) { return 0; }
if (_duration !== undefined) { return _duration; }
if (parentAnimation) { return parentAnimation.getDuration(); }
@@ -245,21 +250,21 @@ export const createAnimation = () => {
return undefined;
};
const getIterations = (): number | undefined => {
const getIterations = () => {
if (_iterations !== undefined) { return _iterations; }
if (parentAnimation) { return parentAnimation.getIterations(); }
return undefined;
};
const getDelay = (): number | undefined => {
const getDelay = () => {
if (_delay !== undefined) { return _delay; }
if (parentAnimation) { return parentAnimation.getDelay(); }
return undefined;
};
const getKeyframes = (): any[] => {
const getKeyframes = () => {
return _keyframes;
};
@@ -269,13 +274,13 @@ export const createAnimation = () => {
return ani;
};
const direction = (animationDirection: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse') => {
const direction = (animationDirection: AnimationDirection) => {
_direction = animationDirection;
return ani;
};
const fill = (animationFill: 'auto' | 'none' | 'forwards' | 'backwards' | 'both') => {
const fill = (animationFill: AnimationFill) => {
_fill = animationFill;
return ani;
@@ -469,7 +474,7 @@ export const createAnimation = () => {
iterationsCount = (getIterations() === Infinity) ? 'infinite' : getIterations()!.toString();
}
element.style.setProperty('animation-iteration-countion', iterationsCount);
element.style.setProperty('animation-iteration-count', iterationsCount);
element.style.setProperty('animation-play-state', 'paused');
}
});
@@ -540,8 +545,8 @@ export const createAnimation = () => {
elements.forEach(element => {
if (_keyframes.length > 0) {
(element as HTMLElement).style.animationDelay = animationDuration;
(element as HTMLElement).style.animationPlayState = 'paused';
element.style.setProperty('animation-delay', animationDuration);
element.style.setProperty('animation-play-state', 'paused');
}
});
}
@@ -643,7 +648,7 @@ export const createAnimation = () => {
return ani;
};
const playAsync = (): Promise<Animation> => {
const playAsync = () => {
return new Promise(resolve => {
onFinish(resolve);
play();
@@ -799,5 +804,5 @@ export const createAnimation = () => {
progressStart,
progressStep,
progressEnd
};
} as Animation;
};

View File

@@ -2,8 +2,37 @@ import { newE2EPage } from '@stencil/core/testing';
import { listenForEvent, waitForFunctionTestContext } from '../../../test/utils';
test(`animation: basic`, async () => {
const page = await newE2EPage({ url: '/src/utils/animation/test/basic?ionic:_testing=true' });
test(`animation:web: basic`, async () => {
const page = await newE2EPage({ url: '/src/utils/animation/test/basic' });
const screenshotCompares = [];
screenshotCompares.push(await page.compareScreenshot());
const ANIMATION_FINISHED = 'onIonAnimationFinished';
const animationFinishedCount: any = { count: 0 };
await page.exposeFunction(ANIMATION_FINISHED, () => {
console.log('yay');
animationFinishedCount.count += 1;
});
const square = await page.$('.square-a');
await listenForEvent(page, 'ionAnimationFinished', square, ANIMATION_FINISHED);
await page.click('.play');
await page.waitForSelector('.play');
await waitForFunctionTestContext((payload: any) => {
return payload.animationFinishedCount.count === 1;
}, { animationFinishedCount });
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);
const screenshotCompares = [];
screenshotCompares.push(await page.compareScreenshot());

View File

@@ -15,7 +15,7 @@
import { createAnimation } from '../../../../dist/index.mjs';
const squareA = document.querySelector('.square-a');
const rootAnimation = createAnimation();
rootAnimation
@@ -36,6 +36,7 @@
document.querySelector('.play').addEventListener('click', () => {
rootAnimation.play();
});
</script>
<style>

View File

@@ -12,7 +12,7 @@
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<script type="module">
import { createAnimation } from '../../../../dist/collection/utils/animation/animation.js';
import { createAnimation } from '../../../../dist/index.mjs';
const squareA = document.querySelectorAll('.square-a');
const squareB = document.querySelectorAll('.square-b');

View File

@@ -12,7 +12,7 @@
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<script type="module">
import { createAnimation } from '../../../../dist/collection/utils/animation/animation.js';
import { createAnimation } from '../../../../dist/index.mjs';
const grid = document.querySelector('.grid-container');

View File

@@ -0,0 +1,71 @@
import { newE2EPage } from '@stencil/core/testing';
import { listenForEvent, waitForFunctionTestContext } from '../../../test/utils';
test(`animation:web: multiple`, async () => {
const page = await newE2EPage({ url: '/src/utils/animation/test/multiple' });
const screenshotCompares = [];
screenshotCompares.push(await page.compareScreenshot());
const ANIMATION_FINISHED = 'onIonAnimationFinished';
const animationStatus: any = {
'AnimationRootFinished': false,
'AnimationAFinished': false,
'AnimationBFinished': false,
'AnimationCFinished': false,
'AnimationCSubAFinished': false
};
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)
});
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.animationStatus['AnimationRootFinished'] === true;
}, { animationStatus });
// need to ensure all other animations resolved
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);
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 square = await page.$('.square-a');
await listenForEvent(page, 'ionAnimationFinished', square, ANIMATION_FINISHED);
await page.click('.play');
await page.waitForSelector('.play');
await waitForFunctionTestContext((payload: any) => {
return payload.animationFinishedCount.count === 1;
}, { animationFinishedCount });
screenshotCompares.push(await page.compareScreenshot());
});
*/

View File

@@ -12,11 +12,11 @@
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<script type="module">
import { createAnimation } from '../../../../dist/collection/utils/animation/animation.js';
import { createAnimation } from '../../../../dist/index.mjs';
const squareA = document.querySelectorAll('.square-a');
const squareB = document.querySelectorAll('.square-b');
const squareC = document.querySelectorAll('.square-c');
const squareA = document.querySelector('.square-a');
const squareB = document.querySelector('.square-b');
const squareC = document.querySelector('.square-c');
const squareCText = document.querySelectorAll('.square-c .text');
const rootAnimation = createAnimation();
@@ -44,7 +44,8 @@
'background': 'rgba(0, 255, 0, 0.5)'
})
.onFinish(() => {
console.log('Animation A Done');
const ev = new CustomEvent('ionAnimationFinished', { detail: 'AnimationAFinished' });
squareA.dispatchEvent(ev);
});
animationB
@@ -65,7 +66,8 @@
'background': 'rgba(0, 255, 0, 0.5)'
})
.onFinish(() => {
console.log('Animation B Done');
const ev = new CustomEvent('ionAnimationFinished', { detail: 'AnimationBFinished' });
squareA.dispatchEvent(ev);
});
animationC
@@ -86,7 +88,8 @@
'background': 'rgba(0, 255, 0, 0.5)'
})
.onFinish(() => {
console.log('Animation C Done')
const ev = new CustomEvent('ionAnimationFinished', { detail: 'AnimationCFinished' });
squareA.dispatchEvent(ev);
});
animationCSubA
@@ -95,7 +98,8 @@
.delay(3000)
.fromTo('color', 'red', 'blue')
.onFinish(() => {
console.log('Animation CSubA Done');
const ev = new CustomEvent('ionAnimationFinished', { detail: 'AnimationCSubAFinished' });
squareA.dispatchEvent(ev);
});
animationC.addAnimation(animationCSubA);
@@ -103,7 +107,8 @@
rootAnimation
.addAnimation([animationA, animationB, animationC])
.onFinish(() => {
console.log('Root Animation Done');
const ev = new CustomEvent('ionAnimationFinished', { detail: 'AnimationRootFinished' });
squareA.dispatchEvent(ev);
});
document.querySelector('.play').addEventListener('click', () => {

View File

@@ -12,7 +12,7 @@
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<script type="module">
import { createAnimation } from '../../../../dist/collection/utils/animation/animation.js';
import { createAnimation } from '../../../../dist/index.mjs';
const square = document.querySelectorAll('.square');
const animation = createAnimation('animation-a');

View File

@@ -182,6 +182,7 @@ export interface IonicConfig {
persistConfig?: boolean;
_forceStatusbarPadding?: boolean;
_testing?: boolean;
_forceCSSAnimations?: boolean;
_zoneGate?: (h: () => any) => any;
}

View File

@@ -35,7 +35,7 @@ export const listenForEvent = async (page: any, eventType: string, element: any,
try {
return await page.evaluate((scopeEventType: string, scopeElement: any, scopeCallbackName: string) => {
scopeElement.addEventListener(scopeEventType, (e: any) => {
(window as any)[scopeCallbackName](e);
(window as any)[scopeCallbackName]({ detail: e.detail });
});
}, eventType, element, callbackName);
} catch (err) {