├── .circleci
└── config.yml
├── .gitignore
├── .hound.yml
├── .lintstagedrc
├── .prettierrc
├── .storybook
└── addons.js
├── .stylelintrc
├── .vscode
└── launch.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── assets
├── image
│ └── testing-structure.png
└── ppt
│ └── testing-structure.pptx
├── codecov.yml
├── commitlint.config.js
├── config
├── client.config.js
├── helpers.js
└── server.config.js
├── dist
├── public
│ ├── client.7f1954cbc82189d2016b.js
│ ├── client.7f1954cbc82189d2016b.js.gz
│ ├── client.7f1954cbc82189d2016b.js.map
│ ├── favicon.svg
│ └── index.html
└── server.js
├── jest.config.js
├── jest
├── __mocks__
│ ├── fileMock.js
│ └── styleMock.js
├── fileTransformer.js
├── generator
│ ├── createJestTest.js
│ ├── generateFile.js
│ └── index.js
└── setup.js
├── package.json
├── src
├── Root.tsx
├── client.tsx
├── components
│ ├── NotFound.tsx
│ └── __tests__
│ │ ├── NotFound.spec.tsx
│ │ └── __snapshots__
│ │ └── NotFound.spec.tsx.snap
├── containers
│ └── Home.tsx
├── favicon.svg
├── index.html
├── models.ts
├── routes.tsx
├── server.ts
├── store
│ ├── configureStore.dev.ts
│ ├── configureStore.prod.ts
│ └── index.ts
└── utils
│ ├── sum.spec.ts
│ └── sum.ts
├── tsconfig.json
├── tsconfig.prod.json
├── tslint.json
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Javascript Node CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details
4 | #
5 | version: 2
6 | jobs:
7 | build:
8 | docker:
9 | # specify the version you desire here
10 | - image: circleci/node:10
11 |
12 | working_directory: ~/repo
13 |
14 | steps:
15 | - checkout
16 |
17 | # Download and cache dependencies
18 | - restore_cache:
19 | keys:
20 | - v1-dependencies-{{ checksum "package.json" }}
21 | # fallback to using the latest cache if no exact match is found
22 | - v1-dependencies-
23 |
24 | - run: yarn
25 |
26 | - save_cache:
27 | paths:
28 | - node_modules
29 | key: v1-dependencies-{{ checksum "package.json" }}
30 |
31 | # run tests
32 | - run: yarn test:coverage
33 | - run: yarn build
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | coverage
3 | reports
4 | tmp
5 | built
6 | build
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 | .nyc_output/
11 | .awcache
12 | .DS_Store
13 | .env
14 | .chrome/
15 | .generate_config.json
16 | package-lock.json
17 | *.orig
18 | jest-test-results.json
--------------------------------------------------------------------------------
/.hound.yml:
--------------------------------------------------------------------------------
1 | tslint:
2 | enabled: true
3 | config_file: tslint.json
4 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": [
3 | "build/*",
4 | "node_modules"
5 | ],
6 | "linters": {
7 | "{src,docs}/**/*.{ts,tsx}": [
8 | "prettier --parser typescript --write",
9 | "tslint -c tslint.json --fix",
10 | "tslint -c tslint.json",
11 | "git add"
12 | ],
13 | "*.{css,scss}": [
14 | "prettier --write",
15 | "stylelint -q -s scss --fix",
16 | "git add"
17 | ],
18 | "*.{png,jpeg,jpg,gif,svg}": [
19 | "imagemin-lint-staged",
20 | "git add"
21 | ],
22 | "src/components/**/*.{ts,tsx}": [
23 | "jest --findRelatedTests --config jest.config.js",
24 | "git add"
25 | ]
26 | }
27 | }
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": true,
7 | "trailingComma": "es5"
8 | }
9 |
--------------------------------------------------------------------------------
/.storybook/addons.js:
--------------------------------------------------------------------------------
1 | import '@storybook/addon-jest/register';
2 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "stylelint-config-standard",
4 | "stylelint-config-idiomatic-order",
5 | "./node_modules/prettier-stylelint/config.js"
6 | ],
7 | "plugins": [
8 | "stylelint-scss"
9 | ],
10 | "rules": {
11 | "max-nesting-depth": 5,
12 | "no-descending-specificity": null,
13 | "selector-list-comma-newline-after": "always-multi-line",
14 | "declaration-empty-line-before": "never",
15 | "declaration-colon-newline-after": null,
16 | "value-list-comma-newline-after": null,
17 | "font-family-no-missing-generic-family-keyword": null,
18 | "at-rule-no-unknown": null,
19 | "scss/at-rule-no-unknown": true
20 | },
21 | "ignoreFiles": ["./node_modules/**", "**/*.ts", "**/*.tsx"]
22 | }
23 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "name": "vscode-jest-tests",
10 | "request": "launch",
11 | "args": [
12 | "--runInBand"
13 | ],
14 | "cwd": "${workspaceFolder}",
15 | "console": "integratedTerminal",
16 | "internalConsoleOptions": "neverOpen",
17 | "program": "${workspaceFolder}/node_modules/jest/bin/jest"
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## [0.1.3](https://github.com/TingGe/defensor-automated-testing/compare/v0.1.2...v0.1.3) (2018-09-03)
3 |
4 |
5 | ### Bug Fixes
6 |
7 | * update README.md ([a043b1b](https://github.com/TingGe/defensor-automated-testing/commit/a043b1b))
8 |
9 |
10 | ### Features
11 |
12 | * add command test:createTests and vscode debug ([54046c8](https://github.com/TingGe/defensor-automated-testing/commit/54046c8))
13 |
14 |
15 |
16 |
17 | ## 0.1.2 (2018-08-30)
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Kevin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Redux 前端研发品质实践
2 |
3 | [](https://codebeat.co/projects/github-com-tingge-defensor-automated-testing-master) [](https://codecov.io/gh/TingGe/defensor-automated-testing) [](https://circleci.com/gh/TingGe/defensor-automated-testing)
4 |
5 | 
6 |
7 | > 最佳适用于 `TypeScript + Scss/Less + React + Redux + React Dom + React Router + React Thunk` 技术栈的前端。
8 | >
9 | > 软件质量测量是对一系列可描述软件特性的属性值进行加权归一化的定量过程。
10 |
11 | 一个 React Redux 项目的模版项目。
12 |
13 | - 采用 `TypeScript + Scss/Less + React + Redux + React Dom + React Router + React Thunk` 技术栈;
14 | - 代码静态审查:husky + lint-staged + tslint + prettier + stylelint + imagemin-lint-staged;
15 | - 测试包括:单元测试、覆盖率测试、接入集成测试服务、e2e 测试和 watch 模式,husky + lint-staged + jest。
16 |
17 | ## Git 规范化注解
18 |
19 | > #### Commit 规范作用
20 | >
21 | > 1.提供更多的信息,方便排查与回退
22 | > 2.过滤关键字,迅速定位
23 | > 3.方便生成文档
24 |
25 | ### 规范
26 |
27 | ```git
28 | ():
29 | ```
30 |
31 | - type 用于说明 `commit` 类别,只允许使用下面7个标识。
32 |
33 | ```git
34 | feat:新功能(feature)
35 | fix:修补bug
36 | docs:文档(documentation)
37 | style: 格式(不影响代码运行的变动)
38 | refactor:重构(即不是新增功能,也不是修改bug的代码变动)
39 | test:增加测试
40 | chore:构建过程或辅助工具的变动
41 | ```
42 |
43 | - scope 用于说明 `commit` 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
44 |
45 | - subject 是 `commit` 目的的简短描述,不超过50个字符。
46 |
47 | ```git
48 | 1.以动词开头,使用第一人称现在时,比如change,而不是changed或changes
49 | 2.第一个字母小写
50 | 3.结尾不加句号(.)
51 | ```
52 |
53 | ### 执行方式
54 |
55 | - 校验 commit 规范:借助 [husky](https://github.com/typicode/husky) 在 commit 时自动校验。
56 | - 生成 Change log:` npm version [patch|minor|major]` ,可自动更新 CHANGELOG.md
57 |
58 | ## 代码静态审查
59 |
60 | 1. Git hook:husky + lint-staged
61 | 2. ts 和 tsx 合规检查和修复:tslint + prettier
62 | 3. scss 和 css 合规检查和修复:stylelint
63 | 4. 图片和 svg 等压缩:imagemin-lint-staged
64 |
65 | ### prettier 执行方式
66 |
67 | 方式一:VS Code 的 [prettier-vscode 插件](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)提示
68 |
69 | 方式二:借助 [husky](https://github.com/typicode/husky) 在代码 commit 时代码审查(自动修复和提示)
70 |
71 | 方式三:根目录执行以下命令(自动修复和提示)
72 |
73 | ```bash
74 | npx prettier --write './src/**/*.{ts,tsx,js,scss}'
75 | ```
76 |
77 | ### tslint 执行方式
78 |
79 | 方式一:VS Code 的 [vscode-tslint 插件](https://marketplace.visualstudio.com/items?itemName=eg2.tslint)提示
80 |
81 | 方式二:借助 [husky](https://github.com/typicode/husky) 在代码 commit 时代码审查(自动修复和提示)
82 |
83 | 方式三:根目录执行以下命令(自动修复和提示)
84 |
85 | ```bash
86 | tslint -c tslint.json --fix './src/**/*.{js,ts,tsx}'
87 | ```
88 |
89 | ### stylelint 执行方式
90 |
91 | 方式一:VS Code 的 [stylelint 插件](https://marketplace.visualstudio.com/items?itemName=shinnn.stylelint)提示
92 |
93 | 方式二:借助 [husky](https://github.com/typicode/husky) 在代码 commit 时代码审查(自动修复和提示)
94 |
95 | 方式三:根目录执行以下命令(自动修复和提示)
96 |
97 | ```Bash
98 | npx stylelint -s scss --fix --stdin-filename ./(src|docs)/**/*.scss
99 | ```
100 |
101 | ## 测试
102 |
103 | ### 关于是否需要自动化测试?
104 |
105 | 自动化测试的长远价值高于手工,所以如果自动化的性价比已经开始高于手工,就可以着手去做。项目后期和维护期,自动化介入为回归测试做准备,可以最大化自动化收益。
106 |
107 | 参考价值公式
108 |
109 | - 自动化收益 = 迭代次数 * 全手动执行成本 - 首次自动化成本 - 维护次数 * 维护成本
110 |
111 | 本项目采用的自动化测试技术方案
112 |
113 | 1. React Redux 测试:Typescript + Jest + Enzyme 组合
114 | 2. 集成测试: [Defensor E2E Testing](https://github.com/TingGe/defensor-e2e-testing)
115 |
116 |
117 | ### 组件测试:Typescript + Jest + Enzyme 组合
118 |
119 | 1. 支持 watch 模式
120 | 2. actions 测试
121 | 3. reducer 测试
122 | 4. select 测试
123 | 5. React + Redux 测试
124 | 6. 覆盖率和输出报告
125 |
126 | ### E2E 测试:Defensor E2E Testing
127 |
128 | > 可独立于项目代码。支持本地运行、手工触发、定时触发、发布流程触发四种方式,实现业务逻辑的持续测试。
129 |
130 | 1. 跨端(多浏览器兼容)自动化测试及报告: [UI Recorder](https://github.com/alibaba/uirecorder)、[F2etest](https://github.com/alibaba/f2etest)
131 | 2. 测试脚本:测试代码的 Github 仓库
132 | 3. 用例、测试计划、任务分派和缺陷管理:Aone
133 | 4. 持续集成(CI)服务:Aone 实验室 CISE
134 | 5. 全球化(G11N)自动测试报告:ACGT
135 | 6. 测试简报、测试计划进度跟踪、待修复缺陷跟踪:OneShot 截屏服务/爬虫服务 + 钉钉群机器人
136 | 7. 容器化: Docker/Kubernetes 编排技术实现的 Selenium Grid
137 | 8. 徽章服务:Aone badge
138 | 9. 多环境管理和健康大盘Chrome扩展:[defensor-multi-environment-manager](https://github.com/TingGe/defensor-multi-environment-manager)
139 | 10. 线上巡检:(可配合线上监控系统和报告数据实现可视化)
140 |
141 | ## 其他辅助工具
142 |
143 | 1. 快速应用 CLI 工具:[defensor-cli](https://github.com/TingGe/defensor-cli)
144 | 2. 命令行工具,主要用于 Newsletter 等群发通知:[defensor-node-cli-broadcast](https://github.com/TingGe/defensor-node-cli-broadcast)
145 |
146 | ## 对比的一些工具
147 |
148 | - Jest:[Create React App](https://github.com/facebookincubator/create-react-app) 、 [Microsoft/TypeScript-React-Starter](Microsoft/TypeScript-React-Starter) 和 [Ant Design](https://github.com/ant-design/ant-design-pro) 中推荐方案,内置断言、测试覆盖率工具,是个一体化方案、开箱即用。提供测试环境Dom API支持、合理的默认值、预处理代码和默认执行并行测试在内的特性;
149 | - AVA: 相对于 Mocha 执行更快,测试环境隔离、支持原子测试,相对于 Jest 组合更加灵活但最佳实践的开发工具、生态链支持稍有欠缺;
150 | - Mocha + Chai:相对较为成熟。
151 |
152 |
153 |
154 | 项目接入持续集成在多人开发同一个仓库时候能起到很大的用途,每次push都能自动触发测试,测试没过会发生告警。
155 |
156 | 如果需求采用 Issues+Merge Request 来管理,每个需求一个Issue + 一个分支,开发完成后提交 Merge Request ,由项目 Owner 负责合并,项目质量将更有保障。
157 |
158 | GITHUB上的小工具,大概分成这么几类:代码质量、持续集成、依赖管理、本地化、监控、项目管理和安全等。
159 |
160 | | 级别 | 类别 | 作用 | 选型 | 同类 |
161 | | ------- | ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
162 | | - | 静态代码审查 | 统一团队代码风格 | [Prettier](https://github.com/prettier/prettier) | - |
163 | | - | 静态代码审查 | 现代 CSS 格式验证工具 | [Stylelint](https://github.com/stylelint/stylelint) | - |
164 | | - | 静态代码审查 | TypeScript 格式验证工具 | [Tslint](https://palantir.github.io/tslint/) | - |
165 | | - | 静态代码审查 | 安全审计,依赖项跟踪 | npm audit fix | [jj](https://github.com/greenkeeperio/greenkeeper), [Libraries.io](https://github.com/librariesio/libraries.io) |
166 | | - | 静态代码审查 | 可访问性、性能和安全的开源检查(Linting)工具 | - | [Webhint](https://github.com/webhintio/hint) |
167 | | - | 代码质量管理平台 | 集成不同的测试工具,代码分析工具,持续集成工具等。自动 Code Review 辅助 | [SonarQube](https://github.com/SonarSource/sonarqube) + [SonarLint](https://marketplace.visualstudio.com/items?itemName=SonarSource.sonarlint-vscode) | [CodeBeat](https://codebeat.co/), [Codacy](https://github.com/codacy), [Code Climat](https://github.com/codeclimate/codeclimate) |
168 | | 单元 | 测试框架 | test runner, snapshots, display, and watch | [Jest](https://jestjs.io/) 内置的 Jasmine | [AVA](https://github.com/avajs/ava), Mocha, Wallaby.js, |
169 | | 单元 | 断言库 | assertions functions | [enzyme](https://github.com/airbnb/enzyme) + Jest 的 Matchers | [Unexpected](https://github.com/unexpectedjs/unexpected), Chai, |
170 | | 单元 | Mock工具 | mocks, spies, and stubs | Jest 的 Mock Functions | [testdouble.js](https://github.com/testdouble/testdouble.js), [sinon](http://sinonjs.org/), |
171 | | 单元 | 测试覆盖率工具 | code coverage | Jest 内置的 Istanbul + [Codecov](https://codecov.io/) | [Coveralls](https://coveralls.io/), [nyc](https://github.com/istanbuljs/nyc) |
172 | | 单元 | 模拟工具 | 模拟浏览器 dom | Jest 内置的 JSDOM | [JsDom](https://github.com/jsdom/jsdom) |
173 | | - | Git 规范化注解向导工具 | Commit 规范,生成 Change log | [commitlint](https://github.com/marionebl/commitlint) + [conventional-changelog](https://github.com/conventional-changelog) | [commitizen](https://github.com/commitizen/cz-cli), [semantic-release](https://github.com/semantic-release/semantic-release) |
174 | | - | - | 与 Storybook 集成 | - | - |
175 | | - | - | 持续集成服务 | [CircleCI](https://circleci.com/) | [Jenkins](https://jenkins.io/), [Travis](https://travis-ci.org/), [Hound](https://houndci.com/) |
176 | | 端到端 | | e2e | [Defensor E2E Testing](https://github.com/TingGe/defensor-e2e-testing) | [Cypress](https://www.cypress.io/), [Nightwatch](http://nightwatchjs.org/), [Protractor](http://www.protractortest.org/), [Casper](http://casperjs.org/), [testcafe](https://github.com/DevExpress/testcafe), [DalekJS](https://github.com/dalekjs), [testwise-recorder](https://github.com/testwisely/testwise-recorder),[Puppeteer Recorder](https://github.com/checkly/puppeteer-recorder) + [Puppeteer](https://github.com/GoogleChrome/puppeteer) |
177 | | - | - | - | - | - |
178 | | ChatOps | 自动化运维 | 查看各项指标;自动发布;发布报告等 | [钉钉机器人](https://open-doc.dingtalk.com/docs/doc.htm?treeId=257&articleId=105735&docType=1) | Lita,Err, [Hubot](https://hubot.github.com/) |
179 | | - | 合规审查 | 自动追踪开源代码的授权许可协议;开源代码合规化 | [Fossa](https://fossa.io/) | - |
180 |
181 | ## 最佳实践
182 |
183 | - 通过 `npm run test:createTests` ,批量自动化生成单元测试代码
184 |
185 |
186 | ## 踩过的坑
187 |
188 | - package.json 中包依赖版本锁定管理:不要忽略 warning,关注 [Enzyme Working with React 16](http://airbnb.io/enzyme/docs/installation/react-16.html) 等配置文档
189 | - ignore-styles 忽略样式和资源文件:需要 hook node 的 require, 因此将 setup.ts 改成 setup.js
190 |
191 | ### API Docs
192 |
193 | - Enzyme: https://github.com/airbnb/enzyme/tree/master/docs/api
194 | - Sinon:http://sinonjs.org/releases/v4.1.2/
195 |
196 | ## 参考
197 |
198 | - [Wings-让单元测试智能全自动生成](http://www.threadingtest.com/newstest/Wings%E5%8F%91%E5%B8%83-%E8%AE%A9%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E6%99%BA%E8%83%BD%E5%85%A8%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90.html)
199 | - [议题解读《我的Web应用安全模糊测试之路》](https://www.anquanke.com/post/id/152729)
200 | - [开发要不要自己做测试?怎么做?](https://mp.weixin.qq.com/s?__biz=MzIzNjUxMzk2NQ==&mid=2247489501&idx=2&sn=fb233a9dcedbecb385cc828f2117b657&chksm=e8d7e81fdfa061098b6d4ec40d6a8aa63395b25af681fcf0faf9f2519bfeed053dc4a80bb124&scene=27#wechat_redirect)
201 |
202 |
203 | - [入门:前端自动化测试karma,Backstopjs,Selenium-webdriver,Moch](https://juejin.im/post/5b13526d6fb9a01e831461e6)
204 |
205 | - [代码自动化扫描系统的建设](https://www.anquanke.com/post/id/158929)
206 | - [你可能会忽略的 Git 提交规范](http://jartto.wang/2018/07/08/git-commit/)
207 | - [使用Jest进行React单元测试](https://www.codetd.com/article/2675508)
208 | - [聊聊前端开发的测试](https://www.diycode.cc/topics/716)
209 | - [如何进行前端自动化测试?](https://www.zhihu.com/question/29922082/answer/46141819)
210 | - [JavaScript 单元测试框架大乱斗:Jasmine、Mocha、AVA、Tape 以及 Jest](https://raygun.com/blog/javascript-unit-testing-frameworks/)
211 | - [基于 JavaScript 的 Web 应用的端到端测试工具对比](https://mo.github.io/2017/07/20/javascript-e2e-integration-testing.html)
212 | - [别再加端到端集成测试了,快换契约测试吧](http://insights.thoughtworks.cn/contract-test/)
213 | - [从工程化角度讨论如何快速构建可靠React组件](https://github.com/lcxfs1991/blog/issues/18)
214 | - [How to Test a React and Redux Application ](https://semaphoreci.com/community/tutorials/getting-started-with-create-react-app-and-ava)
215 | - [How to prevent “Property '…' does not exist on type 'Global'” with jsdom and typescript?](https://stackoverflow.com/questions/40743131/how-to-prevent-property-does-not-exist-on-type-global-with-jsdom-and-t)
216 | - [Using enzyme with JSDOM](http://airbnb.io/enzyme/docs/guides/jsdom.html)
217 | - [Antd Pro UI Test](https://pro.ant.design/docs/ui-test#单元测试)
218 | - [Automated React Component Testing with Jest](https://www.distelli.com/docs/tutorials/test-your-react-component-with-jest/)
219 |
220 | ## 重点解答
221 |
222 | 1. 常用组合和现在组合优缺点;
223 | 2. 各组合适用的应用场景;
224 | 3. 测试的开发体验。
225 |
226 | ## 未来的可能
227 |
228 | 1. 与测试团队整体测试的接入;
229 | 2. 对开发者更加友好,降低用例的创建和维护成本;
230 | 3. 从投入产出角度,减少人工干预环节。
231 |
232 | ## 许可 License
233 |
234 | [](https://app.fossa.io/projects/git%2Bgithub.com%2FTingGe%2Fdefensor-automated-testing?ref=badge_large)
235 |
--------------------------------------------------------------------------------
/assets/image/testing-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TingGe/defensor-automated-testing/caea8a48b78ca203fa807930c7038bf96d0f614a/assets/image/testing-structure.png
--------------------------------------------------------------------------------
/assets/ppt/testing-structure.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TingGe/defensor-automated-testing/caea8a48b78ca203fa807930c7038bf96d0f614a/assets/ppt/testing-structure.pptx
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | token: 293b95d6-2edc-4a1f-8ddd-52b26e95a65e
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] };
2 |
--------------------------------------------------------------------------------
/config/client.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const helpers = require('./helpers');
4 |
5 | const isDev = process.env.NODE_ENV === 'development';
6 |
7 | module.exports = {
8 | cache: isDev,
9 |
10 | target: 'web',
11 |
12 | devtool: isDev ? 'eval-source-map' : 'source-map',
13 |
14 | stats: {
15 | colors: isDev,
16 | reasons: isDev,
17 | errorDetails: isDev,
18 | },
19 |
20 | context: path.resolve(__dirname, '..'),
21 |
22 | entry: {
23 | client: [
24 | isDev && 'webpack-hot-middleware/client',
25 | './src/client.tsx',
26 | ].filter(Boolean),
27 | },
28 |
29 | output: {
30 | path: path.resolve(__dirname, '../dist', 'public'),
31 | filename: isDev ? '[name].js' : '[name].[hash].js',
32 | publicPath: '/',
33 | },
34 |
35 | resolve: {
36 | extensions: ['.json', '.ts', '.tsx', '.js'],
37 | modules: ['src', 'node_modules'],
38 | },
39 |
40 | module: {
41 | rules: [
42 | {
43 | test: /\.tsx?$/,
44 | include: path.resolve(__dirname, '../src'),
45 | use: [
46 | {
47 | loader: 'awesome-typescript-loader',
48 | },
49 | ],
50 | },
51 | ],
52 | },
53 |
54 | plugins: helpers.getPlugins(),
55 | };
56 |
--------------------------------------------------------------------------------
/config/helpers.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 | const CopyWebpackPlugin = require('copy-webpack-plugin');
5 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
6 | const CompressionPlugin = require('compression-webpack-plugin');
7 |
8 | const isDev = process.env.NODE_ENV === 'development';
9 |
10 | module.exports = {
11 | getPlugins: () => {
12 | const plugins = [
13 | new CopyWebpackPlugin([
14 | { from: path.resolve(__dirname, '../src/favicon.svg') },
15 | ]),
16 |
17 | new HtmlWebpackPlugin({
18 | template: path.resolve(__dirname, '../src/index.html'),
19 | }),
20 | ];
21 |
22 | if (isDev) {
23 | plugins.push(
24 | new webpack.HotModuleReplacementPlugin({
25 | multiStep: false, // https://github.com/jantimon/html-webpack-plugin/issues/533
26 | })
27 | );
28 | } else {
29 | plugins.push(
30 | new UglifyJsPlugin({
31 | uglifyOptions: {
32 | output: {
33 | beautify: false,
34 | },
35 | },
36 | sourceMap: true,
37 | }),
38 |
39 | new CompressionPlugin({
40 | asset: '[path].gz[query]',
41 | algorithm: 'gzip',
42 | test: /\.js$|\.css$|\.html$/,
43 | threshold: 10240,
44 | minRatio: 0.8,
45 | })
46 | );
47 | }
48 |
49 | return plugins;
50 | },
51 | };
52 |
--------------------------------------------------------------------------------
/config/server.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 | var nodeExternals = require('webpack-node-externals');
5 |
6 | module.exports = {
7 | mode: 'production',
8 |
9 | target: 'node',
10 |
11 | externals: [nodeExternals()],
12 |
13 | context: path.resolve(__dirname, '..'),
14 |
15 | entry: {
16 | server: ['./src/server.ts'],
17 | },
18 |
19 | output: {
20 | path: path.resolve(__dirname, '../dist'),
21 | filename: '[name].js',
22 | publicPath: '/',
23 | libraryTarget: 'commonjs2',
24 | },
25 |
26 | resolve: {
27 | extensions: ['.json', '.ts', '.tsx', '.js'],
28 | modules: ['src', 'node_modules'],
29 | },
30 |
31 | module: {
32 | rules: [
33 | {
34 | test: /\.tsx?$/,
35 | include: path.resolve(__dirname, '../src'),
36 | use: [
37 | {
38 | loader: 'awesome-typescript-loader',
39 | },
40 | ],
41 | },
42 | ],
43 | },
44 | };
45 |
--------------------------------------------------------------------------------
/dist/public/client.7f1954cbc82189d2016b.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=24)}([function(e,t,n){e.exports=n(34)()},function(e,t,n){"use strict";e.exports=n(26)},function(e,t,n){"use strict";e.exports=function(e,t,n,r,o,i,a,u){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,i,a,u],s=0;(l=new Error(t.replace(/%s/g,function(){return c[s++]}))).name="Invariant Violation"}throw l.framesToPop=1,l}}},function(e,t,n){"use strict";e.exports=function(){}},function(e,t,n){"use strict";e.exports=function(){}},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";var r=n(3),o=n.n(r),i=n(2),a=n.n(i),u=n(1),l=n.n(u),c=n(0),s=n.n(c),f=Object.assign||function(e){for(var t=1;t may have only one child element"),this.unlisten=r.listen(function(){e.setState({match:e.computeMatch(r.location.pathname)})})},t.prototype.componentWillReceiveProps=function(e){o()(this.props.history===e.history,"You cannot change ")},t.prototype.componentWillUnmount=function(){this.unlisten()},t.prototype.render=function(){var e=this.props.children;return e?l.a.Children.only(e):null},t}(l.a.Component);d.propTypes={history:s.a.object.isRequired,children:s.a.node},d.contextTypes={router:s.a.object},d.childContextTypes={router:s.a.object.isRequired},t.a=d},function(e,t,n){"use strict";var r=n(8),o=n.n(r),i={},a=0;t.a=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2];"string"==typeof t&&(t={path:t});var r=t,u=r.path,l=r.exact,c=void 0!==l&&l,s=r.strict,f=void 0!==s&&s,p=r.sensitive,d=void 0!==p&&p;if(null==u)return n;var h=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=i[n]||(i[n]={});if(r[e])return r[e];var u=[],l={re:o()(e,u,t),keys:u};return a<1e4&&(r[e]=l,a++),l}(u,{end:c,strict:f,sensitive:d}),y=h.re,m=h.keys,v=y.exec(e);if(!v)return null;var b=v[0],g=v.slice(1),w=e===b;return c&&!w?null:{path:u,url:"/"===u&&""===b?"/":b,isExact:w,params:m.reduce(function(e,t,n){return e[t.name]=g[n],e},{})}}},function(e,t,n){var r=n(50);e.exports=function e(t,n,o){return r(n)||(o=n||o,n=[]),o=o||{},t instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:"",n=e&&e.split("/")||[],i=t&&t.split("/")||[],a=e&&r(e),u=t&&r(t),l=a||u;if(e&&r(e)?i=n:n.length&&(i.pop(),i=i.concat(n)),!i.length)return"/";var c=void 0;if(i.length){var s=i[i.length-1];c="."===s||".."===s||""===s}else c=!1;for(var f=0,p=i.length;p>=0;p--){var d=i[p];"."===d?o(i,p):".."===d?(o(i,p),f++):f&&(o(i,p),f--)}if(!l)for(;f--;f)i.unshift("..");!l||""===i[0]||i[0]&&r(i[0])||i.unshift("");var h=i.join("/");return c&&"/"!==h.substr(-1)&&(h+="/"),h}},function(e,t,n){"use strict";n.r(t);var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.default=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every(function(t,r){return e(t,n[r])});var o=void 0===t?"undefined":r(t);if(o!==(void 0===n?"undefined":r(n)))return!1;if("object"===o){var i=t.valueOf(),a=n.valueOf();if(i!==t||a!==n)return e(i,a);var u=Object.keys(t),l=Object.keys(n);return u.length===l.length&&u.every(function(r){return e(t[r],n[r])})}return!1}},function(e,t,n){"use strict";(function(e,r){var o,i=n(21);o="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==e?e:r;var a=Object(i.a)(o);t.a=a}).call(this,n(5),n(39)(e))},function(e,t,n){"use strict";var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map(function(e){return t[e]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(e){r[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,a,u=function(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l0&&void 0!==arguments[0]?arguments[0]:s,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.type,r=t.payload;return n===c?l({},e,{location:r}):e}function p(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var d=function(e){function t(){var n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var o=arguments.length,i=Array(o),a=0;aS.length&&S.push(e)}function R(e,t,n){return null==e?0:function e(t,n,r,o){var u=typeof t;"undefined"!==u&&"boolean"!==u||(t=null);var l=!1;if(null===t)l=!0;else switch(u){case"string":case"number":l=!0;break;case"object":switch(t.$$typeof){case i:case a:l=!0}}if(l)return r(o,t,""===n?"."+M(t,0):n),1;if(l=0,n=""===n?".":n+":",Array.isArray(t))for(var c=0;cthis.eventPool.length&&this.eventPool.push(e)}function de(e){e.eventPool=[],e.getPooled=fe,e.release=pe}o(se.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=le)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=le)},persist:function(){this.isPersistent=le},isPersistent:ce,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null,this.isPropagationStopped=this.isDefaultPrevented=ce,this._dispatchInstances=this._dispatchListeners=null}}),se.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null},se.extend=function(e){function t(){}function n(){return r.apply(this,arguments)}var r=this;t.prototype=r.prototype;var i=new t;return o(i,n.prototype),n.prototype=i,n.prototype.constructor=n,n.Interface=o({},r.Interface,e),n.extend=r.extend,de(n),n},de(se);var he=se.extend({data:null}),ye=se.extend({data:null}),me=[9,13,27,32],ve=Y&&"CompositionEvent"in window,be=null;Y&&"documentMode"in document&&(be=document.documentMode);var ge=Y&&"TextEvent"in window&&!be,we=Y&&(!ve||be&&8=be),xe=String.fromCharCode(32),ke={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["compositionend","keypress","textInput","paste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:"blur compositionend keydown keypress keyup mousedown".split(" ")},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:"blur compositionstart keydown keypress keyup mousedown".split(" ")},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:"blur compositionupdate keydown keypress keyup mousedown".split(" ")}},_e=!1;function Oe(e,t){switch(e){case"keyup":return-1!==me.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"blur":return!0;default:return!1}}function Pe(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Ee=!1,Te={eventTypes:ke,extractEvents:function(e,t,n,r){var o=void 0,i=void 0;if(ve)e:{switch(e){case"compositionstart":o=ke.compositionStart;break e;case"compositionend":o=ke.compositionEnd;break e;case"compositionupdate":o=ke.compositionUpdate;break e}o=void 0}else Ee?Oe(e,n)&&(o=ke.compositionEnd):"keydown"===e&&229===n.keyCode&&(o=ke.compositionStart);return o?(we&&"ko"!==n.locale&&(Ee||o!==ke.compositionStart?o===ke.compositionEnd&&Ee&&(i=ue()):(ie="value"in(oe=r)?oe.value:oe.textContent,Ee=!0)),o=he.getPooled(o,t,n,r),i?o.data=i:null!==(i=Pe(n))&&(o.data=i),$(o),i=o):i=null,(e=ge?function(e,t){switch(e){case"compositionend":return Pe(t);case"keypress":return 32!==t.which?null:(_e=!0,xe);case"textInput":return(e=t.data)===xe&&_e?null:e;default:return null}}(e,n):function(e,t){if(Ee)return"compositionend"===e||!ve&&Oe(e,t)?(e=ue(),ae=ie=oe=null,Ee=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1t}return!1}(t,n,o,r)&&(n=null),r||null===o?function(e){return!!st.call(pt,e)||!st.call(ft,e)&&(ct.test(e)?pt[e]=!0:(ft[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):o.mustUseProperty?e[o.propertyName]=null===n?3!==o.type&&"":n:(t=o.attributeName,r=o.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(o=o.type)||4===o&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}function bt(e){switch(typeof e){case"boolean":case"number":case"object":case"string":case"undefined":return e;default:return""}}function gt(e,t){var n=t.checked;return o({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function wt(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=bt(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function xt(e,t){null!=(t=t.checked)&&vt(e,"checked",t,!1)}function kt(e,t){xt(e,t);var n=bt(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?Ot(e,t.type,n):t.hasOwnProperty("defaultValue")&&Ot(e,t.type,bt(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function _t(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!e.defaultChecked,e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function Ot(e,t,n){"number"===t&&e.ownerDocument.activeElement===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(yt,mt);ht[t]=new dt(t,1,!1,e,null)}),"xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(yt,mt);ht[t]=new dt(t,1,!1,e,"http://www.w3.org/1999/xlink")}),["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(yt,mt);ht[t]=new dt(t,1,!1,e,"http://www.w3.org/XML/1998/namespace")}),ht.tabIndex=new dt("tabIndex",1,!1,"tabindex",null);var Pt={change:{phasedRegistrationNames:{bubbled:"onChange",captured:"onChangeCapture"},dependencies:"blur change click focus input keydown keyup selectionchange".split(" ")}};function Et(e,t,n){return(e=se.getPooled(Pt.change,e,t,n)).type="change",Me(n),$(e),e}var Tt=null,St=null;function Ct(e){N(e,!1)}function jt(e){if(qe(F(e)))return e}function Rt(e,t){if("change"===e)return t}var Mt=!1;function Nt(){Tt&&(Tt.detachEvent("onpropertychange",At),St=Tt=null)}function At(e){"value"===e.propertyName&&jt(St)&&De(Ct,e=Et(St,e,We(e)))}function It(e,t,n){"focus"===e?(Nt(),St=n,(Tt=t).attachEvent("onpropertychange",At)):"blur"===e&&Nt()}function Ut(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return jt(St)}function Lt(e,t){if("click"===e)return jt(t)}function Dt(e,t){if("input"===e||"change"===e)return jt(t)}Y&&(Mt=He("input")&&(!document.documentMode||9kn.length&&kn.push(e)}}}var Cn={},jn=0,Rn="_reactListenersID"+(""+Math.random()).slice(2);function Mn(e){return Object.prototype.hasOwnProperty.call(e,Rn)||(e[Rn]=jn++,Cn[e[Rn]]={}),Cn[e[Rn]]}function Nn(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function An(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function In(e,t){var n,r=An(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=An(r)}}function Un(){for(var e=window,t=Nn();t instanceof e.HTMLIFrameElement;){try{e=t.contentDocument.defaultView}catch(e){break}t=Nn(e.document)}return t}function Ln(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var Dn=Y&&"documentMode"in document&&11>=document.documentMode,Fn={select:{phasedRegistrationNames:{bubbled:"onSelect",captured:"onSelectCapture"},dependencies:"blur contextmenu dragend focus keydown keyup mousedown mouseup selectionchange".split(" ")}},zn=null,Wn=null,Hn=null,Bn=!1;function Vn(e,t){var n=t.window===t?t.document:9===t.nodeType?t:t.ownerDocument;return Bn||null==zn||zn!==Nn(n)?null:(n="selectionStart"in(n=zn)&&Ln(n)?{start:n.selectionStart,end:n.selectionEnd}:{anchorNode:(n=(n.ownerDocument&&n.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset},Hn&&en(Hn,n)?null:(Hn=n,(e=se.getPooled(Fn.select,Wn,e,t)).type="select",e.target=zn,$(e),e))}var qn={eventTypes:Fn,extractEvents:function(e,t,n,r){var o,i=r.window===r?r.document:9===r.nodeType?r:r.ownerDocument;if(!(o=!i)){e:{i=Mn(i),o=w.onSelect;for(var a=0;a=t.length||a("93"),t=t[0]),n=t),null==n&&(n="")),e._wrapperState={initialValue:bt(n)}}function Xn(e,t){var n=bt(t.value);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&(e.defaultValue=n)),null!=t.defaultValue&&(e.defaultValue=""+bt(t.defaultValue))}function Gn(e){var t=e.textContent;t===e._wrapperState.initialValue&&(e.value=t)}R.injectEventPluginOrder("ResponderEventPlugin SimpleEventPlugin EnterLeaveEventPlugin ChangeEventPlugin SelectEventPlugin BeforeInputEventPlugin".split(" ")),x=z,k=D,_=F,R.injectEventPluginsByName({SimpleEventPlugin:wn,EnterLeaveEventPlugin:Gt,ChangeEventPlugin:Ft,SelectEventPlugin:qn,BeforeInputEventPlugin:Te});var Jn={html:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"};function Zn(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function er(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?Zn(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var tr=void 0,nr=function(e){return"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(t,n,r,o){MSApp.execUnsafeLocalFunction(function(){return e(t,n)})}:e}(function(e,t){if(e.namespaceURI!==Jn.svg||"innerHTML"in e)e.innerHTML=t;else{for((tr=tr||document.createElement("div")).innerHTML="",t=tr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function rr(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var or={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ir=["Webkit","ms","Moz","O"];function ar(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),o=n,i=t[n];o=null==i||"boolean"==typeof i||""===i?"":r||"number"!=typeof i||0===i||or.hasOwnProperty(o)&&or[o]?(""+i).trim():i+"px","float"===n&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}Object.keys(or).forEach(function(e){ir.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),or[t]=or[e]})});var ur=o({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function lr(e,t){t&&(ur[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML)&&a("137",e,""),null!=t.dangerouslySetInnerHTML&&(null!=t.children&&a("60"),"object"==typeof t.dangerouslySetInnerHTML&&"__html"in t.dangerouslySetInnerHTML||a("61")),null!=t.style&&"object"!=typeof t.style&&a("62",""))}function cr(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function sr(e,t){var n=Mn(e=9===e.nodeType||11===e.nodeType?e:e.ownerDocument);t=w[t];for(var r=0;rgr||(e.current=br[gr],br[gr]=null,gr--)}function xr(e,t){br[++gr]=e.current,e.current=t}var kr={},_r={current:kr},Or={current:!1},Pr=kr;function Er(e,t){var n=e.type.contextTypes;if(!n)return kr;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,i={};for(o in n)i[o]=t[o];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=i),i}function Tr(e){return null!==(e=e.childContextTypes)&&void 0!==e}function Sr(e){wr(Or),wr(_r)}function Cr(e){wr(Or),wr(_r)}function jr(e,t,n){_r.current!==kr&&a("168"),xr(_r,t),xr(Or,n)}function Rr(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var i in r=r.getChildContext())i in e||a("108",ut(t)||"Unknown",i);return o({},n,r)}function Mr(e){var t=e.stateNode;return t=t&&t.__reactInternalMemoizedMergedChildContext||kr,Pr=_r.current,xr(_r,t),xr(Or,Or.current),!0}function Nr(e,t,n){var r=e.stateNode;r||a("169"),n?(t=Rr(e,t,Pr),r.__reactInternalMemoizedMergedChildContext=t,wr(Or),wr(_r),xr(_r,t)):wr(Or),xr(Or,n)}var Ar=null,Ir=null;function Ur(e){return function(t){try{return e(t)}catch(e){}}}function Lr(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=null,this.index=0,this.ref=null,this.pendingProps=t,this.firstContextDependency=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childExpirationTime=this.expirationTime=0,this.alternate=null}function Dr(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Fr(e,t,n){var r=e.alternate;return null===r?((r=new Lr(e.tag,t,e.key,e.mode)).type=e.type,r.stateNode=e.stateNode,r.alternate=e,e.alternate=r):(r.pendingProps=t,r.effectTag=0,r.nextEffect=null,r.firstEffect=null,r.lastEffect=null),r.childExpirationTime=e.childExpirationTime,r.expirationTime=t!==e.pendingProps?n:e.expirationTime,r.child=e.child,r.memoizedProps=e.memoizedProps,r.memoizedState=e.memoizedState,r.updateQueue=e.updateQueue,r.firstContextDependency=e.firstContextDependency,r.sibling=e.sibling,r.index=e.index,r.ref=e.ref,r}function zr(e,t,n){var r=e.type,o=e.key;e=e.props;var i=void 0;if("function"==typeof r)i=Dr(r)?2:4;else if("string"==typeof r)i=7;else e:switch(r){case Ge:return Wr(e.children,t,n,o);case nt:i=10,t|=3;break;case Je:i=10,t|=2;break;case Ze:return(r=new Lr(15,e,o,4|t)).type=Ze,r.expirationTime=n,r;case ot:i=16;break;default:if("object"==typeof r&&null!==r)switch(r.$$typeof){case et:i=12;break e;case tt:i=11;break e;case rt:i=13;break e;default:if("function"==typeof r.then){i=4;break e}}a("130",null==r?r:typeof r,"")}return(t=new Lr(i,e,o,t)).type=r,t.expirationTime=n,t}function Wr(e,t,n,r){return(e=new Lr(9,e,r,t)).expirationTime=n,e}function Hr(e,t,n){return(e=new Lr(8,e,null,t)).expirationTime=n,e}function Br(e,t,n){return(t=new Lr(6,null!==e.children?e.children:[],e.key,t)).expirationTime=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Vr(e,t){e.didError=!1;var n=e.earliestPendingTime;0===n?e.earliestPendingTime=e.latestPendingTime=t:n>t?e.earliestPendingTime=t:e.latestPendingTimee)&&(o=r),0!==(e=o)&&0!==n&&no?(null===a&&(a=l,i=c),(0===u||u>s)&&(u=s)):(c=eo(e,0,l,c,n,r),null!==l.callback&&(e.effectTag|=32,l.nextEffect=null,null===t.lastEffect?t.firstEffect=t.lastEffect=l:(t.lastEffect.nextEffect=l,t.lastEffect=l))),l=l.next}for(s=null,l=t.firstCapturedUpdate;null!==l;){var f=l.expirationTime;f>o?(null===s&&(s=l,null===a&&(i=c)),(0===u||u>f)&&(u=f)):(c=eo(e,0,l,c,n,r),null!==l.callback&&(e.effectTag|=32,l.nextEffect=null,null===t.lastCapturedEffect?t.firstCapturedEffect=t.lastCapturedEffect=l:(t.lastCapturedEffect.nextEffect=l,t.lastCapturedEffect=l))),l=l.next}null===a&&(t.lastUpdate=null),null===s?t.lastCapturedUpdate=null:e.effectTag|=32,null===a&&null===s&&(i=c),t.baseState=i,t.firstUpdate=a,t.firstCapturedUpdate=s,e.expirationTime=u,e.memoizedState=c}function no(e,t,n){null!==t.firstCapturedUpdate&&(null!==t.lastUpdate&&(t.lastUpdate.next=t.firstCapturedUpdate,t.lastUpdate=t.lastCapturedUpdate),t.firstCapturedUpdate=t.lastCapturedUpdate=null),ro(t.firstEffect,n),t.firstEffect=t.lastEffect=null,ro(t.firstCapturedEffect,n),t.firstCapturedEffect=t.lastCapturedEffect=null}function ro(e,t){for(;null!==e;){var n=e.callback;if(null!==n){e.callback=null;var r=t;"function"!=typeof n&&a("191",n),n.call(r)}e=e.nextEffect}}function oo(e,t){return{value:e,source:t,stack:lt(t)}}var io={current:null},ao=null,uo=null,lo=null;function co(e,t){var n=e.type._context;xr(io,n._currentValue),n._currentValue=t}function so(e){var t=io.current;wr(io),e.type._context._currentValue=t}function fo(e){ao=e,lo=uo=null,e.firstContextDependency=null}function po(e,t){return lo!==e&&!1!==t&&0!==t&&("number"==typeof t&&1073741823!==t||(lo=e,t=1073741823),t={context:e,observedBits:t,next:null},null===uo?(null===ao&&a("277"),ao.firstContextDependency=uo=t):uo=uo.next=t),e._currentValue}var ho={},yo={current:ho},mo={current:ho},vo={current:ho};function bo(e){return e===ho&&a("174"),e}function go(e,t){xr(vo,t),xr(mo,e),xr(yo,ho);var n=t.nodeType;switch(n){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:er(null,"");break;default:t=er(t=(n=8===n?t.parentNode:t).namespaceURI||null,n=n.tagName)}wr(yo),xr(yo,t)}function wo(e){wr(yo),wr(mo),wr(vo)}function xo(e){bo(vo.current);var t=bo(yo.current),n=er(t,e.type);t!==n&&(xr(mo,e),xr(yo,n))}function ko(e){mo.current===e&&(wr(yo),wr(mo))}var _o=(new r.Component).refs;function Oo(e,t,n,r){n=null===(n=n(r,t=e.memoizedState))||void 0===n?t:o({},t,n),e.memoizedState=n,null!==(r=e.updateQueue)&&0===e.expirationTime&&(r.baseState=n)}var Po={isMounted:function(e){return!!(e=e._reactInternalFiber)&&2===tn(e)},enqueueSetState:function(e,t,n){e=e._reactInternalFiber;var r=ia(),o=Qr(r=Ri(r,e));o.payload=t,void 0!==n&&null!==n&&(o.callback=n),Gr(e,o),Mi(e,r)},enqueueReplaceState:function(e,t,n){e=e._reactInternalFiber;var r=ia(),o=Qr(r=Ri(r,e));o.tag=1,o.payload=t,void 0!==n&&null!==n&&(o.callback=n),Gr(e,o),Mi(e,r)},enqueueForceUpdate:function(e,t){e=e._reactInternalFiber;var n=ia(),r=Qr(n=Ri(n,e));r.tag=2,void 0!==t&&null!==t&&(r.callback=t),Gr(e,r),Mi(e,n)}};function Eo(e,t,n,r,o,i,a){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,i,a):!(t.prototype&&t.prototype.isPureReactComponent&&en(n,r)&&en(o,i))}function To(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&Po.enqueueReplaceState(t,t.state,null)}function So(e,t,n,r){var o=e.stateNode,i=Tr(t)?Pr:_r.current;o.props=n,o.state=e.memoizedState,o.refs=_o,o.context=Er(e,i),null!==(i=e.updateQueue)&&(to(e,i,n,o,r),o.state=e.memoizedState),"function"==typeof(i=t.getDerivedStateFromProps)&&(Oo(e,t,i,n),o.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof o.getSnapshotBeforeUpdate||"function"!=typeof o.UNSAFE_componentWillMount&&"function"!=typeof o.componentWillMount||(t=o.state,"function"==typeof o.componentWillMount&&o.componentWillMount(),"function"==typeof o.UNSAFE_componentWillMount&&o.UNSAFE_componentWillMount(),t!==o.state&&Po.enqueueReplaceState(o,o.state,null),null!==(i=e.updateQueue)&&(to(e,i,n,o,r),o.state=e.memoizedState)),"function"==typeof o.componentDidMount&&(e.effectTag|=4)}var Co=Array.isArray;function jo(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){var r=void 0;(n=n._owner)&&(2!==n.tag&&3!==n.tag&&a("110"),r=n.stateNode),r||a("147",e);var o=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===o?t.ref:((t=function(e){var t=r.refs;t===_o&&(t=r.refs={}),null===e?delete t[o]:t[o]=e})._stringRef=o,t)}"string"!=typeof e&&a("284"),n._owner||a("254",e)}return e}function Ro(e,t){"textarea"!==e.type&&a("31","[object Object]"===Object.prototype.toString.call(t)?"object with keys {"+Object.keys(t).join(", ")+"}":t,"")}function Mo(e){function t(t,n){if(e){var r=t.lastEffect;null!==r?(r.nextEffect=n,t.lastEffect=n):t.firstEffect=t.lastEffect=n,n.nextEffect=null,n.effectTag=8}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function o(e,t,n){return(e=Fr(e,t,n)).index=0,e.sibling=null,e}function i(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)y?(m=f,f=null):m=f.sibling;var v=d(o,f,u[y],l);if(null===v){null===f&&(f=m);break}e&&f&&null===v.alternate&&t(o,f),a=i(v,a,y),null===s?c=v:s.sibling=v,s=v,f=m}if(y===u.length)return n(o,f),c;if(null===f){for(;ym?(v=y,y=null):v=y.sibling;var g=d(o,y,b.value,c);if(null===g){y||(y=v);break}e&&y&&null===g.alternate&&t(o,y),u=i(g,u,m),null===f?s=g:f.sibling=g,f=g,y=v}if(b.done)return n(o,y),s;if(null===y){for(;!b.done;m++,b=l.next())null!==(b=p(o,b.value,c))&&(u=i(b,u,m),null===f?s=b:f.sibling=b,f=b);return s}for(y=r(o,y);!b.done;m++,b=l.next())null!==(b=h(y,o,m,b.value,c))&&(e&&null!==b.alternate&&y.delete(null===b.key?m:b.key),u=i(b,u,m),null===f?s=b:f.sibling=b,f=b);return e&&y.forEach(function(e){return t(o,e)}),s}return function(e,r,i,l){var c="object"==typeof i&&null!==i&&i.type===Ge&&null===i.key;c&&(i=i.props.children);var s="object"==typeof i&&null!==i;if(s)switch(i.$$typeof){case Qe:e:{for(s=i.key,c=r;null!==c;){if(c.key===s){if(9===c.tag?i.type===Ge:c.type===i.type){n(e,c.sibling),(r=o(c,i.type===Ge?i.props.children:i.props,l)).ref=jo(e,c,i),r.return=e,e=r;break e}n(e,c);break}t(e,c),c=c.sibling}i.type===Ge?((r=Wr(i.props.children,e.mode,l,i.key)).return=e,e=r):((l=zr(i,e.mode,l)).ref=jo(e,r,i),l.return=e,e=l)}return u(e);case Xe:e:{for(c=i.key;null!==r;){if(r.key===c){if(6===r.tag&&r.stateNode.containerInfo===i.containerInfo&&r.stateNode.implementation===i.implementation){n(e,r.sibling),(r=o(r,i.children||[],l)).return=e,e=r;break e}n(e,r);break}t(e,r),r=r.sibling}(r=Br(i,e.mode,l)).return=e,e=r}return u(e)}if("string"==typeof i||"number"==typeof i)return i=""+i,null!==r&&8===r.tag?(n(e,r.sibling),(r=o(r,i,l)).return=e,e=r):(n(e,r),(r=Hr(i,e.mode,l)).return=e,e=r),u(e);if(Co(i))return y(e,r,i,l);if(at(i))return m(e,r,i,l);if(s&&Ro(e,i),void 0===i&&!c)switch(e.tag){case 2:case 3:case 0:a("152",(l=e.type).displayName||l.name||"Component")}return n(e,r)}}var No=Mo(!0),Ao=Mo(!1),Io=null,Uo=null,Lo=!1;function Do(e,t){var n=new Lr(7,null,null,0);n.type="DELETED",n.stateNode=t,n.return=e,n.effectTag=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function Fo(e,t){switch(e.tag){case 7:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 8:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);default:return!1}}function zo(e){if(Lo){var t=Uo;if(t){var n=t;if(!Fo(e,t)){if(!(t=mr(n))||!Fo(e,t))return e.effectTag|=2,Lo=!1,void(Io=e);Do(Io,n)}Io=e,Uo=vr(t)}else e.effectTag|=2,Lo=!1,Io=e}}function Wo(e){for(e=e.return;null!==e&&7!==e.tag&&5!==e.tag;)e=e.return;Io=e}function Ho(e){if(e!==Io)return!1;if(!Lo)return Wo(e),Lo=!0,!1;var t=e.type;if(7!==e.tag||"head"!==t&&"body"!==t&&!yr(t,e.memoizedProps))for(t=Uo;t;)Do(e,t),t=mr(t);return Wo(e),Uo=Io?mr(e.stateNode):null,!0}function Bo(){Uo=Io=null,Lo=!1}var Vo=$e.ReactCurrentOwner;function qo(e,t,n,r){t.child=null===e?Ao(t,null,n,r):No(t,e.child,n,r)}function $o(e,t,n,r,o){n=n.render;var i=t.ref;return Or.current||t.memoizedProps!==r||i!==(null!==e?e.ref:null)?(qo(e,t,n=n(r,i),o),t.memoizedProps=r,t.child):Zo(e,t,o)}function Yo(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.effectTag|=128)}function Ko(e,t,n,r,o){var i=Tr(n)?Pr:_r.current;return i=Er(t,i),fo(t),n=n(r,i),t.effectTag|=1,qo(e,t,n,o),t.memoizedProps=r,t.child}function Qo(e,t,n,r,o){if(Tr(n)){var i=!0;Mr(t)}else i=!1;if(fo(t),null===e)if(null===t.stateNode){var a=Tr(n)?Pr:_r.current,u=n.contextTypes,l=null!==u&&void 0!==u,c=new n(r,u=l?Er(t,a):kr);t.memoizedState=null!==c.state&&void 0!==c.state?c.state:null,c.updater=Po,t.stateNode=c,c._reactInternalFiber=t,l&&((l=t.stateNode).__reactInternalMemoizedUnmaskedChildContext=a,l.__reactInternalMemoizedMaskedChildContext=u),So(t,n,r,o),r=!0}else{a=t.stateNode,u=t.memoizedProps,a.props=u;var s=a.context;l=Er(t,l=Tr(n)?Pr:_r.current);var f=n.getDerivedStateFromProps;(c="function"==typeof f||"function"==typeof a.getSnapshotBeforeUpdate)||"function"!=typeof a.UNSAFE_componentWillReceiveProps&&"function"!=typeof a.componentWillReceiveProps||(u!==r||s!==l)&&To(t,a,r,l),$r=!1;var p=t.memoizedState;s=a.state=p;var d=t.updateQueue;null!==d&&(to(t,d,r,a,o),s=t.memoizedState),u!==r||p!==s||Or.current||$r?("function"==typeof f&&(Oo(t,n,f,r),s=t.memoizedState),(u=$r||Eo(t,n,u,r,p,s,l))?(c||"function"!=typeof a.UNSAFE_componentWillMount&&"function"!=typeof a.componentWillMount||("function"==typeof a.componentWillMount&&a.componentWillMount(),"function"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount()),"function"==typeof a.componentDidMount&&(t.effectTag|=4)):("function"==typeof a.componentDidMount&&(t.effectTag|=4),t.memoizedProps=r,t.memoizedState=s),a.props=r,a.state=s,a.context=l,r=u):("function"==typeof a.componentDidMount&&(t.effectTag|=4),r=!1)}else a=t.stateNode,u=t.memoizedProps,a.props=u,s=a.context,l=Er(t,l=Tr(n)?Pr:_r.current),(c="function"==typeof(f=n.getDerivedStateFromProps)||"function"==typeof a.getSnapshotBeforeUpdate)||"function"!=typeof a.UNSAFE_componentWillReceiveProps&&"function"!=typeof a.componentWillReceiveProps||(u!==r||s!==l)&&To(t,a,r,l),$r=!1,s=t.memoizedState,p=a.state=s,null!==(d=t.updateQueue)&&(to(t,d,r,a,o),p=t.memoizedState),u!==r||s!==p||Or.current||$r?("function"==typeof f&&(Oo(t,n,f,r),p=t.memoizedState),(f=$r||Eo(t,n,u,r,s,p,l))?(c||"function"!=typeof a.UNSAFE_componentWillUpdate&&"function"!=typeof a.componentWillUpdate||("function"==typeof a.componentWillUpdate&&a.componentWillUpdate(r,p,l),"function"==typeof a.UNSAFE_componentWillUpdate&&a.UNSAFE_componentWillUpdate(r,p,l)),"function"==typeof a.componentDidUpdate&&(t.effectTag|=4),"function"==typeof a.getSnapshotBeforeUpdate&&(t.effectTag|=256)):("function"!=typeof a.componentDidUpdate||u===e.memoizedProps&&s===e.memoizedState||(t.effectTag|=4),"function"!=typeof a.getSnapshotBeforeUpdate||u===e.memoizedProps&&s===e.memoizedState||(t.effectTag|=256),t.memoizedProps=r,t.memoizedState=p),a.props=r,a.state=p,a.context=l,r=f):("function"!=typeof a.componentDidUpdate||u===e.memoizedProps&&s===e.memoizedState||(t.effectTag|=4),"function"!=typeof a.getSnapshotBeforeUpdate||u===e.memoizedProps&&s===e.memoizedState||(t.effectTag|=256),r=!1);return Xo(e,t,n,r,i,o)}function Xo(e,t,n,r,o,i){Yo(e,t);var a=0!=(64&t.effectTag);if(!r&&!a)return o&&Nr(t,n,!1),Zo(e,t,i);r=t.stateNode,Vo.current=t;var u=a?null:r.render();return t.effectTag|=1,null!==e&&a&&(qo(e,t,null,i),t.child=null),qo(e,t,u,i),t.memoizedState=r.state,t.memoizedProps=r.props,o&&Nr(t,n,!0),t.child}function Go(e){var t=e.stateNode;t.pendingContext?jr(0,t.pendingContext,t.pendingContext!==t.context):t.context&&jr(0,t.context,!1),go(e,t.containerInfo)}function Jo(e,t){if(e&&e.defaultProps)for(var n in t=o({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}function Zo(e,t,n){null!==e&&(t.firstContextDependency=e.firstContextDependency);var r=t.childExpirationTime;if(0===r||r>n)return null;if(null!==e&&t.child!==e.child&&a("153"),null!==t.child){for(n=Fr(e=t.child,e.pendingProps,e.expirationTime),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Fr(e,e.pendingProps,e.expirationTime)).return=t;n.sibling=null}return t.child}function ei(e){e.effectTag|=4}var ti=void 0,ni=void 0,ri=void 0;function oi(e,t){var n=t.source,r=t.stack;null===r&&null!==n&&(r=lt(n)),null!==n&&ut(n.type),t=t.value,null!==e&&2===e.tag&&ut(e.type);try{console.error(t)}catch(e){setTimeout(function(){throw e})}}function ii(e){var t=e.ref;if(null!==t)if("function"==typeof t)try{t(null)}catch(t){ji(e,t)}else t.current=null}function ai(e){switch("function"==typeof Ir&&Ir(e),e.tag){case 2:case 3:ii(e);var t=e.stateNode;if("function"==typeof t.componentWillUnmount)try{t.props=e.memoizedProps,t.state=e.memoizedState,t.componentWillUnmount()}catch(t){ji(e,t)}break;case 7:ii(e);break;case 6:ci(e)}}function ui(e){return 7===e.tag||5===e.tag||6===e.tag}function li(e){e:{for(var t=e.return;null!==t;){if(ui(t)){var n=t;break e}t=t.return}a("160"),n=void 0}var r=t=void 0;switch(n.tag){case 7:t=n.stateNode,r=!1;break;case 5:case 6:t=n.stateNode.containerInfo,r=!0;break;default:a("161")}16&n.effectTag&&(rr(t,""),n.effectTag&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||ui(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;7!==n.tag&&8!==n.tag;){if(2&n.effectTag)continue t;if(null===n.child||6===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.effectTag)){n=n.stateNode;break e}}for(var o=e;;){if(7===o.tag||8===o.tag)if(n)if(r){var i=t,u=o.stateNode,l=n;8===i.nodeType?i.parentNode.insertBefore(u,l):i.insertBefore(u,l)}else t.insertBefore(o.stateNode,n);else r?(i=t,u=o.stateNode,8===i.nodeType?(l=i.parentNode).insertBefore(u,i):(l=i).appendChild(u),null===l.onclick&&(l.onclick=fr)):t.appendChild(o.stateNode);else if(6!==o.tag&&null!==o.child){o.child.return=o,o=o.child;continue}if(o===e)break;for(;null===o.sibling;){if(null===o.return||o.return===e)return;o=o.return}o.sibling.return=o.return,o=o.sibling}}function ci(e){for(var t=e,n=!1,r=void 0,o=void 0;;){if(!n){n=t.return;e:for(;;){switch(null===n&&a("160"),n.tag){case 7:r=n.stateNode,o=!1;break e;case 5:case 6:r=n.stateNode.containerInfo,o=!0;break e}n=n.return}n=!0}if(7===t.tag||8===t.tag){e:for(var i=t,u=i;;)if(ai(u),null!==u.child&&6!==u.tag)u.child.return=u,u=u.child;else{if(u===i)break;for(;null===u.sibling;){if(null===u.return||u.return===i)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}o?(i=r,u=t.stateNode,8===i.nodeType?i.parentNode.removeChild(u):i.removeChild(u)):r.removeChild(t.stateNode)}else if(6===t.tag?(r=t.stateNode.containerInfo,o=!0):ai(t),null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return;6===(t=t.return).tag&&(n=!1)}t.sibling.return=t.return,t=t.sibling}}function si(e,t){switch(t.tag){case 2:case 3:break;case 7:var n=t.stateNode;if(null!=n){var r=t.memoizedProps,o=null!==e?e.memoizedProps:r;e=t.type;var i=t.updateQueue;if(t.updateQueue=null,null!==i){for(n[U]=r,"input"===e&&"radio"===r.type&&null!=r.name&&xt(n,r),cr(e,o),t=cr(e,r),o=0;o<\/script>",f=i.removeChild(i.firstChild)):"string"==typeof d.is?f=f.createElement(i,{is:d.is}):(f=f.createElement(i),"select"===i&&d.multiple&&(f.multiple=!0)):f=f.createElementNS(s,i),(i=f)[I]=p,i[U]=u;e:for(p=i,d=t,f=d.child;null!==f;){if(7===f.tag||8===f.tag)p.appendChild(f.stateNode);else if(6!==f.tag&&null!==f.child){f.child.return=f,f=f.child;continue}if(f===d)break;for(;null===f.sibling;){if(null===f.return||f.return===d)break e;f=f.return}f.sibling.return=f.return,f=f.sibling}d=i;var h=l,y=cr(f=c,p=u);switch(f){case"iframe":case"object":Pn("load",d),l=p;break;case"video":case"audio":for(l=0;ln)){switch(t.tag){case 5:Go(t),Bo();break;case 7:xo(t);break;case 2:Tr(t.type)&&Mr(t);break;case 3:Tr(t.type._reactResult)&&Mr(t);break;case 6:go(t,t.stateNode.containerInfo);break;case 12:co(t,t.memoizedProps.value)}return Zo(e,t,n)}switch(t.expirationTime=0,t.tag){case 4:return function(e,t,n,r){null!==e&&a("155");var o=t.pendingProps;if("object"==typeof n&&null!==n&&"function"==typeof n.then){var i=n=function(e){switch(e._reactStatus){case 1:return e._reactResult;case 2:throw e._reactResult;case 0:throw e;default:throw e._reactStatus=0,e.then(function(t){if(0===e._reactStatus){if(e._reactStatus=1,"object"==typeof t&&null!==t){var n=t.default;t=void 0!==n&&null!==n?n:t}e._reactResult=t}},function(t){0===e._reactStatus&&(e._reactStatus=2,e._reactResult=t)}),e}}(n);i="function"==typeof i?Dr(i)?3:1:void 0!==i&&null!==i&&i.$$typeof?14:4,i=t.tag=i;var u=Jo(n,o);switch(i){case 1:return Ko(e,t,n,u,r);case 3:return Qo(e,t,n,u,r);case 14:return $o(e,t,n,u,r);default:a("283",n)}}if(i=Er(t,_r.current),fo(t),i=n(o,i),t.effectTag|=1,"object"==typeof i&&null!==i&&"function"==typeof i.render&&void 0===i.$$typeof){t.tag=2,Tr(n)?(u=!0,Mr(t)):u=!1,t.memoizedState=null!==i.state&&void 0!==i.state?i.state:null;var l=n.getDerivedStateFromProps;return"function"==typeof l&&Oo(t,n,l,o),i.updater=Po,t.stateNode=i,i._reactInternalFiber=t,So(t,n,o,r),Xo(e,t,n,!0,u,r)}return t.tag=0,qo(e,t,i,r),t.memoizedProps=o,t.child}(e,t,t.type,n);case 0:return Ko(e,t,t.type,t.pendingProps,n);case 1:var o=t.type._reactResult;return e=Ko(e,t,o,Jo(o,r=t.pendingProps),n),t.memoizedProps=r,e;case 2:return Qo(e,t,t.type,t.pendingProps,n);case 3:return e=Qo(e,t,o=t.type._reactResult,Jo(o,r=t.pendingProps),n),t.memoizedProps=r,e;case 5:return Go(t),null===(r=t.updateQueue)&&a("282"),o=null!==(o=t.memoizedState)?o.element:null,to(t,r,t.pendingProps,null,n),(r=t.memoizedState.element)===o?(Bo(),t=Zo(e,t,n)):(o=t.stateNode,(o=(null===e||null===e.child)&&o.hydrate)&&(Uo=vr(t.stateNode.containerInfo),Io=t,o=Lo=!0),o?(t.effectTag|=2,t.child=Ao(t,null,r,n)):(qo(e,t,r,n),Bo()),t=t.child),t;case 7:xo(t),null===e&&zo(t),r=t.type,o=t.pendingProps;var i=null!==e?e.memoizedProps:null,u=o.children;return yr(r,o)?u=null:null!==i&&yr(r,i)&&(t.effectTag|=16),Yo(e,t),1073741823!==n&&1&t.mode&&o.hidden?(t.expirationTime=1073741823,t.memoizedProps=o,t=null):(qo(e,t,u,n),t.memoizedProps=o,t=t.child),t;case 8:return null===e&&zo(t),t.memoizedProps=t.pendingProps,null;case 16:return null;case 6:return go(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=No(t,null,r,n):qo(e,t,r,n),t.memoizedProps=r,t.child;case 13:return $o(e,t,t.type,t.pendingProps,n);case 14:return e=$o(e,t,o=t.type._reactResult,Jo(o,r=t.pendingProps),n),t.memoizedProps=r,e;case 9:return qo(e,t,r=t.pendingProps,n),t.memoizedProps=r,t.child;case 10:return qo(e,t,r=t.pendingProps.children,n),t.memoizedProps=r,t.child;case 15:return qo(e,t,(r=t.pendingProps).children,n),t.memoizedProps=r,t.child;case 12:e:{if(r=t.type._context,o=t.pendingProps,u=t.memoizedProps,i=o.value,t.memoizedProps=o,co(t,i),null!==u){var l=u.value;if(0==(i=l===i&&(0!==l||1/l==1/i)||l!=l&&i!=i?0:0|("function"==typeof r._calculateChangedBits?r._calculateChangedBits(l,i):1073741823))){if(u.children===o.children&&!Or.current){t=Zo(e,t,n);break e}}else for(null!==(u=t.child)&&(u.return=t);null!==u;){if(null!==(l=u.firstContextDependency))do{if(l.context===r&&0!=(l.observedBits&i)){if(2===u.tag||3===u.tag){var c=Qr(n);c.tag=2,Gr(u,c)}(0===u.expirationTime||u.expirationTime>n)&&(u.expirationTime=n),null!==(c=u.alternate)&&(0===c.expirationTime||c.expirationTime>n)&&(c.expirationTime=n);for(var s=u.return;null!==s;){if(c=s.alternate,0===s.childExpirationTime||s.childExpirationTime>n)s.childExpirationTime=n,null!==c&&(0===c.childExpirationTime||c.childExpirationTime>n)&&(c.childExpirationTime=n);else{if(null===c||!(0===c.childExpirationTime||c.childExpirationTime>n))break;c.childExpirationTime=n}s=s.return}}c=u.child,l=l.next}while(null!==l);else c=12===u.tag&&u.type===t.type?null:u.child;if(null!==c)c.return=u;else for(c=u;null!==c;){if(c===t){c=null;break}if(null!==(u=c.sibling)){u.return=c.return,c=u;break}c=c.return}u=c}}qo(e,t,o.children,n),t=t.child}return t;case 11:return i=t.type,o=(r=t.pendingProps).children,fo(t),o=o(i=po(i,r.unstable_observedBits)),t.effectTag|=1,qo(e,t,o,n),t.memoizedProps=r,t.child;default:a("156")}}(e.alternate,e,xi);return null===t&&(t=Ti(e)),yi.current=null,t}function Ci(e,t,n){bi&&a("243"),bi=!0,yi.currentDispatcher=hi;var r=e.nextExpirationTimeToWorkOn;r===xi&&e===wi&&null!==gi||(Ei(),xi=r,gi=Fr((wi=e).current,null,xi),e.pendingCommitExpirationTime=0);for(var o=!1;;){try{if(t)for(;null!==gi&&!fa();)gi=Si(gi);else for(;null!==gi;)gi=Si(gi)}catch(e){if(null===gi)o=!0,pa(e);else{null===gi&&a("271");var i=gi,u=i.return;if(null!==u){e:{var l=u,c=i,s=e;u=xi,c.effectTag|=512,c.firstEffect=c.lastEffect=null,ki=!0,s=oo(s,c);do{switch(l.tag){case 5:l.effectTag|=1024,l.expirationTime=u,Jr(l,u=fi(l,s,u));break e;case 2:case 3:c=s;var f=l.stateNode;if(0==(64&l.effectTag)&&null!==f&&"function"==typeof f.componentDidCatch&&(null===Pi||!Pi.has(f))){l.effectTag|=1024,l.expirationTime=u,Jr(l,u=pi(l,c,u));break e}}l=l.return}while(null!==l)}gi=Ti(i);continue}o=!0,pa(e)}}break}if(bi=!1,lo=uo=ao=yi.currentDispatcher=null,o)wi=null,e.finishedWork=null;else if(null!==gi)e.finishedWork=null;else{if(null===(t=e.current.alternate)&&a("281"),wi=null,ki){if(o=e.latestPendingTime,i=e.latestSuspendedTime,u=e.latestPingedTime,0!==o&&o>r||0!==i&&i>r||0!==u&&u>r)return e.didError=!1,0!==(n=e.latestPingedTime)&&n<=r&&(e.latestPingedTime=0),n=e.earliestPendingTime,t=e.latestPendingTime,n===r?e.earliestPendingTime=t===r?e.latestPendingTime=0:t:t===r&&(e.latestPendingTime=n),n=e.earliestSuspendedTime,t=e.latestSuspendedTime,0===n?e.earliestSuspendedTime=e.latestSuspendedTime=r:n>r?e.earliestSuspendedTime=r:tWi)&&(Wi=e),e}function Mi(e,t){e:{(0===e.expirationTime||e.expirationTime>t)&&(e.expirationTime=t);var n=e.alternate;null!==n&&(0===n.expirationTime||n.expirationTime>t)&&(n.expirationTime=t);var r=e.return;if(null===r&&5===e.tag)e=e.stateNode;else{for(;null!==r;){if(n=r.alternate,(0===r.childExpirationTime||r.childExpirationTime>t)&&(r.childExpirationTime=t),null!==n&&(0===n.childExpirationTime||n.childExpirationTime>t)&&(n.childExpirationTime=t),null===r.return&&5===r.tag){e=r.stateNode;break e}r=r.return}e=null}}null!==e&&(!bi&&0!==xi&&tZi&&(ea=0,a("185")))}function Ni(e,t,n,r,o){var i=vi;vi=1;try{return e(t,n,r,o)}finally{vi=i}}var Ai=null,Ii=null,Ui=0,Li=void 0,Di=!1,Fi=null,zi=0,Wi=0,Hi=!1,Bi=!1,Vi=null,qi=null,$i=!1,Yi=!1,Ki=!1,Qi=null,Xi=i.unstable_now(),Gi=2+(Xi/10|0),Ji=Gi,Zi=50,ea=0,ta=null,na=1;function ra(){Gi=2+((i.unstable_now()-Xi)/10|0)}function oa(e,t){if(0!==Ui){if(t>Ui)return;null!==Li&&i.unstable_cancelScheduledWork(Li)}Ui=t,e=i.unstable_now()-Xi,Li=i.unstable_scheduleWork(ua,{timeout:10*(t-2)-e})}function ia(){return Di?Ji:(aa(),0!==zi&&1073741823!==zi||(ra(),Ji=Gi),Ji)}function aa(){var e=0,t=null;if(null!==Ii)for(var n=Ii,r=Ai;null!==r;){var o=r.expirationTime;if(0===o){if((null===n||null===Ii)&&a("244"),r===r.nextScheduledRoot){Ai=Ii=r.nextScheduledRoot=null;break}if(r===Ai)Ai=o=r.nextScheduledRoot,Ii.nextScheduledRoot=o,r.nextScheduledRoot=null;else{if(r===Ii){(Ii=n).nextScheduledRoot=Ai,r.nextScheduledRoot=null;break}n.nextScheduledRoot=r.nextScheduledRoot,r.nextScheduledRoot=null}r=n.nextScheduledRoot}else{if((0===e||o=n&&(t.nextExpirationTimeToWorkOn=Gi),t=t.nextScheduledRoot}while(t!==Ai)}la(0,e)}function la(e,t){if(qi=t,aa(),null!==qi)for(ra(),Ji=Gi;null!==Fi&&0!==zi&&(0===e||e>=zi)&&(!Hi||Gi>=zi);)ca(Fi,zi,Gi>=zi),aa(),ra(),Ji=Gi;else for(;null!==Fi&&0!==zi&&(0===e||e>=zi);)ca(Fi,zi,!0),aa();if(null!==qi&&(Ui=0,Li=null),0!==zi&&oa(Fi,zi),qi=null,Hi=!1,ea=0,ta=null,null!==Qi)for(e=Qi,Qi=null,t=0;te.latestSuspendedTime?(e.earliestSuspendedTime=0,e.latestSuspendedTime=0,e.latestPingedTime=0,Vr(e,r)):rg&&(w=g,g=P,P=w),w=In(_,P),x=In(_,g),w&&x&&(1!==O.rangeCount||O.anchorNode!==w.node||O.anchorOffset!==w.offset||O.focusNode!==x.node||O.focusOffset!==x.offset)&&((b=b.createRange()).setStart(w.node,w.offset),O.removeAllRanges(),P>g?(O.addRange(b),O.extend(x.node,x.offset)):(b.setEnd(x.node,x.offset),O.addRange(b))))),O=[];for(P=_;P=P.parentNode;)1===P.nodeType&&O.push({element:P,left:P.scrollLeft,top:P.scrollTop});for("function"==typeof _.focus&&_.focus(),_=0;_na)&&(Hi=!0)}function pa(e){null===Fi&&a("246"),Fi.expirationTime=0,Bi||(Bi=!0,Vi=e)}function da(e,t){var n=$i;$i=!0;try{return e(t)}finally{($i=n)||Di||la(1,null)}}function ha(e,t){if($i&&!Yi){Yi=!0;try{return e(t)}finally{Yi=!1}}return e(t)}function ya(e,t,n){if(Ki)return e(t,n);$i||Di||0===Wi||(la(Wi,null),Wi=0);var r=Ki,o=$i;$i=Ki=!0;try{return e(t,n)}finally{Ki=r,($i=o)||Di||la(1,null)}}function ma(e,t,n,r,o){var i=t.current;return n=function(e){if(!e)return kr;e=e._reactInternalFiber;e:{(2!==tn(e)||2!==e.tag&&3!==e.tag)&&a("170");var t=e;do{switch(t.tag){case 5:t=t.stateNode.context;break e;case 2:if(Tr(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}break;case 3:if(Tr(t.type._reactResult)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);a("171"),t=void 0}if(2===e.tag){var n=e.type;if(Tr(n))return Rr(e,n,t)}else if(3===e.tag&&Tr(n=e.type._reactResult))return Rr(e,n,t);return t}(n),null===t.context?t.context=n:t.pendingContext=n,t=o,(o=Qr(r)).payload={element:e},null!==(t=void 0===t?null:t)&&(o.callback=t),Gr(i,o),Mi(i,r),r}function va(e,t,n,r){var o=t.current;return ma(e,t,n,o=Ri(ia(),o),r)}function ba(e){if(!(e=e.current).child)return null;switch(e.child.tag){case 7:default:return e.child.stateNode}}function ga(e){var t=2+25*(1+((ia()-2+500)/25|0));t<=mi&&(t=mi+1),this._expirationTime=mi=t,this._root=e,this._callbacks=this._next=null,this._hasChildren=this._didComplete=!1,this._children=null,this._defer=!0}function wa(){this._callbacks=null,this._didCommit=!1,this._onCommit=this._onCommit.bind(this)}function xa(e,t,n){e={current:t=new Lr(5,null,null,t?3:0),containerInfo:e,pendingChildren:null,earliestPendingTime:0,latestPendingTime:0,earliestSuspendedTime:0,latestSuspendedTime:0,latestPingedTime:0,didError:!1,pendingCommitExpirationTime:0,finishedWork:null,timeoutHandle:-1,context:null,pendingContext:null,hydrate:n,nextExpirationTimeToWorkOn:0,expirationTime:0,firstBatch:null,nextScheduledRoot:null},this._internalRoot=t.stateNode=e}function ka(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function _a(e,t,n,r,o){ka(n)||a("200");var i=n._reactRootContainer;if(i){if("function"==typeof o){var u=o;o=function(){var e=ba(i._internalRoot);u.call(e)}}null!=e?i.legacy_renderSubtreeIntoContainer(e,t,o):i.render(t,o)}else{if(i=n._reactRootContainer=function(e,t){if(t||(t=!(!(t=e?9===e.nodeType?e.documentElement:e.firstChild:null)||1!==t.nodeType||!t.hasAttribute("data-reactroot"))),!t)for(var n;n=e.lastChild;)e.removeChild(n);return new xa(e,!1,t)}(n,r),"function"==typeof o){var l=o;o=function(){var e=ba(i._internalRoot);l.call(e)}}ha(function(){null!=e?i.legacy_renderSubtreeIntoContainer(e,t,o):i.render(t,o)})}return ba(i._internalRoot)}function Oa(e,t){var n=2n)){e=-1;for(var r=[],o=f;null!==o;){var i=o.timeoutTime;-1!==i&&i<=n?r.push(o):-1!==i&&(-1===e||it&&(t=8),x=t3&&void 0!==arguments[3]?arguments[3]:{},m=Boolean(e),v=e||f,b=void 0;b="function"==typeof t?t:t?(0,u.default)(t):p;var g=n||d,w=s.pure,x=void 0===w||w,k=s.withRef,_=void 0!==k&&k,O=x&&g!==d,P=y++;return function(e){var t="Connect("+function(e){return e.displayName||e.name||"Component"}(e)+")",n=function(n){function i(e,r){!function(e,t){if(!(e instanceof i))throw new TypeError("Cannot call a class as a function")}(this);var o=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,n.call(this,e,r));o.version=P,o.store=e.store||r.store,(0,c.default)(o.store,'Could not find "store" in either the context or props of "'+t+'". Either wrap the root component in a , or explicitly pass "store" as a prop to "'+t+'".');var a=o.store.getState();return o.state={storeState:a},o.clearCache(),o}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(i,n),i.prototype.shouldComponentUpdate=function(){return!x||this.haveOwnPropsChanged||this.hasStoreStateChanged},i.prototype.computeStateProps=function(e,t){if(!this.finalMapStateToProps)return this.configureFinalMapState(e,t);var n=e.getState();return this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(n,t):this.finalMapStateToProps(n)},i.prototype.configureFinalMapState=function(e,t){var n=v(e.getState(),t),r="function"==typeof n;return this.finalMapStateToProps=r?n:v,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,r?this.computeStateProps(e,t):n},i.prototype.computeDispatchProps=function(e,t){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(e,t);var n=e.dispatch;return this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(n,t):this.finalMapDispatchToProps(n)},i.prototype.configureFinalMapDispatch=function(e,t){var n=b(e.dispatch,t),r="function"==typeof n;return this.finalMapDispatchToProps=r?n:b,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,r?this.computeDispatchProps(e,t):n},i.prototype.updateStatePropsIfNeeded=function(){var e=this.computeStateProps(this.store,this.props);return!(this.stateProps&&(0,a.default)(e,this.stateProps)||(this.stateProps=e,0))},i.prototype.updateDispatchPropsIfNeeded=function(){var e=this.computeDispatchProps(this.store,this.props);return!(this.dispatchProps&&(0,a.default)(e,this.dispatchProps)||(this.dispatchProps=e,0))},i.prototype.updateMergedPropsIfNeeded=function(){var e=function(e,t,n){return g(e,t,n)}(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&O&&(0,a.default)(e,this.mergedProps)||(this.mergedProps=e,0))},i.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},i.prototype.trySubscribe=function(){m&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},i.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},i.prototype.componentDidMount=function(){this.trySubscribe()},i.prototype.componentWillReceiveProps=function(e){x&&(0,a.default)(e,this.props)||(this.haveOwnPropsChanged=!0)},i.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},i.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},i.prototype.handleChange=function(){if(this.unsubscribe){var e=this.store.getState(),t=this.state.storeState;if(!x||t!==e){if(x&&!this.doStatePropsDependOnOwnProps){var n=function(e,t){try{return e.apply(t)}catch(e){return h.value=e,h}}(this.updateStatePropsIfNeeded,this);if(!n)return;n===h&&(this.statePropsPrecalculationError=h.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:e})}}},i.prototype.getWrappedInstance=function(){return(0,c.default)(_,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},i.prototype.render=function(){var t=this.haveOwnPropsChanged,n=this.hasStoreStateChanged,i=this.haveStatePropsBeenPrecalculated,a=this.statePropsPrecalculationError,u=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,a)throw a;var l=!0,c=!0;x&&u&&(l=n||t&&this.doStatePropsDependOnOwnProps,c=t&&this.doDispatchPropsDependOnOwnProps);var s=!1,f=!1;return i?s=!0:l&&(s=this.updateStatePropsIfNeeded()),c&&(f=this.updateDispatchPropsIfNeeded()),(s||f||t)&&this.updateMergedPropsIfNeeded()||!u?(this.renderedElement=_?(0,o.createElement)(e,r({},this.mergedProps,{ref:"wrappedInstance"})):(0,o.createElement)(e,this.mergedProps),this.renderedElement):u},i}(o.Component);return n.displayName=t,n.WrappedComponent=e,n.contextTypes={store:i.default},n.propTypes={store:i.default},(0,l.default)(n,e)}};var o=n(1),i=s(n(15)),a=s(n(37)),u=s(n(38)),l=(s(n(16)),s(n(40)),s(n(9))),c=s(n(2));function s(e){return e&&e.__esModule?e:{default:e}}var f=function(e){return{}},p=function(e){return{dispatch:e}},d=function(e,t,n){return r({},n,e,t)},h={value:null},y=0},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e,t){if(e===t)return!0;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(var o=Object.prototype.hasOwnProperty,i=0;ir.createElement(i.ConnectedRouter,{history:e},a.default))}).call(this,n(18)(e))},function(e,t){e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(1),o=n(63),i=n(52),a=n(53),u=r.createElement(o.Switch,null,r.createElement(o.Route,{exact:!0,path:"/",component:a.default}),r.createElement(o.Route,{component:i.default}));t.default=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(1);t.default=(()=>r.createElement("span",null,"404 Not Found"))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(1);t.default=class extends r.Component{componentDidCatch(e){console.log(e.message)}render(){return r.createElement("span",null,"Hello world")}}},function(e,t,n){"use strict";let r;Object.defineProperty(t,"__esModule",{value:!0}),r=n(55),t.default=r},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(56),o=n(57),i=n(20),a=n(61),u=n(62);t.history=o.default();const l=[i.routerMiddleware(t.history),a.default];t.default=((e={})=>r.init({models:u.default,redux:{middlewares:l,reducers:Object.assign({routing:i.routerReducer},e)}}))},function(e,t,n){(function(e,n){!function(t){"use strict";var r="undefined"!=typeof window?window:void 0!==e?e:"undefined"!=typeof self?self:{};function o(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function i(e,t){return e(t={exports:{}},t.exports),t.exports}var a=i(function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.modelHooks=[],t.pluginMiddlewares=[],t.preStore=function(e){e.forEach(function(e){e.middleware&&t.pluginMiddlewares.push(e.middleware),e.onModel&&t.modelHooks.push(e.onModel)})},t.postStore=function(e,t){e.forEach(function(e){e.onStoreCreated&&e.onStoreCreated(t)})}});o(a);var u="object"==typeof e&&e&&e.Object===Object&&e,l="object"==typeof self&&self&&self.Object===Object&&self,c=(u||l||Function("return this")()).Symbol,s=Object.prototype,f=s.hasOwnProperty,p=s.toString,d=c?c.toStringTag:void 0,h=Object.prototype.toString,y="[object Null]",m="[object Undefined]",v=c?c.toStringTag:void 0;function b(e){return null==e?void 0===e?m:y:v&&v in Object(e)?function(e){var t=f.call(e,d),n=e[d];try{e[d]=void 0;var r=!0}catch(e){}var o=p.call(e);return r&&(t?e[d]=n:delete e[d]),o}(e):function(e){return h.call(e)}(e)}var g,w,x=(g=Object.getPrototypeOf,w=Object,function(e){return g(w(e))}),k="[object Object]",_=Function.prototype.toString,O=Object.prototype.hasOwnProperty,P=_.call(Object),E=function(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}("undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==e?e:n),T="@@redux/INIT";function S(e,t){var n=t&&t.type;return"Given action "+(n&&'"'+n+'"'||"an action")+', reducer "'+e+'" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.'}function C(e,t){return function(){return t(e.apply(void 0,arguments))}}function j(){for(var e=arguments.length,t=Array(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1];if(a)throw a;for(var r=!1,o={},u=0;u0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&void 0!==arguments[0]?arguments[0]:{};(0,a.default)(s.canUseDOM,"Browser history needs a DOM");var t=window.history,n=(0,s.supportsHistory)(),f=!(0,s.supportsPopStateOnHashChange)(),d=e.forceRefresh,h=void 0!==d&&d,y=e.getUserConfirmation,m=void 0===y?s.getConfirmation:y,v=e.keyLength,b=void 0===v?6:v,g=e.basename?(0,l.stripTrailingSlash)((0,l.addLeadingSlash)(e.basename)):"",w=function(e){var t=e||{},n=t.key,r=t.state,o=window.location,a=o.pathname+o.search+o.hash;return(0,i.default)(!g||(0,l.hasBasename)(a,g),'You are attempting to use a basename on a page whose URL path does not begin with the basename. Expected path "'+a+'" to begin with "'+g+'".'),g&&(a=(0,l.stripBasename)(a,g)),(0,u.createLocation)(a,r,n)},x=function(){return Math.random().toString(36).substr(2,b)},k=(0,c.default)(),_=function(e){o(U,e),U.length=t.length,k.notifyListeners(U.location,U.action)},O=function(e){(0,s.isExtraneousPopstateEvent)(e)||T(w(e.state))},P=function(){T(w(p()))},E=!1,T=function(e){E?(E=!1,_()):k.confirmTransitionTo(e,"POP",m,function(t){t?_({action:"POP",location:e}):S(e)})},S=function(e){var t=U.location,n=j.indexOf(t.key);-1===n&&(n=0);var r=j.indexOf(e.key);-1===r&&(r=0);var o=n-r;o&&(E=!0,M(o))},C=w(p()),j=[C.key],R=function(e){return g+(0,l.createPath)(e)},M=function(e){t.go(e)},N=0,A=function(e){1===(N+=e)?((0,s.addEventListener)(window,"popstate",O),f&&(0,s.addEventListener)(window,"hashchange",P)):0===N&&((0,s.removeEventListener)(window,"popstate",O),f&&(0,s.removeEventListener)(window,"hashchange",P))},I=!1,U={length:t.length,action:"POP",location:C,createHref:R,push:function(e,o){(0,i.default)(!("object"===(void 0===e?"undefined":r(e))&&void 0!==e.state&&void 0!==o),"You should avoid providing a 2nd state argument to push when the 1st argument is a location-like object that already has state; it is ignored");var a=(0,u.createLocation)(e,o,x(),U.location);k.confirmTransitionTo(a,"PUSH",m,function(e){if(e){var r=R(a),o=a.key,u=a.state;if(n)if(t.pushState({key:o,state:u},null,r),h)window.location.href=r;else{var l=j.indexOf(U.location.key),c=j.slice(0,-1===l?0:l+1);c.push(a.key),j=c,_({action:"PUSH",location:a})}else(0,i.default)(void 0===u,"Browser history cannot push state in browsers that do not support HTML5 history"),window.location.href=r}})},replace:function(e,o){(0,i.default)(!("object"===(void 0===e?"undefined":r(e))&&void 0!==e.state&&void 0!==o),"You should avoid providing a 2nd state argument to replace when the 1st argument is a location-like object that already has state; it is ignored");var a=(0,u.createLocation)(e,o,x(),U.location);k.confirmTransitionTo(a,"REPLACE",m,function(e){if(e){var r=R(a),o=a.key,u=a.state;if(n)if(t.replaceState({key:o,state:u},null,r),h)window.location.replace(r);else{var l=j.indexOf(U.location.key);-1!==l&&(j[l]=a.key),_({action:"REPLACE",location:a})}else(0,i.default)(void 0===u,"Browser history cannot replace state in browsers that do not support HTML5 history"),window.location.replace(r)}})},go:M,goBack:function(){return M(-1)},goForward:function(){return M(1)},block:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=k.setPrompt(e);return I||(A(1),I=!0),function(){return I&&(I=!1,A(-1)),t()}},listen:function(e){var t=k.appendListener(e);return A(1),function(){A(-1),t()}}};return U}},function(e,t,n){"use strict";t.__esModule=!0,t.locationsAreEqual=t.createLocation=void 0;var r=Object.assign||function(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{};p()(P,"Browser history needs a DOM");var t=window.history,n=function(){var e=window.navigator.userAgent;return(-1===e.indexOf("Android 2.")&&-1===e.indexOf("Android 4.0")||-1===e.indexOf("Mobile Safari")||-1!==e.indexOf("Chrome")||-1!==e.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history}(),r=!(-1===window.navigator.userAgent.indexOf("Trident")),o=e.forceRefresh,i=void 0!==o&&o,a=e.getUserConfirmation,u=void 0===a?S:a,l=e.keyLength,c=void 0===l?6:l,f=e.basename?g(y(e.basename)):"",d=function(e){var t=e||{},n=t.key,r=t.state,o=window.location,i=o.pathname+o.search+o.hash;return s()(!f||v(i,f),'You are attempting to use a basename on a page whose URL path does not begin with the basename. Expected path "'+i+'" to begin with "'+f+'".'),f&&(i=b(i,f)),k(i,r,n)},h=function(){return Math.random().toString(36).substr(2,c)},m=O(),x=function(e){j(B,e),B.length=t.length,m.notifyListeners(B.location,B.action)},_=function(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||A(d(e.state))},M=function(){A(d(R()))},N=!1,A=function(e){N?(N=!1,x()):m.confirmTransitionTo(e,"POP",u,function(t){t?x({action:"POP",location:e}):I(e)})},I=function(e){var t=B.location,n=L.indexOf(t.key);-1===n&&(n=0);var r=L.indexOf(e.key);-1===r&&(r=0);var o=n-r;o&&(N=!0,F(o))},U=d(R()),L=[U.key],D=function(e){return f+w(e)},F=function(e){t.go(e)},z=0,W=function(e){1===(z+=e)?(E(window,"popstate",_),r&&E(window,"hashchange",M)):0===z&&(T(window,"popstate",_),r&&T(window,"hashchange",M))},H=!1,B={length:t.length,action:"POP",location:U,createHref:D,push:function(e,r){s()(!("object"===(void 0===e?"undefined":C(e))&&void 0!==e.state&&void 0!==r),"You should avoid providing a 2nd state argument to push when the 1st argument is a location-like object that already has state; it is ignored");var o=k(e,r,h(),B.location);m.confirmTransitionTo(o,"PUSH",u,function(e){if(e){var r=D(o),a=o.key,u=o.state;if(n)if(t.pushState({key:a,state:u},null,r),i)window.location.href=r;else{var l=L.indexOf(B.location.key),c=L.slice(0,-1===l?0:l+1);c.push(o.key),L=c,x({action:"PUSH",location:o})}else s()(void 0===u,"Browser history cannot push state in browsers that do not support HTML5 history"),window.location.href=r}})},replace:function(e,r){s()(!("object"===(void 0===e?"undefined":C(e))&&void 0!==e.state&&void 0!==r),"You should avoid providing a 2nd state argument to replace when the 1st argument is a location-like object that already has state; it is ignored");var o=k(e,r,h(),B.location);m.confirmTransitionTo(o,"REPLACE",u,function(e){if(e){var r=D(o),a=o.key,u=o.state;if(n)if(t.replaceState({key:a,state:u},null,r),i)window.location.replace(r);else{var l=L.indexOf(B.location.key);-1!==l&&(L[l]=o.key),x({action:"REPLACE",location:o})}else s()(void 0===u,"Browser history cannot replace state in browsers that do not support HTML5 history"),window.location.replace(r)}})},go:F,goBack:function(){return F(-1)},goForward:function(){return F(1)},block:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=m.setPrompt(e);return H||(W(1),H=!0),function(){return H&&(H=!1,W(-1)),t()}},listen:function(e){var t=m.appendListener(e);return W(1),function(){W(-1),t()}}};return B},N=Object.assign||function(e){for(var t=1;t=0?t:0)+"#"+e)},L=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};p()(P,"Hash history needs a DOM");var t=window.history,n=-1===window.navigator.userAgent.indexOf("Firefox"),r=e.getUserConfirmation,o=void 0===r?S:r,i=e.hashType,a=void 0===i?"slash":i,u=e.basename?g(y(e.basename)):"",l=A[a],c=l.encodePath,f=l.decodePath,d=function(){var e=f(I());return s()(!u||v(e,u),'You are attempting to use a basename on a page whose URL path does not begin with the basename. Expected path "'+e+'" to begin with "'+u+'".'),u&&(e=b(e,u)),k(e)},h=O(),m=function(e){N(q,e),q.length=t.length,h.notifyListeners(q.location,q.action)},x=!1,C=null,j=function(){var e=I(),t=c(e);if(e!==t)U(t);else{var n=d(),r=q.location;if(!x&&_(r,n))return;if(C===w(n))return;C=null,R(n)}},R=function(e){x?(x=!1,m()):h.confirmTransitionTo(e,"POP",o,function(t){t?m({action:"POP",location:e}):M(e)})},M=function(e){var t=q.location,n=z.lastIndexOf(w(t));-1===n&&(n=0);var r=z.lastIndexOf(w(e));-1===r&&(r=0);var o=n-r;o&&(x=!0,W(o))},L=I(),D=c(L);L!==D&&U(D);var F=d(),z=[w(F)],W=function(e){s()(n,"Hash history go(n) causes a full page reload in this browser"),t.go(e)},H=0,B=function(e){1===(H+=e)?E(window,"hashchange",j):0===H&&T(window,"hashchange",j)},V=!1,q={length:t.length,action:"POP",location:F,createHref:function(e){return"#"+c(u+w(e))},push:function(e,t){s()(void 0===t,"Hash history cannot push state; it is ignored");var n=k(e,void 0,void 0,q.location);h.confirmTransitionTo(n,"PUSH",o,function(e){if(e){var t=w(n),r=c(u+t);if(I()!==r){C=t,function(e){window.location.hash=e}(r);var o=z.lastIndexOf(w(q.location)),i=z.slice(0,-1===o?0:o+1);i.push(t),z=i,m({action:"PUSH",location:n})}else s()(!1,"Hash history cannot PUSH the same path; a new entry will not be added to the history stack"),m()}})},replace:function(e,t){s()(void 0===t,"Hash history cannot replace state; it is ignored");var n=k(e,void 0,void 0,q.location);h.confirmTransitionTo(n,"REPLACE",o,function(e){if(e){var t=w(n),r=c(u+t);I()!==r&&(C=t,U(r));var o=z.indexOf(w(q.location));-1!==o&&(z[o]=t),m({action:"REPLACE",location:n})}})},go:W,goBack:function(){return W(-1)},goForward:function(){return W(1)},block:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=h.setPrompt(e);return V||(B(1),V=!0),function(){return V&&(V=!1,B(-1)),t()}},listen:function(e){var t=h.appendListener(e);return B(1),function(){B(-1),t()}}};return q},D="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},F=Object.assign||function(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{},t=e.getUserConfirmation,n=e.initialEntries,r=void 0===n?["/"]:n,o=e.initialIndex,i=void 0===o?0:o,a=e.keyLength,u=void 0===a?6:a,l=O(),c=function(e){F(m,e),m.length=m.entries.length,l.notifyListeners(m.location,m.action)},f=function(){return Math.random().toString(36).substr(2,u)},p=z(i,0,r.length-1),d=r.map(function(e){return k(e,void 0,"string"==typeof e?f():e.key||f())}),h=w,y=function(e){var n=z(m.index+e,0,m.entries.length-1),r=m.entries[n];l.confirmTransitionTo(r,"POP",t,function(e){e?c({action:"POP",location:r,index:n}):c()})},m={length:d.length,action:"POP",location:d[p],index:p,entries:d,createHref:h,push:function(e,n){s()(!("object"===(void 0===e?"undefined":D(e))&&void 0!==e.state&&void 0!==n),"You should avoid providing a 2nd state argument to push when the 1st argument is a location-like object that already has state; it is ignored");var r=k(e,n,f(),m.location);l.confirmTransitionTo(r,"PUSH",t,function(e){if(e){var t=m.index+1,n=m.entries.slice(0);n.length>t?n.splice(t,n.length-t,r):n.push(r),c({action:"PUSH",location:r,index:t,entries:n})}})},replace:function(e,n){s()(!("object"===(void 0===e?"undefined":D(e))&&void 0!==e.state&&void 0!==n),"You should avoid providing a 2nd state argument to replace when the 1st argument is a location-like object that already has state; it is ignored");var r=k(e,n,f(),m.location);l.confirmTransitionTo(r,"REPLACE",t,function(e){e&&(m.entries[m.index]=r,c({action:"REPLACE",location:r}))})},go:y,goBack:function(){return y(-1)},goForward:function(){return y(1)},canGo:function(e){var t=m.index+e;return t>=0&&t0&&void 0!==arguments[0]&&arguments[0];return l.setPrompt(e)},listen:function(e){return l.appendListener(e)}};return m},H=n(6),B=H.a;function V(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var q=function(e){function t(){var n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var o=arguments.length,i=Array(o),a=0;a ignores the history prop. To use a custom history, use `import { Router }` instead of `import { BrowserRouter as Router }`.")},t.prototype.render=function(){return a.a.createElement(B,{history:this.history,children:this.props.children})},t}(a.a.Component);q.propTypes={basename:l.a.string,forceRefresh:l.a.bool,getUserConfirmation:l.a.func,keyLength:l.a.number,children:l.a.node};var $=q;function Y(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var K=function(e){function t(){var n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var o=arguments.length,i=Array(o),a=0;a ignores the history prop. To use a custom history, use `import { Router }` instead of `import { HashRouter as Router }`.")},t.prototype.render=function(){return a.a.createElement(B,{history:this.history,children:this.props.children})},t}(a.a.Component);K.propTypes={basename:l.a.string,getUserConfirmation:l.a.func,hashType:l.a.oneOf(["hashbang","noslash","slash"]),children:l.a.node};var Q=K,X=Object.assign||function(e){for(var t=1;t=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(e,["replace","to","innerRef"]);p()(this.context.router,"You should not use outside a "),p()(void 0!==t,'You must specify the "to" property');var o=this.context.router.history,i="string"==typeof t?k(t,null,null,o.location):t,u=o.createHref(i);return a.a.createElement("a",X({},r,{onClick:this.handleClick,href:u,ref:n}))},t}(a.a.Component);Z.propTypes={onClick:l.a.func,target:l.a.string,replace:l.a.bool,to:l.a.oneOfType([l.a.string,l.a.object]).isRequired,innerRef:l.a.oneOfType([l.a.string,l.a.func])},Z.defaultProps={replace:!1},Z.contextTypes={router:l.a.shape({history:l.a.shape({push:l.a.func.isRequired,replace:l.a.func.isRequired,createHref:l.a.func.isRequired}).isRequired}).isRequired};var ee=Z;function te(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var ne=function(e){function t(){var n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var o=arguments.length,i=Array(o),a=0;a ignores the history prop. To use a custom history, use `import { Router }` instead of `import { MemoryRouter as Router }`.")},t.prototype.render=function(){return a.a.createElement(H.a,{history:this.history,children:this.props.children})},t}(a.a.Component);ne.propTypes={initialEntries:l.a.array,initialIndex:l.a.number,getUserConfirmation:l.a.func,keyLength:l.a.number,children:l.a.node};var re=ne,oe=n(7),ie=Object.assign||function(e){for(var t=1;t or withRouter() outside a ");var l=t.route,c=(r||l.location).pathname;return Object(oe.a)(c,{path:o,strict:i,exact:a,sensitive:u},l.match)},t.prototype.componentWillMount=function(){o()(!(this.props.component&&this.props.render),"You should not use and in the same route; will be ignored"),o()(!(this.props.component&&this.props.children&&!ue(this.props.children)),"You should not use and in the same route; will be ignored"),o()(!(this.props.render&&this.props.children&&!ue(this.props.children)),"You should not use and in the same route; will be ignored")},t.prototype.componentWillReceiveProps=function(e,t){o()(!(e.location&&!this.props.location),' elements should not change from uncontrolled to controlled (or vice versa). You initially used no "location" prop and then provided one on a subsequent render.'),o()(!(!e.location&&this.props.location),' elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.'),this.setState({match:this.computeMatch(e,t.router)})},t.prototype.render=function(){var e=this.state.match,t=this.props,n=t.children,r=t.component,o=t.render,i=this.context.router,u=i.history,l=i.route,c=i.staticContext,s={match:e,location:this.props.location||l.location,history:u,staticContext:c};return r?e?a.a.createElement(r,s):null:o?e?o(s):null:"function"==typeof n?n(s):n&&!ue(n)?a.a.Children.only(n):null},t}(a.a.Component);le.propTypes={computedMatch:l.a.object,path:l.a.string,exact:l.a.bool,strict:l.a.bool,sensitive:l.a.bool,component:l.a.func,render:l.a.func,children:l.a.oneOfType([l.a.func,l.a.node]),location:l.a.object},le.contextTypes={router:l.a.shape({history:l.a.object.isRequired,route:l.a.object.isRequired,staticContext:l.a.object})},le.childContextTypes={router:l.a.object.isRequired};var ce=le,se=ce,fe=Object.assign||function(e){for(var t=1;t=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(e,["to","exact","strict","location","activeClassName","className","activeStyle","style","isActive","aria-current"]),d="object"===(void 0===t?"undefined":pe(t))?t.pathname:t,h=d&&d.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1");return a.a.createElement(se,{path:h,exact:n,strict:r,location:o,children:function(e){var n=e.location,r=e.match,o=!!(s?s(r,n):r);return a.a.createElement(ee,fe({to:t,className:o?[u,i].filter(function(e){return e}).join(" "):u,style:o?fe({},c,l):c,"aria-current":o&&f||null},p))}})};de.propTypes={to:ee.propTypes.to,exact:l.a.bool,strict:l.a.bool,location:l.a.object,activeClassName:l.a.string,className:l.a.string,activeStyle:l.a.object,style:l.a.object,isActive:l.a.func,"aria-current":l.a.oneOf(["page","step","location","date","time","true"])},de.defaultProps={activeClassName:"active","aria-current":"page"};var he=de,ye=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.prototype.enable=function(e){this.unblock&&this.unblock(),this.unblock=this.context.router.history.block(e)},t.prototype.disable=function(){this.unblock&&(this.unblock(),this.unblock=null)},t.prototype.componentWillMount=function(){p()(this.context.router,"You should not use outside a "),this.props.when&&this.enable(this.props.message)},t.prototype.componentWillReceiveProps=function(e){e.when?this.props.when&&this.props.message===e.message||this.enable(e.message):this.disable()},t.prototype.componentWillUnmount=function(){this.disable()},t.prototype.render=function(){return null},t}(a.a.Component);ye.propTypes={when:l.a.bool,message:l.a.oneOfType([l.a.func,l.a.string]).isRequired},ye.defaultProps={when:!0},ye.contextTypes={router:l.a.shape({history:l.a.shape({block:l.a.func.isRequired}).isRequired}).isRequired};var me=ye,ve=n(8),be=n.n(ve),ge={},we=0,xe=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"/",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return"/"===e?e:function(e){var t=e,n=ge[t]||(ge[t]={});if(n[e])return n[e];var r=be.a.compile(e);return we<1e4&&(n[e]=r,we++),r}(e)(t,{pretty:!0})},ke=Object.assign||function(e){for(var t=1;t outside a "),this.isStatic()&&this.perform()},t.prototype.componentDidMount=function(){this.isStatic()||this.perform()},t.prototype.componentDidUpdate=function(e){var t=k(e.to),n=k(this.props.to);_(t,n)?o()(!1,"You tried to redirect to the same route you're currently on: \""+n.pathname+n.search+'"'):this.perform()},t.prototype.computeTo=function(e){var t=e.computedMatch,n=e.to;return t?"string"==typeof n?xe(n,t.params):ke({},n,{pathname:xe(n.pathname,t.params)}):n},t.prototype.perform=function(){var e=this.context.router.history,t=this.props.push,n=this.computeTo(this.props);t?e.push(n):e.replace(n)},t.prototype.render=function(){return null},t}(a.a.Component);_e.propTypes={computedMatch:l.a.object,push:l.a.bool,from:l.a.string,to:l.a.oneOfType([l.a.string,l.a.object]).isRequired},_e.defaultProps={push:!1},_e.contextTypes={router:l.a.shape({history:l.a.shape({push:l.a.func.isRequired,replace:l.a.func.isRequired}).isRequired,staticContext:l.a.object}).isRequired};var Oe=_e,Pe=Object.assign||function(e){for(var t=1;t",e)}},Re=function(){},Me=function(e){function t(){var n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var o=arguments.length,i=Array(o),a=0;a ignores the history prop. To use a custom history, use `import { Router }` instead of `import { StaticRouter as Router }`.")},t.prototype.render=function(){var e=this.props,t=e.basename,n=(e.context,e.location),r=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(e,["basename","context","location"]),o={createHref:this.createHref,action:"POP",location:function(e,t){if(!e)return t;var n=Te(e);return 0!==t.pathname.indexOf(n)?t:Pe({},t,{pathname:t.pathname.substr(n.length)})}(t,k(n)),push:this.handlePush,replace:this.handleReplace,go:je("go"),goBack:je("goBack"),goForward:je("goForward"),listen:this.handleListen,block:this.handleBlock};return a.a.createElement(H.a,Pe({},r,{history:o}))},t}(a.a.Component);Me.propTypes={basename:l.a.string,context:l.a.object.isRequired,location:l.a.oneOfType([l.a.string,l.a.object])},Me.defaultProps={basename:"",location:"/"},Me.childContextTypes={router:l.a.object.isRequired};var Ne=Me,Ae=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.prototype.componentWillMount=function(){p()(this.context.router,"You should not use outside a ")},t.prototype.componentWillReceiveProps=function(e){o()(!(e.location&&!this.props.location),' elements should not change from uncontrolled to controlled (or vice versa). You initially used no "location" prop and then provided one on a subsequent render.'),o()(!(!e.location&&this.props.location),' elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.')},t.prototype.render=function(){var e=this.context.router.route,t=this.props.children,n=this.props.location||e.location,r=void 0,o=void 0;return a.a.Children.forEach(t,function(t){if(null==r&&a.a.isValidElement(t)){var i=t.props,u=i.path,l=i.exact,c=i.strict,s=i.sensitive,f=i.from,p=u||f;o=t,r=Object(oe.a)(n.pathname,{path:p,exact:l,strict:c,sensitive:s},e.match)}}),r?a.a.cloneElement(o,{location:n,computedMatch:r}):null},t}(a.a.Component);Ae.contextTypes={router:l.a.shape({route:l.a.object.isRequired}).isRequired},Ae.propTypes={children:l.a.node,location:l.a.object};var Ie=Ae,Ue=xe,Le=oe.a,De=n(9),Fe=n.n(De),ze=Object.assign||function(e){for(var t=1;t=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(t,["wrappedComponentRef"]);return a.a.createElement(ce,{children:function(t){return a.a.createElement(e,ze({},r,t,{ref:n}))}})};return t.displayName="withRouter("+(e.displayName||e.name)+")",t.WrappedComponent=e,t.propTypes={wrappedComponentRef:l.a.func},Fe()(t,e)};n.d(t,"BrowserRouter",function(){return $}),n.d(t,"HashRouter",function(){return Q}),n.d(t,"Link",function(){return ee}),n.d(t,"MemoryRouter",function(){return re}),n.d(t,"NavLink",function(){return he}),n.d(t,"Prompt",function(){return me}),n.d(t,"Redirect",function(){return Oe}),n.d(t,"Route",function(){return se}),n.d(t,"Router",function(){return B}),n.d(t,"StaticRouter",function(){return Ne}),n.d(t,"Switch",function(){return Ie}),n.d(t,"generatePath",function(){return Ue}),n.d(t,"matchPath",function(){return Le}),n.d(t,"withRouter",function(){return We})},function(e,t,n){"use strict";n.r(t);var r=n(22),o="object"==typeof self&&self&&self.Object===Object&&self,i=(r.a||o||Function("return this")()).Symbol,a=Object.prototype,u=a.hasOwnProperty,l=a.toString,c=i?i.toStringTag:void 0,s=Object.prototype.toString,f=i?i.toStringTag:void 0,p=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":f&&f in Object(e)?function(e){var t=u.call(e,c),n=e[c];try{e[c]=void 0;var r=!0}catch(e){}var o=l.call(e);return r&&(t?e[c]=n:delete e[c]),o}(e):function(e){return s.call(e)}(e)},d=function(e,t){return function(n){return e(t(n))}}(Object.getPrototypeOf,Object),h=Function.prototype,y=Object.prototype,m=h.toString,v=y.hasOwnProperty,b=m.call(Object),g=function(e){if(!function(e){return null!=e&&"object"==typeof e}(e)||"[object Object]"!=p(e))return!1;var t=d(e);if(null===t)return!0;var n=v.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&m.call(n)==b},w=n(12),x={INIT:"@@redux/INIT"};function k(e,t,n){var r;if("function"==typeof t&&void 0===n&&(n=t,t=void 0),void 0!==n){if("function"!=typeof n)throw new Error("Expected the enhancer to be a function.");return n(k)(e,t)}if("function"!=typeof e)throw new Error("Expected the reducer to be a function.");var o=e,i=t,a=[],u=a,l=!1;function c(){u===a&&(u=a.slice())}function s(){return i}function f(e){if("function"!=typeof e)throw new Error("Expected listener to be a function.");var t=!0;return c(),u.push(e),function(){if(t){t=!1,c();var n=u.indexOf(e);u.splice(n,1)}}}function p(e){if(!g(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if(void 0===e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(l)throw new Error("Reducers may not dispatch actions.");try{l=!0,i=o(i,e)}finally{l=!1}for(var t=a=u,n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1];if(a)throw a;for(var r=!1,o={},u=0;u
--------------------------------------------------------------------------------
/dist/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | A React, Redux, TypeScript and Webpack starter
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/dist/server.js:
--------------------------------------------------------------------------------
1 | module.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(2),o=n(3),u=o();u.use(o.static("./dist/public")),u.get("*.js",(e,t,n)=>{e.url=e.url+".gz",t.set("Content-Encoding","gzip"),n()}),u.listen(8080,e=>{if(e)return console.log(r.default.red.bold(e));console.log(r.default.green.bold("\n\n##################################\n### App listening on port 8080 ###\n##################################"))})},function(e,t){e.exports=require("chalk")},function(e,t){e.exports=require("express")}]);
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | // jest.config.js
2 | module.exports = {
3 | bail: true,
4 | verbose: true,
5 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
6 | testPathIgnorePatterns: ['/node_modules/'],
7 | testRegex: '.*\\.spec\\.(jsx?|tsx?)$',
8 | moduleDirectories: ['node_modules', 'shared'],
9 | moduleNameMapper: {
10 | '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
11 | '/jest/__mocks__/fileMock.js',
12 | '\\.(css|scss|less)$': 'identity-obj-proxy',
13 | },
14 | transform: {
15 | '^.+\\.tsx?$': 'ts-jest',
16 | },
17 | collectCoverageFrom: [
18 | 'src/**/*.{ts,tsx}',
19 | 'src/**/**/*.{ts,tsx}',
20 | '!**/node_modules/**',
21 | '!**/**/*.d.ts',
22 | ],
23 | "coverageDirectory": "./coverage/",
24 | "collectCoverage": true
25 | };
26 |
--------------------------------------------------------------------------------
/jest/__mocks__/fileMock.js:
--------------------------------------------------------------------------------
1 | module.exports = 'test-file-stub';
2 |
--------------------------------------------------------------------------------
/jest/__mocks__/styleMock.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/jest/fileTransformer.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | process(src, filename, config, options) {
5 | return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/jest/generator/createJestTest.js:
--------------------------------------------------------------------------------
1 | function createJestTest(filename) {
2 | const fileWithOutExt = filename.replace(/\.[^/.]+$/, '');
3 | const readableFilename = capitalizeFirstLetter(fileWithOutExt);
4 | return `import * as Enzyme from 'enzyme';
5 | import * as Adapter from 'enzyme-adapter-react-16';
6 | import toJson from 'enzyme-to-json';
7 | import * as React from 'react';
8 | import ${readableFilename} from '../${readableFilename}';
9 |
10 | Enzyme.configure({ adapter: new Adapter() });
11 |
12 | describe('${readableFilename}', () => {
13 | test('Should render ${readableFilename} correctly', () => {
14 | const wrapper = Enzyme.shallow(<${readableFilename} />);
15 | expect(toJson(wrapper)).toMatchSnapshot();
16 | });
17 | });
18 | `;
19 | }
20 |
21 | const capitalizeFirstLetter = string =>
22 | string.charAt(0).toUpperCase() + string.slice(1);
23 |
24 | module.exports = { createJestTest };
25 |
--------------------------------------------------------------------------------
/jest/generator/generateFile.js:
--------------------------------------------------------------------------------
1 | const mkdirp = require('mkdirp'),
2 | createJestFile = require('./createJestTest'),
3 | fs = require('fs');
4 |
5 | const generateFile = (filePath, filename, startPath) => {
6 | return new Promise((resolve, reject) => {
7 | checkIfReactFile(filePath)
8 | .then(({ isReactFile, filePath }) => {
9 | if (isReactFile) {
10 | const testPath = `${startPath}/__tests__`;
11 | const testFileName = `${filename.replace(/\.[^/.]+$/, '')}.spec.tsx`;
12 | const fileContent = createJestFile.createJestTest(filename);
13 |
14 | resolve(
15 | findTestFolder(testPath).then(() =>
16 | createTestFile(`${testPath}/${testFileName}`, fileContent)
17 | )
18 | );
19 | } else {
20 | resolve(0);
21 | }
22 | })
23 | .catch(reject);
24 | });
25 | };
26 |
27 | function createTestFile(filename, content) {
28 | return new Promise((resolve, reject) => {
29 | fs.open(filename, 'r', function(err, fd) {
30 | if (err) {
31 | fs.writeFile(filename, content, function(err) {
32 | if (err) {
33 | reject(err);
34 | } else {
35 | resolve(1);
36 | }
37 | });
38 | } else {
39 | console.log('The file exists!', filename);
40 | resolve(0);
41 | }
42 | });
43 | });
44 | }
45 |
46 | function findTestFolder(path) {
47 | return new Promise((resolve, reject) => {
48 | mkdirp(path, function(err) {
49 | if (err) {
50 | reject(err);
51 | } else {
52 | // console.log(`created test folder: ${path}`);
53 | resolve();
54 | }
55 | });
56 | });
57 | }
58 |
59 | function checkIfReactFile(filePath) {
60 | if (filePath.indexOf('.spec.tsx') > 0 || filePath.indexOf('.test.tsx') > 0) {
61 | // Don't generate files for test files
62 | return Promise.resolve(false);
63 | }
64 |
65 | return new Promise((resolve, reject) => {
66 | fs.readFile(filePath, function(err1, data) {
67 | if (err1) {
68 | console.error(err1);
69 | reject();
70 | } else {
71 | const res = {
72 | filePath,
73 | isReactFile: isReactFile(data),
74 | };
75 | resolve(res);
76 | }
77 | });
78 | });
79 | }
80 |
81 | function isReactFile(data) {
82 | // naive way of trying to check if the file is a React comp
83 | if (
84 | data.indexOf(`require('react')`) >= 0 ||
85 | data.indexOf(`from 'react'`) >= 0
86 | ) {
87 | return true;
88 | } else {
89 | return false;
90 | }
91 | }
92 |
93 | module.exports = { generateFile };
94 |
--------------------------------------------------------------------------------
/jest/generator/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const path = require('path'),
4 | fs = require('fs');
5 | const { generateFile } = require('./generateFile');
6 |
7 | let counter = 0;
8 | function fromDir(startPath, fileExt) {
9 | if (!fs.existsSync(startPath)) {
10 | console.log('no dir ', startPath);
11 | return Promise.reject();
12 | }
13 |
14 | const files = fs.readdirSync(startPath);
15 | return Promise.all(
16 | files.map(file => {
17 | const filename = file;
18 | const filePath = path.join(startPath, file);
19 | const stat = fs.lstatSync(filePath);
20 | if (stat.isDirectory()) {
21 | return fromDir(filePath, fileExt); //recurse
22 | } else if (filename.indexOf(fileExt) >= 0) {
23 | return generateFile(`./${filePath}`, filename, startPath).then(
24 | numberOfCreatedFiles => (counter = counter + numberOfCreatedFiles)
25 | );
26 | } else {
27 | return Promise.resolve();
28 | }
29 | })
30 | );
31 | }
32 |
33 | const projectPath = process.argv[2];
34 |
35 | if (!projectPath) {
36 | throw Error('Not path given');
37 | }
38 | const ext = process.argv[3] || '.tsx';
39 |
40 | fromDir(projectPath, ext)
41 | .then(() => {
42 | console.log(`Finished, created ${counter} jest snapshot files`);
43 | })
44 | .catch(err => console.log('jest-generator', err));
45 |
--------------------------------------------------------------------------------
/jest/setup.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Todo: 测试环境初始化配置
3 | */
4 |
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": false,
3 | "name": "defensor-automated-testing",
4 | "version": "0.1.3",
5 | "description": "A React, Redux, TypeScript and Webpack starter",
6 | "main": "index.js",
7 | "repository": {
8 | "type": "git",
9 | "url": "git+https://github.com/TingGe/defensor-automated-testing.git"
10 | },
11 | "scripts": {
12 | "clean": "rimraf dist",
13 | "start": "yarn run start:dev",
14 | "start:dev": "cross-env NODE_ENV=development ts-node src/server.ts",
15 | "start:prod": "yarn run build && node dist/server.js",
16 | "build": "yarn run clean && yarn run build:server && yarn run build:prod",
17 | "build:server": "cross-env webpack --progress --colors --config config/server.config.js",
18 | "build:prod": "cross-env webpack --progress --colors --mode production --config config/client.config.js",
19 | "lint": "tslint --project tsconfig.json",
20 | "prebuild": "npm test",
21 | "lint:fix": "prettier --write './src/**/*.{ts,tsx,js,scss}' && tslint -c tslint.json --fix './src/**/*.{js,ts,tsx}'",
22 | "test": "jest",
23 | "test:coverage": "jest --coverage && codecov",
24 | "test:createTests": "node jest/generator/index.js src/components",
25 | "test:update-snapshot": "jest -u",
26 | "test:generate-output": "jest --json --outputFile=.jest-test-results.json || true",
27 | "precommit": "lint-staged",
28 | "test:watch": "npm run test:generate-output -- --watch",
29 | "commitmsg": "commitlint -E GIT_PARAMS",
30 | "prebuild:storybook": "npm run test:generate-output",
31 | "build:storybook": "build-storybook -c .storybook -o build/",
32 | "predeploy": "npm run build:storybook",
33 | "version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
34 | },
35 | "devDependencies": {
36 | "@commitlint/cli": "^7.1.1",
37 | "@commitlint/config-conventional": "^7.1.1",
38 | "@types/enzyme": "^3.1.13",
39 | "@types/enzyme-adapter-react-16": "^1.0.3",
40 | "@types/enzyme-to-json": "^1.5.2",
41 | "@types/jest": "^23.3.1",
42 | "@types/react": "^16.4.11",
43 | "@types/react-dom": "^16.0.7",
44 | "@types/react-hot-loader": "^4.1.0",
45 | "@types/react-router-redux": "^5.0.15",
46 | "@types/redux-immutable": "^3.0.38",
47 | "@types/webpack": "^4.4.10",
48 | "@types/webpack-env": "^1.13.6",
49 | "awesome-typescript-loader": "^5.2.0",
50 | "codecov": "^3.0.4",
51 | "compression-webpack-plugin": "^1.1.11",
52 | "conventional-changelog-cli": "^2.0.5",
53 | "copy-webpack-plugin": "^4.5.2",
54 | "cross-env": "^5.2.0",
55 | "enzyme": "^3.4.4",
56 | "enzyme-adapter-react-16": "^1.2.0",
57 | "enzyme-to-json": "^3.3.4",
58 | "html-webpack-plugin": "^3.2.0",
59 | "husky": "^0.14.3",
60 | "identity-obj-proxy": "^3.0.0",
61 | "imagemin-lint-staged": "^0.3.0",
62 | "jest": "^23.5.0",
63 | "lint-staged": "^7.2.2",
64 | "nyc": "^12.0.2",
65 | "prettier": "^1.14.2",
66 | "prettier-stylelint": "^0.4.2",
67 | "rimraf": "^2.6.2",
68 | "stylelint-config-idiomatic-order": "^5.0.0",
69 | "stylelint-config-standard": "^18.2.0",
70 | "stylelint-scss": "^3.3.0",
71 | "ts-jest": "^23.1.4",
72 | "ts-node": "^7.0.1",
73 | "tslint": "^5.11.0",
74 | "tslint-react": "^3.6.0",
75 | "typescript": "^3.0.1",
76 | "uglifyjs-webpack-plugin": "^1.3.0",
77 | "webpack": "^4.17.1",
78 | "webpack-cli": "^3.1.0",
79 | "webpack-dev-middleware": "^3.1.3",
80 | "webpack-hot-middleware": "^2.22.3",
81 | "webpack-node-externals": "^1.7.2"
82 | },
83 | "dependencies": {
84 | "@rematch/core": "^0.6.0",
85 | "chalk": "^2.4.1",
86 | "express": "^4.16.3",
87 | "history": "^4.7.2",
88 | "immutable": "^3.8.2",
89 | "react": "^16.4.2",
90 | "react-dom": "^16.4.2",
91 | "react-hot-loader": "^4.3.4",
92 | "react-redux": "^4.4.9",
93 | "react-router-dom": "^4.3.1",
94 | "react-router-redux": "^5.0.0-alpha.9",
95 | "redux-logger": "^3.0.6",
96 | "redux-thunk": "2.2.0"
97 | },
98 | "husky": {
99 | "hooks": {
100 | "pre-commit": "lint-staged"
101 | }
102 | },
103 | "author": "TingGe<505253293@163.com>",
104 | "license": "MIT"
105 | }
106 |
--------------------------------------------------------------------------------
/src/Root.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { hot } from 'react-hot-loader';
3 | import { ConnectedRouter } from 'react-router-redux';
4 |
5 | import routes from './routes';
6 |
7 | const Root = ({ history }) => {
8 | return {routes};
9 | };
10 |
11 | export default hot(module)(Root);
12 |
--------------------------------------------------------------------------------
/src/client.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from 'react-dom';
3 | import { AppContainer } from 'react-hot-loader';
4 | import { Provider } from 'react-redux';
5 |
6 | import Root from './Root';
7 | import configureStore from './store';
8 |
9 | const store = configureStore.default();
10 | const history = configureStore.history;
11 |
12 | render(
13 |
14 |
15 |
16 |
17 | ,
18 | document.getElementById('root'),
19 | );
20 |
--------------------------------------------------------------------------------
/src/components/NotFound.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | const NotFound = () => 404 Not Found;
4 |
5 | export default NotFound;
6 |
--------------------------------------------------------------------------------
/src/components/__tests__/NotFound.spec.tsx:
--------------------------------------------------------------------------------
1 | import * as Enzyme from 'enzyme';
2 | import * as Adapter from 'enzyme-adapter-react-16';
3 | import toJson from 'enzyme-to-json';
4 | import * as React from 'react';
5 | import NotFound from '../NotFound';
6 |
7 | Enzyme.configure({ adapter: new Adapter() });
8 |
9 | describe('NotFound', () => {
10 | test('Should render NotFound correctly', () => {
11 | const wrapper = Enzyme.shallow();
12 | expect(toJson(wrapper)).toMatchSnapshot();
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/components/__tests__/__snapshots__/NotFound.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`NotFound Should render NotFound correctly 1`] = `
4 |
5 | 404 Not Found
6 |
7 | `;
8 |
--------------------------------------------------------------------------------
/src/containers/Home.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export default class Home extends React.Component {
4 | public componentDidCatch(ex: Error) {
5 | console.log(ex.message);
6 | }
7 | public render() {
8 | return Hello world;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | A React, Redux, TypeScript and Webpack starter
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/models.ts:
--------------------------------------------------------------------------------
1 | const models = {};
2 |
3 | export default models;
4 |
--------------------------------------------------------------------------------
/src/routes.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Route, Switch } from 'react-router-dom';
3 |
4 | import NotFound from './components/NotFound';
5 | import Home from './containers/Home';
6 |
7 | const routes = (
8 |
9 |
10 |
11 |
12 | );
13 |
14 | export default routes;
15 |
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
1 | // tslint:disable:no-var-requires
2 | import chalk from 'chalk';
3 | import * as express from 'express';
4 |
5 | const app = express();
6 |
7 | if (process.env.NODE_ENV !== 'production') {
8 | // Apply only in development mode
9 | const webpack = require('webpack');
10 | const webpackConfig = require('../config/client.config.js');
11 |
12 | const compiler = webpack({
13 | mode: 'development',
14 | ...webpackConfig,
15 | });
16 |
17 | const webpackDevMiddleware = require('webpack-dev-middleware')(compiler, {
18 | headers: {
19 | 'Access-Control-Allow-Origin': '*',
20 | },
21 | noInfo: true,
22 | poll: true,
23 | publicPath: webpackConfig.output.publicPath,
24 | quiet: false,
25 | reload: true,
26 | stats: { colors: true },
27 | });
28 |
29 | const webpackHotMiddleware = require('webpack-hot-middleware')(compiler, {
30 | reload: true,
31 | });
32 |
33 | app.use(webpackDevMiddleware);
34 | app.use(webpackHotMiddleware);
35 | } else {
36 | // Apply only in production mode
37 | app.use(express.static('./dist/public'));
38 |
39 | app.get('*.js', (req, res, next) => {
40 | req.url = req.url + '.gz';
41 | res.set('Content-Encoding', 'gzip');
42 | next();
43 | });
44 | }
45 |
46 | app.listen(8080, err => {
47 | if (err) {
48 | // tslint:disable-next-line:no-console
49 | return console.log(chalk.red.bold(err));
50 | }
51 |
52 | // tslint:disable-next-line:no-console
53 | console.log(
54 | chalk.green.bold(
55 | '\n\n' +
56 | '##################################\n' +
57 | '### App listening on port 8080 ###\n' +
58 | '##################################',
59 | ),
60 | );
61 | });
62 |
--------------------------------------------------------------------------------
/src/store/configureStore.dev.ts:
--------------------------------------------------------------------------------
1 | import { init, model } from '@rematch/core';
2 | import createHistory from 'history/createBrowserHistory';
3 | import { Iterable } from 'immutable';
4 | import { routerMiddleware, routerReducer } from 'react-router-redux';
5 | import { createLogger } from 'redux-logger';
6 | import thunkMiddleware from 'redux-thunk';
7 |
8 | import models from '../models';
9 |
10 | // tslint:disable-next-line:no-any
11 | declare var module: { hot: any };
12 |
13 | export const history = createHistory();
14 |
15 | const middlewares = [
16 | routerMiddleware(history),
17 | thunkMiddleware,
18 | createLogger({
19 | collapsed: true,
20 | stateTransformer: state => {
21 | return Iterable.isIterable(state) ? state.toJS() : state;
22 | },
23 | }),
24 | ];
25 |
26 | const configureStore = (initialState = {}) => {
27 | const store = init({
28 | models,
29 | redux: {
30 | middlewares,
31 | reducers: {
32 | routing: routerReducer,
33 | ...initialState,
34 | },
35 | },
36 | });
37 |
38 | if (module.hot) {
39 | // Hot module replacement for reducers
40 | module.hot.accept('../models', () => {
41 | Object.keys(models).forEach(modelKey => {
42 | model({
43 | name: modelKey,
44 | ...models[modelKey],
45 | });
46 | });
47 | });
48 | }
49 |
50 | return store;
51 | };
52 |
53 | export default configureStore;
54 |
--------------------------------------------------------------------------------
/src/store/configureStore.prod.ts:
--------------------------------------------------------------------------------
1 | import { init, model } from '@rematch/core';
2 | import createHistory from 'history/createBrowserHistory';
3 | import { routerMiddleware, routerReducer } from 'react-router-redux';
4 | import thunkMiddleware from 'redux-thunk';
5 |
6 | import models from '../models';
7 |
8 | export const history = createHistory();
9 |
10 | const middlewares = [routerMiddleware(history), thunkMiddleware];
11 |
12 | const configureStore = (initialState = {}) => {
13 | const store = init({
14 | models,
15 | redux: {
16 | middlewares,
17 | reducers: {
18 | routing: routerReducer,
19 | ...initialState,
20 | },
21 | },
22 | });
23 |
24 | return store;
25 | };
26 |
27 | export default configureStore;
28 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | // tslint:disable-next-line:no-any
2 | let configureStore: any;
3 |
4 | // tslint:disable-next-line:prefer-conditional-expression
5 | if (process.env.NODE_ENV === 'production') {
6 | // tslint:disable-next-line:no-var-requires
7 | configureStore = require('./configureStore.prod');
8 | } else {
9 | // tslint:disable-next-line:no-var-requires
10 | configureStore = require('./configureStore.dev');
11 | }
12 |
13 | export default configureStore;
14 |
--------------------------------------------------------------------------------
/src/utils/sum.spec.ts:
--------------------------------------------------------------------------------
1 | import sum from './sum';
2 |
3 | describe('sum equal ', () => {
4 | beforeAll(() => {
5 | console.log('sum before all');
6 | });
7 |
8 | afterAll(() => {
9 | console.log('sum after all');
10 | });
11 |
12 | beforeEach(() => {
13 | console.log('sum before each');
14 | });
15 |
16 | afterEach(() => {
17 | console.log('sum after each');
18 | });
19 |
20 | it('test 1 + 2 = 3 ', () => {
21 | expect(sum(1, 2)).toBe(3);
22 | });
23 |
24 | it('test 2 + 3 = 5', () => {
25 | expect(sum(2, 3)).toEqual(5);
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/utils/sum.ts:
--------------------------------------------------------------------------------
1 | function sum(a, b) {
2 | return a + b;
3 | }
4 |
5 | export default sum;
6 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./src",
4 | "types": ["node"],
5 | "module": "commonjs",
6 | "moduleResolution": "node",
7 | "declaration": false,
8 | "noImplicitAny": false,
9 | "pretty": true,
10 | "removeComments": true,
11 | "emitDecoratorMetadata": true,
12 | "experimentalDecorators": true,
13 | "allowSyntheticDefaultImports": true,
14 | "target": "es6",
15 | "sourceMap": true,
16 | "jsx": "react",
17 | "allowJs": true,
18 | "outDir": "./dist",
19 | "typeRoots": ["types"]
20 | },
21 | "include": ["src/**/*"],
22 | "exclude": ["node_modules", "src/**/*.spec.*"]
23 | }
24 |
--------------------------------------------------------------------------------
/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "sourceMap": false,
5 | "outDir": "build"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint:latest", "tslint-react"],
3 | "rules": {
4 | "arrow-parens": [true, "ban-single-arg-parens"],
5 | "max-line-length": {
6 | "options": [80]
7 | },
8 | "no-any": true,
9 | "quotemark": [true, "single", "jsx-double"],
10 | "no-implicit-dependencies": false,
11 | "semicolon": [true, "always"],
12 | "no-submodule-imports": false,
13 | "jsx-boolean-value": [true, "never"],
14 | "jsx-no-lambda": false,
15 | "no-angle-bracket-type-assertion": false,
16 | "no-console": false,
17 | "ordered-imports":false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------