Skip to content

Commit

Permalink
[enzyme-adapter-react-{16,16.3}] [new] support shallow rendering `cre…
Browse files Browse the repository at this point in the history
…ateContext()` providers and consumers
  • Loading branch information
minznerjosh committed Jan 22, 2019
1 parent 2a00a00 commit 107a3f4
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 4 deletions.
27 changes: 25 additions & 2 deletions packages/enzyme-adapter-react-16.3/src/ReactSixteenThreeAdapter.js
Expand Up @@ -14,6 +14,8 @@ import {
isPortal,
isForwardRef,
isValidElementType,
isContextProvider,
isContextConsumer,
AsyncMode,
Fragment,
ContextConsumer,
Expand Down Expand Up @@ -327,11 +329,29 @@ class ReactSixteenThreeAdapter extends EnzymeAdapter {
let isDOM = false;
let cachedNode = null;
return {
render(el, context) {
render(el, context, {
providerValues = new Map(),
} = {}) {
cachedNode = el;
/* eslint consistent-return: 0 */
if (typeof el.type === 'string') {
isDOM = true;
} else if (isContextProvider(el)) {
providerValues.set(el.type, el.props.value);
const MockProvider = Object.assign(
props => props.children,
el.type,
);
return withSetStateAllowed(() => renderer.render({ ...el, type: MockProvider }));
} else if (isContextConsumer(el)) {
const value = providerValues.has(el.type.Provider)
? providerValues.get(el.type.Provider)
: el.type.Provider._context._defaultValue;
const MockConsumer = Object.assign(
props => props.children(value),
el.type,
);
return withSetStateAllowed(() => renderer.render({ ...el, type: MockConsumer }));
} else {
isDOM = false;
const { type: Component } = el;
Expand Down Expand Up @@ -508,7 +528,10 @@ class ReactSixteenThreeAdapter extends EnzymeAdapter {
if (!inst || !this.isValidElement(inst)) {
return false;
}
return typeof inst.type === 'function' || isForwardRef(inst);
return typeof inst.type === 'function'
|| isForwardRef(inst)
|| isContextProvider(inst)
|| isContextConsumer(inst);
}

createElement(...args) {
Expand Down
52 changes: 50 additions & 2 deletions packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Expand Up @@ -14,6 +14,8 @@ import {
isPortal,
isForwardRef,
isValidElementType,
isContextProvider,
isContextConsumer,
AsyncMode,
ConcurrentMode,
Fragment,
Expand Down Expand Up @@ -252,6 +254,31 @@ function getEmptyStateValue() {
return testRenderer._instance.state;
}

function getProviderFromConsumer(Consumer) {
// React stores references to the Provider on a Consumer differently across versions.
let Provider;
if (Consumer.Provider) {
({ Provider } = Consumer);
} else if (Consumer._context) {
({ Provider } = Consumer._context);
}
if (Provider) {
return Provider;
}
throw new Error('Enzyme Internal Error: can\'t figure out how to get Provider from Consumer');
}

function getProviderDefaultValue(Provider) {
// React stores references to the Provider's defaultValue differently across versions.
if ('_defaultValue' in Provider._context) {
return Provider._context._defaultValue;
}
if ('_currentValue' in Provider._context) {
return Provider._context._currentValue;
}
throw new Error('Enzyme Internal Error: can\'t figure out how to get Provider\'s default value');
}

class ReactSixteenAdapter extends EnzymeAdapter {
constructor() {
super();
Expand Down Expand Up @@ -350,11 +377,29 @@ class ReactSixteenAdapter extends EnzymeAdapter {
let isDOM = false;
let cachedNode = null;
return {
render(el, unmaskedContext) {
render(el, unmaskedContext, {
providerValues = new Map(),
} = {}) {
cachedNode = el;
/* eslint consistent-return: 0 */
if (typeof el.type === 'string') {
isDOM = true;
} else if (isContextProvider(el)) {
providerValues.set(el.type, el.props.value);
const MockProvider = Object.assign(
props => props.children,
el.type,
);
return withSetStateAllowed(() => renderer.render({ ...el, type: MockProvider }));
} else if (isContextConsumer(el)) {
const Provider = getProviderFromConsumer(el.type);
const value = providerValues.has(Provider)
? providerValues.get(Provider) : getProviderDefaultValue(Provider);
const MockConsumer = Object.assign(
props => props.children(value),
el.type,
);
return withSetStateAllowed(() => renderer.render({ ...el, type: MockConsumer }));
} else {
isDOM = false;
const { type: Component } = el;
Expand Down Expand Up @@ -557,7 +602,10 @@ class ReactSixteenAdapter extends EnzymeAdapter {
if (!inst || !this.isValidElement(inst)) {
return false;
}
return typeof inst.type === 'function' || isForwardRef(inst);
return typeof inst.type === 'function'
|| isForwardRef(inst)
|| isContextProvider(inst)
|| isContextConsumer(inst);
}

createElement(...args) {
Expand Down

0 comments on commit 107a3f4

Please sign in to comment.