Skip to content

Commit

Permalink
fix: Allow usage outside of Next.js (e.g. Jest and Storybook) (#76)
Browse files Browse the repository at this point in the history
* fix: Allow usage outside of Next.js (e.g. Jest and Storybook)

* Wording
  • Loading branch information
amannn committed Jan 4, 2022
1 parent 6304d08 commit 7c6925b
Show file tree
Hide file tree
Showing 10 changed files with 1,212 additions and 19 deletions.
3 changes: 3 additions & 0 deletions packages/example-advanced/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ require('eslint-config-molindo/setupPlugins');

module.exports = {
extends: ['molindo/typescript', 'molindo/react', 'plugin:@next/next/recommended'],
env: {
node: true
},
rules: {
'react/react-in-jsx-scope': 'off',
'jsx-a11y/anchor-is-valid': 'off',
Expand Down
5 changes: 5 additions & 0 deletions packages/example-advanced/config/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Used by Jest

module.exports = {
presets: ['next/babel']
};
7 changes: 7 additions & 0 deletions packages/example-advanced/config/jest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"testEnvironment": "jsdom",
"rootDir": "../",
"transform": {
"\\.tsx$": ["babel-jest", { "configFile": "./config/babel.config.js" }]
}
}
6 changes: 4 additions & 2 deletions packages/example-advanced/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"dev": "next dev",
"lint": "eslint src && tsc",
"test": "echo 'No tests yet'",
"test": "jest --config config/jest.json",
"build": "next build",
"start": "next start"
},
Expand All @@ -18,9 +18,11 @@
"react-dom": "^17.0.0"
},
"devDependencies": {
"@testing-library/react": "12.1.2",
"@types/lodash": "4.14.176",
"eslint": "7.4.0",
"eslint-config-molindo": "5.0.1",
"eslint-config-next": "^12.0.0"
"eslint-config-next": "^12.0.0",
"jest": "27.4.5"
}
}
30 changes: 30 additions & 0 deletions packages/example-advanced/src/components/Navigation.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// @ts-ignore

import {render} from '@testing-library/react';
import {pick} from 'lodash';
import {NextIntlProvider} from 'next-intl';
import messages from '../../messages/en.json';
import Navigation from './Navigation';

// If the tested component uses features from Next.js, you have to mock them.
// Note that next-intl only has an optional dependency on Next.js.
jest.mock('next/router', () => ({
useRouter() {
return {
route: '/',
locale: 'en',
locales: ['en', 'de']
};
}
}));

it('renders', () => {
render(
<NextIntlProvider
locale="en"
messages={pick(messages, Navigation.messages)}
>
<Navigation />
</NextIntlProvider>
);
});
2 changes: 1 addition & 1 deletion packages/example-advanced/src/components/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {useTranslations} from 'next-intl';
import {useRouter} from 'next/dist/client/router';
import Link from 'next/link';
import {useRouter} from 'next/router';

export default function Navigation() {
const t = useTranslations('Navigation');
Expand Down
1 change: 1 addition & 0 deletions packages/example-advanced/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"include": [
"next-env.d.ts",
"**/*.js",
"**/*.ts",
"**/*.tsx"
],
Expand Down
9 changes: 7 additions & 2 deletions packages/next-intl/src/NextIntlProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ type Props = Omit<ComponentProps<typeof IntlProvider>, 'locale'> & {
};

export default function NextIntlProvider({locale, ...rest}: Props) {
const nextLocale = useRouter().locale;
if (!locale && nextLocale) locale = nextLocale;
// The router can be undefined if used in a context outside
// of Next.js (e.g. unit tests, Storybook, ...)
const nextLocale = useRouter()?.locale;

if (!locale && nextLocale) {
locale = nextLocale;
}

if (!locale) {
throw new Error(
Expand Down
6 changes: 6 additions & 0 deletions packages/website/pages/docs/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ Yes, see [`use-intl`](https://github.com/amannn/next-intl/tree/main/packages/use
This library is only concerned with formatting dates. A great library to parse and manipulate dates is [date-fns](https://date-fns.org/).

Note that parsing dates with `new Date(dateString)` and `Date.parse(dateString)` is discouraged due to browser differences and inconsistencies (see [the MDN docs on the `Date` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date)).

## Can next-intl be used with testing libraries like Jest and Storybook?

Yes. These environments pose the challenge that components render in isolation and therefore relevant providers might be missing. To fix this, you should wrap the component with `NextIntlProvider`.

Please see the [Jest example](https://github.com/amannn/next-intl/blob/main/packages/example-advanced/src/components/Navigation.spec.tsx) to explore a working setup. For Storybook, you have to [add a global decorator](https://storybook.js.org/docs/react/writing-stories/decorators#global-decorators) that configures the provider.

1 comment on commit 7c6925b

@vercel
Copy link

@vercel vercel bot commented on 7c6925b Jan 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.