Skip to content

Commit 74f4599

Browse files
committed
add tests
1 parent c8ed09f commit 74f4599

File tree

3 files changed

+280
-0
lines changed

3 files changed

+280
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import {
2+
_interopDefault,
3+
_interopNamespace,
4+
_interopNamespaceDefaultOnly,
5+
_interopRequireDefault,
6+
_interopRequireWildcard,
7+
} from '../../src/buildPolyfills';
8+
import { RequireResult } from '../../src/buildPolyfills/types';
9+
import {
10+
_interopDefault as _interopDefaultOrig,
11+
_interopNamespace as _interopNamespaceOrig,
12+
_interopNamespaceDefaultOnly as _interopNamespaceDefaultOnlyOrig,
13+
_interopRequireDefault as _interopRequireDefaultOrig,
14+
_interopRequireWildcard as _interopRequireWildcardOrig,
15+
} from './originals';
16+
17+
// Note: In real life, there are some test-case/function pairings here which would never happen, but by testing all
18+
// combinations, we're guaranteed to have tested the ones which show up in the wild.
19+
20+
const dogStr = 'dogs are great!';
21+
const dogFunc = () => dogStr;
22+
const dogAdjectives = { maisey: 'silly', charlie: 'goofy' };
23+
24+
const withESModuleFlag = { __esModule: true, ...dogAdjectives };
25+
const withESModuleFlagAndDefault = { __esModule: true, default: dogFunc, ...dogAdjectives };
26+
const namedExports = { ...dogAdjectives };
27+
const withNonEnumerableProp = { ...dogAdjectives };
28+
// Properties added using `Object.defineProperty` are non-enumerable by default
29+
Object.defineProperty(withNonEnumerableProp, 'hiddenProp', { value: 'shhhhhhhh' });
30+
const withDefaultExport = { default: dogFunc, ...dogAdjectives };
31+
const withOnlyDefaultExport = { default: dogFunc };
32+
const exportsEquals = dogFunc as RequireResult;
33+
const exportsEqualsWithDefault = dogFunc as RequireResult;
34+
exportsEqualsWithDefault.default = exportsEqualsWithDefault;
35+
36+
const requireResults: Record<string, RequireResult> = {
37+
withESModuleFlag,
38+
withESModuleFlagAndDefault,
39+
namedExports,
40+
withNonEnumerableProp,
41+
withDefaultExport,
42+
withOnlyDefaultExport,
43+
exportsEquals: exportsEquals,
44+
exportsEqualsWithDefault: exportsEqualsWithDefault as unknown as RequireResult,
45+
};
46+
47+
const testLabels: Record<string, string> = {
48+
withESModuleFlag: 'module with `__esModule` flag',
49+
withESModuleFlagAndDefault: 'module with `__esModule` flag and default export',
50+
namedExports: 'module with named exports',
51+
withNonEnumerableProp: 'module with named exports and non-enumerable prop',
52+
withDefaultExport: 'module with default export',
53+
withOnlyDefaultExport: 'module with only default export',
54+
exportsEquals: 'module using `exports =`',
55+
exportsEqualsWithDefault: 'module using `exports =` with default export',
56+
};
57+
58+
function makeTestCases(expectedValues: Record<string, RequireResult>): Array<[string, RequireResult, RequireResult]> {
59+
return Object.keys(testLabels).map(key => [testLabels[key], requireResults[key], expectedValues[key]]);
60+
}
61+
62+
describe('_interopNamespace', () => {
63+
describe('returns the same result as the original', () => {
64+
const expectedValues: Record<string, RequireResult> = {
65+
withESModuleFlag: withESModuleFlag,
66+
withESModuleFlagAndDefault: withESModuleFlagAndDefault,
67+
namedExports: { ...namedExports, default: namedExports },
68+
withNonEnumerableProp: {
69+
...withNonEnumerableProp,
70+
default: withNonEnumerableProp,
71+
},
72+
withDefaultExport: { ...withDefaultExport, default: withDefaultExport },
73+
withOnlyDefaultExport: { default: withOnlyDefaultExport },
74+
exportsEquals: { default: exportsEquals },
75+
exportsEqualsWithDefault: { default: exportsEqualsWithDefault },
76+
};
77+
78+
const testCases = makeTestCases(expectedValues);
79+
80+
it.each(testCases)('%s', (_, requireResult, expectedValue) => {
81+
expect(_interopNamespace(requireResult)).toEqual(_interopNamespaceOrig(requireResult));
82+
expect(_interopNamespace(requireResult)).toEqual(expectedValue);
83+
});
84+
});
85+
});
86+
87+
describe('_interopNamespaceDefaultOnly', () => {
88+
describe('returns the same result as the original', () => {
89+
const expectedValues: Record<string, RequireResult> = {
90+
withESModuleFlag: { default: withESModuleFlag },
91+
withESModuleFlagAndDefault: { default: withESModuleFlagAndDefault },
92+
namedExports: { default: namedExports },
93+
withNonEnumerableProp: { default: withNonEnumerableProp },
94+
withDefaultExport: { default: withDefaultExport },
95+
withOnlyDefaultExport: { default: withOnlyDefaultExport },
96+
exportsEquals: { default: exportsEquals },
97+
exportsEqualsWithDefault: { default: exportsEqualsWithDefault },
98+
};
99+
100+
const testCases = makeTestCases(expectedValues);
101+
102+
it.each(testCases)('%s', (_, requireResult, expectedValue) => {
103+
expect(_interopNamespaceDefaultOnly(requireResult)).toEqual(_interopNamespaceDefaultOnlyOrig(requireResult));
104+
expect(_interopNamespaceDefaultOnly(requireResult)).toEqual(expectedValue);
105+
});
106+
});
107+
});
108+
109+
describe('_interopRequireWildcard', () => {
110+
describe('returns the same result as the original', () => {
111+
const expectedValues: Record<string, RequireResult> = {
112+
withESModuleFlag: withESModuleFlag,
113+
withESModuleFlagAndDefault: withESModuleFlagAndDefault,
114+
namedExports: { ...namedExports, default: namedExports },
115+
withNonEnumerableProp: {
116+
...withNonEnumerableProp,
117+
default: withNonEnumerableProp,
118+
},
119+
withDefaultExport: { ...withDefaultExport, default: withDefaultExport },
120+
withOnlyDefaultExport: { default: withOnlyDefaultExport },
121+
exportsEquals: { default: exportsEquals },
122+
exportsEqualsWithDefault: { default: exportsEqualsWithDefault },
123+
};
124+
125+
const testCases = makeTestCases(expectedValues);
126+
127+
it.each(testCases)('%s', (_, requireResult, expectedValue) => {
128+
expect(_interopRequireWildcard(requireResult)).toEqual(_interopRequireWildcardOrig(requireResult));
129+
expect(_interopRequireWildcard(requireResult)).toEqual(expectedValue);
130+
});
131+
});
132+
});
133+
134+
describe('_interopDefault', () => {
135+
describe('returns the same result as the original', () => {
136+
const expectedValues: Record<string, RequireResult> = {
137+
withESModuleFlag: undefined as unknown as RequireResult,
138+
withESModuleFlagAndDefault: withESModuleFlagAndDefault.default as RequireResult,
139+
namedExports: namedExports,
140+
withNonEnumerableProp: withNonEnumerableProp,
141+
withDefaultExport: withDefaultExport,
142+
withOnlyDefaultExport: withOnlyDefaultExport,
143+
exportsEquals: exportsEquals,
144+
exportsEqualsWithDefault: exportsEqualsWithDefault,
145+
};
146+
147+
const testCases = makeTestCases(expectedValues);
148+
149+
it.each(testCases)('%s', (_, requireResult, expectedValue) => {
150+
expect(_interopDefault(requireResult)).toEqual(_interopDefaultOrig(requireResult));
151+
expect(_interopDefault(requireResult)).toEqual(expectedValue);
152+
});
153+
});
154+
});
155+
156+
describe('_interopRequireDefault', () => {
157+
describe('returns the same result as the original', () => {
158+
const expectedValues: Record<string, RequireResult> = {
159+
withESModuleFlag: withESModuleFlag,
160+
withESModuleFlagAndDefault: withESModuleFlagAndDefault,
161+
namedExports: { default: namedExports },
162+
withNonEnumerableProp: { default: withNonEnumerableProp },
163+
withDefaultExport: { default: withDefaultExport },
164+
withOnlyDefaultExport: { default: withOnlyDefaultExport },
165+
exportsEquals: { default: exportsEquals },
166+
exportsEqualsWithDefault: { default: exportsEqualsWithDefault },
167+
};
168+
169+
const testCases = makeTestCases(expectedValues);
170+
171+
it.each(testCases)('%s', (_, requireResult, expectedValue) => {
172+
expect(_interopRequireDefault(requireResult)).toEqual(_interopRequireDefaultOrig(requireResult));
173+
expect(_interopRequireDefault(requireResult)).toEqual(expectedValue);
174+
});
175+
});
176+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { _nullishCoalesce } from '../../src/buildPolyfills';
2+
import { Value } from '../../src/buildPolyfills/types';
3+
import { _nullishCoalesce as _nullishCoalesceOrig } from './originals';
4+
5+
const dogStr = 'dogs are great!';
6+
const dogFunc = () => dogStr;
7+
const dogAdjectives = { maisey: 'silly', charlie: 'goofy' };
8+
const dogAdjectiveFunc = () => dogAdjectives;
9+
10+
describe('_nullishCoalesce', () => {
11+
describe('returns the same result as the original', () => {
12+
const testCases: Array<[string, Value, () => Value, Value]> = [
13+
['null LHS', null, dogFunc, dogStr],
14+
['undefined LHS', undefined, dogFunc, dogStr],
15+
['false LHS', false, dogFunc, false],
16+
['zero LHS', 0, dogFunc, 0],
17+
['empty string LHS', '', dogFunc, ''],
18+
['true LHS', true, dogFunc, true],
19+
['truthy primitive LHS', 12312012, dogFunc, 12312012],
20+
['truthy object LHS', dogAdjectives, dogFunc, dogAdjectives],
21+
['truthy function LHS', dogAdjectiveFunc, dogFunc, dogAdjectiveFunc],
22+
];
23+
24+
it.each(testCases)('%s', (_, lhs, rhs, expectedValue) => {
25+
expect(_nullishCoalesce(lhs, rhs)).toEqual(_nullishCoalesceOrig(lhs, rhs));
26+
expect(_nullishCoalesce(lhs, rhs)).toEqual(expectedValue);
27+
});
28+
});
29+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { _optionalChain } from '../../src/buildPolyfills';
2+
import { GenericFunction, GenericObject, Value } from '../../src/buildPolyfills/types';
3+
import { _optionalChain as _optionalChainOrig } from './originals';
4+
5+
type OperationType = 'access' | 'call' | 'optionalAccess' | 'optionalCall';
6+
type OperationExecutor =
7+
| ((intermediateValue: GenericObject) => Value)
8+
| ((intermediateValue: GenericFunction) => Value);
9+
type Operation = [OperationType, OperationExecutor];
10+
11+
const truthy = { maisey: 'silly', charlie: 'goofy' };
12+
const nullish = null;
13+
const truthyFunc = (): GenericObject => truthy;
14+
const nullishFunc = undefined;
15+
const truthyReturn = (): GenericObject => truthy;
16+
const nullishReturn = (): null => nullish;
17+
18+
describe('_optionalChain', () => {
19+
describe('returns the same result as the original', () => {
20+
// In these test cases, the array passed to `_optionalChain` has been broken up into the first entry followed by an
21+
// array of pairs of subsequent elements (so `[A, B, C, D, E]` becomes `A, [[B, C], [D, E]]`, as the second and third
22+
// entries in each test case), because this seemed the easiest way to express the type, which is really
23+
// [Value, OperationType, Value => Value, OperationType, Value => Value, OperationType, Value => Value, ...].
24+
// We then undo this wrapping before passing the data to our functions.
25+
const testCases: Array<[string, Value, Operation[], Value]> = [
26+
['truthy?.charlie', truthy, [['optionalAccess', (_: GenericObject) => _.charlie]], 'goofy'],
27+
['nullish?.maisey', nullish, [['optionalAccess', (_: GenericObject) => _.maisey]], undefined],
28+
[
29+
'truthyFunc?.().maisey',
30+
truthyFunc,
31+
[
32+
['optionalCall', (_: GenericFunction) => _()],
33+
['access', (_: GenericObject) => _.maisey],
34+
],
35+
'silly',
36+
],
37+
[
38+
'nullishFunc?.().charlie',
39+
nullishFunc,
40+
[
41+
['optionalCall', (_: GenericFunction) => _()],
42+
['access', (_: GenericObject) => _.charlie],
43+
],
44+
undefined,
45+
],
46+
[
47+
'truthyReturn()?.maisey',
48+
truthyReturn,
49+
[
50+
['call', (_: GenericFunction) => _()],
51+
['optionalAccess', (_: GenericObject) => _.maisey],
52+
],
53+
'silly',
54+
],
55+
[
56+
'nullishReturn()?.charlie',
57+
nullishReturn,
58+
[
59+
['call', (_: GenericFunction) => _()],
60+
['optionalAccess', (_: GenericObject) => _.charlie],
61+
],
62+
undefined,
63+
],
64+
];
65+
66+
it.each(testCases)('%s', (_, initialChainComponent, operations, expectedValue) => {
67+
// `operations` is flattened and spread in order to undo the wrapping done in the test cases for TS purposes. See
68+
// note above test cases.
69+
expect(_optionalChain([initialChainComponent, ...operations.flat()])).toEqual(
70+
_optionalChainOrig([initialChainComponent, ...operations.flat()]),
71+
);
72+
expect(_optionalChain([initialChainComponent, ...operations.flat()])).toEqual(expectedValue);
73+
});
74+
});
75+
});

0 commit comments

Comments
 (0)