UNPKG

5.27 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8/* global expect, describe, it */
9
10'use strict';
11
12const fs = require('fs');
13const path = require('path');
14
15function applyTransform(module, options, input, testOptions = {}) {
16 // Handle ES6 modules using default export for the transform
17 const transform = module.default ? module.default : module;
18
19 // Jest resets the module registry after each test, so we need to always get
20 // a fresh copy of jscodeshift on every test run.
21 let jscodeshift = require('./core');
22 if (testOptions.parser || module.parser) {
23 jscodeshift = jscodeshift.withParser(testOptions.parser || module.parser);
24 }
25
26 const output = transform(
27 input,
28 {
29 jscodeshift,
30 j: jscodeshift,
31 stats: () => {},
32 },
33 options || {}
34 );
35
36 return (output || '').trim();
37}
38exports.applyTransform = applyTransform;
39
40function runSnapshotTest(module, options, input) {
41 const output = applyTransform(module, options, input);
42 expect(output).toMatchSnapshot();
43 return output;
44}
45exports.runSnapshotTest = runSnapshotTest;
46
47function runInlineTest(module, options, input, expectedOutput, testOptions) {
48 const output = applyTransform(module, options, input, testOptions);
49 expect(output).toEqual(expectedOutput.trim());
50 return output;
51}
52exports.runInlineTest = runInlineTest;
53
54function extensionForParser(parser) {
55 switch (parser) {
56 case 'ts':
57 case 'tsx':
58 return parser;
59 default:
60 return 'js'
61 }
62}
63
64/**
65 * Utility function to run a jscodeshift script within a unit test. This makes
66 * several assumptions about the environment:
67 *
68 * - `dirName` contains the name of the directory the test is located in. This
69 * should normally be passed via __dirname.
70 * - The test should be located in a subdirectory next to the transform itself.
71 * Commonly tests are located in a directory called __tests__.
72 * - `transformName` contains the filename of the transform being tested,
73 * excluding the .js extension.
74 * - `testFilePrefix` optionally contains the name of the file with the test
75 * data. If not specified, it defaults to the same value as `transformName`.
76 * This will be suffixed with ".input.js" for the input file and ".output.js"
77 * for the expected output. For example, if set to "foo", we will read the
78 * "foo.input.js" file, pass this to the transform, and expect its output to
79 * be equal to the contents of "foo.output.js".
80 * - Test data should be located in a directory called __testfixtures__
81 * alongside the transform and __tests__ directory.
82 */
83function runTest(dirName, transformName, options, testFilePrefix, testOptions = {}) {
84 if (!testFilePrefix) {
85 testFilePrefix = transformName;
86 }
87
88 // Assumes transform is one level up from __tests__ directory
89 const module = require(path.join(dirName, '..', transformName));
90 const extension = extensionForParser(testOptions.parser || module.parser)
91 const fixtureDir = path.join(dirName, '..', '__testfixtures__');
92 const inputPath = path.join(fixtureDir, testFilePrefix + `.input.${extension}`);
93 const source = fs.readFileSync(inputPath, 'utf8');
94 const expectedOutput = fs.readFileSync(
95 path.join(fixtureDir, testFilePrefix + `.output.${extension}`),
96 'utf8'
97 );
98 runInlineTest(module, options, {
99 path: inputPath,
100 source
101 }, expectedOutput, testOptions);
102}
103exports.runTest = runTest;
104
105/**
106 * Handles some boilerplate around defining a simple jest/Jasmine test for a
107 * jscodeshift transform.
108 */
109function defineTest(dirName, transformName, options, testFilePrefix, testOptions) {
110 const testName = testFilePrefix
111 ? `transforms correctly using "${testFilePrefix}" data`
112 : 'transforms correctly';
113 describe(transformName, () => {
114 it(testName, () => {
115 runTest(dirName, transformName, options, testFilePrefix, testOptions);
116 });
117 });
118}
119exports.defineTest = defineTest;
120
121function defineInlineTest(module, options, input, expectedOutput, testName) {
122 it(testName || 'transforms correctly', () => {
123 runInlineTest(module, options, {
124 source: input
125 }, expectedOutput);
126 });
127}
128exports.defineInlineTest = defineInlineTest;
129
130function defineSnapshotTest(module, options, input, testName) {
131 it(testName || 'transforms correctly', () => {
132 runSnapshotTest(module, options, {
133 source: input
134 });
135 });
136}
137exports.defineSnapshotTest = defineSnapshotTest;
138
139/**
140 * Handles file-loading boilerplates, using same defaults as defineTest
141 */
142function defineSnapshotTestFromFixture(dirName, module, options, testFilePrefix, testName, testOptions = {}) {
143 const extension = extensionForParser(testOptions.parser || module.parser)
144 const fixtureDir = path.join(dirName, '..', '__testfixtures__');
145 const inputPath = path.join(fixtureDir, testFilePrefix + `.input.${extension}`);
146 const source = fs.readFileSync(inputPath, 'utf8');
147 defineSnapshotTest(module, options, source, testName)
148}
149exports.defineSnapshotTestFromFixture = defineSnapshotTestFromFixture;