mirror of
https://github.com/HSLdevcom/digitransit-ui
synced 2026-04-26 16:39:51 +02:00
136 lines
3.8 KiB
JavaScript
136 lines
3.8 KiB
JavaScript
/**
|
|
* Components using react-intl need an intl context.
|
|
* - shallowWithIntl: injects a real intl object via legacy context AND stubs useIntl()
|
|
* so both class components (contextTypes) and function components (useIntl hook) work.
|
|
* Also stubs useConfigContext() and useRouter() since shallow rendering does not
|
|
* support context providers for hooks.
|
|
* - mountWithIntl: wraps with IntlProvider + IntlBridge + TestProviders for full mount tests
|
|
*/
|
|
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { mount, shallow } from 'enzyme';
|
|
import sinon from 'sinon';
|
|
import * as ReactIntl from 'react-intl';
|
|
import { createIntl, createIntlCache, IntlProvider } from 'react-intl';
|
|
import * as found from 'found';
|
|
import translations from '../../../app/translations/en';
|
|
import IntlBridge from '../../../app/util/IntlBridge';
|
|
import * as ConfigContext from '../../../app/configurations/ConfigContext';
|
|
import TestProviders from './mock-providers';
|
|
import { mockContext } from './mock-context';
|
|
|
|
const getMessages = locale => translations[locale] || {};
|
|
|
|
const intlCache = createIntlCache();
|
|
|
|
// Tracks stubs created by shallowWithIntl (not by test-specific code)
|
|
// so init.js can restore them after each test.
|
|
let ownedUseIntlStub = null;
|
|
let ownedConfigContextStub = null;
|
|
let ownedUseRouterStub = null;
|
|
|
|
export function restoreOwnedIntlStub() {
|
|
if (ownedUseIntlStub) {
|
|
ownedUseIntlStub.restore();
|
|
ownedUseIntlStub = null;
|
|
}
|
|
}
|
|
|
|
export function restoreOwnedContextStubs() {
|
|
if (ownedConfigContextStub) {
|
|
ownedConfigContextStub.restore();
|
|
ownedConfigContextStub = null;
|
|
}
|
|
if (ownedUseRouterStub) {
|
|
ownedUseRouterStub.restore();
|
|
ownedUseRouterStub = null;
|
|
}
|
|
}
|
|
|
|
function applyContextStubs({ config, match, router } = {}) {
|
|
const configValue = config || mockContext.config;
|
|
const routerValue = {
|
|
match: match || mockContext.match,
|
|
router: router || mockContext.router,
|
|
};
|
|
|
|
const configAlreadyStubbed =
|
|
typeof ConfigContext.useConfigContext.restore === 'function';
|
|
if (!configAlreadyStubbed) {
|
|
ownedConfigContextStub = sinon
|
|
.stub(ConfigContext, 'useConfigContext')
|
|
.returns(configValue);
|
|
}
|
|
|
|
const routerAlreadyStubbed = typeof found.useRouter.restore === 'function';
|
|
if (!routerAlreadyStubbed) {
|
|
ownedUseRouterStub = sinon.stub(found, 'useRouter').returns(routerValue);
|
|
}
|
|
}
|
|
|
|
export const shallowWithIntl = (
|
|
node,
|
|
{
|
|
context = {},
|
|
locale = 'en',
|
|
messages = getMessages(locale),
|
|
config,
|
|
match,
|
|
router,
|
|
...additionalOptions
|
|
} = {},
|
|
) => {
|
|
const intl = createIntl({ locale, messages }, intlCache);
|
|
|
|
// Stub useIntl() for function components, unless already stubbed by test code.
|
|
const alreadyStubbed = typeof ReactIntl.useIntl.restore === 'function';
|
|
if (!alreadyStubbed) {
|
|
if (!ownedUseIntlStub) {
|
|
ownedUseIntlStub = sinon.stub(ReactIntl, 'useIntl').returns(intl);
|
|
} else {
|
|
ownedUseIntlStub.returns(intl);
|
|
}
|
|
}
|
|
|
|
applyContextStubs({ config, match, router });
|
|
|
|
return shallow(node, {
|
|
context: { intl, ...context },
|
|
...additionalOptions,
|
|
});
|
|
};
|
|
|
|
export const mountWithIntl = (
|
|
node,
|
|
{
|
|
context = {},
|
|
childContextTypes = {},
|
|
locale = 'en',
|
|
messages = getMessages(locale),
|
|
config,
|
|
match,
|
|
router,
|
|
...additionalOptions
|
|
} = {},
|
|
) => {
|
|
const fullChildContextTypes = {
|
|
intl: PropTypes.object,
|
|
config: PropTypes.object,
|
|
...childContextTypes,
|
|
};
|
|
|
|
return mount(
|
|
<IntlProvider locale={locale} messages={messages}>
|
|
<IntlBridge>{node}</IntlBridge>
|
|
</IntlProvider>,
|
|
{
|
|
context: {
|
|
...context,
|
|
},
|
|
childContextTypes: fullChildContextTypes,
|
|
wrappingComponent: TestProviders,
|
|
wrappingComponentProps: { config, match, router },
|
|
...additionalOptions,
|
|
},
|
|
);
|
|
};
|