UNPKG

9.74 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/extends";
2import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
4function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
5
6function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
7
8/**
9 * This file contains helper methods to create expected snapshot structures
10 * of both instance and ES6 exports.
11 *
12 * The files are located here and not under /test or /tools so it's transpiled
13 * into ES5 code under /lib and can be used straight by node.js
14 */
15import assert from 'assert';
16import * as allIsFunctions from './is.js';
17import { create } from '../core/create.js';
18import { endsWith } from './string.js';
19export function validateBundle(expectedBundleStructure, bundle) {
20 var originalWarn = console.warn;
21
22 console.warn = function () {
23 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
24 args[_key] = arguments[_key];
25 }
26
27 if (args.join(' ').indexOf('is moved to') !== -1 && args.join(' ').indexOf('Please use the new location instead') !== -1) {
28 // Ignore warnings like:
29 // Warning: math.type.isNumber is moved to math.isNumber in v6.0.0. Please use the new location instead.
30 return;
31 }
32
33 originalWarn.apply(console, args);
34 };
35
36 try {
37 var issues = []; // see whether all expected functions and objects are there
38
39 traverse(expectedBundleStructure, (expectedType, path) => {
40 var actualValue = get(bundle, path);
41 var actualType = validateTypeOf(actualValue);
42 var message = actualType === 'undefined' ? 'Missing entry in bundle. ' + "Path: ".concat(JSON.stringify(path), ", expected type: ").concat(expectedType, ", actual type: ").concat(actualType) : 'Unexpected entry type in bundle. ' + "Path: ".concat(JSON.stringify(path), ", expected type: ").concat(expectedType, ", actual type: ").concat(actualType);
43
44 if (actualType !== expectedType) {
45 issues.push({
46 actualType,
47 expectedType,
48 message
49 });
50 console.warn(message);
51 }
52 }); // see whether there are any functions or objects that shouldn't be there
53
54 traverse(bundle, (actualValue, path) => {
55 var actualType = validateTypeOf(actualValue);
56 var expectedType = get(expectedBundleStructure, path) || 'undefined'; // FIXME: ugly to have these special cases
57
58 if (path.join('.').indexOf('docs.') !== -1) {
59 // ignore the contents of docs
60 return;
61 }
62
63 if (path.join('.').indexOf('all.') !== -1) {
64 // ignore the contents of all dependencies
65 return;
66 }
67
68 var message = expectedType === 'undefined' ? 'Unknown entry in bundle. ' + 'Is there a new function added which is missing in this snapshot test? ' + "Path: ".concat(JSON.stringify(path), ", expected type: ").concat(expectedType, ", actual type: ").concat(actualType) : 'Unexpected entry type in bundle. ' + "Path: ".concat(JSON.stringify(path), ", expected type: ").concat(expectedType, ", actual type: ").concat(actualType);
69
70 if (actualType !== expectedType) {
71 issues.push({
72 actualType,
73 expectedType,
74 message
75 });
76 console.warn(message);
77 }
78 }); // assert on the first issue (if any)
79
80 if (issues.length > 0) {
81 var {
82 actualType,
83 expectedType,
84 message
85 } = issues[0];
86 console.warn("".concat(issues.length, " bundle issues found"));
87 assert.strictEqual(actualType, expectedType, message);
88 }
89 } finally {
90 console.warn = originalWarn;
91 }
92}
93/**
94 * Based on an object with factory functions, create the expected
95 * structures for ES6 export and a mathjs instance.
96 * @param {Object} factories
97 * @return {{expectedInstanceStructure: Object, expectedES6Structure: Object}}
98 */
99
100export function createSnapshotFromFactories(factories) {
101 var math = create(factories);
102 var allFactoryFunctions = {};
103 var allFunctionsConstantsClasses = {};
104 var allFunctionsConstants = {};
105 var allTransformFunctions = {};
106 var allDependencyCollections = {};
107 var allClasses = {};
108 var allNodeClasses = {};
109 Object.keys(factories).forEach(factoryName => {
110 var factory = factories[factoryName];
111 var name = factory.fn;
112 var isTransformFunction = factory.meta && factory.meta.isTransformFunction;
113 var isClass = !isLowerCase(name[0]) && validateTypeOf(math[name]) === 'Function';
114 var dependenciesName = factory.fn + (isTransformFunction ? 'Transform' : '') + 'Dependencies';
115 allFactoryFunctions[factoryName] = 'Function';
116 allFunctionsConstantsClasses[name] = validateTypeOf(math[name]);
117 allDependencyCollections[dependenciesName] = 'Object';
118
119 if (isTransformFunction) {
120 allTransformFunctions[name] = 'Function';
121 }
122
123 if (isClass) {
124 if (endsWith(name, 'Node')) {
125 allNodeClasses[name] = 'Function';
126 } else {
127 allClasses[name] = 'Function';
128 }
129 } else {
130 allFunctionsConstants[name] = validateTypeOf(math[name]);
131 }
132 });
133 var embeddedDocs = {};
134 Object.keys(factories).forEach(factoryName => {
135 var factory = factories[factoryName];
136 var name = factory.fn;
137
138 if (isLowerCase(factory.fn[0])) {
139 // ignore class names starting with upper case
140 embeddedDocs[name] = 'Object';
141 }
142 });
143 embeddedDocs = exclude(embeddedDocs, ['equalScalar', 'apply', 'addScalar', 'multiplyScalar', 'print', 'divideScalar', 'parse', 'compile', 'parser', 'chain', 'reviver', 'replacer']);
144 var allTypeChecks = {};
145 Object.keys(allIsFunctions).forEach(name => {
146 if (name.indexOf('is') === 0) {
147 allTypeChecks[name] = 'Function';
148 }
149 });
150 var allErrorClasses = {
151 ArgumentsError: 'Function',
152 DimensionError: 'Function',
153 IndexError: 'Function'
154 };
155
156 var expectedInstanceStructure = _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, allFunctionsConstantsClasses), {}, {
157 on: 'Function',
158 off: 'Function',
159 once: 'Function',
160 emit: 'Function',
161 import: 'Function',
162 config: 'Function',
163 create: 'Function',
164 factory: 'Function'
165 }, allTypeChecks), allErrorClasses), {}, {
166 expression: {
167 transform: _objectSpread({}, allTransformFunctions),
168 mathWithTransform: _objectSpread(_objectSpread({}, exclude(allFunctionsConstants, ['chain'])), {}, {
169 config: 'Function'
170 })
171 }
172 });
173
174 var expectedES6Structure = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, exclude(allFunctionsConstantsClasses, ['E', 'false', 'Infinity', 'NaN', 'null', 'PI', 'true'])), {}, {
175 create: 'Function',
176 config: 'Function',
177 factory: 'Function',
178 _true: 'boolean',
179 _false: 'boolean',
180 _null: 'null',
181 _Infinity: 'number',
182 _NaN: 'number'
183 }, allTypeChecks), allErrorClasses), allDependencyCollections), allFactoryFunctions), {}, {
184 docs: embeddedDocs
185 });
186
187 return {
188 expectedInstanceStructure,
189 expectedES6Structure
190 };
191}
192export function validateTypeOf(x) {
193 if (x && x.type === 'Unit') {
194 return 'Unit';
195 }
196
197 if (x && x.type === 'Complex') {
198 return 'Complex';
199 }
200
201 if (Array.isArray(x)) {
202 return 'Array';
203 }
204
205 if (x === null) {
206 return 'null';
207 }
208
209 if (typeof x === 'function') {
210 return 'Function';
211 }
212
213 if (typeof x === 'object') {
214 return 'Object';
215 }
216
217 return typeof x;
218}
219
220function traverse(obj) {
221 var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : (value, path) => {};
222 var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
223
224 // FIXME: ugly to have these special cases
225 if (path.length > 0 && path[0].indexOf('Dependencies') !== -1) {
226 // special case for objects holding a collection of dependencies
227 callback(obj, path);
228 } else if (validateTypeOf(obj) === 'Array') {
229 obj.map((item, index) => traverse(item, callback, path.concat(index)));
230 } else if (validateTypeOf(obj) === 'Object') {
231 Object.keys(obj).forEach(key => {
232 // FIXME: ugly to have these special cases
233 // ignore special case of deprecated docs
234 if (key === 'docs' && path.join('.') === 'expression') {
235 return;
236 }
237
238 traverse(obj[key], callback, path.concat(key));
239 });
240 } else {
241 callback(obj, path);
242 }
243}
244
245function get(object, path) {
246 var child = object;
247
248 for (var i = 0; i < path.length; i++) {
249 var key = path[i];
250 child = child ? child[key] : undefined;
251 }
252
253 return child;
254}
255/**
256 * Create a copy of the provided `object` and delete
257 * all properties listed in `excludedProperties`
258 * @param {Object} object
259 * @param {string[]} excludedProperties
260 * @return {Object}
261 */
262
263
264function exclude(object, excludedProperties) {
265 var strippedObject = _extends({}, object);
266
267 excludedProperties.forEach(excludedProperty => {
268 delete strippedObject[excludedProperty];
269 });
270 return strippedObject;
271}
272
273function isLowerCase(text) {
274 return typeof text === 'string' && text.toLowerCase() === text;
275}
\No newline at end of file