Skip to content

Commit

Permalink
Hide animation mocks inside a function
Browse files Browse the repository at this point in the history
  • Loading branch information
trurl-master committed Jul 31, 2022
1 parent 824062f commit 570b0c3
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 136 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsdom-testing-mocks",
"version": "1.5.0-beta.5",
"version": "1.5.0-beta.6",
"author": "Ivan Galiatin",
"license": "MIT",
"description": "A set of tools for emulating browser behavior in jsdom environment",
Expand Down
39 changes: 25 additions & 14 deletions src/mocks/web-animations-api/Animation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import './AnimationEffect';
import './KeyframeEffect';
import './AnimationPlaybackEvent';
import './DocumentTimeline';
import { mockKeyframeEffect } from './KeyframeEffect';
import { mockAnimationPlaybackEvent } from './AnimationPlaybackEvent';
import { mockDocumentTimeline } from './DocumentTimeline';
import { getEasingFunctionFromString } from './easingFunctions';

type ActiveAnimationTimeline = AnimationTimeline & {
Expand Down Expand Up @@ -167,6 +166,11 @@ class MockedAnimation extends EventTarget implements Animation {
});
}

#silentlyRejectFinishedPromise(error: Error) {
this.#finishedPromise.catch(noop);
this.#resolvers.finished.reject(error);
}

#hasPendingTask() {
return this.#pendingPauseTask || this.#pendingPlayTask;
}
Expand Down Expand Up @@ -401,7 +405,9 @@ class MockedAnimation extends EventTarget implements Animation {
this.#applyPendingPlaybackRate();

// 5. Reject animation’s current ready promise with a DOMException named "AbortError".
this.#resolvers.ready.reject(new DOMException('AbortError'));
this.#silentlyRejectFinishedPromise(
new DOMException(undefined, 'AbortError')
);

// 6. Set the [[PromiseIsHandled]] internal slot of animation’s current ready promise to true.

Expand Down Expand Up @@ -1145,8 +1151,7 @@ class MockedAnimation extends EventTarget implements Animation {
this.#resetPendingTasks();

// Reject the current finished promise with a DOMException named "AbortError".
// this.#resolvers.finished.reject(new DOMException('AbortError'));
this.#resolvers.finished.reject(
this.#silentlyRejectFinishedPromise(
new DOMException('The user aborted a request.', 'AbortError')
);

Expand Down Expand Up @@ -1688,12 +1693,18 @@ class MockedAnimation extends EventTarget implements Animation {
}
}

if (typeof Animation === 'undefined') {
Object.defineProperty(window, 'Animation', {
writable: true,
configurable: true,
value: MockedAnimation,
});
function mockAnimation() {
mockKeyframeEffect();
mockAnimationPlaybackEvent();
mockDocumentTimeline();

if (typeof Animation === 'undefined') {
Object.defineProperty(window, 'Animation', {
writable: true,
configurable: true,
value: MockedAnimation,
});
}
}

export { MockedAnimation };
export { MockedAnimation, mockAnimation };
4 changes: 3 additions & 1 deletion src/mocks/web-animations-api/AnimationEffect.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import './AnimationEffect';
import { mockAnimationEffect } from './AnimationEffect';

mockAnimationEffect();

describe('AnimationEffect', () => {
it('should be defined', () => {
Expand Down
16 changes: 9 additions & 7 deletions src/mocks/web-animations-api/AnimationEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ class MockedAnimationEffect implements AnimationEffect {
}
}

if (typeof AnimationEffect === 'undefined') {
Object.defineProperty(window, 'AnimationEffect', {
writable: true,
configurable: true,
value: MockedAnimationEffect,
});
function mockAnimationEffect() {
if (typeof AnimationEffect === 'undefined') {
Object.defineProperty(window, 'AnimationEffect', {
writable: true,
configurable: true,
value: MockedAnimationEffect,
});
}
}

export { MockedAnimationEffect };
export { MockedAnimationEffect, mockAnimationEffect };
22 changes: 14 additions & 8 deletions src/mocks/web-animations-api/AnimationPlaybackEvent.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
class MockedAnimationPlaybackEvent extends Event
implements AnimationPlaybackEvent {
class MockedAnimationPlaybackEvent
extends Event
implements AnimationPlaybackEvent
{
readonly currentTime = null;
readonly timelineTime = null;
}

if (typeof AnimationPlaybackEvent === 'undefined') {
Object.defineProperty(window, 'AnimationPlaybackEvent', {
writable: true,
configurable: true,
value: MockedAnimationPlaybackEvent,
});
function mockAnimationPlaybackEvent() {
if (typeof AnimationPlaybackEvent === 'undefined') {
Object.defineProperty(window, 'AnimationPlaybackEvent', {
writable: true,
configurable: true,
value: MockedAnimationPlaybackEvent,
});
}
}

export { mockAnimationPlaybackEvent };
4 changes: 3 additions & 1 deletion src/mocks/web-animations-api/AnimationTimeline.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import './AnimationTimeline';
import { mockAnimationTimeline } from './AnimationTimeline';

mockAnimationTimeline();

describe('AnimationTimeline', () => {
it('should be defined', () => {
Expand Down
16 changes: 10 additions & 6 deletions src/mocks/web-animations-api/AnimationTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ class MockedAnimationTimeline implements AnimationTimeline {
}
}

if (typeof AnimationTimeline === 'undefined') {
Object.defineProperty(window, 'AnimationTimeline', {
writable: true,
configurable: true,
value: MockedAnimationTimeline,
});
function mockAnimationTimeline() {
if (typeof AnimationTimeline === 'undefined') {
Object.defineProperty(window, 'AnimationTimeline', {
writable: true,
configurable: true,
value: MockedAnimationTimeline,
});
}
}

export { MockedAnimationTimeline, mockAnimationTimeline };
3 changes: 2 additions & 1 deletion src/mocks/web-animations-api/DocumentTimeline.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import './DocumentTimeline';
import { mockDocumentTimeline } from './DocumentTimeline';

mockDocumentTimeline();
jest.useFakeTimers();

describe('DocumentTimeline', () => {
Expand Down
37 changes: 23 additions & 14 deletions src/mocks/web-animations-api/DocumentTimeline.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import './AnimationTimeline';
import {
mockAnimationTimeline,
MockedAnimationTimeline,
} from './AnimationTimeline';

class MockedDocumentTimeline
extends AnimationTimeline
extends MockedAnimationTimeline
implements DocumentTimeline
{
#originTime = 0;
Expand All @@ -17,16 +20,22 @@ class MockedDocumentTimeline
}
}

if (typeof DocumentTimeline === 'undefined') {
Object.defineProperty(window, 'DocumentTimeline', {
writable: true,
configurable: true,
value: MockedDocumentTimeline,
});

Object.defineProperty(Document.prototype, 'timeline', {
writable: true,
configurable: true,
value: new MockedDocumentTimeline(),
});
function mockDocumentTimeline() {
mockAnimationTimeline();

if (typeof DocumentTimeline === 'undefined') {
Object.defineProperty(window, 'DocumentTimeline', {
writable: true,
configurable: true,
value: MockedDocumentTimeline,
});

Object.defineProperty(Document.prototype, 'timeline', {
writable: true,
configurable: true,
value: new MockedDocumentTimeline(),
});
}
}

export { mockDocumentTimeline };
3 changes: 3 additions & 0 deletions src/mocks/web-animations-api/KeyframeEffect.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
MockedKeyframeEffect,
convertPropertyIndexedKeyframes,
mockKeyframeEffect,
} from './KeyframeEffect';

mockKeyframeEffect();

describe('KeyframeEffect', () => {
it('should have correct properties by default', () => {
const element = document.createElement('div');
Expand Down
40 changes: 22 additions & 18 deletions src/mocks/web-animations-api/KeyframeEffect.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MockedAnimationEffect } from "./AnimationEffect";
import { mockAnimationEffect, MockedAnimationEffect } from './AnimationEffect';

/**
Given the structure of PropertyIndexedKeyframes as such:
Expand Down Expand Up @@ -35,7 +35,7 @@ export function convertPropertyIndexedKeyframes(

const piKeyframe = propertyArray[keyframeIndex];

if (typeof piKeyframe === "undefined" || piKeyframe === null) {
if (typeof piKeyframe === 'undefined' || piKeyframe === null) {
continue;
}

Expand All @@ -62,7 +62,7 @@ class MockedKeyframeEffect
extends MockedAnimationEffect
implements KeyframeEffect
{
composite: CompositeOperation = "replace";
composite: CompositeOperation = 'replace';
iterationComposite: IterationCompositeOperation;
pseudoElement: string | null = null;
target: Element | null;
Expand All @@ -75,17 +75,17 @@ class MockedKeyframeEffect
) {
super();

if (typeof options === "number") {
if (typeof options === 'number') {
options = { duration: options };
}

const { composite, iterationComposite, pseudoElement, ...timing } = options;

this.setKeyframes(keyframes);
this.target = target;
this.composite = composite || "replace";
this.composite = composite || 'replace';
// not actually implemented, just to make ts happy
this.iterationComposite = iterationComposite || "replace";
this.iterationComposite = iterationComposite || 'replace';
this.pseudoElement = pseudoElement || null;
this.updateTiming(timing);
}
Expand All @@ -96,14 +96,14 @@ class MockedKeyframeEffect
keyframes.forEach((keyframe) => {
const offset = keyframe.offset;

if (typeof offset === "number") {
if (typeof offset === 'number') {
if (offset < 0 || offset > 1) {
throw new TypeError(
"Failed to construct 'KeyframeEffect': Offsets must be null or in the range [0,1]."
);
}

if (typeof lastExplicitOffset === "number") {
if (typeof lastExplicitOffset === 'number') {
if (offset < lastExplicitOffset) {
throw new TypeError(
"Failed to construct 'KeyframeEffect': Offsets must be monotonically non-decreasing."
Expand Down Expand Up @@ -131,7 +131,7 @@ class MockedKeyframeEffect
const computedKeyframe = {
offset: offset ?? null,
composite: composite ?? this.composite,
easing: easing ?? "linear",
easing: easing ?? 'linear',
computedOffset: currentOffset,
...keyframe,
};
Expand All @@ -144,7 +144,7 @@ class MockedKeyframeEffect
for (let i = index + 1; i < totalKeyframes; i++) {
const offset = this.#keyframes[i].offset;

if (typeof offset === "number") {
if (typeof offset === 'number') {
nextOffset = offset;
keyframesUntilNextOffset = i - index;
break;
Expand All @@ -157,7 +157,7 @@ class MockedKeyframeEffect
}

const offsetDiff =
typeof keyframesUntilNextOffset === "number" &&
typeof keyframesUntilNextOffset === 'number' &&
keyframesUntilNextOffset > 0
? (nextOffset - currentOffset) / keyframesUntilNextOffset
: 0;
Expand Down Expand Up @@ -186,12 +186,16 @@ class MockedKeyframeEffect
}
}

if (typeof KeyframeEffect === "undefined") {
Object.defineProperty(window, "KeyframeEffect", {
writable: true,
configurable: true,
value: MockedKeyframeEffect,
});
function mockKeyframeEffect() {
mockAnimationEffect();

if (typeof KeyframeEffect === 'undefined') {
Object.defineProperty(window, 'KeyframeEffect', {
writable: true,
configurable: true,
value: MockedKeyframeEffect,
});
}
}

export { MockedKeyframeEffect };
export { MockedKeyframeEffect, mockKeyframeEffect };
10 changes: 4 additions & 6 deletions src/mocks/web-animations-api/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import './Animation';
import { mockAnimation } from './Animation';

const elementAnimations = new Map<Element, Animation[]>();

Expand Down Expand Up @@ -42,13 +42,13 @@ function getAllAnimations() {
return Array.from(elementAnimations.values()).flat();
}

// type MockAnimationsApiOptions = {};

function mockAnimationsApi(/* {}: MockAnimationsApiOptions = {} */) {
function mockAnimationsApi() {
const savedAnimate = Element.prototype.animate;
const savedGetAnimations = Element.prototype.getAnimations;
const savedGetAllAnimations = Document.prototype.getAnimations;

mockAnimation();

Object.defineProperties(Element.prototype, {
animate: {
writable: true,
Expand Down Expand Up @@ -77,8 +77,6 @@ function mockAnimationsApi(/* {}: MockAnimationsApiOptions = {} */) {
Element.prototype.getAnimations = savedGetAnimations;
Document.prototype.getAnimations = savedGetAllAnimations;
});

// return {};
}

export { mockAnimationsApi };
17 changes: 0 additions & 17 deletions src/mocks/web-animations-api/testHelpers.ts

This file was deleted.

Loading

0 comments on commit 570b0c3

Please sign in to comment.