├── .browserslistrc ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .npmrc ├── .playroom └── FrameComponent.js ├── .prettierrc ├── .storybook ├── main.js ├── manager.js └── preview.js ├── .stylelintignore ├── .stylelintrc ├── .travis.yml ├── README.md ├── UNLICENSE ├── babel.config.js ├── flow-typed └── npm │ ├── @storybook │ ├── addon-a11y_v3.x.x.js │ ├── addon-actions_v3.x.x.js │ ├── addon-info_v3.x.x.js │ ├── addon-knobs_v3.x.x.js │ ├── addon-options_v4.x.x.js │ └── react_v5.x.x.js │ ├── @testing-library │ ├── jest-dom_v5.5.x.js │ ├── react_v11.x.x.js │ └── user-event_v12.x.x.js │ ├── clsx_v1.x.x.js │ ├── jest_v26.x.x.js │ ├── react-dom_v16.x.x.js │ └── sponge_v0.1.x.js ├── jest.config.js ├── package.json ├── playroom.config.js ├── postcss.config.js ├── rollup.config.js ├── src ├── components │ ├── Button │ │ ├── Button.css │ │ ├── Button.css.flow │ │ ├── Button.js │ │ ├── Button.spec.js │ │ ├── Button.stories.js │ │ ├── __snapshots__ │ │ │ └── Button.spec.js.snap │ │ └── index.js │ └── Header │ │ ├── Header.css │ │ ├── Header.css.flow │ │ ├── Header.js │ │ ├── Header.spec.js │ │ ├── Header.stories.js │ │ ├── __snapshots__ │ │ └── Header.spec.js.snap │ │ └── index.js ├── index.js └── styles │ └── variables.css └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 versions 2 | > 0.25% 3 | Firefox ESR 4 | not dead 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | flow-typed 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "babel-eslint", 4 | "extends": [ 5 | "airbnb", 6 | "plugin:flowtype/recommended", 7 | "plugin:css-modules/recommended", 8 | "plugin:jest/recommended", 9 | "plugin:testing-library/react", 10 | "prettier", 11 | "prettier/flowtype", 12 | "prettier/react" 13 | ], 14 | "plugins": ["babel", "flowtype", "css-modules", "jest", "testing-library"], 15 | "env": { 16 | "jest": true 17 | }, 18 | "rules": { 19 | "prefer-const": "off", 20 | "comma-dangle": [ 21 | "error", 22 | { 23 | "arrays": "always-multiline", 24 | "objects": "always-multiline", 25 | "imports": "always-multiline", 26 | "exports": "always-multiline", 27 | "functions": "ignore" 28 | } 29 | ], 30 | "no-unused-expressions": "off", 31 | "no-unused-vars": [ 32 | "error", 33 | { 34 | "ignoreRestSiblings": true 35 | } 36 | ], 37 | 38 | "babel/no-unused-expressions": "error", 39 | 40 | "react/jsx-uses-react": "off", 41 | "react/react-in-jsx-scope": "off", 42 | "react/require-default-props": "off", 43 | "react/jsx-wrap-multilines": "off", 44 | "react/jsx-props-no-spreading": "off", 45 | "react/jsx-filename-extension": [ 46 | "error", 47 | { 48 | "extensions": [".js", ".jsx"] 49 | } 50 | ], 51 | "react/sort-comp": [ 52 | "error", 53 | { 54 | "order": [ 55 | "type-annotations", 56 | "static-methods", 57 | "lifecycle", 58 | "everything-else", 59 | "render" 60 | ] 61 | } 62 | ], 63 | 64 | "import/no-extraneous-dependencies": [ 65 | "error", 66 | { 67 | "devDependencies": true, 68 | "optionalDependencies": false, 69 | "peerDependencies": false 70 | } 71 | ] 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /dist 3 | 4 | [untyped] 5 | 6 | [include] 7 | 8 | [libs] 9 | flow-typed 10 | 11 | [lints] 12 | all=warn 13 | 14 | [options] 15 | include_warnings=true 16 | 17 | [strict] 18 | deprecated-type 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | coverage 4 | reports 5 | flow-coverage 6 | .eslintcache 7 | .jest-cache 8 | .size-snapshot.json 9 | .cache 10 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org 2 | package-lock=false 3 | -------------------------------------------------------------------------------- /.playroom/FrameComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import '../dist/react-module-boilerplate.css'; 4 | 5 | export default ({ children }) => children; 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid", 4 | "overrides": [ 5 | { 6 | "files": [".eslintrc", ".stylelintrc"], 7 | "options": { 8 | "parser": "json" 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../src/**/*.stories.js'], 3 | 4 | addons: ['@storybook/addon-docs', '@storybook/addon-a11y/register'], 5 | 6 | webpackFinal: config => { 7 | config.module.rules = config.module.rules.filter( 8 | rule => rule.test.toString() !== '/\\.css$/' 9 | ); 10 | 11 | config.module.rules.push({ 12 | test: /\.css$/, 13 | use: [ 14 | { 15 | loader: 'style-loader', 16 | }, 17 | { 18 | loader: 'css-loader', 19 | options: { 20 | modules: { 21 | localIdentName: '[name]-[local]_[hash:base64:5]', 22 | }, 23 | importLoaders: 1, 24 | }, 25 | }, 26 | { 27 | loader: 'postcss-loader', 28 | }, 29 | ], 30 | }); 31 | 32 | return config; 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | 3 | addons.setConfig({ 4 | name: 'React module boilerplate', 5 | sidebarAnimations: true, 6 | showPanel: true, 7 | panelPosition: 'right', 8 | }); 9 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | import '../src/styles/variables.css'; 2 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-standard", 4 | "stylelint-config-css-modules", 5 | "stylelint-config-prettier" 6 | ], 7 | "plugins": ["stylelint-value-no-unknown-custom-properties", "stylelint-a11y"], 8 | "rules": { 9 | "value-keyword-case": null, 10 | "csstools/value-no-unknown-custom-properties": [ 11 | true, 12 | { 13 | "importFrom": "src/styles/variables.css" 14 | } 15 | ], 16 | "a11y/media-prefers-reduced-motion": [true, { "severity": "warning" }], 17 | "a11y/no-outline-none": [true, { "severity": "warning" }], 18 | "a11y/selector-pseudo-class-focus": [true, { "severity": "warning" }], 19 | "a11y/content-property-no-static-value": [true, { "severity": "warning" }], 20 | "a11y/font-size-is-readable": [true, { "severity": "warning" }], 21 | "a11y/line-height-is-vertical-rhythmed": [true, { "severity": "warning" }], 22 | "a11y/no-display-none": [true, { "severity": "warning" }], 23 | "a11y/no-spread-text": [true, { "severity": "warning" }], 24 | "a11y/no-obsolete-attribute": [true, { "severity": "warning" }], 25 | "a11y/no-obsolete-element": [true, { "severity": "warning" }], 26 | "a11y/no-text-align-justify": [true, { "severity": "warning" }], 27 | "a11y/media-prefers-color-scheme": [true, { "severity": "warning" }] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - lts/* 5 | - stable 6 | 7 | sudo: false 8 | 9 | git: 10 | depth: 10 11 | 12 | script: yarn run test:ci 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > :warning: **Outdated**: Most of the code samples and configs here are outdated by now 2 | 3 | # react-module-boilerplate 4 | 5 | [![Build Status][travis-image]][travis-url] 6 | 7 | > Sample React components package. 8 | 9 | ## About 10 | 11 | Showcase and document techniques and glued tools to build and maintain either 12 | single component or UI systems packages. 13 | Strive for keeping things simple and efficient. 14 | 15 | ## Features 16 | 17 | JS, ESnext 18 | 19 | - ES2018+ with `@babel/preset-env` 20 | - Ship both ESM, commonjs, UMD modules with Rollup 21 | 22 | Styling 23 | 24 | - CSS modules 25 | - CSS next with `postcss-preset-env` 26 | - custom properties (theming) 27 | - Autoprefixer 28 | - Ship two stylesheets 29 | - Local scoped styles 30 | - Global styles 31 | - Ship individual CSS modules 32 | - Allows for picking just the needed ones 33 | 34 | Unit Testing 35 | 36 | - Jest 37 | - testing-library/react 38 | - testing-library/jest-dom 39 | - CI reports (tests results, coverage) 40 | - `babel-plugin-css-modules-transform` (Test classNames) 41 | 42 | Code Quality 43 | 44 | - ESLint 45 | - Flow 46 | - `flow-coverage-report` 47 | - Stylelint 48 | - Prettier 49 | 50 | Development environment, styleguide 51 | 52 | - Storybook 53 | - Playroom 54 | 55 | ## Credits 56 | 57 | - [Pascal Duez](https://github.com/pascalduez) 58 | 59 | ## Licence 60 | 61 | react-module-boilerplate is [unlicensed](http://unlicense.org/). 62 | 63 | [travis-url]: https://travis-ci.org/pascalduez/react-module-boilerplate?branch=master 64 | [travis-image]: http://img.shields.io/travis/pascalduez/react-module-boilerplate.svg?style=flat-square 65 | [license-image]: http://img.shields.io/npm/l/postcss-apply.svg?style=flat-square 66 | [license-url]: UNLICENSE 67 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [ES2020+] 3 | * https://babeljs.io/docs/en/babel-preset-env 4 | * 5 | * [Proposals] 6 | * https://babeljs.io/docs/en/babel-plugin-proposal-class-properties 7 | * https://babeljs.io/docs/en/babel-plugin-proposal-decorators 8 | * 9 | * [React] 10 | * https://babeljs.io/docs/en/babel-preset-react 11 | * 12 | * [Flow] 13 | * https://babeljs.io/docs/en/babel-preset-flow 14 | * 15 | * [Other] 16 | * https://babeljs.io/docs/en/babel-plugin-transform-runtime 17 | * 18 | * [CSS modules] 19 | * https://github.com/css-modules/css-modules 20 | * https://github.com/michalkvasnicak/babel-plugin-css-modules-transform 21 | */ 22 | 23 | module.exports = api => { 24 | let env = api.env(); 25 | 26 | let envOps = { 27 | targets: { 28 | esmodules: true, 29 | }, 30 | bugfixes: true, 31 | }; 32 | 33 | let runtimeOps = { 34 | corejs: 2, 35 | helpers: true, 36 | regenerator: true, 37 | useESModules: true, 38 | version: '7.9.0', 39 | }; 40 | 41 | let presets = [ 42 | ['@babel/preset-env', envOps], 43 | ['@babel/preset-react', { runtime: 'automatic' }], 44 | // '@babel/preset-react', 45 | '@babel/preset-flow', 46 | ]; 47 | 48 | let plugins = [ 49 | ['@babel/plugin-transform-runtime', runtimeOps], 50 | '@babel/plugin-proposal-class-properties', 51 | '@babel/plugin-proposal-do-expressions', 52 | ]; 53 | 54 | if (env === 'test') { 55 | runtimeOps.useESModules = false; 56 | plugins.push('@babel/plugin-transform-modules-commonjs', [ 57 | 'babel-plugin-css-modules-transform', 58 | { 59 | generateScopedName: '[name]-[local]', 60 | }, 61 | ]); 62 | } 63 | 64 | return { 65 | presets, 66 | plugins, 67 | }; 68 | }; 69 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-a11y_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 56dc5bc86fec2d6287b51039aba84313 2 | // flow-typed version: f7a6cce046/@storybook/addon-a11y_v3.x.x/flow_>=v0.25.x 3 | 4 | declare module '@storybook/addon-a11y' { 5 | declare type Context = { kind: string, story: string }; 6 | declare type Renderable = React$Element<*>; 7 | declare type RenderFunction = () => Renderable | Array; 8 | 9 | declare type StoryDecorator = ( 10 | story: RenderFunction, 11 | context: Context 12 | ) => Renderable | null; 13 | 14 | declare type AxeCheck = { 15 | id: string, 16 | evaluate: (options: mixed) => void, 17 | after?: () => void, 18 | options?: mixed, 19 | enabled?: boolean, 20 | }; 21 | 22 | declare type AxeOptions = { 23 | branding?: { 24 | brand?: string, 25 | application?: string, 26 | }, 27 | reporter?: 'v1' | 'v2', 28 | checks?: Array, 29 | rules?: Array<{ 30 | id: string, 31 | selector?: string, 32 | excludeHidden?: boolean, 33 | enabled?: boolean, 34 | pageLevel?: boolean, 35 | any?: Array, 36 | all?: Array, 37 | none?: Array, 38 | tags?: Array, 39 | matches?: string, 40 | }>, 41 | disableOtherRules?: boolean, 42 | }; 43 | 44 | declare module.exports: { 45 | checkA11y: StoryDecorator, 46 | configureA11y: (options?: AxeOptions) => void, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-actions_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2f5b0f18c5b5b31b01f63163429685c7 2 | // flow-typed version: 5edd39ab2e/@storybook/addon-actions_v3.x.x/flow_>=v0.25.x 3 | 4 | declare module '@storybook/addon-actions' { 5 | declare type Action = (name: string) => (...args: Array) => void; 6 | declare type DecorateFn = (args: Array) => Array; 7 | 8 | declare module.exports: { 9 | action: Action, 10 | decorateAction(args: Array): Action; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-info_v3.x.x.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import type { Story, RenderFunction } from '@storybook/react'; 3 | 4 | declare module '@storybook/addon-info' { 5 | declare type Options = { 6 | text?: string | React.Element, 7 | inline?: boolean, 8 | header?: boolean, 9 | source?: boolean, 10 | propTables?: ?Array>, 11 | maxPropsIntoLine?: number, 12 | maxPropObjectKeys?: number, 13 | maxPropArrayLength?: number, 14 | maxPropStringLength?: number, 15 | }; 16 | 17 | declare export function addWithInfo( 18 | storyName: string, 19 | info: string, 20 | callback: RenderFunction, 21 | options: Options 22 | ): Story; 23 | 24 | declare export function withInfo(options: Options): Story; 25 | } 26 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-knobs_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9c1ab3525378c509e969778c18af18b7 2 | // flow-typed version: ae374bc338/@storybook/addon-knobs_v3.x.x/flow_vx.x.x 3 | 4 | declare module "@storybook/addon-knobs/react" { 5 | declare type Context = { kind: string, story: string }; 6 | declare type Renderable = React$Element<*>; 7 | declare type RenderFunction = () => Renderable | Array; 8 | declare type GroupId = string; 9 | 10 | declare function array(string, (Array | {}), ?string, ?GroupId): Array; 11 | declare function boolean(string, boolean, ?GroupId): boolean; 12 | declare function button(string, ((?{}) => void), ?GroupId): void; 13 | declare function color(string, string, ?GroupId): string; 14 | declare function date(string, Date, ?GroupId): number; 15 | declare function number(string, number, ?{ range?: boolean, min?: number, max?: number, step?: number }, ?GroupId): number; 16 | declare function object(string, any, ?GroupId): any; 17 | declare function select(string, Array | { [T]: string }, T, ?GroupId): T; 18 | declare function selectV2(string, Array | { [string]: T }, T, ?GroupId): T; 19 | declare function text(string, string, ?GroupId): string; 20 | declare function withKnobs( 21 | story: RenderFunction, 22 | context: Context 23 | ): Renderable | null; 24 | } 25 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-options_v4.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: d87955256c0438e8d919bd2cfe5423e9 2 | // flow-typed version: 028ef45280/@storybook/addon-options_v4.x.x/flow_>=v0.25.x 3 | 4 | declare module '@storybook/addon-options' { 5 | declare type Theme = { 6 | /** 7 | * applied to root `background` 8 | * @default: 'linear-gradient(to bottom right, black, gray' 9 | */ 10 | mainBackground?: string, 11 | /** 12 | * applied to panels `border` 13 | * @default: '1px solid rgba(0,0,0,0.1)' 14 | */ 15 | mainBorder?: string, 16 | /** 17 | * applied for most borders 18 | * @default: 'rgba(0,0,0,0.1)' 19 | */ 20 | mainBorderColor?: string, 21 | /** 22 | * applied to panels, buttons, inputs 23 | * @default: 4 24 | */ 25 | mainBorderRadius?: string, 26 | /** 27 | * applied to panels `background` 28 | * @default: 'rgba(255,255,255,0.89)' 29 | */ 30 | mainFill?: string, 31 | /** 32 | * applied to TabsBar `background` 33 | * @default: 'rgba(255,255,255,1)' 34 | */ 35 | barFill?: string, 36 | /** 37 | * applied to Input `background` 38 | * @default: 'rgba(0,0,0,0.05)' 39 | */ 40 | inputFill?: string, 41 | /** 42 | * applied to root `font-family` 43 | */ 44 | mainTextFace?: string, 45 | /** 46 | * applied to root & buttons & input `color` 47 | * @default: black 48 | */ 49 | mainTextColor?: string, 50 | /** 51 | * applied to root 52 | * @default: 13 53 | */ 54 | mainTextSize?: string, 55 | /** 56 | * applied in less important text 57 | * @default: 'rgba(0,0,0,0.4)' 58 | */ 59 | dimmedTextColor?: string, 60 | /** 61 | * applied to indicate selection 62 | * @default: '#9fdaff' 63 | */ 64 | highlightColor?: string, 65 | /** 66 | * applied to indicate positive 67 | * @default: '#0edf62' 68 | */ 69 | successColor?: string, 70 | /** 71 | * applied to indicate negative 72 | * @default: '#ff3f3f' 73 | */ 74 | failColor?: string, 75 | /** 76 | * applied to indicate ow-ow 77 | * @default: 'orange' 78 | */ 79 | warnColor?: string, 80 | /** 81 | * applied to pre, 82 | */ 83 | monoTextFace?: string, 84 | /** 85 | * applied to space panels 86 | * @default: 10 87 | */ 88 | layoutMargin?: string, 89 | /** 90 | * applied to overlay `background` 91 | * @default: 'linear-gradient(to bottom right, rgba(233, 233, 233, 0.6), rgba(255, 255, 255, 0.8))' 92 | */ 93 | overlayBackground?: string, 94 | }; 95 | 96 | declare type Options = { 97 | theme?: Theme, 98 | /** 99 | * name to display in the top left corner 100 | */ 101 | name?: string, 102 | /** 103 | * URL for name in top left corner to link to 104 | */ 105 | url?: string, 106 | /** 107 | * show story component as full screen 108 | */ 109 | goFullScreen?: boolean, 110 | /** 111 | * display panel that shows a list of stories 112 | */ 113 | showStoriesPanel?: boolean, 114 | /** 115 | * display panel that shows addon configurations 116 | */ 117 | showAddonPanel?: boolean, 118 | /** 119 | * display floating search box to search through stories 120 | */ 121 | showSearchBox?: boolean, 122 | /** 123 | * show addon panel as a vertical panel on the right 124 | */ 125 | addonPanelInRight?: boolean, 126 | /** 127 | * sorts stories 128 | */ 129 | sortStoriesByKind?: boolean, 130 | /** 131 | * regex for finding the hierarchy separator 132 | * @example: 133 | * null - turn off hierarchy 134 | * /\// - split by `/` 135 | * /\./ - split by `.` 136 | * /\/|\./ - split by `/` or `.` 137 | */ 138 | hierarchySeparator?: RegExp | string, 139 | /** 140 | * regex for finding the hierarchy root separator 141 | * @example: 142 | * null - turn off multiple hierarchy roots 143 | * /\|/ - split by `|` 144 | */ 145 | hierarchyRootSeparator?: RegExp | string, 146 | /** 147 | * sidebar tree animations 148 | */ 149 | sidebarAnimations?: boolean, 150 | /** 151 | * id to select an addon panel 152 | * The order of addons in the "Addon panel" is the same as you import them in 'addons.js'. 153 | * The first panel will be opened by default as you run Storybook 154 | */ 155 | selectedAddonPanel?: string, 156 | /** 157 | * enable/disable shortcuts 158 | * @default true 159 | */ 160 | enableShortcuts?: boolean, 161 | }; 162 | 163 | declare function setOptions(options: $Exact): void; // deprecated: use `withOptions` 164 | declare function withOptions(options: $Exact): void; 165 | } 166 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/react_v5.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: e484579841f3cb1e8f57a768abc4642d 2 | // flow-typed version: c6154227d1/@storybook/react_v5.x.x/flow_>=v0.104.x 3 | 4 | type NodeModule = typeof module; 5 | 6 | declare module '@storybook/react' { 7 | declare type Context = { 8 | kind: string, 9 | story: string, 10 | ... 11 | }; 12 | declare type Renderable = 13 | | string 14 | | number 15 | | React$Element 16 | | Iterable; 17 | declare type RenderCallback = ( 18 | context: Context 19 | ) => Renderable; 20 | declare type RenderFunction = () => Renderable; 21 | 22 | declare type StoryDecorator = ( 23 | story: RenderFunction, 24 | context: Context 25 | ) => Renderable; 26 | 27 | declare type DecoratorParameters = { [key: string]: any, ... }; 28 | 29 | declare interface Story { 30 | +kind: string; 31 | add( 32 | storyName: string, 33 | callback: RenderCallback, 34 | parameters?: DecoratorParameters 35 | ): Story; 36 | addDecorator(decorator: StoryDecorator): Story; 37 | addParameters(parameters: DecoratorParameters): Story; 38 | } 39 | 40 | declare interface StoryObject { 41 | name: string; 42 | render: RenderFunction; 43 | } 44 | 45 | declare interface StoryBucket { 46 | kind: string; 47 | filename: string; 48 | stories: Array; 49 | } 50 | 51 | declare function addDecorator(decorator: StoryDecorator): void; 52 | declare function addParameters(parameters: DecoratorParameters): void; 53 | declare function clearDecorators(): void; 54 | declare function configure(fn: () => void, module: NodeModule): void; 55 | declare function setAddon(addon: Object): void; 56 | declare function storiesOf(name: string, module: NodeModule): Story; 57 | declare function storiesOf(name: string, module: NodeModule): Story & T; 58 | declare function forceReRender(): void; 59 | 60 | declare function getStorybook(): Array; 61 | } 62 | -------------------------------------------------------------------------------- /flow-typed/npm/@testing-library/jest-dom_v5.5.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 0c9447942a6ffdb5f79f218bfe8e58d9 2 | // flow-typed version: fe9fda6713/@testing-library/jest-dom_v5.5.x/flow_>=v0.104.x 3 | 4 | declare module '@testing-library/jest-dom' { 5 | declare type JestMatcherResult = { 6 | message?: string | (() => string), 7 | pass: boolean, 8 | ... 9 | }; 10 | 11 | declare type Result = JestMatcherResult | Promise; 12 | 13 | declare module.exports: {| 14 | /** 15 | * @deprecated 16 | */ 17 | toBeInTheDOM(container?: HTMLElement): Result, 18 | 19 | toBeInTheDocument(): Result, 20 | toBeVisible(): Result, 21 | toBeEmpty(): Result, 22 | toBeDisabled(): Result, 23 | toBeEnabled(): Result, 24 | toBeInvalid(): Result, 25 | toBeRequired(): Result, 26 | toBeValid(): Result, 27 | toContainElement(element: HTMLElement | null): Result, 28 | toContainHTML(htmlText: string): Result, 29 | toHaveAttribute(attr: string, value?: any): Result, 30 | toHaveClass(...classNames: string[]): Result, 31 | toHaveFocus(): Result, 32 | toHaveFormValues(expectedValues: { [name: string]: any, ... }): Result, 33 | toHaveStyle(css: string | { [name: string]: any, ... }): Result, 34 | toHaveTextContent( 35 | text: string | RegExp, 36 | options?: {| normalizeWhitespace: boolean |} 37 | ): Result, 38 | toHaveValue(value?: string | string[] | number): Result, 39 | toHaveDisplayValue(value: string | string[]): Result, 40 | toBeChecked(): Result, 41 | |}; 42 | } 43 | 44 | declare module '@testing-library/jest-dom/extend-expect' { 45 | declare module.exports: any; 46 | } 47 | -------------------------------------------------------------------------------- /flow-typed/npm/@testing-library/react_v11.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 22edda8a9d63305e5aed4cd94ee90e95 2 | // flow-typed version: 0663320449/@testing-library/react_v11.x.x/flow_>=v0.104.x 3 | 4 | declare module '@testing-library/react' { 5 | // This type comes from 6 | // https://github.com/facebook/flow/blob/v0.104.0/lib/react-dom.js#L64 7 | declare type ReactDOMTestUtilsThenable = { 8 | then(resolve: () => mixed, reject?: () => mixed): mixed, 9 | ... 10 | }; 11 | // This type comes from 12 | // https://github.com/facebook/flow/blob/v0.104.0/lib/react-dom.js#L116 13 | declare type ReactDOMTestUtilsAct = ( 14 | callback: () => void | ReactDOMTestUtilsThenable 15 | ) => ReactDOMTestUtilsThenable; 16 | 17 | declare type WaitForElementOptions = {| 18 | container?: HTMLElement, 19 | timeout?: number, 20 | mutationObserverOptions?: MutationObserverInit, 21 | |}; 22 | 23 | declare type TextMatch = 24 | | string 25 | | RegExp 26 | | ((content: string, element: HTMLElement) => boolean); 27 | 28 | declare type TextMatchOptions = { 29 | exact?: boolean, 30 | trim?: boolean, 31 | collapseWhitespace?: boolean, 32 | normalizer?: (text: string) => string, 33 | ... 34 | }; 35 | 36 | declare type SelectorMatchOptions = { 37 | selector?: string, 38 | ... 39 | } & TextMatchOptions; 40 | 41 | declare type QueryByBoundAttribute = ( 42 | text: TextMatch, 43 | options?: TextMatchOptions 44 | ) => ?HTMLElement; 45 | 46 | declare type AllByBoundAttribute = ( 47 | text: TextMatch, 48 | options?: TextMatchOptions 49 | ) => Array; 50 | 51 | declare type FindAllByBoundAttribute = ( 52 | text: TextMatch, 53 | options?: TextMatchOptions, 54 | waitForElementOptions?: WaitForElementOptions 55 | ) => Promise; 56 | 57 | declare type GetByBoundAttribute = ( 58 | text: TextMatch, 59 | options?: TextMatchOptions 60 | ) => HTMLElement; 61 | 62 | declare type FindByBoundAttribute = ( 63 | text: TextMatch, 64 | options?: TextMatchOptions, 65 | waitForElementOptions?: WaitForElementOptions 66 | ) => Promise; 67 | 68 | declare type QueryByText = ( 69 | text: TextMatch, 70 | options?: SelectorMatchOptions 71 | ) => ?HTMLElement; 72 | 73 | declare type AllByText = ( 74 | text: TextMatch, 75 | options?: SelectorMatchOptions 76 | ) => Array; 77 | 78 | declare type FindAllByText = ( 79 | text: TextMatch, 80 | options?: SelectorMatchOptions, 81 | waitForElementOptions?: WaitForElementOptions 82 | ) => Promise; 83 | 84 | declare type GetByText = ( 85 | text: TextMatch, 86 | options?: SelectorMatchOptions 87 | ) => HTMLElement; 88 | 89 | declare type FindByText = ( 90 | text: TextMatch, 91 | options?: SelectorMatchOptions, 92 | waitForElementOptions?: WaitForElementOptions 93 | ) => Promise; 94 | 95 | declare type ByRoleOptions = { 96 | /** 97 | * If true includes elements in the query set that are usually excluded from 98 | * the accessibility tree. `role="none"` or `role="presentation"` are included 99 | * in either case. 100 | */ 101 | hidden?: boolean, 102 | /** 103 | * If true only includes elements in the query set that are marked as 104 | * selected in the accessibility tree, i.e., `aria-selected="true"` 105 | */ 106 | selected?: boolean, 107 | /** 108 | * If true only includes elements in the query set that are marked as 109 | * checked in the accessibility tree, i.e., `aria-checked="true"` 110 | */ 111 | checked?: boolean, 112 | /** 113 | * If true only includes elements in the query set that are marked as 114 | * pressed in the accessibility tree, i.e., `aria-pressed="true"` 115 | */ 116 | pressed?: boolean, 117 | /** 118 | * Includes elements with the `"heading"` role matching the indicated level, 119 | * either by the semantic HTML heading elements `

-

` or matching 120 | * the `aria-level` attribute. 121 | */ 122 | level?: number, 123 | /** 124 | * Includes every role used in the `role` attribute 125 | * For example *ByRole('progressbar', {queryFallbacks: true})` will find
`. 126 | */ 127 | queryFallbacks?: boolean, 128 | /** 129 | * Only considers elements with the specified accessible name. 130 | */ 131 | name?: 132 | | string 133 | | RegExp 134 | | ((accessibleName: string, element: Element) => boolean), 135 | ... 136 | } & TextMatchOptions; 137 | 138 | declare type AllByRole = ( 139 | role: TextMatch, 140 | options?: ByRoleOptions 141 | ) => HTMLElement[]; 142 | 143 | declare type GetByRole = ( 144 | role: TextMatch, 145 | options?: ByRoleOptions 146 | ) => HTMLElement; 147 | 148 | declare type QueryByRole = ( 149 | role: TextMatch, 150 | options?: ByRoleOptions 151 | ) => HTMLElement | null; 152 | 153 | declare type FindByRole = ( 154 | role: TextMatch, 155 | options?: ByRoleOptions, 156 | waitForElementOptions?: WaitForElementOptions 157 | ) => Promise; 158 | 159 | declare type FindAllByRole = ( 160 | role: Matcher, 161 | options?: ByRoleOptions, 162 | waitForElementOptions?: WaitForElementOptions 163 | ) => Promise; 164 | 165 | declare type GetsAndQueries = {| 166 | getByLabelText: GetByText, 167 | getAllByLabelText: AllByText, 168 | queryByLabelText: QueryByText, 169 | queryAllByLabelText: AllByText, 170 | findByLabelText: FindByText, 171 | findAllByLabelText: FindAllByText, 172 | 173 | getByPlaceholderText: GetByBoundAttribute, 174 | getAllByPlaceholderText: AllByBoundAttribute, 175 | queryByPlaceholderText: QueryByBoundAttribute, 176 | queryAllByPlaceholderText: AllByBoundAttribute, 177 | findByPlaceholderText: FindByBoundAttribute, 178 | findAllByPlaceholderText: FindAllByBoundAttribute, 179 | 180 | getByText: GetByText, 181 | getAllByText: AllByText, 182 | queryByText: QueryByText, 183 | queryAllByText: AllByText, 184 | findByText: FindByText, 185 | findAllByText: FindAllByText, 186 | 187 | getByAltText: GetByBoundAttribute, 188 | getAllByAltText: AllByBoundAttribute, 189 | queryByAltText: QueryByBoundAttribute, 190 | queryAllByAltText: AllByBoundAttribute, 191 | findByAltText: FindByBoundAttribute, 192 | findAllByAltText: FindAllByBoundAttribute, 193 | 194 | getByTitle: GetByBoundAttribute, 195 | getAllByTitle: AllByBoundAttribute, 196 | queryByTitle: QueryByBoundAttribute, 197 | queryAllByTitle: AllByBoundAttribute, 198 | findByTitle: FindByBoundAttribute, 199 | findAllByTitle: FindAllByBoundAttribute, 200 | 201 | getByDisplayValue: GetByBoundAttribute, 202 | getAllByDisplayValue: AllByBoundAttribute, 203 | queryByDisplayValue: QueryByBoundAttribute, 204 | queryAllByDisplayValue: AllByBoundAttribute, 205 | findByDisplayValue: FindByBoundAttribute, 206 | findAllByDisplayValue: FindAllByBoundAttribute, 207 | 208 | getByRole: GetByRole, 209 | getAllByRole: AllByRole, 210 | queryByRole: QueryByRole, 211 | queryAllByRole: AllByRole, 212 | findByRole: FindByRole, 213 | findAllByRole: FindAllByRole, 214 | 215 | getByTestId: GetByBoundAttribute, 216 | getAllByTestId: AllByBoundAttribute, 217 | queryByTestId: QueryByBoundAttribute, 218 | queryAllByTestId: AllByBoundAttribute, 219 | findByTestId: FindByBoundAttribute, 220 | findAllByTestId: FindAllByBoundAttribute, 221 | |}; 222 | 223 | declare type FireEvent = ( 224 | element: HTMLElement, 225 | eventProperties?: TInit 226 | ) => boolean; 227 | 228 | declare type Screen = { 229 | ...Queries, 230 | /** 231 | * Convenience function for `pretty-dom` which also allows an array 232 | * of elements 233 | */ 234 | debug: ( 235 | baseElement?: 236 | | HTMLElement 237 | | DocumentFragment 238 | | Array, 239 | maxLength?: number, 240 | options?: { ... } // @TODO pretty format OptionsReceived 241 | ) => void, 242 | /** 243 | * Convenience function for `Testing Playground` which logs URL that 244 | * can be opened in a browser 245 | */ 246 | logTestingPlaygroundURL: (element?: Element | Document) => void, 247 | ... 248 | }; 249 | 250 | declare type RenderResult = { 251 | ...Queries, 252 | container: HTMLElement, 253 | unmount: () => boolean, 254 | baseElement: HTMLElement, 255 | asFragment: () => DocumentFragment, 256 | debug: ( 257 | baseElement?: 258 | | HTMLElement 259 | | DocumentFragment 260 | | Array, 261 | maxLength?: number 262 | ) => void, 263 | rerender: (ui: React$Element<*>) => void, 264 | ... 265 | }; 266 | 267 | declare export type RenderOptionsWithoutCustomQueries = {| 268 | container?: HTMLElement, 269 | baseElement?: HTMLElement, 270 | hydrate?: boolean, 271 | wrapper?: React.ComponentType, 272 | |}; 273 | 274 | declare export type RenderOptionsWithCustomQueries< 275 | CustomQueries: { ... } 276 | > = {| 277 | queries: CustomQueries, 278 | container?: HTMLElement, 279 | baseElement?: HTMLElement, 280 | hydrate?: boolean, 281 | wrapper?: React.ComponentType, 282 | |}; 283 | 284 | declare export function render( 285 | ui: React.ReactElement, 286 | options?: RenderOptionsWithoutCustomQueries 287 | ): RenderResult<>; 288 | declare export function render< 289 | CustomQueries: { [string]: (...args: Array) => any, ... } 290 | >( 291 | ui: React.ReactElement, 292 | options: RenderOptionsWithCustomQueries 293 | ): RenderResult; 294 | 295 | declare export var act: ReactDOMTestUtilsAct; 296 | declare export function cleanup(): void; 297 | 298 | declare export function waitFor( 299 | callback: () => T | Promise, 300 | options?: {| 301 | container?: HTMLElement, 302 | timeout?: number, 303 | interval?: number, 304 | mutationObserverOptions?: MutationObserverInit, 305 | |} 306 | ): Promise; 307 | 308 | declare export function waitForElementToBeRemoved( 309 | callback: (() => T) | T, 310 | options?: {| 311 | container?: HTMLElement, 312 | timeout?: number, 313 | interval?: number, 314 | mutationObserverOptions?: MutationObserverInit, 315 | |} 316 | ): Promise; 317 | 318 | /** 319 | * @deprecated `wait` has been deprecated and replaced by `waitFor` instead. 320 | * In most cases you should be able to find/replace `wait` with `waitFor`. 321 | * Learn more: https://testing-library.com/docs/dom-testing-library/api-async#waitfor. 322 | */ 323 | declare export function wait( 324 | callback?: () => void, 325 | options?: { 326 | timeout?: number, 327 | interval?: number, 328 | ... 329 | } 330 | ): Promise; 331 | 332 | /** 333 | * @deprecated `waitForDomChange` has been deprecated. 334 | * Use `waitFor` instead: https://testing-library.com/docs/dom-testing-library/api-async#waitfor. 335 | */ 336 | declare export function waitForDomChange(options?: { 337 | container?: HTMLElement, 338 | timeout?: number, 339 | mutationObserverOptions?: MutationObserverInit, 340 | ... 341 | }): Promise; 342 | 343 | /** 344 | * @deprecated `waitForElement` has been deprecated. 345 | * Use a `find*` query (preferred: https://testing-library.com/docs/dom-testing-library/api-queries#findby) 346 | * or use `waitFor` instead: https://testing-library.com/docs/dom-testing-library/api-async#waitfor 347 | */ 348 | declare export function waitForElement( 349 | callback?: () => T, 350 | options?: { 351 | container?: HTMLElement, 352 | timeout?: number, 353 | mutationObserverOptions?: MutationObserverInit, 354 | ... 355 | } 356 | ): Promise; 357 | 358 | declare export function within( 359 | element: HTMLElement, 360 | queriesToBind?: GetsAndQueries | Array 361 | ): GetsAndQueries; 362 | 363 | declare export var fireEvent: {| 364 | (element: HTMLElement, event: Event): void, 365 | 366 | copy: FireEvent, 367 | cut: FireEvent, 368 | paste: FireEvent, 369 | compositionEnd: FireEvent, 370 | compositionStart: FireEvent, 371 | compositionUpdate: FireEvent, 372 | keyDown: FireEvent, 373 | keyPress: FireEvent, 374 | keyUp: FireEvent, 375 | focus: FireEvent, 376 | blur: FireEvent, 377 | change: FireEvent, 378 | input: FireEvent, 379 | invalid: FireEvent, 380 | submit: FireEvent, 381 | click: FireEvent, 382 | contextMenu: FireEvent, 383 | dblClick: FireEvent, 384 | doubleClick: FireEvent, 385 | drag: FireEvent, 386 | dragEnd: FireEvent, 387 | dragEnter: FireEvent, 388 | dragExit: FireEvent, 389 | dragLeave: FireEvent, 390 | dragOver: FireEvent, 391 | dragStart: FireEvent, 392 | drop: FireEvent, 393 | mouseDown: FireEvent, 394 | mouseEnter: FireEvent, 395 | mouseLeave: FireEvent, 396 | mouseMove: FireEvent, 397 | mouseOut: FireEvent, 398 | mouseOver: FireEvent, 399 | mouseUp: FireEvent, 400 | select: FireEvent, 401 | touchCancel: FireEvent, 402 | touchEnd: FireEvent, 403 | touchMove: FireEvent, 404 | touchStart: FireEvent, 405 | scroll: FireEvent, 406 | wheel: FireEvent, 407 | abort: FireEvent, 408 | canPlay: FireEvent, 409 | canPlayThrough: FireEvent, 410 | durationChange: FireEvent, 411 | emptied: FireEvent, 412 | encrypted: FireEvent, 413 | ended: FireEvent, 414 | loadedData: FireEvent, 415 | loadedMetadata: FireEvent, 416 | loadStart: FireEvent, 417 | pause: FireEvent, 418 | play: FireEvent, 419 | playing: FireEvent, 420 | progress: FireEvent, 421 | rateChange: FireEvent, 422 | seeked: FireEvent, 423 | seeking: FireEvent, 424 | stalled: FireEvent, 425 | suspend: FireEvent, 426 | timeUpdate: FireEvent, 427 | volumeChange: FireEvent, 428 | waiting: FireEvent, 429 | load: FireEvent, 430 | error: FireEvent, 431 | animationStart: FireEvent, 432 | animationEnd: FireEvent, 433 | animationIteration: FireEvent, 434 | transitionEnd: FireEvent, 435 | |}; 436 | // dom-testing-library re-declares 437 | declare export function queryByTestId( 438 | container: HTMLElement, 439 | id: TextMatch, 440 | options?: TextMatchOptions 441 | ): ?HTMLElement; 442 | declare export function getByTestId( 443 | container: HTMLElement, 444 | id: TextMatch, 445 | options?: TextMatchOptions 446 | ): HTMLElement; 447 | declare export function queryByText( 448 | container: HTMLElement, 449 | text: TextMatch, 450 | options?: TextMatchOptions 451 | ): ?HTMLElement; 452 | declare export function getByText( 453 | container: HTMLElement, 454 | text: TextMatch, 455 | options?: { selector?: string, ... } & TextMatchOptions 456 | ): HTMLElement; 457 | declare export function queryByPlaceholderText( 458 | container: HTMLElement, 459 | text: TextMatch, 460 | options?: TextMatchOptions 461 | ): ?HTMLElement; 462 | declare export function getByPlaceholderText( 463 | container: HTMLElement, 464 | text: TextMatch, 465 | options?: TextMatchOptions 466 | ): HTMLElement; 467 | declare export function queryByLabelText( 468 | container: HTMLElement, 469 | text: TextMatch, 470 | options?: TextMatchOptions 471 | ): ?HTMLElement; 472 | declare export function getByLabelText( 473 | container: HTMLElement, 474 | text: TextMatch, 475 | options?: { selector?: string, ... } & TextMatchOptions 476 | ): HTMLElement; 477 | declare export function queryByAltText( 478 | container: HTMLElement, 479 | text: TextMatch, 480 | options?: TextMatchOptions 481 | ): ?HTMLElement; 482 | declare export function getByAltText( 483 | container: HTMLElement, 484 | text: TextMatch, 485 | options?: TextMatchOptions 486 | ): HTMLElement; 487 | declare export function getNodeText(node: HTMLElement): string; 488 | declare export var screen: Screen<>; 489 | } 490 | -------------------------------------------------------------------------------- /flow-typed/npm/@testing-library/user-event_v12.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6a6252b4e3cb976db493544a72da3039 2 | // flow-typed version: 47a326d3b8/@testing-library/user-event_v12.x.x/flow_>=v0.104.x 3 | 4 | declare module '@testing-library/user-event' { 5 | declare type TypeOpts = {| 6 | skipClick?: boolean, 7 | skipAutoClose?: boolean, 8 | delay?: number, 9 | initialSelectionStart?: number, 10 | initialSelectionEnd?: number, 11 | |}; 12 | 13 | declare type TabUserOptions = {| 14 | shift?: boolean, 15 | focusTrap?: Document | Element, 16 | |}; 17 | 18 | // As of Flow 0.134.x WindowProxy is any, which would annihilate all typechecking. 19 | declare type TargetElement = Element; /* | WindowProxy */ 20 | 21 | declare type FilesArgument = File | File[]; 22 | 23 | declare type UploadInitArgument = {| 24 | clickInit?: MouseEvent$MouseEventInit, 25 | changeInit?: Event, 26 | |}; 27 | 28 | declare type ClickOptions = {| 29 | skipHover?: boolean, 30 | clickCount?: number, 31 | |}; 32 | 33 | declare type UserEvent = {| 34 | clear: (element: TargetElement) => void, 35 | 36 | click: ( 37 | element: TargetElement, 38 | eventInit?: MouseEvent$MouseEventInit, 39 | options?: ClickOptions 40 | ) => void, 41 | 42 | dblClick: ( 43 | element: TargetElement, 44 | eventInit?: MouseEvent$MouseEventInit, 45 | options?: ClickOptions 46 | ) => void, 47 | 48 | selectOptions: ( 49 | element: TargetElement, 50 | values: string | string[] | HTMLElement | HTMLElement[], 51 | eventInit?: MouseEvent$MouseEventInit 52 | ) => void, 53 | 54 | deselectOptions: ( 55 | element: TargetElement, 56 | values: string | string[] | HTMLElement | HTMLElement[], 57 | eventInit?: MouseEvent$MouseEventInit 58 | ) => void, 59 | 60 | upload: ( 61 | element: TargetElement, 62 | files: FilesArgument, 63 | init?: UploadInitArgument 64 | ) => void, 65 | 66 | type: ( 67 | element: TargetElement, 68 | text: string, 69 | userOpts?: TypeOpts 70 | ) => Promise, 71 | 72 | tab: (userOpts?: TabUserOptions) => void, 73 | 74 | paste: ( 75 | element: TargetElement, 76 | text: string, 77 | eventInit?: MouseEvent$MouseEventInit, 78 | pasteOptions?: {| 79 | initialSelectionStart?: number, 80 | initialSelectionEnd?: number, 81 | |} 82 | ) => void, 83 | 84 | hover: (element: TargetElement, init?: MouseEvent$MouseEventInit) => void, 85 | 86 | unhover: (element: TargetElement, init?: MouseEvent$MouseEventInit) => void, 87 | |}; 88 | 89 | declare export default UserEvent; 90 | } 91 | -------------------------------------------------------------------------------- /flow-typed/npm/clsx_v1.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 4df2ba2381766154281e22a2c742750e 2 | // flow-typed version: c6154227d1/clsx_v1.x.x/flow_>=v0.104.x 3 | 4 | declare module 'clsx' { 5 | declare type Classes = 6 | | Array 7 | | { [className: string]: *, ... } 8 | | string 9 | | number 10 | | boolean 11 | | void 12 | | null; 13 | 14 | declare module.exports: (...classes: Array) => string; 15 | } 16 | -------------------------------------------------------------------------------- /flow-typed/npm/jest_v26.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: e60c7806ec0ddaf4588f438843ef37bd 2 | // flow-typed version: 7afca48d86/jest_v26.x.x/flow_>=v0.104.x 3 | 4 | type JestMockFn, TReturn> = { 5 | (...args: TArguments): TReturn, 6 | /** 7 | * An object for introspecting mock calls 8 | */ 9 | mock: { 10 | /** 11 | * An array that represents all calls that have been made into this mock 12 | * function. Each call is represented by an array of arguments that were 13 | * passed during the call. 14 | */ 15 | calls: Array, 16 | /** 17 | * An array that contains all the object instances that have been 18 | * instantiated from this mock function. 19 | */ 20 | instances: Array, 21 | /** 22 | * An array that contains all the object results that have been 23 | * returned by this mock function call 24 | */ 25 | results: Array<{ 26 | isThrow: boolean, 27 | value: TReturn, 28 | ... 29 | }>, 30 | ... 31 | }, 32 | /** 33 | * Resets all information stored in the mockFn.mock.calls and 34 | * mockFn.mock.instances arrays. Often this is useful when you want to clean 35 | * up a mock's usage data between two assertions. 36 | */ 37 | mockClear(): void, 38 | /** 39 | * Resets all information stored in the mock. This is useful when you want to 40 | * completely restore a mock back to its initial state. 41 | */ 42 | mockReset(): void, 43 | /** 44 | * Removes the mock and restores the initial implementation. This is useful 45 | * when you want to mock functions in certain test cases and restore the 46 | * original implementation in others. Beware that mockFn.mockRestore only 47 | * works when mock was created with jest.spyOn. Thus you have to take care of 48 | * restoration yourself when manually assigning jest.fn(). 49 | */ 50 | mockRestore(): void, 51 | /** 52 | * Accepts a function that should be used as the implementation of the mock. 53 | * The mock itself will still record all calls that go into and instances 54 | * that come from itself -- the only difference is that the implementation 55 | * will also be executed when the mock is called. 56 | */ 57 | mockImplementation( 58 | fn: (...args: TArguments) => TReturn 59 | ): JestMockFn, 60 | /** 61 | * Accepts a function that will be used as an implementation of the mock for 62 | * one call to the mocked function. Can be chained so that multiple function 63 | * calls produce different results. 64 | */ 65 | mockImplementationOnce( 66 | fn: (...args: TArguments) => TReturn 67 | ): JestMockFn, 68 | /** 69 | * Accepts a string to use in test result output in place of "jest.fn()" to 70 | * indicate which mock function is being referenced. 71 | */ 72 | mockName(name: string): JestMockFn, 73 | /** 74 | * Just a simple sugar function for returning `this` 75 | */ 76 | mockReturnThis(): void, 77 | /** 78 | * Accepts a value that will be returned whenever the mock function is called. 79 | */ 80 | mockReturnValue(value: TReturn): JestMockFn, 81 | /** 82 | * Sugar for only returning a value once inside your mock 83 | */ 84 | mockReturnValueOnce(value: TReturn): JestMockFn, 85 | /** 86 | * Sugar for jest.fn().mockImplementation(() => Promise.resolve(value)) 87 | */ 88 | mockResolvedValue(value: TReturn): JestMockFn>, 89 | /** 90 | * Sugar for jest.fn().mockImplementationOnce(() => Promise.resolve(value)) 91 | */ 92 | mockResolvedValueOnce( 93 | value: TReturn 94 | ): JestMockFn>, 95 | /** 96 | * Sugar for jest.fn().mockImplementation(() => Promise.reject(value)) 97 | */ 98 | mockRejectedValue(value: TReturn): JestMockFn>, 99 | /** 100 | * Sugar for jest.fn().mockImplementationOnce(() => Promise.reject(value)) 101 | */ 102 | mockRejectedValueOnce(value: TReturn): JestMockFn>, 103 | ... 104 | }; 105 | 106 | type JestAsymmetricEqualityType = { 107 | /** 108 | * A custom Jasmine equality tester 109 | */ 110 | asymmetricMatch(value: mixed): boolean, 111 | ... 112 | }; 113 | 114 | type JestCallsType = { 115 | allArgs(): mixed, 116 | all(): mixed, 117 | any(): boolean, 118 | count(): number, 119 | first(): mixed, 120 | mostRecent(): mixed, 121 | reset(): void, 122 | ... 123 | }; 124 | 125 | type JestClockType = { 126 | install(): void, 127 | mockDate(date: Date): void, 128 | tick(milliseconds?: number): void, 129 | uninstall(): void, 130 | ... 131 | }; 132 | 133 | type JestMatcherResult = { 134 | message?: string | (() => string), 135 | pass: boolean, 136 | ... 137 | }; 138 | 139 | type JestMatcher = ( 140 | received: any, 141 | ...actual: Array 142 | ) => JestMatcherResult | Promise; 143 | 144 | type JestPromiseType = { 145 | /** 146 | * Use rejects to unwrap the reason of a rejected promise so any other 147 | * matcher can be chained. If the promise is fulfilled the assertion fails. 148 | */ 149 | rejects: JestExpectType, 150 | /** 151 | * Use resolves to unwrap the value of a fulfilled promise so any other 152 | * matcher can be chained. If the promise is rejected the assertion fails. 153 | */ 154 | resolves: JestExpectType, 155 | ... 156 | }; 157 | 158 | /** 159 | * Jest allows functions and classes to be used as test names in test() and 160 | * describe() 161 | */ 162 | type JestTestName = string | Function; 163 | 164 | /** 165 | * Plugin: jest-styled-components 166 | */ 167 | 168 | type JestStyledComponentsMatcherValue = 169 | | string 170 | | JestAsymmetricEqualityType 171 | | RegExp 172 | | typeof undefined; 173 | 174 | type JestStyledComponentsMatcherOptions = { 175 | media?: string, 176 | modifier?: string, 177 | supports?: string, 178 | ... 179 | }; 180 | 181 | type JestStyledComponentsMatchersType = { 182 | toHaveStyleRule( 183 | property: string, 184 | value: JestStyledComponentsMatcherValue, 185 | options?: JestStyledComponentsMatcherOptions 186 | ): void, 187 | ... 188 | }; 189 | 190 | /** 191 | * Plugin: jest-enzyme 192 | */ 193 | type EnzymeMatchersType = { 194 | // 5.x 195 | toBeEmpty(): void, 196 | toBePresent(): void, 197 | // 6.x 198 | toBeChecked(): void, 199 | toBeDisabled(): void, 200 | toBeEmptyRender(): void, 201 | toContainMatchingElement(selector: string): void, 202 | toContainMatchingElements(n: number, selector: string): void, 203 | toContainExactlyOneMatchingElement(selector: string): void, 204 | toContainReact(element: React$Element): void, 205 | toExist(): void, 206 | toHaveClassName(className: string): void, 207 | toHaveHTML(html: string): void, 208 | toHaveProp: ((propKey: string, propValue?: any) => void) & 209 | ((props: { ... }) => void), 210 | toHaveRef(refName: string): void, 211 | toHaveState: ((stateKey: string, stateValue?: any) => void) & 212 | ((state: { ... }) => void), 213 | toHaveStyle: ((styleKey: string, styleValue?: any) => void) & 214 | ((style: { ... }) => void), 215 | toHaveTagName(tagName: string): void, 216 | toHaveText(text: string): void, 217 | toHaveValue(value: any): void, 218 | toIncludeText(text: string): void, 219 | toMatchElement( 220 | element: React$Element, 221 | options?: {| ignoreProps?: boolean, verbose?: boolean |} 222 | ): void, 223 | toMatchSelector(selector: string): void, 224 | // 7.x 225 | toHaveDisplayName(name: string): void, 226 | ... 227 | }; 228 | 229 | // DOM testing library extensions (jest-dom) 230 | // https://github.com/testing-library/jest-dom 231 | type DomTestingLibraryType = { 232 | /** 233 | * @deprecated 234 | */ 235 | toBeInTheDOM(container?: HTMLElement): void, 236 | 237 | // 4.x 238 | toBeInTheDocument(): void, 239 | toBeVisible(): void, 240 | toBeEmpty(): void, 241 | toBeDisabled(): void, 242 | toBeEnabled(): void, 243 | toBeInvalid(): void, 244 | toBeRequired(): void, 245 | toBeValid(): void, 246 | toContainElement(element: HTMLElement | null): void, 247 | toContainHTML(htmlText: string): void, 248 | toHaveAttribute(attr: string, value?: any): void, 249 | toHaveClass(...classNames: string[]): void, 250 | toHaveFocus(): void, 251 | toHaveFormValues(expectedValues: { [name: string]: any, ... }): void, 252 | toHaveStyle(css: string | { [name: string]: any, ... }): void, 253 | toHaveTextContent( 254 | text: string | RegExp, 255 | options?: {| normalizeWhitespace: boolean |} 256 | ): void, 257 | toHaveValue(value?: string | string[] | number): void, 258 | 259 | // 5.x 260 | toHaveDisplayValue(value: string | string[]): void, 261 | toBeChecked(): void, 262 | ... 263 | }; 264 | 265 | // Jest JQuery Matchers: https://github.com/unindented/custom-jquery-matchers 266 | type JestJQueryMatchersType = { 267 | toExist(): void, 268 | toHaveLength(len: number): void, 269 | toHaveId(id: string): void, 270 | toHaveClass(className: string): void, 271 | toHaveTag(tag: string): void, 272 | toHaveAttr(key: string, val?: any): void, 273 | toHaveProp(key: string, val?: any): void, 274 | toHaveText(text: string | RegExp): void, 275 | toHaveData(key: string, val?: any): void, 276 | toHaveValue(val: any): void, 277 | toHaveCss(css: { [key: string]: any, ... }): void, 278 | toBeChecked(): void, 279 | toBeDisabled(): void, 280 | toBeEmpty(): void, 281 | toBeHidden(): void, 282 | toBeSelected(): void, 283 | toBeVisible(): void, 284 | toBeFocused(): void, 285 | toBeInDom(): void, 286 | toBeMatchedBy(sel: string): void, 287 | toHaveDescendant(sel: string): void, 288 | toHaveDescendantWithText(sel: string, text: string | RegExp): void, 289 | ... 290 | }; 291 | 292 | // Jest Extended Matchers: https://github.com/jest-community/jest-extended 293 | type JestExtendedMatchersType = { 294 | /** 295 | * Note: Currently unimplemented 296 | * Passing assertion 297 | * 298 | * @param {String} message 299 | */ 300 | // pass(message: string): void; 301 | 302 | /** 303 | * Note: Currently unimplemented 304 | * Failing assertion 305 | * 306 | * @param {String} message 307 | */ 308 | // fail(message: string): void; 309 | 310 | /** 311 | * Use .toBeEmpty when checking if a String '', Array [] or Object {} is empty. 312 | */ 313 | toBeEmpty(): void, 314 | /** 315 | * Use .toBeOneOf when checking if a value is a member of a given Array. 316 | * @param {Array.<*>} members 317 | */ 318 | toBeOneOf(members: any[]): void, 319 | /** 320 | * Use `.toBeNil` when checking a value is `null` or `undefined`. 321 | */ 322 | toBeNil(): void, 323 | /** 324 | * Use `.toSatisfy` when you want to use a custom matcher by supplying a predicate function that returns a `Boolean`. 325 | * @param {Function} predicate 326 | */ 327 | toSatisfy(predicate: (n: any) => boolean): void, 328 | /** 329 | * Use `.toBeArray` when checking if a value is an `Array`. 330 | */ 331 | toBeArray(): void, 332 | /** 333 | * Use `.toBeArrayOfSize` when checking if a value is an `Array` of size x. 334 | * @param {Number} x 335 | */ 336 | toBeArrayOfSize(x: number): void, 337 | /** 338 | * Use `.toIncludeAllMembers` when checking if an `Array` contains all of the same members of a given set. 339 | * @param {Array.<*>} members 340 | */ 341 | toIncludeAllMembers(members: any[]): void, 342 | /** 343 | * Use `.toIncludeAnyMembers` when checking if an `Array` contains any of the members of a given set. 344 | * @param {Array.<*>} members 345 | */ 346 | toIncludeAnyMembers(members: any[]): void, 347 | /** 348 | * Use `.toSatisfyAll` when you want to use a custom matcher by supplying a predicate function that returns a `Boolean` for all values in an array. 349 | * @param {Function} predicate 350 | */ 351 | toSatisfyAll(predicate: (n: any) => boolean): void, 352 | /** 353 | * Use `.toBeBoolean` when checking if a value is a `Boolean`. 354 | */ 355 | toBeBoolean(): void, 356 | /** 357 | * Use `.toBeTrue` when checking a value is equal (===) to `true`. 358 | */ 359 | toBeTrue(): void, 360 | /** 361 | * Use `.toBeFalse` when checking a value is equal (===) to `false`. 362 | */ 363 | toBeFalse(): void, 364 | /** 365 | * Use .toBeDate when checking if a value is a Date. 366 | */ 367 | toBeDate(): void, 368 | /** 369 | * Use `.toBeFunction` when checking if a value is a `Function`. 370 | */ 371 | toBeFunction(): void, 372 | /** 373 | * Use `.toHaveBeenCalledBefore` when checking if a `Mock` was called before another `Mock`. 374 | * 375 | * Note: Required Jest version >22 376 | * Note: Your mock functions will have to be asynchronous to cause the timestamps inside of Jest to occur in a differentJS event loop, otherwise the mock timestamps will all be the same 377 | * 378 | * @param {Mock} mock 379 | */ 380 | toHaveBeenCalledBefore(mock: JestMockFn): void, 381 | /** 382 | * Use `.toBeNumber` when checking if a value is a `Number`. 383 | */ 384 | toBeNumber(): void, 385 | /** 386 | * Use `.toBeNaN` when checking a value is `NaN`. 387 | */ 388 | toBeNaN(): void, 389 | /** 390 | * Use `.toBeFinite` when checking if a value is a `Number`, not `NaN` or `Infinity`. 391 | */ 392 | toBeFinite(): void, 393 | /** 394 | * Use `.toBePositive` when checking if a value is a positive `Number`. 395 | */ 396 | toBePositive(): void, 397 | /** 398 | * Use `.toBeNegative` when checking if a value is a negative `Number`. 399 | */ 400 | toBeNegative(): void, 401 | /** 402 | * Use `.toBeEven` when checking if a value is an even `Number`. 403 | */ 404 | toBeEven(): void, 405 | /** 406 | * Use `.toBeOdd` when checking if a value is an odd `Number`. 407 | */ 408 | toBeOdd(): void, 409 | /** 410 | * Use `.toBeWithin` when checking if a number is in between the given bounds of: start (inclusive) and end (exclusive). 411 | * 412 | * @param {Number} start 413 | * @param {Number} end 414 | */ 415 | toBeWithin(start: number, end: number): void, 416 | /** 417 | * Use `.toBeObject` when checking if a value is an `Object`. 418 | */ 419 | toBeObject(): void, 420 | /** 421 | * Use `.toContainKey` when checking if an object contains the provided key. 422 | * 423 | * @param {String} key 424 | */ 425 | toContainKey(key: string): void, 426 | /** 427 | * Use `.toContainKeys` when checking if an object has all of the provided keys. 428 | * 429 | * @param {Array.} keys 430 | */ 431 | toContainKeys(keys: string[]): void, 432 | /** 433 | * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. 434 | * 435 | * @param {Array.} keys 436 | */ 437 | toContainAllKeys(keys: string[]): void, 438 | /** 439 | * Use `.toContainAnyKeys` when checking if an object contains at least one of the provided keys. 440 | * 441 | * @param {Array.} keys 442 | */ 443 | toContainAnyKeys(keys: string[]): void, 444 | /** 445 | * Use `.toContainValue` when checking if an object contains the provided value. 446 | * 447 | * @param {*} value 448 | */ 449 | toContainValue(value: any): void, 450 | /** 451 | * Use `.toContainValues` when checking if an object contains all of the provided values. 452 | * 453 | * @param {Array.<*>} values 454 | */ 455 | toContainValues(values: any[]): void, 456 | /** 457 | * Use `.toContainAllValues` when checking if an object only contains all of the provided values. 458 | * 459 | * @param {Array.<*>} values 460 | */ 461 | toContainAllValues(values: any[]): void, 462 | /** 463 | * Use `.toContainAnyValues` when checking if an object contains at least one of the provided values. 464 | * 465 | * @param {Array.<*>} values 466 | */ 467 | toContainAnyValues(values: any[]): void, 468 | /** 469 | * Use `.toContainEntry` when checking if an object contains the provided entry. 470 | * 471 | * @param {Array.} entry 472 | */ 473 | toContainEntry(entry: [string, string]): void, 474 | /** 475 | * Use `.toContainEntries` when checking if an object contains all of the provided entries. 476 | * 477 | * @param {Array.>} entries 478 | */ 479 | toContainEntries(entries: [string, string][]): void, 480 | /** 481 | * Use `.toContainAllEntries` when checking if an object only contains all of the provided entries. 482 | * 483 | * @param {Array.>} entries 484 | */ 485 | toContainAllEntries(entries: [string, string][]): void, 486 | /** 487 | * Use `.toContainAnyEntries` when checking if an object contains at least one of the provided entries. 488 | * 489 | * @param {Array.>} entries 490 | */ 491 | toContainAnyEntries(entries: [string, string][]): void, 492 | /** 493 | * Use `.toBeExtensible` when checking if an object is extensible. 494 | */ 495 | toBeExtensible(): void, 496 | /** 497 | * Use `.toBeFrozen` when checking if an object is frozen. 498 | */ 499 | toBeFrozen(): void, 500 | /** 501 | * Use `.toBeSealed` when checking if an object is sealed. 502 | */ 503 | toBeSealed(): void, 504 | /** 505 | * Use `.toBeString` when checking if a value is a `String`. 506 | */ 507 | toBeString(): void, 508 | /** 509 | * Use `.toEqualCaseInsensitive` when checking if a string is equal (===) to another ignoring the casing of both strings. 510 | * 511 | * @param {String} string 512 | */ 513 | toEqualCaseInsensitive(string: string): void, 514 | /** 515 | * Use `.toStartWith` when checking if a `String` starts with a given `String` prefix. 516 | * 517 | * @param {String} prefix 518 | */ 519 | toStartWith(prefix: string): void, 520 | /** 521 | * Use `.toEndWith` when checking if a `String` ends with a given `String` suffix. 522 | * 523 | * @param {String} suffix 524 | */ 525 | toEndWith(suffix: string): void, 526 | /** 527 | * Use `.toInclude` when checking if a `String` includes the given `String` substring. 528 | * 529 | * @param {String} substring 530 | */ 531 | toInclude(substring: string): void, 532 | /** 533 | * Use `.toIncludeRepeated` when checking if a `String` includes the given `String` substring the correct number of times. 534 | * 535 | * @param {String} substring 536 | * @param {Number} times 537 | */ 538 | toIncludeRepeated(substring: string, times: number): void, 539 | /** 540 | * Use `.toIncludeMultiple` when checking if a `String` includes all of the given substrings. 541 | * 542 | * @param {Array.} substring 543 | */ 544 | toIncludeMultiple(substring: string[]): void, 545 | ... 546 | }; 547 | 548 | // Diffing snapshot utility for Jest (snapshot-diff) 549 | // https://github.com/jest-community/snapshot-diff 550 | type SnapshotDiffType = { 551 | /** 552 | * Compare the difference between the actual in the `expect()` 553 | * vs the object inside `valueB` with some extra options. 554 | */ 555 | toMatchDiffSnapshot( 556 | valueB: any, 557 | options?: {| 558 | expand?: boolean, 559 | colors?: boolean, 560 | contextLines?: number, 561 | stablePatchmarks?: boolean, 562 | aAnnotation?: string, 563 | bAnnotation?: string, 564 | |}, 565 | testName?: string 566 | ): void, 567 | ... 568 | }; 569 | 570 | interface JestExpectType { 571 | not: JestExpectType & 572 | EnzymeMatchersType & 573 | DomTestingLibraryType & 574 | JestJQueryMatchersType & 575 | JestStyledComponentsMatchersType & 576 | JestExtendedMatchersType & 577 | SnapshotDiffType; 578 | /** 579 | * If you have a mock function, you can use .lastCalledWith to test what 580 | * arguments it was last called with. 581 | */ 582 | lastCalledWith(...args: Array): void; 583 | /** 584 | * toBe just checks that a value is what you expect. It uses === to check 585 | * strict equality. 586 | */ 587 | toBe(value: any): void; 588 | /** 589 | * Use .toBeCalledWith to ensure that a mock function was called with 590 | * specific arguments. 591 | */ 592 | toBeCalledWith(...args: Array): void; 593 | /** 594 | * Using exact equality with floating point numbers is a bad idea. Rounding 595 | * means that intuitive things fail. 596 | */ 597 | toBeCloseTo(num: number, delta: any): void; 598 | /** 599 | * Use .toBeDefined to check that a variable is not undefined. 600 | */ 601 | toBeDefined(): void; 602 | /** 603 | * Use .toBeFalsy when you don't care what a value is, you just want to 604 | * ensure a value is false in a boolean context. 605 | */ 606 | toBeFalsy(): void; 607 | /** 608 | * To compare floating point numbers, you can use toBeGreaterThan. 609 | */ 610 | toBeGreaterThan(number: number): void; 611 | /** 612 | * To compare floating point numbers, you can use toBeGreaterThanOrEqual. 613 | */ 614 | toBeGreaterThanOrEqual(number: number): void; 615 | /** 616 | * To compare floating point numbers, you can use toBeLessThan. 617 | */ 618 | toBeLessThan(number: number): void; 619 | /** 620 | * To compare floating point numbers, you can use toBeLessThanOrEqual. 621 | */ 622 | toBeLessThanOrEqual(number: number): void; 623 | /** 624 | * Use .toBeInstanceOf(Class) to check that an object is an instance of a 625 | * class. 626 | */ 627 | toBeInstanceOf(cls: Class<*>): void; 628 | /** 629 | * .toBeNull() is the same as .toBe(null) but the error messages are a bit 630 | * nicer. 631 | */ 632 | toBeNull(): void; 633 | /** 634 | * Use .toBeTruthy when you don't care what a value is, you just want to 635 | * ensure a value is true in a boolean context. 636 | */ 637 | toBeTruthy(): void; 638 | /** 639 | * Use .toBeUndefined to check that a variable is undefined. 640 | */ 641 | toBeUndefined(): void; 642 | /** 643 | * Use .toContain when you want to check that an item is in a list. For 644 | * testing the items in the list, this uses ===, a strict equality check. 645 | */ 646 | toContain(item: any): void; 647 | /** 648 | * Use .toContainEqual when you want to check that an item is in a list. For 649 | * testing the items in the list, this matcher recursively checks the 650 | * equality of all fields, rather than checking for object identity. 651 | */ 652 | toContainEqual(item: any): void; 653 | /** 654 | * Use .toEqual when you want to check that two objects have the same value. 655 | * This matcher recursively checks the equality of all fields, rather than 656 | * checking for object identity. 657 | */ 658 | toEqual(value: any): void; 659 | /** 660 | * Use .toHaveBeenCalled to ensure that a mock function got called. 661 | */ 662 | toHaveBeenCalled(): void; 663 | toBeCalled(): void; 664 | /** 665 | * Use .toHaveBeenCalledTimes to ensure that a mock function got called exact 666 | * number of times. 667 | */ 668 | toHaveBeenCalledTimes(number: number): void; 669 | toBeCalledTimes(number: number): void; 670 | /** 671 | * 672 | */ 673 | toHaveBeenNthCalledWith(nthCall: number, ...args: Array): void; 674 | nthCalledWith(nthCall: number, ...args: Array): void; 675 | /** 676 | * 677 | */ 678 | toHaveReturned(): void; 679 | toReturn(): void; 680 | /** 681 | * 682 | */ 683 | toHaveReturnedTimes(number: number): void; 684 | toReturnTimes(number: number): void; 685 | /** 686 | * 687 | */ 688 | toHaveReturnedWith(value: any): void; 689 | toReturnWith(value: any): void; 690 | /** 691 | * 692 | */ 693 | toHaveLastReturnedWith(value: any): void; 694 | lastReturnedWith(value: any): void; 695 | /** 696 | * 697 | */ 698 | toHaveNthReturnedWith(nthCall: number, value: any): void; 699 | nthReturnedWith(nthCall: number, value: any): void; 700 | /** 701 | * Use .toHaveBeenCalledWith to ensure that a mock function was called with 702 | * specific arguments. 703 | */ 704 | toHaveBeenCalledWith(...args: Array): void; 705 | toBeCalledWith(...args: Array): void; 706 | /** 707 | * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called 708 | * with specific arguments. 709 | */ 710 | toHaveBeenLastCalledWith(...args: Array): void; 711 | lastCalledWith(...args: Array): void; 712 | /** 713 | * Check that an object has a .length property and it is set to a certain 714 | * numeric value. 715 | */ 716 | toHaveLength(number: number): void; 717 | /** 718 | * 719 | */ 720 | toHaveProperty(propPath: string | $ReadOnlyArray, value?: any): void; 721 | /** 722 | * Use .toMatch to check that a string matches a regular expression or string. 723 | */ 724 | toMatch(regexpOrString: RegExp | string): void; 725 | /** 726 | * Use .toMatchObject to check that a javascript object matches a subset of the properties of an object. 727 | */ 728 | toMatchObject(object: Object | Array): void; 729 | /** 730 | * Use .toStrictEqual to check that a javascript object matches a subset of the properties of an object. 731 | */ 732 | toStrictEqual(value: any): void; 733 | /** 734 | * This ensures that an Object matches the most recent snapshot. 735 | */ 736 | toMatchSnapshot(propertyMatchers?: any, name?: string): void; 737 | /** 738 | * This ensures that an Object matches the most recent snapshot. 739 | */ 740 | toMatchSnapshot(name: string): void; 741 | 742 | toMatchInlineSnapshot(snapshot?: string): void; 743 | toMatchInlineSnapshot(propertyMatchers?: any, snapshot?: string): void; 744 | /** 745 | * Use .toThrow to test that a function throws when it is called. 746 | * If you want to test that a specific error gets thrown, you can provide an 747 | * argument to toThrow. The argument can be a string for the error message, 748 | * a class for the error, or a regex that should match the error. 749 | * 750 | * Alias: .toThrowError 751 | */ 752 | toThrow(message?: string | Error | Class | RegExp): void; 753 | toThrowError(message?: string | Error | Class | RegExp): void; 754 | /** 755 | * Use .toThrowErrorMatchingSnapshot to test that a function throws a error 756 | * matching the most recent snapshot when it is called. 757 | */ 758 | toThrowErrorMatchingSnapshot(): void; 759 | toThrowErrorMatchingInlineSnapshot(snapshot?: string): void; 760 | } 761 | 762 | type JestObjectType = { 763 | /** 764 | * Disables automatic mocking in the module loader. 765 | * 766 | * After this method is called, all `require()`s will return the real 767 | * versions of each module (rather than a mocked version). 768 | */ 769 | disableAutomock(): JestObjectType, 770 | /** 771 | * An un-hoisted version of disableAutomock 772 | */ 773 | autoMockOff(): JestObjectType, 774 | /** 775 | * Enables automatic mocking in the module loader. 776 | */ 777 | enableAutomock(): JestObjectType, 778 | /** 779 | * An un-hoisted version of enableAutomock 780 | */ 781 | autoMockOn(): JestObjectType, 782 | /** 783 | * Clears the mock.calls and mock.instances properties of all mocks. 784 | * Equivalent to calling .mockClear() on every mocked function. 785 | */ 786 | clearAllMocks(): JestObjectType, 787 | /** 788 | * Resets the state of all mocks. Equivalent to calling .mockReset() on every 789 | * mocked function. 790 | */ 791 | resetAllMocks(): JestObjectType, 792 | /** 793 | * Restores all mocks back to their original value. 794 | */ 795 | restoreAllMocks(): JestObjectType, 796 | /** 797 | * Removes any pending timers from the timer system. 798 | */ 799 | clearAllTimers(): void, 800 | /** 801 | * Returns the number of fake timers still left to run. 802 | */ 803 | getTimerCount(): number, 804 | /** 805 | * The same as `mock` but not moved to the top of the expectation by 806 | * babel-jest. 807 | */ 808 | doMock(moduleName: string, moduleFactory?: any): JestObjectType, 809 | /** 810 | * The same as `unmock` but not moved to the top of the expectation by 811 | * babel-jest. 812 | */ 813 | dontMock(moduleName: string): JestObjectType, 814 | /** 815 | * Returns a new, unused mock function. Optionally takes a mock 816 | * implementation. 817 | */ 818 | fn, TReturn>( 819 | implementation?: (...args: TArguments) => TReturn 820 | ): JestMockFn, 821 | /** 822 | * Determines if the given function is a mocked function. 823 | */ 824 | isMockFunction(fn: Function): boolean, 825 | /** 826 | * Given the name of a module, use the automatic mocking system to generate a 827 | * mocked version of the module for you. 828 | */ 829 | genMockFromModule(moduleName: string): any, 830 | /** 831 | * Mocks a module with an auto-mocked version when it is being required. 832 | * 833 | * The second argument can be used to specify an explicit module factory that 834 | * is being run instead of using Jest's automocking feature. 835 | * 836 | * The third argument can be used to create virtual mocks -- mocks of modules 837 | * that don't exist anywhere in the system. 838 | */ 839 | mock( 840 | moduleName: string, 841 | moduleFactory?: any, 842 | options?: Object 843 | ): JestObjectType, 844 | /** 845 | * Returns the actual module instead of a mock, bypassing all checks on 846 | * whether the module should receive a mock implementation or not. 847 | */ 848 | requireActual(m: $Flow$ModuleRef | string): T, 849 | /** 850 | * Returns a mock module instead of the actual module, bypassing all checks 851 | * on whether the module should be required normally or not. 852 | */ 853 | requireMock(moduleName: string): any, 854 | /** 855 | * Resets the module registry - the cache of all required modules. This is 856 | * useful to isolate modules where local state might conflict between tests. 857 | */ 858 | resetModules(): JestObjectType, 859 | /** 860 | * Creates a sandbox registry for the modules that are loaded inside the 861 | * callback function. This is useful to isolate specific modules for every 862 | * test so that local module state doesn't conflict between tests. 863 | */ 864 | isolateModules(fn: () => void): JestObjectType, 865 | /** 866 | * Exhausts the micro-task queue (usually interfaced in node via 867 | * process.nextTick). 868 | */ 869 | runAllTicks(): void, 870 | /** 871 | * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(), 872 | * setInterval(), and setImmediate()). 873 | */ 874 | runAllTimers(): void, 875 | /** 876 | * Exhausts all tasks queued by setImmediate(). 877 | */ 878 | runAllImmediates(): void, 879 | /** 880 | * Executes only the macro task queue (i.e. all tasks queued by setTimeout() 881 | * or setInterval() and setImmediate()). 882 | */ 883 | advanceTimersByTime(msToRun: number): void, 884 | /** 885 | * Executes only the macro task queue (i.e. all tasks queued by setTimeout() 886 | * or setInterval() and setImmediate()). 887 | * 888 | * Renamed to `advanceTimersByTime`. 889 | */ 890 | runTimersToTime(msToRun: number): void, 891 | /** 892 | * Executes only the macro-tasks that are currently pending (i.e., only the 893 | * tasks that have been queued by setTimeout() or setInterval() up to this 894 | * point) 895 | */ 896 | runOnlyPendingTimers(): void, 897 | /** 898 | * Explicitly supplies the mock object that the module system should return 899 | * for the specified module. Note: It is recommended to use jest.mock() 900 | * instead. 901 | */ 902 | setMock(moduleName: string, moduleExports: any): JestObjectType, 903 | /** 904 | * Indicates that the module system should never return a mocked version of 905 | * the specified module from require() (e.g. that it should always return the 906 | * real module). 907 | */ 908 | unmock(moduleName: string): JestObjectType, 909 | /** 910 | * Instructs Jest to use fake versions of the standard timer functions 911 | * (setTimeout, setInterval, clearTimeout, clearInterval, nextTick, 912 | * setImmediate and clearImmediate). 913 | */ 914 | useFakeTimers(mode?: 'modern' | 'legacy'): JestObjectType, 915 | /** 916 | * Instructs Jest to use the real versions of the standard timer functions. 917 | */ 918 | useRealTimers(): JestObjectType, 919 | /** 920 | * Creates a mock function similar to jest.fn but also tracks calls to 921 | * object[methodName]. 922 | */ 923 | spyOn( 924 | object: Object, 925 | methodName: string, 926 | accessType?: 'get' | 'set' 927 | ): JestMockFn, 928 | /** 929 | * Set the default timeout interval for tests and before/after hooks in milliseconds. 930 | * Note: The default timeout interval is 5 seconds if this method is not called. 931 | */ 932 | setTimeout(timeout: number): JestObjectType, 933 | ... 934 | }; 935 | 936 | type JestSpyType = { calls: JestCallsType, ... }; 937 | 938 | type JestDoneFn = {| 939 | (error?: Error): void, 940 | fail: (error: Error) => void, 941 | |}; 942 | 943 | /** Runs this function after every test inside this context */ 944 | declare function afterEach( 945 | fn: (done: JestDoneFn) => ?Promise, 946 | timeout?: number 947 | ): void; 948 | /** Runs this function before every test inside this context */ 949 | declare function beforeEach( 950 | fn: (done: JestDoneFn) => ?Promise, 951 | timeout?: number 952 | ): void; 953 | /** Runs this function after all tests have finished inside this context */ 954 | declare function afterAll( 955 | fn: (done: JestDoneFn) => ?Promise, 956 | timeout?: number 957 | ): void; 958 | /** Runs this function before any tests have started inside this context */ 959 | declare function beforeAll( 960 | fn: (done: JestDoneFn) => ?Promise, 961 | timeout?: number 962 | ): void; 963 | 964 | /** A context for grouping tests together */ 965 | declare var describe: { 966 | /** 967 | * Creates a block that groups together several related tests in one "test suite" 968 | */ 969 | (name: JestTestName, fn: () => void): void, 970 | /** 971 | * Only run this describe block 972 | */ 973 | only(name: JestTestName, fn: () => void): void, 974 | /** 975 | * Skip running this describe block 976 | */ 977 | skip(name: JestTestName, fn: () => void): void, 978 | /** 979 | * each runs this test against array of argument arrays per each run 980 | * 981 | * @param {table} table of Test 982 | */ 983 | each( 984 | ...table: Array | mixed> | [Array, string] 985 | ): ( 986 | name: JestTestName, 987 | fn?: (...args: Array) => ?Promise, 988 | timeout?: number 989 | ) => void, 990 | ... 991 | }; 992 | 993 | /** An individual test unit */ 994 | declare var it: { 995 | /** 996 | * An individual test unit 997 | * 998 | * @param {JestTestName} Name of Test 999 | * @param {Function} Test 1000 | * @param {number} Timeout for the test, in milliseconds. 1001 | */ 1002 | ( 1003 | name: JestTestName, 1004 | fn?: (done: JestDoneFn) => ?Promise, 1005 | timeout?: number 1006 | ): void, 1007 | /** 1008 | * Only run this test 1009 | * 1010 | * @param {JestTestName} Name of Test 1011 | * @param {Function} Test 1012 | * @param {number} Timeout for the test, in milliseconds. 1013 | */ 1014 | only: {| 1015 | ( 1016 | name: JestTestName, 1017 | fn?: (done: JestDoneFn) => ?Promise, 1018 | timeout?: number 1019 | ): void, 1020 | each( 1021 | ...table: Array | mixed> | [Array, string] 1022 | ): ( 1023 | name: JestTestName, 1024 | fn?: (...args: Array) => ?Promise, 1025 | timeout?: number 1026 | ) => void, 1027 | |}, 1028 | /** 1029 | * Skip running this test 1030 | * 1031 | * @param {JestTestName} Name of Test 1032 | * @param {Function} Test 1033 | * @param {number} Timeout for the test, in milliseconds. 1034 | */ 1035 | skip( 1036 | name: JestTestName, 1037 | fn?: (done: JestDoneFn) => ?Promise, 1038 | timeout?: number 1039 | ): void, 1040 | /** 1041 | * Highlight planned tests in the summary output 1042 | * 1043 | * @param {String} Name of Test to do 1044 | */ 1045 | todo(name: string): void, 1046 | /** 1047 | * Run the test concurrently 1048 | * 1049 | * @param {JestTestName} Name of Test 1050 | * @param {Function} Test 1051 | * @param {number} Timeout for the test, in milliseconds. 1052 | */ 1053 | concurrent( 1054 | name: JestTestName, 1055 | fn?: (done: JestDoneFn) => ?Promise, 1056 | timeout?: number 1057 | ): void, 1058 | /** 1059 | * each runs this test against array of argument arrays per each run 1060 | * 1061 | * @param {table} table of Test 1062 | */ 1063 | each( 1064 | ...table: Array | mixed> | [Array, string] 1065 | ): ( 1066 | name: JestTestName, 1067 | fn?: (...args: Array) => ?Promise, 1068 | timeout?: number 1069 | ) => void, 1070 | ... 1071 | }; 1072 | 1073 | declare function fit( 1074 | name: JestTestName, 1075 | fn: (done: JestDoneFn) => ?Promise, 1076 | timeout?: number 1077 | ): void; 1078 | /** An individual test unit */ 1079 | declare var test: typeof it; 1080 | /** A disabled group of tests */ 1081 | declare var xdescribe: typeof describe; 1082 | /** A focused group of tests */ 1083 | declare var fdescribe: typeof describe; 1084 | /** A disabled individual test */ 1085 | declare var xit: typeof it; 1086 | /** A disabled individual test */ 1087 | declare var xtest: typeof it; 1088 | 1089 | type JestPrettyFormatColors = { 1090 | comment: { 1091 | close: string, 1092 | open: string, 1093 | ... 1094 | }, 1095 | content: { 1096 | close: string, 1097 | open: string, 1098 | ... 1099 | }, 1100 | prop: { 1101 | close: string, 1102 | open: string, 1103 | ... 1104 | }, 1105 | tag: { 1106 | close: string, 1107 | open: string, 1108 | ... 1109 | }, 1110 | value: { 1111 | close: string, 1112 | open: string, 1113 | ... 1114 | }, 1115 | ... 1116 | }; 1117 | 1118 | type JestPrettyFormatIndent = (string) => string; 1119 | type JestPrettyFormatRefs = Array; 1120 | type JestPrettyFormatPrint = (any) => string; 1121 | type JestPrettyFormatStringOrNull = string | null; 1122 | 1123 | type JestPrettyFormatOptions = {| 1124 | callToJSON: boolean, 1125 | edgeSpacing: string, 1126 | escapeRegex: boolean, 1127 | highlight: boolean, 1128 | indent: number, 1129 | maxDepth: number, 1130 | min: boolean, 1131 | plugins: JestPrettyFormatPlugins, 1132 | printFunctionName: boolean, 1133 | spacing: string, 1134 | theme: {| 1135 | comment: string, 1136 | content: string, 1137 | prop: string, 1138 | tag: string, 1139 | value: string, 1140 | |}, 1141 | |}; 1142 | 1143 | type JestPrettyFormatPlugin = { 1144 | print: ( 1145 | val: any, 1146 | serialize: JestPrettyFormatPrint, 1147 | indent: JestPrettyFormatIndent, 1148 | opts: JestPrettyFormatOptions, 1149 | colors: JestPrettyFormatColors 1150 | ) => string, 1151 | test: (any) => boolean, 1152 | ... 1153 | }; 1154 | 1155 | type JestPrettyFormatPlugins = Array; 1156 | 1157 | /** The expect function is used every time you want to test a value */ 1158 | declare var expect: { 1159 | /** The object that you want to make assertions against */ 1160 | ( 1161 | value: any 1162 | ): JestExpectType & 1163 | JestPromiseType & 1164 | EnzymeMatchersType & 1165 | DomTestingLibraryType & 1166 | JestJQueryMatchersType & 1167 | JestStyledComponentsMatchersType & 1168 | JestExtendedMatchersType & 1169 | SnapshotDiffType, 1170 | /** Add additional Jasmine matchers to Jest's roster */ 1171 | extend(matchers: { [name: string]: JestMatcher, ... }): void, 1172 | /** Add a module that formats application-specific data structures. */ 1173 | addSnapshotSerializer(pluginModule: JestPrettyFormatPlugin): void, 1174 | assertions(expectedAssertions: number): void, 1175 | hasAssertions(): void, 1176 | any(value: mixed): JestAsymmetricEqualityType, 1177 | anything(): any, 1178 | arrayContaining(value: Array): Array, 1179 | objectContaining(value: Object): Object, 1180 | /** Matches any received string that contains the exact expected string. */ 1181 | stringContaining(value: string): string, 1182 | stringMatching(value: string | RegExp): string, 1183 | not: { 1184 | arrayContaining: (value: $ReadOnlyArray) => Array, 1185 | objectContaining: (value: { ... }) => Object, 1186 | stringContaining: (value: string) => string, 1187 | stringMatching: (value: string | RegExp) => string, 1188 | ... 1189 | }, 1190 | ... 1191 | }; 1192 | 1193 | // TODO handle return type 1194 | // http://jasmine.github.io/2.4/introduction.html#section-Spies 1195 | declare function spyOn(value: mixed, method: string): Object; 1196 | 1197 | /** Holds all functions related to manipulating test runner */ 1198 | declare var jest: JestObjectType; 1199 | 1200 | /** 1201 | * The global Jasmine object, this is generally not exposed as the public API, 1202 | * using features inside here could break in later versions of Jest. 1203 | */ 1204 | declare var jasmine: { 1205 | DEFAULT_TIMEOUT_INTERVAL: number, 1206 | any(value: mixed): JestAsymmetricEqualityType, 1207 | anything(): any, 1208 | arrayContaining(value: Array): Array, 1209 | clock(): JestClockType, 1210 | createSpy(name: string): JestSpyType, 1211 | createSpyObj( 1212 | baseName: string, 1213 | methodNames: Array 1214 | ): { [methodName: string]: JestSpyType, ... }, 1215 | objectContaining(value: Object): Object, 1216 | stringMatching(value: string): string, 1217 | ... 1218 | }; 1219 | -------------------------------------------------------------------------------- /flow-typed/npm/react-dom_v16.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a333d1cdbb5a4103d0be63a412070e22 2 | // flow-typed version: b2693c1879/react-dom_v16.x.x/flow_>=v0.117.x 3 | 4 | declare module 'react-dom' { 5 | declare function findDOMNode( 6 | componentOrElement: Element | ?React$Component, 7 | ): null | Element | Text; 8 | 9 | declare function render( 10 | element: React$Element, 11 | container: Element, 12 | callback?: () => void, 13 | ): React$ElementRef; 14 | 15 | declare function hydrate( 16 | element: React$Element, 17 | container: Element, 18 | callback?: () => void, 19 | ): React$ElementRef; 20 | 21 | declare function createPortal( 22 | node: React$Node, 23 | container: Element, 24 | ): React$Portal; 25 | 26 | declare function unmountComponentAtNode(container: any): boolean; 27 | declare var version: string; 28 | 29 | declare function unstable_batchedUpdates( 30 | callback: (a: A, b: B, c: C, d: D, e: E) => mixed, 31 | a: A, 32 | b: B, 33 | c: C, 34 | d: D, 35 | e: E, 36 | ): void; 37 | declare function unstable_renderSubtreeIntoContainer< 38 | ElementType: React$ElementType, 39 | >( 40 | parentComponent: React$Component, 41 | nextElement: React$Element, 42 | container: any, 43 | callback?: () => void, 44 | ): React$ElementRef; 45 | } 46 | 47 | declare module 'react-dom/server' { 48 | declare function renderToString(element: React$Node): string; 49 | declare function renderToStaticMarkup(element: React$Node): string; 50 | declare function renderToNodeStream(element: React$Node): stream$Readable; 51 | declare function renderToStaticNodeStream( 52 | element: React$Node, 53 | ): stream$Readable; 54 | declare var version: string; 55 | } 56 | 57 | type Thenable = { then(resolve: () => mixed, reject?: () => mixed): mixed, ... }; 58 | 59 | declare module 'react-dom/test-utils' { 60 | declare var Simulate: { [eventName: string]: (element: Element, eventData?: Object) => void, ... }; 61 | declare function renderIntoDocument( 62 | instance: React$Element, 63 | ): React$Component; 64 | declare function mockComponent( 65 | componentClass: React$ElementType, 66 | mockTagName?: string, 67 | ): Object; 68 | declare function isElement(element: React$Element): boolean; 69 | declare function isElementOfType( 70 | element: React$Element, 71 | componentClass: React$ElementType, 72 | ): boolean; 73 | declare function isDOMComponent(instance: any): boolean; 74 | declare function isCompositeComponent( 75 | instance: React$Component, 76 | ): boolean; 77 | declare function isCompositeComponentWithType( 78 | instance: React$Component, 79 | componentClass: React$ElementType, 80 | ): boolean; 81 | declare function findAllInRenderedTree( 82 | tree: React$Component, 83 | test: (child: React$Component) => boolean, 84 | ): Array>; 85 | declare function scryRenderedDOMComponentsWithClass( 86 | tree: React$Component, 87 | className: string, 88 | ): Array; 89 | declare function findRenderedDOMComponentWithClass( 90 | tree: React$Component, 91 | className: string, 92 | ): ?Element; 93 | declare function scryRenderedDOMComponentsWithTag( 94 | tree: React$Component, 95 | tagName: string, 96 | ): Array; 97 | declare function findRenderedDOMComponentWithTag( 98 | tree: React$Component, 99 | tagName: string, 100 | ): ?Element; 101 | declare function scryRenderedComponentsWithType( 102 | tree: React$Component, 103 | componentClass: React$ElementType, 104 | ): Array>; 105 | declare function findRenderedComponentWithType( 106 | tree: React$Component, 107 | componentClass: React$ElementType, 108 | ): ?React$Component; 109 | declare function act(callback: () => void | Thenable): Thenable; 110 | } 111 | -------------------------------------------------------------------------------- /flow-typed/npm/sponge_v0.1.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 905be200a0a4ae64bcfcae1292e5e2ed 2 | // flow-typed version: c6154227d1/sponge_v0.1.x/flow_>=v0.104.x 3 | 4 | declare module "sponge" { 5 | declare function sponge(): stream$Transform; 6 | declare function sponge(file: string): stream$Writable; 7 | 8 | declare module.exports: typeof sponge; 9 | } 10 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const env = process.env.NODE_ENV || ''; 2 | const pkg = require('./package.json'); 3 | 4 | const config = { 5 | cacheDirectory: '/.jest-cache', 6 | coverageDirectory: '/reports/coverage', 7 | collectCoverageFrom: [ 8 | 'src/**/*.js', 9 | '!**/index.js', 10 | '!**/*.story.js', 11 | '!**/stories/*.js', 12 | ], 13 | setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'], 14 | watchPlugins: [ 15 | 'jest-watch-typeahead/filename', 16 | 'jest-watch-typeahead/testname', 17 | ], 18 | }; 19 | 20 | if (env === 'ci') { 21 | Object.assign(config, { 22 | cache: false, 23 | collectCoverage: true, 24 | reporters: [ 25 | 'default', 26 | [ 27 | 'jest-junit', 28 | { 29 | suiteName: `${pkg.name} unit tests`, 30 | outputDirectory: '/reports', 31 | outputName: 'junit-report.xml', 32 | }, 33 | ], 34 | [ 35 | 'jest-html-reporter', 36 | { 37 | pageTitle: `${pkg.name} unit tests`, 38 | outputPath: '/reports/output-report.html', 39 | }, 40 | ], 41 | ], 42 | }); 43 | } 44 | 45 | module.exports = config; 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-module-boilerplate", 3 | "version": "0.1.0", 4 | "description": "Sample React presentational components package", 5 | "keywords": [ 6 | "react", 7 | "component", 8 | "boilerplate", 9 | "ui", 10 | "system", 11 | "css-modules", 12 | "styleguide", 13 | "snapshot" 14 | ], 15 | "author": { 16 | "name": "Pascal Duez", 17 | "url": "https://github.com/pascalduez" 18 | }, 19 | "homepage": "https://github.com/pascalduez/react-module-boilerplate", 20 | "bugs": "https://github.com/pascalduez/react-module-boilerplate/issues", 21 | "repository": { 22 | "type": "git", 23 | "url": "git://github.com/pascalduez/react-module-boilerplate.git" 24 | }, 25 | "license": "Unlicense", 26 | "files": [ 27 | "dist", 28 | "src/**/!(*.spec|*.story).(js|css)", 29 | "README.md", 30 | "UNLICENSE" 31 | ], 32 | "main": "dist/react-module-boilerplate.cjs.js", 33 | "module": "dist/react-module-boilerplate.esm.js", 34 | "browser": "dist/react-module-boilerplate.umd.js", 35 | "sideEffects": [ 36 | "*.css" 37 | ], 38 | "scripts": { 39 | "lint:css": "stylelint 'src/**/*.css'", 40 | "lint:js": "eslint src/", 41 | "lint": "run-s lint:*", 42 | "typecheck": "flow check src/", 43 | "typecheck:coverage": "flow-coverage-report -t text -t html -i 'src/**/*.js' -x 'src/**/*.{spec,story}.js'", 44 | "validate": "run-s lint typecheck", 45 | "test": "BABEL_ENV=test jest", 46 | "test:ci": "NODE_ENV=ci run-s validate test", 47 | "pretest:ci": "rm -rf reports/", 48 | "styleguide": "start-storybook -p 1337 -c .storybook", 49 | "playroom": "playroom start", 50 | "format": "prettier --write ./src/**/*", 51 | "clean": "rm -r dist/ coverage/ reports/ flow-coverage/", 52 | "build:css": "cat src/styles/variables.css dist/react-module-boilerplate.css | sponge dist/react-module-boilerplate.css", 53 | "build": "rollup -c", 54 | "prebuild": "rm -rf dist/ && mkdir dist/", 55 | "postbuild": "run-s build:css", 56 | "prepare": "run-s build", 57 | "prepublishOnly": "run-s validate test" 58 | }, 59 | "resolutions": { 60 | "postcss-modules": "^3.2.2" 61 | }, 62 | "dependencies": {}, 63 | "devDependencies": { 64 | "@babel/cli": "^7.12.1", 65 | "@babel/core": "^7.12.3", 66 | "@babel/plugin-proposal-class-properties": "^7.12.1", 67 | "@babel/plugin-proposal-do-expressions": "^7.12.1", 68 | "@babel/plugin-transform-runtime": "^7.12.1", 69 | "@babel/preset-env": "^7.12.1", 70 | "@babel/preset-flow": "^7.12.1", 71 | "@babel/preset-react": "^7.12.5", 72 | "@babel/runtime-corejs2": "^7.12.5", 73 | "@rollup/plugin-babel": "^5.2.1", 74 | "@rollup/plugin-commonjs": "^16.0.0", 75 | "@rollup/plugin-node-resolve": "^10.0.0", 76 | "@storybook/addon-a11y": "^6.1.1", 77 | "@storybook/addon-docs": "^6.1.1", 78 | "@storybook/addons": "^6.1.1", 79 | "@storybook/react": "^6.1.1", 80 | "@storybook/theming": "^6.1.1", 81 | "@testing-library/jest-dom": "^5.11.6", 82 | "@testing-library/react": "^11.2.1", 83 | "@testing-library/user-event": "^12.2.2", 84 | "babel-eslint": "^10.1.0", 85 | "babel-loader": "^8.2.1", 86 | "babel-plugin-css-modules-transform": "^1.6.2", 87 | "clsx": "^1.1.1", 88 | "eslint": "^7.13.0", 89 | "eslint-config-airbnb": "^18.2.1", 90 | "eslint-config-prettier": "^6.15.0", 91 | "eslint-plugin-babel": "^5.3.1", 92 | "eslint-plugin-css-modules": "^2.11.0", 93 | "eslint-plugin-flowtype": "^5.2.0", 94 | "eslint-plugin-import": "^2.22.1", 95 | "eslint-plugin-jest": "^24.1.3", 96 | "eslint-plugin-jsx-a11y": "6.4.1", 97 | "eslint-plugin-react": "^7.21.5", 98 | "eslint-plugin-testing-library": "^3.10.1", 99 | "flow-bin": "^0.138.0", 100 | "flow-coverage-report": "^0.8.0", 101 | "jest": "^26.6.3", 102 | "jest-html-reporter": "^3.3.0", 103 | "jest-junit": "^12.0.0", 104 | "jest-watch-typeahead": "^0.6.1", 105 | "npm-run-all": "^4.1.5", 106 | "playroom": "^0.22.3", 107 | "postcss": "^7.0.32", 108 | "postcss-loader": "^3.0.0", 109 | "postcss-modules": "^3.2.2", 110 | "postcss-preset-env": "^6.7.0", 111 | "postcss-reporter": "^6.0.1", 112 | "prettier": "^2.1.2", 113 | "react": "^17.0.1", 114 | "react-dom": "^17.0.1", 115 | "react-test-renderer": "^17.0.1", 116 | "rollup": "^2.33.3", 117 | "rollup-plugin-flow-entry": "^0.3.4", 118 | "rollup-plugin-node-externals": "^2.2.0", 119 | "rollup-plugin-postcss": "^3.1.8", 120 | "rollup-plugin-size-snapshot": "^0.12.0", 121 | "sponge": "^0.1.0", 122 | "stylelint": "^13.8.0", 123 | "stylelint-a11y": "^1.2.3", 124 | "stylelint-config-css-modules": "^2.2.0", 125 | "stylelint-config-prettier": "^8.0.2", 126 | "stylelint-config-standard": "^20.0.0", 127 | "stylelint-value-no-unknown-custom-properties": "^3.0.0" 128 | }, 129 | "peerDependencies": { 130 | "@babel/runtime-corejs2": "^7.0.0", 131 | "clsx": "^1.0.2", 132 | "react": "^16.0.0", 133 | "react-dom": "^16.0.0" 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /playroom.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Playroom', 3 | outputPath: 'dist/playroom', 4 | components: 'dist/react-module-boilerplate.cjs.js', 5 | frameComponent: '.playroom/FrameComponent.js', 6 | widths: [320, 375, 768, 1024], 7 | exampleCode: ` 8 | 9 | 10 | 11 | `, 12 | webpackConfig: () => ({ 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.css$/, 17 | exclude: /node_modules/, 18 | use: [ 19 | { 20 | loader: 'style-loader', 21 | }, 22 | { 23 | loader: 'css-loader', 24 | }, 25 | ], 26 | }, 27 | ], 28 | }, 29 | }), 30 | }; 31 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-preset-env': { 4 | importFrom: 'src/styles/variables.css', 5 | // exportTo: 'dist/config.css', 6 | }, 7 | 'postcss-reporter': {}, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import { sizeSnapshot } from 'rollup-plugin-size-snapshot'; 2 | import externals from 'rollup-plugin-node-externals'; 3 | import resolve from '@rollup/plugin-node-resolve'; 4 | import flowEntry from 'rollup-plugin-flow-entry'; 5 | import commonjs from '@rollup/plugin-commonjs'; 6 | import postcss from 'rollup-plugin-postcss'; 7 | import babel from '@rollup/plugin-babel'; 8 | import pkg from './package.json'; 9 | 10 | let plugins = [ 11 | externals(), 12 | postcss({ 13 | modules: true, 14 | extract: `${pkg.name}.css`, 15 | }), 16 | babel({ 17 | exclude: ['node_modules/**'], 18 | babelHelpers: 'runtime', 19 | }), 20 | resolve(), 21 | commonjs(), 22 | sizeSnapshot(), 23 | ]; 24 | 25 | export default { 26 | plugins, 27 | input: 'src/index.js', 28 | output: [ 29 | { 30 | file: pkg.browser, 31 | name: pkg.name, 32 | format: 'umd', 33 | }, 34 | { 35 | file: pkg.main, 36 | format: 'cjs', 37 | plugins: [flowEntry()], 38 | }, 39 | { 40 | file: pkg.module, 41 | format: 'esm', 42 | }, 43 | ], 44 | }; 45 | -------------------------------------------------------------------------------- /src/components/Button/Button.css: -------------------------------------------------------------------------------- 1 | .root { 2 | padding: 1rem 2rem; 3 | border: 1px solid; 4 | background-color: transparent; 5 | cursor: pointer; 6 | } 7 | 8 | .primary { 9 | color: var(--color-primary); 10 | } 11 | 12 | .secondary { 13 | color: var(--color-secondary); 14 | } 15 | 16 | .danger { 17 | color: var(--color-danger); 18 | } 19 | -------------------------------------------------------------------------------- /src/components/Button/Button.css.flow: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare module.exports: $ReadOnly<{ 4 | root: string, 5 | primary: string, 6 | secondary: string, 7 | danger: string, 8 | }>; 9 | -------------------------------------------------------------------------------- /src/components/Button/Button.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | /* eslint css-modules/no-unused-class: [2, { markAsUsed: ['primary', 'secondary', 'danger'] }] */ 3 | /* eslint-disable react/button-has-type */ 4 | 5 | import * as React from 'react'; 6 | import clsx from 'clsx'; 7 | 8 | import styles from './Button.css'; 9 | 10 | export type Props = {| 11 | children: React.Node, 12 | theme?: 'primary' | 'secondary' | 'danger', 13 | type?: 'submit' | 'button' | 'reset', 14 | className?: string, 15 | onClick?: (evt: SyntheticEvent) => mixed, 16 | |}; 17 | 18 | function Button({ 19 | theme = 'primary', 20 | type = 'submit', 21 | className, 22 | ...extraProps 23 | }: Props): React.Element<'button'> { 24 | return ( 25 | ); 13 | 14 | const button = screen.getByText('Test'); 15 | 16 | expect(button.tagName).toBe('BUTTON'); 17 | }); 18 | 19 | it('should render the default classes', () => { 20 | render(); 21 | 22 | const button = screen.getByText('Test'); 23 | 24 | expect(button).toHaveClass(styles.root); 25 | expect(button).toHaveClass(styles.primary); 26 | }); 27 | 28 | // Which is equivalent to: 29 | 30 | it('should render the default markup and classes [snapshot]', () => { 31 | const { asFragment } = render(); 32 | 33 | expect(asFragment()).toMatchSnapshot(); 34 | }); 35 | 36 | // Event handlers. 37 | 38 | it('should trigger click event handlers', () => { 39 | const spy = jest.fn(); 40 | render(); 41 | 42 | const button = screen.getByText('Test'); 43 | 44 | userEvent.click(button); 45 | 46 | expect(spy).toHaveBeenCalled(); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /src/components/Button/Button.stories.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import * as React from 'react'; 4 | 5 | import Button from './Button'; 6 | 7 | export default { 8 | component: Button, 9 | title: 'Button', 10 | }; 11 | 12 | export const primary = (): React.Node => ; 13 | 14 | export const secondary = (): React.Node => ; 15 | 16 | export const danger = (): React.Node => ; 17 | -------------------------------------------------------------------------------- /src/components/Button/__snapshots__/Button.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[` 11 | 12 | `; 13 | -------------------------------------------------------------------------------- /src/components/Button/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export { default } from './Button'; 4 | export type { Props as ButtonProps } from './Button'; 5 | -------------------------------------------------------------------------------- /src/components/Header/Header.css: -------------------------------------------------------------------------------- 1 | .root { 2 | color: orangeRed; 3 | background-color: var(--color-gray); 4 | } 5 | 6 | .title { 7 | margin: 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/components/Header/Header.css.flow: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare module.exports: $ReadOnly<{ 4 | root: string, 5 | title: string, 6 | }>; 7 | -------------------------------------------------------------------------------- /src/components/Header/Header.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import * as React from 'react'; 4 | import clsx from 'clsx'; 5 | 6 | import styles from './Header.css'; 7 | 8 | export type Props = {| 9 | title: string, 10 | className?: string, 11 | |}; 12 | 13 | function Header({ title, className, ...extraProps }: Props): React.Element<'header'> { 14 | return ( 15 |
20 |

{title}

21 |
22 | ); 23 | } 24 | 25 | export default Header; 26 | -------------------------------------------------------------------------------- /src/components/Header/Header.spec.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { render, screen } from '@testing-library/react'; 4 | 5 | import Header from './Header'; 6 | import styles from './Header.css'; 7 | 8 | describe('
', () => { 9 | it('should render the default markup', () => { 10 | const { container } = render(
); 11 | 12 | const title = screen.getByText('Test'); 13 | 14 | expect((container.firstChild: any).tagName).toBe('HEADER'); 15 | expect(title.tagName).toBe('H1'); 16 | }); 17 | 18 | it('should render the default classes', () => { 19 | const { container } = render(
); 20 | 21 | const title = screen.getByText('Test'); 22 | 23 | expect(container.firstChild).toHaveClass(styles.root); 24 | expect(title).toHaveClass(styles.title); 25 | }); 26 | 27 | // Which is equivalent to: 28 | 29 | it('should render the default markup and classes [snapshot]', () => { 30 | const { asFragment } = render(
); 31 | 32 | expect(asFragment()).toMatchSnapshot(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /src/components/Header/Header.stories.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import * as React from 'react'; 4 | 5 | import Header from './Header'; 6 | 7 | export default { 8 | component: Header, 9 | title: 'Header', 10 | }; 11 | 12 | export const text = (): React.Node =>
; 13 | 14 | export const emoji = (): React.Node =>
; 15 | -------------------------------------------------------------------------------- /src/components/Header/__snapshots__/Header.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`
should render the default markup and classes [snapshot] 1`] = ` 4 | 5 | 15 | 16 | `; 17 | -------------------------------------------------------------------------------- /src/components/Header/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export { default } from './Header'; 4 | export type { Props as HeaderProps } from './Header'; 5 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export { default as Header } from './components/Header'; 4 | export { default as Button } from './components/Button'; 5 | -------------------------------------------------------------------------------- /src/styles/variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --color-primary: green; 3 | --color-secondary: blue; 4 | --color-danger: red; 5 | --color-gray: #ccc; 6 | } 7 | --------------------------------------------------------------------------------