UNPKG

12.4 kBJavaScriptView Raw
1import * as Utils from '../utils';
2
3describe('Utils', () => {
4 describe('mapToCssModules', () => {
5 describe('without css module', () => {
6 it('should return a string', () => {
7 expect(Utils.mapToCssModules('btn btn-primary')).toEqual(
8 expect.any(String),
9 );
10 });
11
12 it('should return the classnames it was given, unchanged', () => {
13 expect(Utils.mapToCssModules('btn btn-primary')).toBe(
14 'btn btn-primary',
15 );
16 });
17 });
18
19 describe('with css module', () => {
20 it('should return a string', () => {
21 const cssModule = {
22 btn: 'a1',
23 'btn-success': 'b1',
24 'btn-primary': 'c2',
25 };
26 expect(Utils.mapToCssModules('btn btn-primary', cssModule)).toEqual(
27 expect.any(String),
28 );
29 });
30
31 it('should return the mapped classnames', () => {
32 const cssModule = {
33 btn: 'a1',
34 'btn-success': 'b1',
35 'btn-primary': 'c2',
36 };
37 expect(Utils.mapToCssModules('btn btn-primary', cssModule)).toBe(
38 'a1 c2',
39 );
40 });
41
42 it('should return the original classname when it is not in the map', () => {
43 const cssModule = {
44 btn: 'a1',
45 'btn-success': 'b1',
46 };
47 expect(Utils.mapToCssModules('btn btn-primary', cssModule)).toBe(
48 'a1 btn-primary',
49 );
50 });
51 });
52 });
53
54 describe('omit', () => {
55 it('should omit keys', () => {
56 const input = {
57 hello: 'world',
58 speed: 'fast',
59 size: 'small',
60 };
61 expect(Utils.omit(input, ['hello'])).toEqual({
62 speed: 'fast',
63 size: 'small',
64 });
65 });
66
67 it('should not alter source object', () => {
68 const input = {
69 hello: 'world',
70 speed: 'fast',
71 size: 'small',
72 };
73 expect(Utils.omit(input, ['hello'])).toEqual({
74 speed: 'fast',
75 size: 'small',
76 });
77 expect(input).toEqual({
78 hello: 'world',
79 speed: 'fast',
80 size: 'small',
81 });
82 });
83
84 it('should ignore non-existing keys', () => {
85 const input = {
86 hello: 'world',
87 speed: 'fast',
88 size: 'small',
89 };
90 expect(Utils.omit(input, ['non-existing', 'hello'])).toEqual({
91 speed: 'fast',
92 size: 'small',
93 });
94 });
95
96 it('should return a new object', () => {
97 const input = {
98 hello: 'world',
99 };
100 // toBe tests equality using `===` and so will test if it's not the same object.
101 expect(Utils.omit(input, [])).not.toBe(input);
102 });
103 });
104
105 describe('DOMElement', () => {
106 it('should not return an error when the prop is an instance of an Element', () => {
107 const props = {
108 dom: document.createElement('div'),
109 };
110 const propName = 'dom';
111 const componentName = 'ComponentName';
112
113 expect(Utils.DOMElement(props, propName, componentName)).toBeUndefined();
114 });
115
116 it('should return an error when the prop is NOT an instance of an Element', () => {
117 const props = {
118 dom: 'not an Element',
119 };
120 const propName = 'dom';
121 const componentName = 'ComponentName';
122
123 expect(Utils.DOMElement(props, propName, componentName)).toEqual(
124 new Error(
125 'Invalid prop `' +
126 propName +
127 '` supplied to `' +
128 componentName +
129 '`. Expected prop to be an instance of Element. Validation failed.',
130 ),
131 );
132 });
133 });
134
135 describe('getTarget', () => {
136 it('should return the result of target if target is a function', () => {
137 const data = {};
138 const spy = jest.fn(() => data);
139 expect(Utils.getTarget(spy)).toEqual(data);
140 expect(spy).toHaveBeenCalled();
141 });
142
143 it('should return all matching elements if allElement param is true', () => {
144 const element = document.createElement('div');
145 element.innerHTML = `<span class='example'>span 1</span>
146 <span class='example'>span 2</span>`;
147 document.body.appendChild(element);
148
149 jest.spyOn(document, 'querySelectorAll');
150 const elements = Utils.getTarget('.example', true);
151 expect(elements.length).toEqual(2);
152 expect(elements[1].textContent).toEqual('span 2');
153 expect(document.querySelectorAll).toHaveBeenCalledWith('.example');
154 document.querySelectorAll.mockRestore();
155 });
156
157 it('should return elements as array like object if allElement param is true', () => {
158 const data = {};
159 const spy = jest.fn(() => data);
160 const elements = Utils.getTarget(spy, true);
161 expect(elements).toHaveProperty('length');
162 expect(elements).toContain(data);
163 expect(spy).toHaveBeenCalled();
164 });
165
166 it('should query the document for the target if the target is a string', () => {
167 const element = document.createElement('div');
168 element.className = 'thing';
169 document.body.appendChild(element);
170 jest.spyOn(document, 'querySelectorAll');
171 expect(Utils.getTarget('.thing')).toEqual(element);
172 expect(document.querySelectorAll).toHaveBeenCalledWith('.thing');
173 document.querySelectorAll.mockRestore();
174 });
175
176 it('should query the document for the id target if the target is a string and could not be found normally', () => {
177 const element = document.createElement('div');
178 element.setAttribute('id', 'thing');
179 document.body.appendChild(element);
180 jest.spyOn(document, 'querySelectorAll');
181 expect(Utils.getTarget('thing')).toEqual(element);
182 expect(document.querySelectorAll).toHaveBeenCalledWith('#thing');
183 document.querySelectorAll.mockRestore();
184 });
185
186 it('should return the input target if it is not a function nor a string', () => {
187 const target = {};
188 expect(Utils.getTarget(target)).toEqual(target);
189 });
190
191 it('should not return an error when the target could be identified', () => {
192 const element = document.createElement('div');
193 element.className = 'thing';
194 document.body.appendChild(element);
195 jest.spyOn(document, 'querySelector');
196 expect(() => {
197 Utils.getTarget('.thing');
198 }).not.toThrow();
199 });
200
201 it('should return an error when the target could not be identified', () => {
202 const target = 'not a target';
203 expect(() => {
204 Utils.getTarget(target);
205 }).toThrow(
206 `The target '${target}' could not be identified in the dom, tip: check spelling`,
207 );
208 });
209
210 it('should return the value of the `current` object if it is a react Ref object', () => {
211 const target = { current: { name: 'hello' } };
212 expect(Utils.getTarget(target)).toEqual(target.current);
213 });
214
215 it('should return null if the `current` property of the target is null', () => {
216 const target = { current: null };
217 expect(Utils.getTarget(target)).toBeNull();
218 expect(Utils.getTarget(target, true)).toStrictEqual([]);
219 });
220 });
221
222 describe('setGlobalCssModule', () => {
223 it('should return the mapped classnames', () => {
224 const globalCssModule = {
225 btn: 'a1',
226 'btn-success': 'b1',
227 'btn-primary': 'c2',
228 };
229 Utils.setGlobalCssModule(globalCssModule);
230 expect(Utils.mapToCssModules('btn btn-primary')).toBe('a1 c2');
231 });
232 });
233
234 describe('isFunction', () => {
235 it('should return `true` for functions', () => {
236 function test() {}
237
238 expect(Utils.isFunction(test)).toBe(true);
239 expect(Utils.isFunction(Array.prototype.slice)).toBe(true);
240 });
241
242 it('should return `true` for async functions', () => {
243 async function asyncFunc() {}
244
245 expect(Utils.isFunction(asyncFunc)).toEqual(
246 typeof asyncFunc === 'function',
247 );
248 });
249
250 it('should return `true` for generator functions', () => {
251 function* genFunc() {}
252
253 expect(Utils.isFunction(genFunc)).toEqual(typeof genFunc === 'function');
254 });
255
256 it('should return `false` for non-functions', () => {
257 function toArgs(array) {
258 return function () {
259 return arguments;
260 }.apply(undefined, array);
261 }
262
263 expect(Utils.isFunction(toArgs([1, 2, 3]))).toBe(false);
264 expect(Utils.isFunction([1, 2, 3])).toBe(false);
265 expect(Utils.isFunction(true)).toBe(false);
266 expect(Utils.isFunction(new Date())).toBe(false);
267 expect(Utils.isFunction(new Error())).toBe(false);
268 expect(Utils.isFunction({ a: 1 })).toBe(false);
269 expect(Utils.isFunction(1)).toBe(false);
270 expect(Utils.isFunction(/x/)).toBe(false);
271 expect(Utils.isFunction('a')).toBe(false);
272 expect(Utils.isFunction(Symbol('a'))).toBe(false);
273 //
274 if (document) {
275 expect(Utils.isFunction(document.getElementsByTagName('body'))).toBe(
276 false,
277 );
278 }
279 });
280 });
281
282 describe('isObject', () => {
283 it('should return `true` for objects', () => {
284 expect(Utils.isObject([1, 2, 3])).toBe(true);
285 expect(Utils.isObject(Object(false))).toBe(true);
286 expect(Utils.isObject(new Date())).toBe(true);
287 expect(Utils.isObject(new Error())).toBe(true);
288 expect(Utils.isObject({ a: 1 })).toBe(true);
289 expect(Utils.isObject({ a: 1 })).toBe(true);
290 expect(Utils.isObject(Object(0))).toBe(true);
291 expect(Utils.isObject(/x/)).toBe(true);
292 expect(Utils.isObject(Object('a'))).toBe(true);
293 if (document) {
294 expect(Utils.isObject(document.body)).toBe(true);
295 }
296 });
297
298 it('should return `false` for non-objects', () => {
299 expect(Utils.isObject(0)).toBe(false);
300 expect(Utils.isObject(false)).toBe(false);
301 expect(Utils.isObject(1)).toBe(false);
302 });
303 });
304
305 describe('toNumber', () => {
306 it('should return number', () => {
307 expect(Utils.toNumber('5')).toEqual(5);
308 expect(Utils.toNumber('5.0')).toEqual(5);
309 expect(Utils.toNumber('1.1')).toEqual(1.1);
310 expect(Utils.toNumber('-1.1')).toEqual(-1.1);
311 expect(Utils.toNumber(0 / 0)).toEqual(NaN);
312 expect(Utils.toNumber(0)).toEqual(0);
313 });
314 });
315
316 describe('addDefaultProps', () => {
317 it('should return an object', () => {
318 const defaultProps = {
319 a: 1,
320 b: 2,
321 c: 3,
322 };
323 const props = {
324 a: 4,
325 b: 5,
326 };
327 expect(Utils.addDefaultProps(defaultProps, props)).toEqual(
328 expect.any(Object),
329 );
330 });
331
332 it('should return an object with default props', () => {
333 const defaultProps = {
334 a: 1,
335 b: 2,
336 c: 3,
337 d: {
338 e: 4,
339 f: 5,
340 },
341 };
342 const props = {
343 a: 4,
344 b: 5,
345 d: {
346 e: 6,
347 f: 5,
348 },
349 };
350 expect(Utils.addDefaultProps(defaultProps, props)).toEqual({
351 a: 4,
352 b: 5,
353 c: 3,
354 d: {
355 e: 6,
356 f: 5,
357 },
358 });
359 });
360 });
361
362 // TODO
363 // describe('getScrollbarWidth', () => {
364 // // jsdom workaround https://github.com/tmpvar/jsdom/issues/135#issuecomment-68191941
365 // Object.defineProperties(window.HTMLElement.prototype, {
366 // offsetLeft: {
367 // get: function () { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
368 // },
369 // offsetTop: {
370 // get: function () { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
371 // },
372 // offsetHeight: {
373 // get: function () { return parseFloat(window.getComputedStyle(this).height) || 0; }
374 // },
375 // offsetWidth: {
376 // get: function () { return parseFloat(window.getComputedStyle(this).width) || 0; }
377 // }
378 // });
379 //
380 // it('should return scrollbarWidth', () => {
381 // expect(Utils.getScrollbarWidth()).toBe();
382 // });
383 // });
384
385 // TODO verify setScrollbarWidth is called with values when body overflows
386 // it('should conditionallyUpdateScrollbar when isBodyOverflowing is true', () => {
387 // const stubbedSetScrollbarWidth = jest.fn().and.callThrough();
388 // const prevClientWidth = document.body.clientWidth;
389 // const prevWindowInnerWidth = window.innerWidth;
390 // document.body.clientWidth = 100;
391 // window.innerWidth = 500;
392 //
393 // conditionallyUpdateScrollbar();
394 // expect(stubbedSetScrollbarWidth).toHaveBeenCalled();
395 //
396 // document.body.clientWidth = prevClientWidth;
397 // window.innerWidth = prevWindowInnerWidth;
398 // });
399});