mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
add base tests
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
71
core/src/utils/animation/test/multiple/e2e.ts
Normal file
71
core/src/utils/animation/test/multiple/e2e.ts
Normal 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());
|
||||
});
|
||||
*/
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -182,6 +182,7 @@ export interface IonicConfig {
|
||||
persistConfig?: boolean;
|
||||
_forceStatusbarPadding?: boolean;
|
||||
_testing?: boolean;
|
||||
_forceCSSAnimations?: boolean;
|
||||
_zoneGate?: (h: () => any) => any;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user