Skip to content

Commit

Permalink
mock useContext for shallow rendered tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristopherChudzicki committed Dec 12, 2023
1 parent 704ef30 commit d96e268
Show file tree
Hide file tree
Showing 22 changed files with 117 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe("CourseProductDetailEnroll", () => {
course = makeCourseDetailWithRuns()
enrollment = makeCourseRunEnrollment()
currentUser = makeUser()
renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
CourseProductDetailEnroll,
InnerCourseProductDetailEnroll,
{
Expand Down Expand Up @@ -289,6 +289,7 @@ describe("CourseProductDetailEnroll", () => {
const enrollBtn = inner.find("form > button.enroll-now")
assert.isTrue(enrollBtn.exists())
})

;[
[true, 201],
[false, 400]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe("NotificationContainer component", () => {
getAlertPropsStub = helper.sandbox
.stub(notificationsApi, "getNotificationAlertProps")
.returns({})
render = helper.configureMountRenderer(
render = helper.configureHOCRenderer(
NotificationContainer,
InnerNotificationContainer,
{
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/src/components/PrivateRoute_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("PrivateRoute component", () => {

beforeEach(() => {
helper = new IntegrationTestHelper()
renderComponent = helper.configureMountRenderer(
renderComponent = helper.configureHOCRenderer(
PrivateRoute,
InnerPrivateRoute,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("ProgramProductDetailEnroll", () => {
programs = [makeProgramWithReqTree()]
programEnrollments = [makeProgramEnrollment()]

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
ProgramProductDetailEnroll,
InnerProgramProductDetailEnroll,
{
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/src/containers/App_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("Top-level App", () => {
notificationsApi,
"removeStoredUserMessage"
)
renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
App,
InnerApp,
{},
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/src/containers/HeaderApp_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe("Top-level HeaderApp", () => {
notificationsApi,
"removeStoredUserMessage"
)
renderPage = helper.configureMountRenderer(HeaderApp, InnerHeaderApp, {}, {})
renderPage = helper.configureHOCRenderer(HeaderApp, InnerHeaderApp, {}, {})
})

afterEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/src/containers/pages/CatalogPage_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe("CatalogPage", function() {
helper = new IntegrationTestHelper()
window.IntersectionObserver = mockIntersectionObserver

renderPage = helper.configureMountRenderer(CatalogPage, InnerCatalogPage)
renderPage = helper.configureHOCRenderer(CatalogPage, InnerCatalogPage)

SETTINGS.features = {
"mitxonline-new-product-page": true
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/src/containers/pages/DashboardPage_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("DashboardPage", () => {
userEnrollments = [makeCourseRunEnrollment(), makeCourseRunEnrollment()]
currentUser = makeUser()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
DashboardPage,
InnerDashboardPage,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe("OrderReceiptPage", () => {
beforeEach(() => {
helper = new IntegrationTestHelper()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
OrderReceiptPage,
InnerOrderReceiptPage,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe("LoginEmailPage", () => {
setSubmittingStub = helper.sandbox.stub()
setErrorsStub = helper.sandbox.stub()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
LoginEmailPage,
InnerLoginEmailPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe("LoginForgotPasswordConfirmPage", () => {

setSubmittingStub = helper.sandbox.stub()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
LoginForgotPasswordConfirmPage,
InnerLoginForgotPasswordConfirmPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("LoginForgotPasswordPage", () => {

setSubmittingStub = helper.sandbox.stub()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
LoginForgotPasswordPage,
InnerLoginForgotPasswordPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("LoginPasswordPage", () => {
state: STATE_LOGIN_PASSWORD
})

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
LoginPasswordPage,
InnerLoginPasswordPage,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe("EditProfilePage", () => {
beforeEach(() => {
helper = new IntegrationTestHelper()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
EditProfilePage,
InnerEditProfilePage,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("RegisterConfirmPage", () => {

beforeEach(() => {
helper = new IntegrationTestHelper()
renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
RegisterConfirmPage,
InnerRegisterConfirmPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("RegisterConfirmSentPage", () => {

helper = new IntegrationTestHelper()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
RegisterConfirmSentPage,
InnerRegisterConfirmSentPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("RegisterDeniedPage", () => {

helper = new IntegrationTestHelper()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
RegisterDeniedPage,
InnerRegisterDeniedPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe("RegisterDetailsPage", () => {
setSubmittingStub = helper.sandbox.stub()
setErrorsStub = helper.sandbox.stub()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
RegisterDetailsPage,
InnerRegisterDetailsPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe("RegisterEmailPage", () => {
setSubmittingStub = helper.sandbox.stub()
setErrorsStub = helper.sandbox.stub()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
RegisterEmailPage,
InnerRegisterEmailPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe("AccountSettingsPage", () => {

setSubmittingStub = helper.sandbox.stub()

renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
AccountSettingsPage,
InnerAccountSettingsPage,
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("EmailConfirmPage", () => {

beforeEach(() => {
helper = new IntegrationTestHelper()
renderPage = helper.configureMountRenderer(
renderPage = helper.configureHOCRenderer(
EmailConfirmPage,
InnerEmailConfirmPage,
{},
Expand Down
102 changes: 95 additions & 7 deletions frontend/public/src/util/integration_test_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import configureStoreMain from "../store/configureStore"

import type { Sandbox } from "../flow/sinonTypes"
import * as networkInterfaceFuncs from "../store/network_interface"
import {Provider} from "react-redux"
import {Provider, ReactReduxContext} from "react-redux"
import {Route, Router} from "react-router"

export default class IntegrationTestHelper {
Expand Down Expand Up @@ -45,6 +45,9 @@ export default class IntegrationTestHelper {
const resText = (response && response.text) || undefined
const resHeaders = (response && response.header) || undefined

// console.log(`Responding to request ${method} ${url} with`)
// console.log(resBody)

callback(err, resStatus, resBody, resText, resHeaders)
},
abort: () => {
Expand All @@ -56,6 +59,12 @@ export default class IntegrationTestHelper {
cleanup() {
this.actions = []
this.sandbox.restore()

if (this.wrapper) {
this.wrapper.unmount()
delete this.wrapper
this.wrapper = null
}
}

configureShallowRenderer(
Expand Down Expand Up @@ -98,6 +107,79 @@ export default class IntegrationTestHelper {
}
}

configureHOCRenderer(
WrappedComponent: Class<React.Component<*, *>>,
InnerComponent: Class<React.Component<*, *>>,
defaultState: Object,
defaultProps = {}
) {
const history = this.browserHistory
return async (extraState = {}, extraProps = {}) => {
const initialState = R.mergeDeepRight(defaultState, extraState)
const store = configureStoreMain(initialState)

const useContextFake = this.sandbox.stub(React, "useContext")
useContextFake.callsFake(context => {
if (context === ReactReduxContext) return { store }

This comment has been minimized.

Copy link
@ChristopherChudzicki

ChristopherChudzicki Dec 12, 2023

Author Contributor

Mock useContext specifically for ReactReduxContext.

The actual return value that redux would give is here and includes subscription, which I think is pretty rarely used.

const msg = [
"useContext called in enzyme shallow render with un-mocked return",
"value. See See https://github.com/enzymejs/enzyme/issues/2176#issuecomment-532361526",
"for more."
].join(" ")
throw new Error(msg)
})

const wrapper = await shallow(
<WrappedComponent
store={store}
dispatch={store.dispatch}
history={history}
{...defaultProps}
{...extraProps}
/>,
{
context: {
// TODO: should be removed in the near future after upgrading enzyme
store
},
}
)


// just a little convenience method
store.getLastAction = function() {
const actions = this.getActions()
return actions[actions.length - 1]
}

// dive through layers of HOCs until we reach the desired inner component
let inner = wrapper
while (!inner.is(InnerComponent)) {
// determine the type before we dive
const cls = inner.type()
if (InnerComponent === cls.WrappedComponent) {
break
}

// shallow render this component
inner = await inner.dive()

// if it defines WrappedComponent, find() that so we skip over any intermediaries
if (
cls &&
cls.hasOwnProperty("WrappedComponent") && // eslint-disable-line no-prototype-builtins
inner.find(cls.WrappedComponent).length
) {
inner = inner.find(cls.WrappedComponent)
}
}
// one more time to shallow render the InnerComponent
inner = await inner.dive()

return { wrapper, inner, store }
}
}

configureMountRenderer(
WrappedComponent: Class<React.Component<*, *>>,
InnerComponent: Class<React.Component<*, *>>,
Expand All @@ -113,12 +195,18 @@ export default class IntegrationTestHelper {
const store = configureStoreMain(initialState)

console.log(InnerComponent)
const ComponentWithProps = () => (
<WrappedComponent
{...defaultProps}
{...extraProps}
/>
)
const ComponentWithProps = () => {
console.log("state")
console.log(store.getState())
return (
<WrappedComponent
history={history}
store={store}
{...defaultProps}
{...extraProps}
/>
)
}

console.log(ComponentWithProps)

Expand Down

0 comments on commit d96e268

Please sign in to comment.