From ddeff88b9e875b9866446ffadd4bc2e80e9e2e86 Mon Sep 17 00:00:00 2001 From: Evilebot Tnawi Date: Fri, 17 Apr 2020 16:00:46 +0300 Subject: [PATCH] test: refactor (#835) --- .../validate-options.test.js.snap | 90 +++++++++-- test/validate-options.test.js | 143 +++++++++++------- 2 files changed, 164 insertions(+), 69 deletions(-) diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap index bea22769..9175f4a6 100644 --- a/test/__snapshots__/validate-options.test.js.snap +++ b/test/__snapshots__/validate-options.test.js.snap @@ -1,13 +1,30 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`validate options 1`] = ` +exports[`validate options should throw an error on the "implementation" option with "string" value 1`] = ` "Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. - options.implementation should be an object: object { … } -> The implementation of the sass to be used (https://github.com/webpack-contrib/sass-loader#implementation)." `; -exports[`validate options 2`] = ` +exports[`validate options should throw an error on the "implementation" option with "true" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options.implementation should be an object: + object { … } + -> The implementation of the sass to be used (https://github.com/webpack-contrib/sass-loader#implementation)." +`; + +exports[`validate options should throw an error on the "prependData" option with "true" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options.prependData should be one of these: + string | function + -> Prepends \`Sass\`/\`SCSS\` code before the actual entry file (https://github.com/webpack-contrib/sass-loader#prependdata). + Details: + * options.prependData should be a string. + * options.prependData should be an instance of function." +`; + +exports[`validate options should throw an error on the "sassOptions" option with "string" value 1`] = ` "Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. - options.sassOptions should be one of these: object { … } | function @@ -18,24 +35,73 @@ exports[`validate options 2`] = ` * options.sassOptions should be an instance of function." `; -exports[`validate options 3`] = ` +exports[`validate options should throw an error on the "sassOptions" option with "true" value 1`] = ` "Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. - - options.prependData should be one of these: - string | function - -> Prepends \`Sass\`/\`SCSS\` code before the actual entry file (https://github.com/webpack-contrib/sass-loader#prependdata). + - options.sassOptions should be one of these: + object { … } | function + -> Options for \`node-sass\` or \`sass\` (\`Dart Sass\`) implementation. (https://github.com/webpack-contrib/sass-loader#implementation). Details: - * options.prependData should be a string. - * options.prependData should be an instance of function." + * options.sassOptions should be an object: + object { … } + * options.sassOptions should be an instance of function." `; -exports[`validate options 4`] = ` +exports[`validate options should throw an error on the "sourceMap" option with "string" value 1`] = ` "Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. - - options.webpackImporter should be a boolean. - -> Enables/Disables default \`webpack\` importer (https://github.com/webpack-contrib/sass-loader#webpackimporter)." + - options.sourceMap should be a boolean. + -> Enables/Disables generation of source maps (https://github.com/webpack-contrib/sass-loader#sourcemap)." +`; + +exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" `; -exports[`validate options 5`] = ` +exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` "Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" `; + +exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options has an unknown property 'unknown'. These properties are valid: + object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }" +`; + +exports[`validate options should throw an error on the "webpackImporter" option with "string" value 1`] = ` +"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema. + - options.webpackImporter should be a boolean. + -> Enables/Disables default \`webpack\` importer (https://github.com/webpack-contrib/sass-loader#webpackimporter)." +`; diff --git a/test/validate-options.test.js b/test/validate-options.test.js index e11c8672..8aeacb55 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -1,67 +1,96 @@ import Fiber from 'fibers'; -import loader from '../src/cjs'; +import { + getCompiler, + compile, + getTestId, + getImplementationByName, +} from './helpers/index'; -beforeEach(() => { - // The `sass` (`Dart Sass`) package modify the `Function` prototype, but the `jest` lose a prototype - Object.setPrototypeOf(Fiber, Function.prototype); -}); +describe('validate options', () => { + beforeEach(() => { + // The `sass` (`Dart Sass`) package modify the `Function` prototype, but the `jest` lose a prototype + Object.setPrototypeOf(Fiber, Function.prototype); + }); -it('validate options', () => { - const validate = (options) => - loader.call( - Object.assign( - {}, - { - query: options, - loaders: [], - resourcePath: 'file.scss', - getResolve: () => () => {}, - async: () => (error) => { - if (error) { - throw error; - } - }, - } - ), - 'a { color: red; }' - ); + const tests = { + implementation: { + // eslint-disable-next-line global-require + success: [require('sass'), require('node-sass')], + failure: [true, 'string'], + }, + sassOptions: { + success: [{}, { indentWidth: 6 }, () => ({ indentWidth: 6 })], + failure: [true, 'string'], + }, + prependData: { + success: ['$color: red;', () => '$color: red;'], + failure: [true], + }, + sourceMap: { + success: [true, false], + failure: ['string'], + }, + webpackImporter: { + success: [true, false], + failure: ['string'], + }, + unknown: { + success: [], + failure: [1, true, false, 'test', /test/, [], {}, { foo: 'bar' }], + }, + }; - expect(() => - // eslint-disable-next-line global-require - validate({ implementation: require('node-sass') }) - ).not.toThrow(); - expect(() => - // eslint-disable-next-line global-require - validate({ implementation: require('sass') }) - ).not.toThrow(); - expect(() => - validate({ implementation: true }) - ).toThrowErrorMatchingSnapshot(); + function stringifyValue(value) { + if ( + Array.isArray(value) || + (value && typeof value === 'object' && value.constructor === Object) + ) { + return JSON.stringify(value); + } - expect(() => validate({ sassOptions: {} })).not.toThrow(); - expect(() => - validate({ - sassOptions: () => { - return {}; - }, - }) - ).not.toThrow(); - expect(() => validate({ sassOptions: () => {} })).not.toThrow(); - expect(() => validate({ sassOptions: true })).toThrowErrorMatchingSnapshot(); - expect(() => - validate({ sassOptions: { indentWidth: 6, linefeed: 'crlf' } }) - ).not.toThrow(); + return value; + } - expect(() => validate({ prependData: '$color: red;' })).not.toThrow(); - expect(() => validate({ prependData: () => '$color: red;' })).not.toThrow(); - expect(() => validate({ prependData: true })).toThrowErrorMatchingSnapshot(); + async function createTestCase(key, value, type) { + it(`should ${ + type === 'success' ? 'successfully validate' : 'throw an error on' + } the "${key}" option with "${stringifyValue(value)}" value`, async () => { + const testId = getTestId('language', 'scss'); + const compiler = getCompiler(testId, { + loader: { + options: { + implementation: getImplementationByName('dart-sass'), + [key]: value, + }, + }, + }); + let stats; + + try { + stats = await compile(compiler); + } finally { + if (type === 'success') { + expect(stats.hasErrors()).toBe(false); + } else if (type === 'failure') { + const { + compilation: { errors }, + } = stats; - expect(() => validate({ webpackImporter: true })).not.toThrow(); - expect(() => validate({ webpackImporter: false })).not.toThrow(); - expect(() => - validate({ webpackImporter: 'unknown' }) - ).toThrowErrorMatchingSnapshot(); + expect(errors).toHaveLength(1); + expect(() => { + throw new Error(errors[0].error.message); + }).toThrowErrorMatchingSnapshot(); + } + } + }); + } - expect(() => validate({ unknown: 'unknown' })).toThrowErrorMatchingSnapshot(); + for (const [key, values] of Object.entries(tests)) { + for (const type of Object.keys(values)) { + for (const value of values[type]) { + createTestCase(key, value, type); + } + } + } });