From 339c43be0745c3baa0913131243e1b09817d32e2 Mon Sep 17 00:00:00 2001 From: "Miguel Osorio @kelvur" Date: Sat, 28 Mar 2020 20:48:14 +0100 Subject: [PATCH 1/9] chore: replace actual testing packages by jest --- package.json | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3f4b42e..d52876d 100644 --- a/package.json +++ b/package.json @@ -96,23 +96,26 @@ "@babel/preset-react": "^7.0.0", "@babel/register": "^7.0.0", "@k14v/i18njs": "0.0.8", - "ava": "^1.2.1", - "babel-eslint": "^10.0.1", - "browser-env": "^3.2.5", - "cross-env": "^5.2.0", - "enzyme": "^3.8.0", - "enzyme-adapter-react-16": "^1.9.1", + "@testing-library/jest-dom": "^5.3.0", + "@testing-library/react": "^10.0.1", + "@testing-library/user-event": "^10.0.0", + "babel-eslint": "^10.1.0", + "babel-jest": "^25.2.3", + "babel-loader": "8.0.6", + "babel-plugin-named-asset-import": "^0.3.6", + "babel-preset-react-app": "^9.1.1", "eslint": "^5.13.0", "eslint-config-airbnb": "^17.1.0", "eslint-plugin-import": "^2.16.0", "eslint-plugin-jsx-a11y": "^6.1.1", "eslint-plugin-react": "^7.12.4", "husky": "^1.3.1", - "nyc": "^13.2.0", + "jest": "^25.2.3", + "jest-environment-jsdom-fourteen": "^1.0.1", + "jest-resolve": "^25.2.3", "prop-types": "^15.7.2", - "react": "^16.8.4", - "react-dom": "^16.8.4", - "sinon": "^7.2.3" + "react": "^16.13.1", + "react-dom": "^16.13.1" }, "peerDependencies": { "prop-types": "^15.7.2", From bf97c4f27a5a04c44bffd1ada4991ad237d575e2 Mon Sep 17 00:00:00 2001 From: "Miguel Osorio @kelvur" Date: Sat, 28 Mar 2020 20:48:58 +0100 Subject: [PATCH 2/9] chore: remove previous test config --- test/shims/index.js | 2 -- test/shims/react-enzyme-adapter.js | 5 ----- test/shims/setup-browser-env.js | 5 ----- 3 files changed, 12 deletions(-) delete mode 100644 test/shims/index.js delete mode 100644 test/shims/react-enzyme-adapter.js delete mode 100644 test/shims/setup-browser-env.js diff --git a/test/shims/index.js b/test/shims/index.js deleted file mode 100644 index 2648eb0..0000000 --- a/test/shims/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import './react-enzyme-adapter'; -import './setup-browser-env'; diff --git a/test/shims/react-enzyme-adapter.js b/test/shims/react-enzyme-adapter.js deleted file mode 100644 index 422e543..0000000 --- a/test/shims/react-enzyme-adapter.js +++ /dev/null @@ -1,5 +0,0 @@ -import { configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - - -configure({adapter: new Adapter()}); diff --git a/test/shims/setup-browser-env.js b/test/shims/setup-browser-env.js deleted file mode 100644 index 314ef96..0000000 --- a/test/shims/setup-browser-env.js +++ /dev/null @@ -1,5 +0,0 @@ -// Core -import browserEnv from 'browser-env'; - - -browserEnv(['window', 'document', 'navigator']); From 5a47223e20103b468183f484b5856a434fa0fda6 Mon Sep 17 00:00:00 2001 From: "Miguel Osorio @kelvur" Date: Sat, 28 Mar 2020 20:50:36 +0100 Subject: [PATCH 3/9] chore: add jest config --- babel.config.js | 41 +++++++++++++++++++++++++++++ package.json | 66 ++++++++++++++++++++--------------------------- src/setupTests.ts | 5 ++++ 3 files changed, 74 insertions(+), 38 deletions(-) create mode 100644 babel.config.js create mode 100644 src/setupTests.ts diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..1edaa1d --- /dev/null +++ b/babel.config.js @@ -0,0 +1,41 @@ + +const testConfig = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + '@babel/preset-react', + ], +}; + +const config = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + ie: '11', + }, + useBuiltIns: 'usage', + }, + ], + '@babel/preset-react', + ], + plugins: [ + '@babel/plugin-syntax-dynamic-import', + '@babel/plugin-proposal-class-properties', + '@babel/plugin-proposal-export-namespace-from', + ], +}; + +module.exports = (api) => { + const isTest = api.env('test'); + if (isTest) return testConfig; + + return config; +}; diff --git a/package.json b/package.json index d52876d..4a24c90 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,10 @@ "description": "React utilities for internationalization", "main": "index.js", "scripts": { - "test": "cross-env NODE_ENV=test nyc --reporter=html --reporter=text ava", - "test:watch": "cross-env NODE_ENV=test ava --watch", + "test": "jest --watch", + "test:nowatch": "jest", "postbuild": "./scripts/nlink lib", - "build": "babel src --out-dir lib --ignore **/*.spec.js", + "build": "babel src --out-dir lib --ignore **/*.test.js", "prepublishOnly": "npm run build", "prepack": "npm run build", "lint": "eslint src", @@ -47,41 +47,6 @@ } ], "license": "MIT", - "babel": { - "presets": [ - [ - "@babel/preset-env", - { - "targets": { - "ie": "11" - }, - "useBuiltIns": "usage" - } - ], - "@babel/preset-react" - ], - "plugins": [ - "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-export-namespace-from" - ] - }, - "ava": { - "files": [ - "src/**/*.spec.js" - ], - "require": [ - "@babel/register", - "./test/shims" - ] - }, - "nyc": { - "exclude": [ - "src/**/index.js", - "src/**/*.spec.js", - "test" - ] - }, "dependencies": { "hoist-non-react-statics": "^3.3.0", "memoize-one": "^5.0.0" @@ -121,5 +86,30 @@ "prop-types": "^15.7.2", "react": "^16.8.4", "react-dom": "^16.8.4" + }, + "jest": { + "roots": [ + "/src" + ], + "collectCoverageFrom": [ + "src/**/*.{js,jsx}" + ], + "setupFilesAfterEnv": [ + "/src/setupTests.ts" + ], + "testMatch": [ + "/src/**/__tests__/**/*.{js,jsx}", + "/src/**/*.test.{js,jsx}" + ], + "testEnvironment": "jest-environment-jsdom-fourteen", + "transform": { + "^.+\\.(js|jsx)$": "/node_modules/babel-jest" + }, + "transformIgnorePatterns": [ + "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$" + ], + "modulePaths": [ + "/src" + ] } } diff --git a/src/setupTests.ts b/src/setupTests.ts new file mode 100644 index 0000000..6772e22 --- /dev/null +++ b/src/setupTests.ts @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +require('@testing-library/jest-dom/extend-expect'); From cfc17f08699ca064e2c5f140431e24c2c6af3fac Mon Sep 17 00:00:00 2001 From: "Miguel Osorio @kelvur" Date: Sat, 28 Mar 2020 20:51:22 +0100 Subject: [PATCH 4/9] test: remove previous test --- src/I18nContext.spec.js | 53 --------------------- src/I18nProvider.spec.js | 94 -------------------------------------- src/useI18n.spec.js | 74 ------------------------------ src/useTranslation.spec.js | 72 ----------------------------- src/withI18n.spec.js | 66 -------------------------- 5 files changed, 359 deletions(-) delete mode 100644 src/I18nContext.spec.js delete mode 100644 src/I18nProvider.spec.js delete mode 100644 src/useI18n.spec.js delete mode 100644 src/useTranslation.spec.js delete mode 100644 src/withI18n.spec.js diff --git a/src/I18nContext.spec.js b/src/I18nContext.spec.js deleted file mode 100644 index 59ea38b..0000000 --- a/src/I18nContext.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -// Core -import React from 'react'; -import ReactDOM from 'react-dom'; -// Test -import {act} from 'react-dom/test-utils'; -import test from 'ava'; -import sinon from 'sinon'; -// I18n library -import i18njs from '@k14v/i18njs'; -// Hook -import useI18n from './useI18n'; -// Constants -import {I18N_EVENTS} from './constants'; - - -const locales = { - es: { - 'Hello World': 'Hola Mundo', - }, - en: { - 'Hello World': 'Hello World', - }, -}; - -const Consumer = (_) => { - const i18n = useI18n(); - return ( -

{i18n.trls.__('Hello World')}

- ); -}; - -test.cb('it should throw a warning, when used a consumer without provider', (t) => { - t.timeout(10000); - t.plan(1); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type}) => { - if (type === I18N_EVENTS.LOADED) { - const warnSpy = sinon.spy(console, 'warn'); - const container = document.createElement('div'); - document.body.appendChild(container); - act(() => { - ReactDOM.render( - , - container - ); - }); - t.true(warnSpy.calledOnce); - warnSpy.restore(); - t.end(); - } - }); - -}); diff --git a/src/I18nProvider.spec.js b/src/I18nProvider.spec.js deleted file mode 100644 index 8fc8673..0000000 --- a/src/I18nProvider.spec.js +++ /dev/null @@ -1,94 +0,0 @@ -// Core -import React from 'react'; -import ReactDOM from 'react-dom'; -// Test -import {act} from 'react-dom/test-utils'; -import test from 'ava'; -import {shallow} from 'enzyme'; -// I18n library -import i18njs from '@k14v/i18njs'; -// Provider -import I18nProvider from './I18nProvider'; -// Hooks -import useI18n from './useI18n'; -// Constants -import {I18N_EVENTS} from './constants'; - - -const locales = { - es: { - 'Hello World': 'Hola Mundo', - }, - en: { - 'Hello World': 'Hello World', - }, -}; - -const Provider = ({i18n, children}) => ( - {children} -); - -const Consumer = () => { - const {trls} = useI18n(); - return

{trls.__('Hello World')}

; -}; - -test('it should render', (t) => { - const wrapper = shallow(); - t.true(wrapper.exists()); -}); - -test.cb('it should have the text translated', (t) => { - t.timeout(10000); - t.plan(1); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type}) => { - if (type === I18N_EVENTS.LOADED) { - const container = document.createElement('div'); - document.body.appendChild(container); - act(() => { - ReactDOM.render( - - - , - container - ); - }); - t.true(container.querySelector('p').textContent === i18n.trls.__('Hello World')); - t.end(); - } - }); -}); - -// Need to improve the test -test.skip('it should update the text after a setLanguage', (t) => { - t.timeout(10000); - t.plan(2); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type, locale}) => { - if (type === I18N_EVENTS.LOADED) { - const container = document.createElement('div'); - document.body.appendChild(container); - act(() => { - ReactDOM.render( - - - , - container - ); - }); - if (locale === 'es') { - t.log(container.querySelector('p').textContent); - t.true(container.querySelector('p').textContent === i18n.trls.__('Hello World')); - // Set language - act(() => { - i18n.setLocale('en'); - }); - } - if (locale === 'en') { - t.true(document.querySelector('p').textContent === i18n.trls.__('Hello World')); - t.end(); - } - } - }); -}); diff --git a/src/useI18n.spec.js b/src/useI18n.spec.js deleted file mode 100644 index 3cebebf..0000000 --- a/src/useI18n.spec.js +++ /dev/null @@ -1,74 +0,0 @@ -// Core -import React from 'react'; -import ReactDOM from 'react-dom'; -// Test -import {act} from 'react-dom/test-utils'; -import test from 'ava'; -import {shallow} from 'enzyme'; -// I18n library -import i18njs from '@k14v/i18njs'; -// Provider -import I18nProvider from './I18nProvider'; -// Hooks -import useI18n from './useI18n'; -// Constants -import {I18N_EVENTS} from './constants'; - - -const locales = { - es: { - 'Hello World': 'Hola Mundo', - }, - en: { - 'Hello World': 'Hello World', - }, -}; - -const Provider = ({i18n, children}) => {children}; - -const Consumer = (_) => { - const i18n = useI18n(); - return ( -

{i18n.trls.__('Hello World')}

- ); -}; - -test.cb('it should render', (t) => { - t.timeout(10000); - t.plan(1); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type}) => { - if (type === I18N_EVENTS.LOADED) { - const wrapper = shallow( - - - - ); - t.true(wrapper.exists()); - t.end(); - } - }); -}); - -test.cb('it should translate', (t) => { - t.timeout(10000); - t.plan(1); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type}) => { - if (type === I18N_EVENTS.LOADED) { - const container = document.createElement('div'); - document.body.appendChild(container); - act(() => { - ReactDOM.render( - - - , - container - ); - }); - const p = container.querySelector('p'); - t.true(p.textContent === locales.en['Hello World']); - t.end(); - } - }); -}); diff --git a/src/useTranslation.spec.js b/src/useTranslation.spec.js deleted file mode 100644 index 906c474..0000000 --- a/src/useTranslation.spec.js +++ /dev/null @@ -1,72 +0,0 @@ -// Core -import React from 'react'; -import ReactDOM from 'react-dom'; -// Test -import {act} from 'react-dom/test-utils'; -import test from 'ava'; -import {shallow} from 'enzyme'; -// I18n library -import i18njs from '@k14v/i18njs'; -// Provider -import I18nProvider from './I18nProvider'; -// Hooks -import useTranslation from './useTranslation'; -// Constants -import {I18N_EVENTS} from './constants'; - - -const locales = { - es: { - 'Hello World': 'Hola Mundo', - }, - en: { - 'Hello World': 'Hello World', - }, -}; - -const Provider = ({i18n, children}) => {children}; - -const Consumer = (_) => { - const trls = useTranslation(); - return

{trls.__('Hello World')}

; -}; - -test.cb('it should render', (t) => { - t.timeout(10000); - t.plan(1); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type}) => { - if (type === I18N_EVENTS.LOADED) { - const wrapper = shallow( - - - - ); - t.true(wrapper.exists()); - t.end(); - } - }); -}); - -test.cb('it should translate', (t) => { - t.timeout(10000); - t.plan(1); - const i18n = i18njs({locales, locale: 'es'}); - i18n.subscribe(({type}) => { - if (type === I18N_EVENTS.LOADED) { - const container = document.createElement('div'); - document.body.appendChild(container); - act(() => { - ReactDOM.render( - - - , - container - ); - }); - const p = container.querySelector('p'); - t.true(p.textContent === locales.en['Hello World']); - t.end(); - } - }); -}); diff --git a/src/withI18n.spec.js b/src/withI18n.spec.js deleted file mode 100644 index d28315e..0000000 --- a/src/withI18n.spec.js +++ /dev/null @@ -1,66 +0,0 @@ -// Core -import React, { useRef } from 'react'; -import ReactDOM from 'react-dom'; -// Test -import {act} from 'react-dom/test-utils'; -import test from 'ava'; -import {mount} from 'enzyme'; -import sinon from 'sinon'; -// I18n library -import i18njs from '@k14v/i18njs'; -// Providers -import I18nProvider from './I18nProvider'; -// Decorators -import withI18n from './withI18n'; - - -const BaseComponent = _ =>

Hello World!

; - -const WrappedComponent = withI18n()(BaseComponent); - -const ProviderComponent = _ => ( - - - -); - -test('it should render', (t) => { - const warnSpy = sinon.spy(console, 'warn'); - const wrapper = mount(); - t.true(wrapper.exists()); - warnSpy.restore(); -}); - -test('it should render with I18nProvider', (t) => { - const wrapper = mount(); - t.true(wrapper.exists()); -}); - -test('it\'s forwarding the ref', (t) => { - const INITIAL_VALUE = 'Popeye'; - const Inner = React.forwardRef((props, ref) => { - t.truthy(ref); - t.true(ref.current === INITIAL_VALUE); - return ( -