/
resolveToValue-test.js
202 lines (165 loc) · 5.99 KB
/
resolveToValue-test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import { builders } from 'ast-types';
import { parse } from '../../../tests/utils';
import resolveToValue from '../resolveToValue';
describe('resolveToValue', () => {
function parsePath(src, options = {}) {
const root = parse(src.trim(), options);
return root.get('body', root.node.body.length - 1, 'expression');
}
it('resolves simple variable declarations', () => {
const path = parsePath(['var foo = 42;', 'foo;'].join('\n'));
expect(resolveToValue(path)).toEqualASTNode(builders.literal(42));
});
it('resolves object destructuring', () => {
const path = parsePath(['var {foo: {bar: baz}} = bar;', 'baz;'].join('\n'));
// Node should be equal to bar.foo.bar
expect(resolveToValue(path)).toEqualASTNode(
builders.memberExpression(
builders.memberExpression(
builders.identifier('bar'),
builders.identifier('foo'),
),
builders.identifier('bar'),
),
);
});
it('handles SpreadElements properly', () => {
const path = parsePath(
['var {foo: {bar}, ...baz} = bar;', 'baz;'].join('\n'),
);
expect(resolveToValue(path)).toEqualASTNode(path);
});
it('returns the original path if it cannot be resolved', () => {
const path = parsePath(['function foo() {}', 'foo()'].join('\n'));
expect(resolveToValue(path)).toEqualASTNode(path);
});
it('resolves variable declarators to their init value', () => {
const path = parse('var foo = 42;').get('body', 0, 'declarations', 0);
expect(resolveToValue(path)).toEqualASTNode(builders.literal(42));
});
it('resolves to class declarations', () => {
const path = parsePath(`
class Foo {}
Foo;
`);
expect(resolveToValue(path).node.type).toBe('ClassDeclaration');
});
it('resolves to class function declaration', () => {
const path = parsePath(`
function foo() {}
foo;
`);
expect(resolveToValue(path).node.type).toBe('FunctionDeclaration');
});
describe('flow', () => {
it('resolves type cast expressions', () => {
const path = parsePath(`
function foo() {}
(foo: any);
`);
expect(resolveToValue(path).node.type).toBe('FunctionDeclaration');
});
});
describe('typescript', () => {
const parseTypescript = src =>
parsePath(src, { parserOptions: { plugins: ['typescript'] } });
it('resolves type as expressions', () => {
const path = parseTypescript(`
function foo() {}
(foo as any);
`);
expect(resolveToValue(path).node.type).toBe('FunctionDeclaration');
});
it('resolves type assertions', () => {
const path = parseTypescript(`
function foo() {}
(<any> foo);
`);
expect(resolveToValue(path).node.type).toBe('FunctionDeclaration');
});
});
describe('assignments', () => {
it('resolves to assigned values', () => {
const path = parsePath(['var foo;', 'foo = 42;', 'foo;'].join('\n'));
expect(resolveToValue(path)).toEqualASTNode(builders.literal(42));
});
});
describe('ImportDeclaration', () => {
it('resolves default import references to the import declaration', () => {
const path = parsePath(['import foo from "Foo"', 'foo;'].join('\n'));
const value = resolveToValue(path);
expect(Array.isArray(value.value)).toBe(false);
expect(value.node.type).toBe('ImportDeclaration');
});
it('resolves named import references to the import declaration', () => {
const path = parsePath(['import {foo} from "Foo"', 'foo;'].join('\n'));
const value = resolveToValue(path);
expect(Array.isArray(value.value)).toBe(false);
expect(value.node.type).toBe('ImportDeclaration');
});
it('resolves aliased import references to the import declaration', () => {
const path = parsePath(
['import {foo as bar} from "Foo"', 'bar;'].join('\n'),
);
const value = resolveToValue(path);
expect(Array.isArray(value.value)).toBe(false);
expect(value.node.type).toBe('ImportDeclaration');
});
it('resolves namespace import references to the import declaration', () => {
const path = parsePath(['import * as bar from "Foo"', 'bar;'].join('\n'));
const value = resolveToValue(path);
expect(Array.isArray(value.value)).toBe(false);
expect(value.node.type).toBe('ImportDeclaration');
});
});
describe('MemberExpression', () => {
it("resolves a MemberExpression to it's init value", () => {
const path = parsePath(['var foo = { bar: 1 };', 'foo.bar;'].join('\n'));
expect(resolveToValue(path)).toEqualASTNode(builders.literal(1));
});
it('resolves a MemberExpression in the scope chain', () => {
const path = parsePath(
['var foo = 1;', 'var bar = { baz: foo };', 'bar.baz;'].join('\n'),
);
expect(resolveToValue(path)).toEqualASTNode(builders.literal(1));
});
it('resolves a nested MemberExpression in the scope chain', () => {
const path = parsePath(
[
'var foo = { bar: 1 };',
'var bar = { baz: foo.bar };',
'bar.baz;',
].join('\n'),
);
expect(resolveToValue(path)).toEqualASTNode(builders.literal(1));
});
it('returns the last resolvable MemberExpression', () => {
const path = parsePath(
[
'import foo from "bar";',
'var bar = { baz: foo.bar };',
'bar.baz;',
].join('\n'),
);
expect(resolveToValue(path)).toEqualASTNode(
builders.memberExpression(
builders.identifier('foo'),
builders.identifier('bar'),
),
);
});
it('returns the path itself if it can not resolve it any further', () => {
const path = parsePath(
['var foo = {};', 'foo.bar = 1;', 'foo.bar;'].join('\n'),
);
expect(resolveToValue(path)).toEqualASTNode(path);
});
});
});