kopia lustrzana https://github.com/wagtail/wagtail
Create `transition` util to resolve a promise when an animation ends
rodzic
4760509d65
commit
d42af56220
client/src/utils
|
@ -0,0 +1,83 @@
|
|||
import { transition } from './transition';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
describe('transition', () => {
|
||||
beforeAll(() => {
|
||||
document.body.innerHTML = `<main id="main"></main>`;
|
||||
});
|
||||
|
||||
it('should resolve the immediately if maxDelay is 0 or falsy', async () => {
|
||||
expect(
|
||||
await transition(document.getElementById('main'), { maxDelay: 0 }),
|
||||
).toBe(null);
|
||||
|
||||
expect(
|
||||
await transition(document.getElementById('main'), { maxDelay: false }),
|
||||
).toBe(null);
|
||||
|
||||
expect(
|
||||
await transition(document.getElementById('main'), { maxDelay: -1 }),
|
||||
).toBe(null);
|
||||
});
|
||||
|
||||
it('should resolve after the maxDelay (350ms) if no events are fired', async () => {
|
||||
const resolve = jest.fn();
|
||||
|
||||
transition(document.getElementById('main')).then(resolve);
|
||||
|
||||
await jest.advanceTimersByTimeAsync(200);
|
||||
|
||||
expect(resolve).not.toHaveBeenCalled();
|
||||
|
||||
await jest.advanceTimersByTimeAsync(149);
|
||||
|
||||
expect(resolve).not.toHaveBeenCalled();
|
||||
|
||||
await jest.advanceTimersByTimeAsync(1);
|
||||
|
||||
expect(resolve).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should resolve if transitionend or animationend is fired', async () => {
|
||||
const resolve = jest.fn();
|
||||
|
||||
transition(document.getElementById('main')).then(resolve);
|
||||
|
||||
await jest.advanceTimersByTimeAsync(200);
|
||||
|
||||
expect(resolve).not.toHaveBeenCalled();
|
||||
|
||||
const event = new Event('transitionend', {
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
});
|
||||
|
||||
document.getElementById('main').dispatchEvent(event);
|
||||
|
||||
await jest.advanceTimersByTimeAsync(0);
|
||||
|
||||
expect(resolve).toHaveBeenCalledWith(event);
|
||||
});
|
||||
|
||||
it('should resolve if animationend is fired', async () => {
|
||||
const resolve = jest.fn();
|
||||
|
||||
transition(document.getElementById('main')).then(resolve);
|
||||
|
||||
await jest.advanceTimersByTimeAsync(200);
|
||||
|
||||
expect(resolve).not.toHaveBeenCalled();
|
||||
|
||||
const event = new Event('animationend', {
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
});
|
||||
|
||||
document.getElementById('main').dispatchEvent(event);
|
||||
|
||||
await jest.advanceTimersByTimeAsync(0);
|
||||
|
||||
expect(resolve).toHaveBeenCalledWith(event);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Returns a promise that will resolve after either the animation, transition
|
||||
* or the max delay of time is reached.
|
||||
*
|
||||
* If `maxDelay` is provided as zero or a falsy value, the promise resolve immediately.
|
||||
*/
|
||||
export const transition = (element: HTMLElement, { maxDelay = 350 } = {}) =>
|
||||
new Promise<AnimationEvent | TransitionEvent | null>((resolve) => {
|
||||
if (!maxDelay || maxDelay <= 0) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let timer: number | undefined;
|
||||
|
||||
const finish = (event: AnimationEvent | TransitionEvent | null) => {
|
||||
if (event && event.target !== element) return;
|
||||
window.clearTimeout(timer);
|
||||
element.removeEventListener('transitionend', finish);
|
||||
element.removeEventListener('animationend', finish);
|
||||
resolve(event || null);
|
||||
};
|
||||
|
||||
element.addEventListener('animationend', finish);
|
||||
element.addEventListener('transitionend', finish);
|
||||
timer = window.setTimeout(finish, maxDelay);
|
||||
});
|
Ładowanie…
Reference in New Issue