Skip to content

Commit 5a9b53b

Browse files
authoredSep 3, 2023
Merge pull request #51 from trurl-master/dont-error-on-other-envs
Remove dependency on window during import time
2 parents 684f710 + 9b0dc92 commit 5a9b53b

15 files changed

+163
-39
lines changed
 

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jsdom-testing-mocks",
3-
"version": "1.9.0",
3+
"version": "1.10.0",
44
"author": "Ivan Galiatin",
55
"license": "MIT",
66
"description": "A set of tools for emulating browser behavior in jsdom environment",

‎src/helper.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,23 @@ export class UndefinedHookError extends Error {
44

55
// @ts-ignore
66
if (typeof global?.['vi'] !== 'undefined') {
7-
message = `Jsdom Testing Mocks: ${hook} is not defined. You can enable globals in your config or pass the hook manually to the configMocks function`;
7+
message = `jsdom-testing-mocks: ${hook} is not defined. You can enable globals in your config or pass the hook manually to the configMocks function`;
88
} else {
9-
message = `Jsdom Testing Mocks: ${hook} is not defined. If you need to pass it manually, please use the configMocks function`;
9+
message = `jsdom-testing-mocks: ${hook} is not defined. If you need to pass it manually, please use the configMocks function`;
1010
}
1111

1212
super(message);
1313
}
1414
}
15+
16+
export class WrongEnvironmentError extends Error {
17+
constructor() {
18+
super(
19+
'jsdom-testing-mocks: window is not defined. Please use this library in a browser environment'
20+
);
21+
}
22+
}
23+
24+
export const isJsdomEnv = () => {
25+
return typeof window !== 'undefined';
26+
};

‎src/mocks/MediaQueryListEvent.ts

+17-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
export class MockedMediaQueryListEvent
2-
extends Event
3-
implements MediaQueryListEvent
4-
{
1+
import { isJsdomEnv, WrongEnvironmentError } from '../helper';
2+
3+
class MockedMediaQueryListEvent extends Event implements MediaQueryListEvent {
54
readonly matches: boolean;
65
readonly media: string;
76

@@ -13,10 +12,18 @@ export class MockedMediaQueryListEvent
1312
}
1413
}
1514

16-
if (typeof MediaQueryListEvent === 'undefined') {
17-
Object.defineProperty(window, 'MediaQueryListEvent', {
18-
writable: true,
19-
configurable: true,
20-
value: MockedMediaQueryListEvent,
21-
});
15+
function mockMediaQueryListEvent() {
16+
if (!isJsdomEnv()) {
17+
throw new WrongEnvironmentError();
18+
}
19+
20+
if (typeof MediaQueryListEvent === 'undefined') {
21+
Object.defineProperty(window, 'MediaQueryListEvent', {
22+
writable: true,
23+
configurable: true,
24+
value: MockedMediaQueryListEvent,
25+
});
26+
}
2227
}
28+
29+
export { MockedMediaQueryListEvent, mockMediaQueryListEvent };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
import { WrongEnvironmentError } from '../helper';
6+
import { mockIntersectionObserver } from './intersection-observer';
7+
8+
describe('mockIntersectionObserver', () => {
9+
it('throws an error when used in a non jsdom environment', () => {
10+
expect(() => {
11+
mockIntersectionObserver();
12+
}).toThrowError(WrongEnvironmentError);
13+
});
14+
});

‎src/mocks/intersection-observer.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Writable, PartialDeep } from 'type-fest';
2-
import './size/DOMRect';
2+
import { mockDOMRect } from './size/DOMRect';
33
import { getConfig } from '../tools';
4+
import { isJsdomEnv, WrongEnvironmentError } from '../helper';
45

56
const config = getConfig();
67

@@ -192,6 +193,12 @@ export class MockedIntersectionObserver implements IntersectionObserver {
192193
}
193194

194195
function mockIntersectionObserver() {
196+
if (!isJsdomEnv()) {
197+
throw new WrongEnvironmentError();
198+
}
199+
200+
mockDOMRect();
201+
195202
const savedImplementation = window.IntersectionObserver;
196203

197204
Object.defineProperty(window, 'IntersectionObserver', {

‎src/mocks/resize-observer.env.test.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
import { WrongEnvironmentError } from '../helper';
6+
import { mockResizeObserver } from './resize-observer';
7+
8+
describe('mockResizeObserver', () => {
9+
it('throws an error when used in a non jsdom environment', () => {
10+
expect(() => {
11+
mockResizeObserver();
12+
}).toThrowError(WrongEnvironmentError);
13+
});
14+
});

‎src/mocks/resize-observer.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { RequireAtLeastOne } from 'type-fest';
2+
import { mockDOMRect } from './size/DOMRect';
3+
import { isJsdomEnv, WrongEnvironmentError } from '../helper';
24
import { getConfig } from '../tools';
35

46
const config = getConfig();
@@ -142,6 +144,12 @@ function elementToEntry(element: HTMLElement): ResizeObserverEntry | null {
142144
}
143145

144146
function mockResizeObserver() {
147+
if (!isJsdomEnv()) {
148+
throw new WrongEnvironmentError();
149+
}
150+
151+
mockDOMRect();
152+
145153
const savedImplementation = window.ResizeObserver;
146154

147155
Object.defineProperty(window, 'ResizeObserver', {
@@ -290,10 +298,4 @@ function mockResizeObserver() {
290298
};
291299
}
292300

293-
const { mockElementSize } = mockResizeObserver();
294-
295-
mockElementSize(document.body, {
296-
contentBoxSize: [{ blockSize: 100, inlineSize: 100 }],
297-
});
298-
299301
export { mockResizeObserver };

‎src/mocks/size/DOMRect.env.test.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
import { WrongEnvironmentError } from '../../helper';
6+
import { mockDOMRect } from './DOMRect';
7+
8+
describe('mockDOMRect', () => {
9+
it('throws an error when used in a non jsdom environment', () => {
10+
expect(() => {
11+
mockDOMRect();
12+
}).toThrowError(WrongEnvironmentError);
13+
});
14+
});

‎src/mocks/size/DOMRect.test.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/* eslint-disable @typescript-eslint/ban-ts-comment */
2-
import './DOMRect';
2+
import { mockDOMRect } from './DOMRect';
3+
4+
mockDOMRect();
35

46
describe('DOMRectReadOnly', () => {
57
test('constructor and props', () => {

‎src/mocks/size/DOMRect.ts

+24-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { isJsdomEnv, WrongEnvironmentError } from '../../helper';
2+
13
const protectedProps = ['_x', '_y', '_width', '_height'];
24

35
class MockedDOMRectReadOnly implements DOMRectReadOnly {
@@ -107,7 +109,7 @@ class MockedDOMRectReadOnly implements DOMRectReadOnly {
107109
}
108110
}
109111

110-
export class MockedDOMRect extends MockedDOMRectReadOnly implements DOMRect {
112+
class MockedDOMRect extends MockedDOMRectReadOnly implements DOMRect {
111113
constructor(x = 0, y = 0, width = 0, height = 0) {
112114
super(x, y, width, height);
113115
}
@@ -149,18 +151,26 @@ export class MockedDOMRect extends MockedDOMRectReadOnly implements DOMRect {
149151
}
150152
}
151153

152-
if (typeof DOMRectReadOnly === 'undefined') {
153-
Object.defineProperty(window, 'DOMRectReadOnly', {
154-
writable: true,
155-
configurable: true,
156-
value: MockedDOMRectReadOnly,
157-
});
158-
}
154+
function mockDOMRect() {
155+
if (!isJsdomEnv()) {
156+
throw new WrongEnvironmentError();
157+
}
159158

160-
if (typeof DOMRect === 'undefined') {
161-
Object.defineProperty(window, 'DOMRect', {
162-
writable: true,
163-
configurable: true,
164-
value: MockedDOMRect,
165-
});
159+
if (typeof DOMRectReadOnly === 'undefined') {
160+
Object.defineProperty(window, 'DOMRectReadOnly', {
161+
writable: true,
162+
configurable: true,
163+
value: MockedDOMRectReadOnly,
164+
});
165+
}
166+
167+
if (typeof DOMRect === 'undefined') {
168+
Object.defineProperty(window, 'DOMRect', {
169+
writable: true,
170+
configurable: true,
171+
value: MockedDOMRect,
172+
});
173+
}
166174
}
175+
176+
export { MockedDOMRectReadOnly, MockedDOMRect, mockDOMRect };

‎src/mocks/size/size.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import './DOMRect';
1+
import { mockDOMRect } from './DOMRect';
22

33
export const mockElementBoundingClientRect = (
44
element: HTMLElement,
@@ -9,6 +9,8 @@ export const mockElementBoundingClientRect = (
99
height = 0,
1010
}: Partial<Pick<DOMRect, 'x' | 'y' | 'width' | 'height'>>
1111
) => {
12+
mockDOMRect();
13+
1214
const savedImplementation = element.getBoundingClientRect;
1315

1416
element.getBoundingClientRect = () =>

‎src/mocks/viewport.env.test.tsx

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
import { WrongEnvironmentError } from '../helper';
6+
import { mockViewport } from './viewport';
7+
8+
describe('mockViewport', () => {
9+
it('throws an error when used in a non jsdom environment', () => {
10+
expect(() => {
11+
mockViewport({ width: 0, height: 0 });
12+
}).toThrowError(WrongEnvironmentError);
13+
});
14+
});

‎src/mocks/viewport.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import mediaQuery, { MediaValues } from 'css-mediaquery';
2-
import './MediaQueryListEvent';
2+
import { mockMediaQueryListEvent } from './MediaQueryListEvent';
33
import { getConfig } from '../tools';
4+
import { isJsdomEnv, WrongEnvironmentError } from '../helper';
45

56
const config = getConfig();
67

78
/**
8-
* A tool that allows testing components that use js media queries (matchMedia)
9+
* A tool that allows testing components that use js media queries (matchMedia)
910
* `mockViewport` must be called before rendering the component
10-
* @example using react testing library
11+
* @example using react testing library
1112
*
1213
* const viewport = mockViewport({ width: '320px', height: '568px' })
1314
*
@@ -46,6 +47,12 @@ function isEventListenerObject(
4647
}
4748

4849
function mockViewport(desc: ViewportDescription): MockViewport {
50+
if (!isJsdomEnv()) {
51+
throw new WrongEnvironmentError();
52+
}
53+
54+
mockMediaQueryListEvent();
55+
4956
const state: {
5057
currentDesc: ViewportDescription;
5158
oldListeners: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @jest-environment node
3+
*/
4+
5+
import { WrongEnvironmentError } from '../../../helper';
6+
import { mockAnimationsApi } from '../';
7+
8+
describe('mockAnimationsApi', () => {
9+
it('throws an error when used in a non jsdom environment', () => {
10+
expect(() => {
11+
mockAnimationsApi();
12+
}).toThrowError(WrongEnvironmentError);
13+
});
14+
});

‎src/mocks/web-animations-api/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
clearAnimations,
66
} from './elementAnimations';
77
import { getConfig } from '../../tools';
8+
import { isJsdomEnv, WrongEnvironmentError } from '../../helper';
89

910
const config = getConfig();
1011

@@ -26,6 +27,10 @@ function animate(
2627
}
2728

2829
function mockAnimationsApi() {
30+
if (!isJsdomEnv()) {
31+
throw new WrongEnvironmentError();
32+
}
33+
2934
const savedAnimate = Element.prototype.animate;
3035
const savedGetAnimations = Element.prototype.getAnimations;
3136
const savedGetAllAnimations = Document.prototype.getAnimations;

0 commit comments

Comments
 (0)
Please sign in to comment.