Skip to content

Commit e9d5aa1

Browse files
committed
feat: allow testing entire babel transform result via outputRaw
closes #186
1 parent ce6d60c commit e9d5aa1

File tree

14 files changed

+576
-126
lines changed

14 files changed

+576
-126
lines changed

README.md

Lines changed: 184 additions & 102 deletions
Large diffs are not rendered by default.

babel.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ module.exports = {
5454
modules: 'cjs',
5555
targets: NODE_LTS,
5656
useBuiltIns: 'usage',
57-
corejs: '3.35',
57+
corejs: '3.36',
5858
shippedProposals: true,
5959
exclude: ['proposal-dynamic-import']
6060
}

src/errors.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const ErrorMessage = {
6767
ExpectedErrorToMatchRegExp: (resultString: string, expectedError: RegExp) =>
6868
`expected "${resultString}" to match ${expectedError}`,
6969
BabelOutputTypeIsNotString: (rawBabelOutput: unknown) =>
70-
`unexpected babel output type "${typeof rawBabelOutput}" (expected string)`,
70+
`unexpected babel output of type "${typeof rawBabelOutput}" (expected 'code' property to be of type "string")`,
7171
BabelOutputUnexpectedlyEmpty: () =>
7272
'attempted to execute babel output but it was empty. An empty string cannot be evaluated',
7373
AttemptedToSnapshotUnmodifiedBabelOutput: () =>
@@ -107,6 +107,8 @@ export const ErrorMessage = {
107107
? 'neither `output` nor `outputFixture` can be provided with `throws` or `error`'
108108
: 'a fixture cannot be provided with `throws` or `error` and also contain an output file';
109109
},
110+
InvalidHasThrowsAndOutputRaw: () =>
111+
'`outputRaw` cannot be provided with `throws` or `error`',
110112
InvalidHasThrowsAndExec: (
111113
testConfig: Pick<MaybePluginTesterTestConfig, typeof $type>
112114
) => {

src/plugin-tester.ts

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ function pluginTester(options: PluginTesterOptions = {}) {
726726
setup,
727727
teardown,
728728
formatResult,
729+
outputRaw,
729730
fixtureOutputName,
730731
fixtureOutputExt
731732
} = localOptions;
@@ -799,6 +800,7 @@ function pluginTester(options: PluginTesterOptions = {}) {
799800
code,
800801
codeFixture: codePath,
801802
output,
803+
outputRaw,
802804
outputFixture: outputPath,
803805
exec,
804806
execFixture: execPath
@@ -868,13 +870,14 @@ function pluginTester(options: PluginTesterOptions = {}) {
868870
teardown,
869871
formatResult,
870872
snapshot,
871-
code: rawCode,
872-
output: rawOutput,
873-
exec: rawExec,
873+
code: originalCode,
874+
output: originalOutput,
875+
outputRaw,
876+
exec: originalExec,
874877
fixture,
875-
codeFixture: rawCodeFixture,
878+
codeFixture: originalCodeFixture,
876879
outputFixture,
877-
execFixture: rawExecFixture
880+
execFixture: originalExecFixture
878881
} = mergeWith(
879882
{
880883
setup: noop,
@@ -886,19 +889,23 @@ function pluginTester(options: PluginTesterOptions = {}) {
886889

887890
const codeFixture = getAbsolutePathUsingFilepathDirname(
888891
filepath,
889-
rawCodeFixture ?? fixture
892+
originalCodeFixture ?? fixture
890893
);
891894

892-
const execFixture = getAbsolutePathUsingFilepathDirname(filepath, rawExecFixture);
895+
const execFixture = getAbsolutePathUsingFilepathDirname(
896+
filepath,
897+
originalExecFixture
898+
);
893899

894-
const code = rawCode !== undefined ? stripIndent(rawCode) : readCode(codeFixture);
900+
const code =
901+
originalCode !== undefined ? stripIndent(originalCode) : readCode(codeFixture);
895902

896903
const output =
897-
rawOutput !== undefined
898-
? stripIndent(rawOutput)
904+
originalOutput !== undefined
905+
? stripIndent(originalOutput)
899906
: readCode(filepath, outputFixture);
900907

901-
const exec = rawExec ?? readCode(execFixture);
908+
const exec = originalExec ?? readCode(execFixture);
902909

903910
const testConfig: MaybePluginTesterTestObjectConfig = mergeWith(
904911
{ [$type]: 'test-object' } as const,
@@ -945,6 +952,7 @@ function pluginTester(options: PluginTesterOptions = {}) {
945952
output !== undefined
946953
? trimAndFixLineEndings(output, endOfLine, code)
947954
: undefined,
955+
outputRaw,
948956
outputFixture,
949957
exec,
950958
execFixture:
@@ -973,9 +981,9 @@ function pluginTester(options: PluginTesterOptions = {}) {
973981
verbose3('finalized test object: %O', testConfig);
974982

975983
validateTestConfig(testConfig, {
976-
hasCodeAndCodeFixture: !!(rawCode && codeFixture),
977-
hasOutputAndOutputFixture: !!(rawOutput && outputFixture),
978-
hasExecAndExecFixture: !!(rawExec && execFixture)
984+
hasCodeAndCodeFixture: !!(originalCode && codeFixture),
985+
hasOutputAndOutputFixture: !!(originalOutput && outputFixture),
986+
hasExecAndExecFixture: !!(originalExec && execFixture)
979987
});
980988

981989
hasTests = true;
@@ -1124,6 +1132,7 @@ function pluginTester(options: PluginTesterOptions = {}) {
11241132
code,
11251133
codeFixture,
11261134
output,
1135+
outputRaw,
11271136
outputFixture,
11281137
exec,
11291138
execFixture
@@ -1141,7 +1150,7 @@ function pluginTester(options: PluginTesterOptions = {}) {
11411150
`calling babel transform function (${transformer.name}) with parameters: %O`,
11421151
parameters
11431152
);
1144-
return (await transformer(...parameters))?.code;
1153+
return await transformer(...parameters);
11451154
} catch (error) {
11461155
verbose2(`babel transformation failed with error: ${error}`);
11471156
if (expectedError) {
@@ -1188,18 +1197,37 @@ function pluginTester(options: PluginTesterOptions = {}) {
11881197
);
11891198
} // ? Else condition is handled by the typeof === 'function' branch
11901199
}
1191-
} else if (typeof rawBabelOutput !== 'string') {
1192-
throw new TypeError(ErrorMessage.BabelOutputTypeIsNotString(rawBabelOutput));
11931200
} else {
11941201
debug2('expecting babel transform function to succeed');
1202+
1203+
// ? Since expectedError is not truthy, we know that rawBabelOutput must
1204+
// ? be the return type of the babel transformer function
1205+
const isRawBabelOutput = !!rawBabelOutput && typeof rawBabelOutput === 'object';
1206+
const hasRawBabelOutputCode = isRawBabelOutput && 'code' in rawBabelOutput;
1207+
1208+
if (isRawBabelOutput && outputRaw) {
1209+
debug2('executing provided outputRaw function before final comparison');
1210+
await outputRaw(rawBabelOutput);
1211+
}
1212+
1213+
if (!hasRawBabelOutputCode || typeof rawBabelOutput.code !== 'string') {
1214+
throw new TypeError(
1215+
ErrorMessage.BabelOutputTypeIsNotString(
1216+
hasRawBabelOutputCode ? rawBabelOutput.code : rawBabelOutput
1217+
)
1218+
);
1219+
}
1220+
1221+
debug2('performing final comparison');
1222+
11951223
const formatResultFilepath = codeFixture || execFixture || filepath;
11961224

11971225
// ? We split rawBabelOutput and result into two steps to ensure
11981226
// ? exceptions thrown by trimAndFixLineEndings and formatResult are not
11991227
// ? erroneously captured when we only really care about errors thrown by
12001228
// ? babel
12011229
const result = trimAndFixLineEndings(
1202-
await formatResult(rawBabelOutput || '', {
1230+
await formatResult(rawBabelOutput.code || '', {
12031231
cwd: formatResultFilepath ? path.dirname(formatResultFilepath) : undefined,
12041232
filepath: formatResultFilepath,
12051233
filename: formatResultFilepath
@@ -1294,7 +1322,8 @@ function pluginTester(options: PluginTesterOptions = {}) {
12941322
exec,
12951323
output,
12961324
babelOptions,
1297-
expectedError
1325+
expectedError,
1326+
outputRaw
12981327
} = testConfig;
12991328

13001329
if (knownViolations) {
@@ -1348,6 +1377,10 @@ function pluginTester(options: PluginTesterOptions = {}) {
13481377
throwTypeErrorWithDebugOutput(ErrorMessage.InvalidHasThrowsAndOutput(testConfig));
13491378
}
13501379

1380+
if (outputRaw !== undefined && expectedError !== undefined) {
1381+
throwTypeErrorWithDebugOutput(ErrorMessage.InvalidHasThrowsAndOutputRaw());
1382+
}
1383+
13511384
if (exec !== undefined && expectedError !== undefined) {
13521385
throwTypeErrorWithDebugOutput(ErrorMessage.InvalidHasThrowsAndExec(testConfig));
13531386
}

src/types.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ export type SetupFunction = () => Promisable<void | TeardownFunction>;
4343
*/
4444
export type TeardownFunction = () => Promisable<void>;
4545

46+
/**
47+
* The shape of an `outputRaw` test object or fixture option.
48+
*
49+
* @see https://npm.im/babel-plugin-tester#outputraw
50+
*/
51+
export type OutputTesterFunction = (output: Babel.BabelFileResult) => Promisable<void>;
52+
4653
/**
4754
* Options passed as parameters to the `pluginTester` function.
4855
*
@@ -418,6 +425,18 @@ export interface FixtureOptions {
418425
* @see https://npm.im/babel-plugin-tester#formatResult-1
419426
*/
420427
formatResult?: ResultFormatter;
428+
/**
429+
* This is a `fixtures` option similar in intent to `output.js` except it
430+
* tests against the entire `BabelFileResult` object returned by babel's
431+
* `transform` function instead of only the `code` property of
432+
* `BabelFileResult`.
433+
*
434+
* As it requires a function value, this option must be used in `options.js`
435+
* instead of `options.json`.
436+
*
437+
* @see https://npm.im/babel-plugin-tester#outputRaw
438+
*/
439+
outputRaw?: OutputTesterFunction;
421440
/**
422441
* This is a `fixtures` option used to provide your own fixture output file
423442
* name. Defaults to `"output"`.
@@ -599,6 +618,15 @@ export interface TestObject {
599618
* @see https://npm.im/babel-plugin-tester#output
600619
*/
601620
output?: string;
621+
/**
622+
* This is a `tests` object option similar in intent to the `output` option
623+
* except it tests against the entire `BabelFileResult` object returned by
624+
* babel's `transform` function instead of only the `code` property of
625+
* `BabelFileResult`.
626+
*
627+
* @see https://npm.im/babel-plugin-tester#outputRaw-1
628+
*/
629+
outputRaw?: OutputTesterFunction;
602630
/**
603631
* This is a `tests` object option that will be transformed just like the
604632
* `code` property, except the output will be _evaluated_ in the same context
@@ -768,6 +796,7 @@ type PluginTesterSharedTestConfigProperties = {
768796
only?: TestObject['only'] | FixtureOptions['only'];
769797
skip?: TestObject['skip'] | FixtureOptions['skip'];
770798
expectedError?: TestObject['throws'] | FixtureOptions['throws'];
799+
outputRaw?: TestObject['outputRaw'] | FixtureOptions['outputRaw'];
771800
testSetup: NonNullable<PluginTesterOptions['setup']>;
772801
testTeardown: NonNullable<PluginTesterOptions['teardown']>;
773802
formatResult: NonNullable<PluginTesterOptions['formatResult']>;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('hello');
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
outputRaw: () => undefined
3+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('hello');
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
throws: true,
3+
outputRaw: () => undefined
4+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const hello = 'hey';

0 commit comments

Comments
 (0)