From f4f87c65027ba3616e1bdc7637fd4ecd6deb1c67 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 13 Jan 2018 01:35:16 -0800 Subject: [PATCH] [Fix] improve "bad adapter" error message Fixes #1437 --- .../enzyme-test-suite/test/Adapter-spec.jsx | 27 +++++++++++++++-- .../test/_helpers/adapter.js | 29 ++++++++++++++++++ .../test/_helpers/setupAdapters.js | 29 +----------------- packages/enzyme/src/validateAdapter.js | 30 +++++++++++++++++-- 4 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 packages/enzyme-test-suite/test/_helpers/adapter.js diff --git a/packages/enzyme-test-suite/test/Adapter-spec.jsx b/packages/enzyme-test-suite/test/Adapter-spec.jsx index 92435fc4a..66835ae7d 100644 --- a/packages/enzyme-test-suite/test/Adapter-spec.jsx +++ b/packages/enzyme-test-suite/test/Adapter-spec.jsx @@ -2,8 +2,10 @@ import React from 'react'; import { expect } from 'chai'; import jsdom from 'jsdom'; import configuration from 'enzyme/build/configuration'; +import { configure, shallow } from 'enzyme'; import './_helpers/setupAdapters'; +import Adapter from './_helpers/adapter'; import { renderToString } from './_helpers/react-compat'; import { REACT013, REACT16 } from './_helpers/version'; import { itIf, describeWithDOM } from './_helpers'; @@ -36,8 +38,30 @@ function cleanNode(node) { } describe('Adapter', () => { - describeWithDOM('mounted render', () => { + describe('error message', () => { + afterEach(() => { + configure({ adapter }); + }); + + it('fails to render when no adapter is configured', () => { + configure({ adapter: undefined }); + expect(() => shallow(
)).to.throw(Error, /Enzyme expects an adapter to be configured, but found none/); + }); + it('fails to render when an object that does not inherit from the base class is configured', () => { + expect(() => configure({ adapter: {} })).to.throw(Error, /configured enzyme adapter did not inherit from the EnzymeAdapter base class/); + }); + + it('fails to render when an adapter constructor is configured', () => { + expect(() => configure({ adapter: Adapter })).to.throw(Error, /you provided an adapter \*constructor\*/); + }); + + it('fails to render when a non-adapter-constructor function is configured', () => { + expect(() => configure({ adapter() {} })).to.throw(Error, /an enzyme adapter must be an object instance; you provided a function/); + }); + }); + + describeWithDOM('mounted render', () => { function hydratedTreeMatchesUnhydrated(element) { const markup = renderToString(element); const dom = jsdom.jsdom(`
${markup}
`); @@ -763,5 +787,4 @@ describe('Adapter', () => { }, })); }); - }); diff --git a/packages/enzyme-test-suite/test/_helpers/adapter.js b/packages/enzyme-test-suite/test/_helpers/adapter.js new file mode 100644 index 000000000..fefd3274e --- /dev/null +++ b/packages/enzyme-test-suite/test/_helpers/adapter.js @@ -0,0 +1,29 @@ +/* eslint global-require: 0, import/no-extraneous-dependencies: 0, import/no-unresolved: 0 */ +/** + * This file is needed only because we run our unit tests on multiple + * versions of React at a time. This file basically figures out which + * version of React is loaded, and exports the correct adapter for configuring. + */ +const { + REACT013, + REACT014, + REACT15, + REACT155, + REACT16, +} = require('./version'); + +let Adapter = null; + +if (REACT013) { + Adapter = require('enzyme-adapter-react-13'); +} else if (REACT014) { + Adapter = require('enzyme-adapter-react-14'); +} else if (REACT155) { + Adapter = require('enzyme-adapter-react-15'); +} else if (REACT15) { + Adapter = require('enzyme-adapter-react-15.4'); +} else if (REACT16) { + Adapter = require('enzyme-adapter-react-16'); +} + +module.exports = Adapter; diff --git a/packages/enzyme-test-suite/test/_helpers/setupAdapters.js b/packages/enzyme-test-suite/test/_helpers/setupAdapters.js index f9fa7cac1..6d5cc4475 100644 --- a/packages/enzyme-test-suite/test/_helpers/setupAdapters.js +++ b/packages/enzyme-test-suite/test/_helpers/setupAdapters.js @@ -1,31 +1,4 @@ -/* eslint global-require: 0, import/no-extraneous-dependencies: 0, import/no-unresolved: 0 */ -/** - * This file is needed only because we run our unit tests on multiple - * versions of React at a time. This file basically figures out which - * version of React is loaded, and configures enzyme to use the right - * corresponding adapter. - */ -const { - REACT013, - REACT014, - REACT15, - REACT155, - REACT16, -} = require('./version'); const Enzyme = require('enzyme'); - -let Adapter = null; - -if (REACT013) { - Adapter = require('enzyme-adapter-react-13'); -} else if (REACT014) { - Adapter = require('enzyme-adapter-react-14'); -} else if (REACT155) { - Adapter = require('enzyme-adapter-react-15'); -} else if (REACT15) { - Adapter = require('enzyme-adapter-react-15.4'); -} else if (REACT16) { - Adapter = require('enzyme-adapter-react-16'); -} +const Adapter = require('./adapter'); Enzyme.configure({ adapter: new Adapter() }); diff --git a/packages/enzyme/src/validateAdapter.js b/packages/enzyme/src/validateAdapter.js index 8911ba3fb..4132a1951 100644 --- a/packages/enzyme/src/validateAdapter.js +++ b/packages/enzyme/src/validateAdapter.js @@ -3,8 +3,34 @@ import EnzymeAdapter from './EnzymeAdapter'; export default function validateAdapter(adapter) { if (!adapter) { throw new Error(` - Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none. To - configure an adapter, you should call \`Enzyme.configure({ adapter: new Adapter() })\` + Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none. + To configure an adapter, you should call \`Enzyme.configure({ adapter: new Adapter() })\` + before using any of Enzyme's top level APIs, where \`Adapter\` is the adapter + corresponding to the library currently being tested. For example: + + import Adapter from 'enzyme-adapter-react-15'; + + To find out more about this, see http://airbnb.io/enzyme/docs/installation/index.html + `); + } + if (typeof adapter === 'function') { + if (Object.getPrototypeOf(adapter) === EnzymeAdapter) { + throw new Error(` + Enzyme Internal Error: Enzyme expects an adapter instance to be configured - + you provided an adapter *constructor*. + To configure an adapter, you should call \`Enzyme.configure({ adapter: new Adapter() })\` + before using any of Enzyme's top level APIs, where \`Adapter\` is the adapter + corresponding to the library currently being tested. For example: + + import Adapter from 'enzyme-adapter-react-15'; + + To find out more about this, see http://airbnb.io/enzyme/docs/installation/index.html + `); + } + throw new Error(` + Enzyme Internal Error: Enzyme expects an adapter to be configured - + an enzyme adapter must be an object instance; you provided a function. + To configure an adapter, you should call \`Enzyme.configure({ adapter: new Adapter() })\` before using any of Enzyme's top level APIs, where \`Adapter\` is the adapter corresponding to the library currently being tested. For example: