diff --git a/.babelrc b/.babelrc index b84a1a7..efd2c83 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,4 @@ { - "presets": [ - ["@verdaccio", { "typescript": true }] - ] + "presets": [["@verdaccio"]], + "plugins": ["emotion"] } diff --git a/.circleci/config.yml b/.circleci/config.yml index a6ff13b..cbdf419 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,6 +5,9 @@ aliases: ~/ui-theme - &defaults working_directory: *repo_path + - &node_latest_browser + docker: + - image: circleci/node:latest-browsers - &node_latest_executor docker: - image: circleci/node:latest @@ -47,9 +50,12 @@ jobs: - run: name: Install dependencies command: yarn install --frozen-lockfile + - run: + name: Lint code + command: yarn lint - run: name: Build project - command: yarn run build + command: yarn build - save_cache: key: *yarn_cache_key paths: @@ -61,15 +67,6 @@ jobs: paths: - ./* - lint: - <<: *defaults - <<: *default_executor - steps: - - *restore_repo - - run: - name: Lint code - command: yarn lint - test_bundlesize: <<: *defaults <<: *default_executor @@ -92,6 +89,15 @@ jobs: paths: - coverage + test_e2e: + <<: *defaults + <<: *node_latest_browser + steps: + - *restore_repo + - run: + name: Test E2E Node (LTS) + command: yarn test:e2e + test_node_lts: <<: *defaults <<: *node_lts_executor @@ -138,10 +144,6 @@ workflows: jobs: - prepare: <<: *ignore_non_dev_branches - - lint: - requires: - - prepare - <<: *ignore_non_dev_branches - test_bundlesize: requires: - prepare @@ -154,15 +156,19 @@ workflows: requires: - prepare <<: *ignore_non_dev_branches + - test_e2e: + requires: + - prepare + <<: *ignore_non_dev_branches - coverage: requires: - test_node_latest <<: *ignore_non_dev_branches - publish_package: requires: - - lint - test_bundlesize - test_node_latest - test_node_lts + - test_e2e - coverage <<: *execute_on_release diff --git a/.eslintignore b/.eslintignore index 897c1d5..a063e81 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,7 @@ coverage/ static/ .github/ .circleci/ +build *.md *.lock *.yaml @@ -10,3 +11,4 @@ Dockerfile *.html *.scss *.png +doc diff --git a/.eslintrc b/.eslintrc index a4a9a7a..3340ea9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,8 @@ "plugin:jest/recommended", "plugin:prettier/recommended", "plugin:verdaccio/recommended", - "plugin:jsx-a11y/recommended" + "plugin:jsx-a11y/recommended", + "plugin:import/typescript" ], "plugins": [ "react", @@ -14,19 +15,22 @@ "verdaccio", "jsx-a11y", "codeceptjs", - "react-hooks" + "react-hooks", + "import" ], "settings": { "react": { "version": "detect" } }, + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaFeatures": { "jsx": true } }, "rules": { + "import/order": ["error", {"newlines-between": "always"}], "babel/no-invalid-this": 0, "no-invalid-this": 0, "no-console": ["error", { "allow": ["warn", "error"] }], diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml new file mode 100644 index 0000000..6955cc7 --- /dev/null +++ b/.github/workflows/canary.yml @@ -0,0 +1,50 @@ +name: CI Canary + +on: [pull_request] + +jobs: + build_test_lint: + name: Node Smoke Test Befor Canary + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: '12.x' + registry-url: 'https://registry.verdaccio.org' + - name: Install + run: yarn install --frozen-lockfile + - name: Lint + run: yarn lint + - name: Build + run: yarn build + - name: Archive production artifacts + uses: actions/upload-artifact@v1 + with: + name: static + path: static + canary: + name: Publish Canary Version of a PR + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Download math result for job 2 + uses: actions/download-artifact@v1 + with: + name: static + - uses: verdaccio/github-actions/canary@v0.4.0 + with: + message: 'Thanks for your PR, the @verdaccio/ui package will be accessible from here for testing purposes:' + is-global: false + package-name: '@verdaccio/ui-theme' + registry: 'https://registry.verdaccio.org' + repo-token: ${{ secrets.GITHUB_TOKEN }} + bot-token: ${{ secrets.VERDACCIO_BOT_TOKEN }} + - uses: actions/setup-node@v1 + with: + node-version: '12.x' + registry-url: 'https://registry.verdaccio.org' + - run: npm publish --tag canary + env: + NODE_AUTH_TOKEN: ${{ secrets.VERDACCIO_TOKEN }} + needs: build_test_lint diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1639c53..99bab14 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,6 @@ name: CI -on: push +on: [push, pull_request] jobs: build_test_lint: @@ -9,20 +9,20 @@ jobs: strategy: fail-fast: false matrix: - node_version: [10, 12] + node_version: [12, 13] os: [ubuntu-latest, windows-latest, macOS-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node_version }} - uses: actions/setup-node@v1 - with: - version: ${{ matrix.node_version }} - - name: Install - run: yarn install --frozen-lockfile - - name: Build - run: yarn build - - name: Lint - run: yarn lint + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node_version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node_version }} + - name: Install + run: yarn install --frozen-lockfile + - name: Lint + run: yarn lint + - name: Build + run: yarn build diff --git a/.gitignore b/.gitignore index 6922247..8101f3d 100755 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ npm-debug.log verdaccio-*.tgz .DS_Store build/ +doc + ### node_modules package-lock.json diff --git a/.secrets-baseline b/.secrets-baseline new file mode 100644 index 0000000..992b28f --- /dev/null +++ b/.secrets-baseline @@ -0,0 +1,40 @@ +{ + "exclude": { + "files": null, + "lines": null + }, + "generated_at": "2019-09-29T18:19:50Z", + "plugins_used": [ + { + "name": "AWSKeyDetector" + }, + { + "name": "ArtifactoryDetector" + }, + { + "base64_limit": 4.5, + "name": "Base64HighEntropyString" + }, + { + "name": "BasicAuthDetector" + }, + { + "hex_limit": 3, + "name": "HexHighEntropyString" + }, + { + "name": "KeywordDetector" + }, + { + "name": "PrivateKeyDetector" + }, + { + "name": "SlackDetector" + }, + { + "name": "StripeDetector" + } + ], + "results": {}, + "version": "0.12.4" +} diff --git a/.vscode/settings.json b/.vscode/settings.json index c3f06ca..76537af 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,6 @@ "javascriptreact", "typescript", "typescriptreact" - ] + ], + "typescript.tsdk": "node_modules/typescript/lib" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dd1856..febb835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,106 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.3.6](https://github.com/verdaccio/ui/compare/v0.3.5...v0.3.6) (2019-11-08) + +### [0.3.5](https://github.com/verdaccio/ui/compare/v0.3.4...v0.3.5) (2019-11-07) + + +### Bug Fixes + +* adds unit tests for api service ([#235](https://github.com/verdaccio/ui/issues/235)) ([803da1c](https://github.com/verdaccio/ui/commit/803da1c)) +* convert Engine component to hooks ([#233](https://github.com/verdaccio/ui/issues/233)) ([5cb47ed](https://github.com/verdaccio/ui/commit/5cb47ed)) +* refactor/116 RegistryInfoContent is converted to functional component ([#229](https://github.com/verdaccio/ui/issues/229)) ([b74ca22](https://github.com/verdaccio/ui/commit/b74ca22)), closes [#116](https://github.com/verdaccio/ui/issues/116) [#116](https://github.com/verdaccio/ui/issues/116) +* rest MUI components - Introduced ForwardRef ([#224](https://github.com/verdaccio/ui/issues/224)) ([b56e438](https://github.com/verdaccio/ui/commit/b56e438)) + + +### Features + +* added download tarball button at list ([#237](https://github.com/verdaccio/ui/issues/237)) ([bdef686](https://github.com/verdaccio/ui/commit/bdef686)) +* update date fns to v2 ([#232](https://github.com/verdaccio/ui/issues/232)) ([a4cdd14](https://github.com/verdaccio/ui/commit/a4cdd14)) + +### [0.3.4](https://github.com/verdaccio/ui/compare/v0.3.3...v0.3.4) (2019-10-26) + + +### Bug Fixes + +* adds no uplink spec ([#213](https://github.com/verdaccio/ui/issues/213)) ([ade548a](https://github.com/verdaccio/ui/commit/ade548a)) +* api typings ([#210](https://github.com/verdaccio/ui/issues/210)) ([5d6ad3d](https://github.com/verdaccio/ui/commit/5d6ad3d)) +* PackageList component is converted to functional ([#219](https://github.com/verdaccio/ui/issues/219)) [#116](https://github.com/verdaccio/ui/issues/116) ([ae0222c](https://github.com/verdaccio/ui/commit/ae0222c)) +* routes - Replaced class by func. comp ([#159](https://github.com/verdaccio/ui/issues/159)) ([5c06ace](https://github.com/verdaccio/ui/commit/5c06ace)) +* version Page - Replaces class by func. ([#171](https://github.com/verdaccio/ui/issues/171)) ([f5c77ff](https://github.com/verdaccio/ui/commit/f5c77ff)) +* **162:** added forwardRef Card ([#216](https://github.com/verdaccio/ui/issues/216)) ([2bc49f3](https://github.com/verdaccio/ui/commit/2bc49f3)) +* **installlistitem:** changed the wrong icon ([#211](https://github.com/verdaccio/ui/issues/211)) ([4498aad](https://github.com/verdaccio/ui/commit/4498aad)) + +### [0.3.3](https://github.com/verdaccio/ui/compare/v0.3.2...v0.3.3) (2019-10-16) + + +### Bug Fixes + +* **deps:** remove types from dependencies ([#201](https://github.com/verdaccio/ui/issues/201)) ([48c03fe](https://github.com/verdaccio/ui/commit/48c03fe)) +* add new window property to interface definition ([b35baa0](https://github.com/verdaccio/ui/commit/b35baa0)) +* added typings for react-autosuggest ([#200](https://github.com/verdaccio/ui/issues/200)) ([cfb29ce](https://github.com/verdaccio/ui/commit/cfb29ce)) +* better type inference for MediaQuery ([#180](https://github.com/verdaccio/ui/issues/180)) ([e0e7c07](https://github.com/verdaccio/ui/commit/e0e7c07)) +* changes font size for items of the register-info component ([#196](https://github.com/verdaccio/ui/issues/196)) ([6f87be6](https://github.com/verdaccio/ui/commit/6f87be6)), closes [#193](https://github.com/verdaccio/ui/issues/193) +* convert Dist component to hooks ([#156](https://github.com/verdaccio/ui/issues/156)) ([f1f8f8a](https://github.com/verdaccio/ui/commit/f1f8f8a)) +* detailContainer Component - Replaced class by func. comp ([#130](https://github.com/verdaccio/ui/issues/130)) ([f84fd79](https://github.com/verdaccio/ui/commit/f84fd79)) +* dist-tags attribute [#175](https://github.com/verdaccio/ui/issues/175) ([#178](https://github.com/verdaccio/ui/issues/178)) ([752e2b9](https://github.com/verdaccio/ui/commit/752e2b9)) +* fix DependencyBlock props interface ([35d691c](https://github.com/verdaccio/ui/commit/35d691c)) +* fixed import ([#176](https://github.com/verdaccio/ui/issues/176)) ([d0d4139](https://github.com/verdaccio/ui/commit/d0d4139)) +* fixed imports & func's name ([#182](https://github.com/verdaccio/ui/issues/182)) ([3888736](https://github.com/verdaccio/ui/commit/3888736)) +* Header Component - Replaced class by func. comp ([#142](https://github.com/verdaccio/ui/issues/142)) ([d1ce828](https://github.com/verdaccio/ui/commit/d1ce828)) +* improve jest mock typings ([852f6ee](https://github.com/verdaccio/ui/commit/852f6ee)) +* improved typing ([#174](https://github.com/verdaccio/ui/issues/174)) ([e0642a9](https://github.com/verdaccio/ui/commit/e0642a9)) +* incorrect Tooltip import in avatar component ([#160](https://github.com/verdaccio/ui/issues/160)) ([43a9628](https://github.com/verdaccio/ui/commit/43a9628)) +* install Component - Replaced class by func. comp ([#152](https://github.com/verdaccio/ui/issues/152)) ([9eb698f](https://github.com/verdaccio/ui/commit/9eb698f)) +* introduced forwardRef ([#163](https://github.com/verdaccio/ui/issues/163)) ([626bcce](https://github.com/verdaccio/ui/commit/626bcce)) +* introduced forwardRef ([#164](https://github.com/verdaccio/ui/issues/164)) ([909a8d9](https://github.com/verdaccio/ui/commit/909a8d9)) +* introduced ForwardRef ([#177](https://github.com/verdaccio/ui/issues/177)) ([af8ed8b](https://github.com/verdaccio/ui/commit/af8ed8b)) +* introduced forwardRef ([#181](https://github.com/verdaccio/ui/issues/181)) ([0c4fb7d](https://github.com/verdaccio/ui/commit/0c4fb7d)) +* introduced forwardRef ([#185](https://github.com/verdaccio/ui/issues/185)) ([7548c89](https://github.com/verdaccio/ui/commit/7548c89)) +* introduced SvgIcon ([#184](https://github.com/verdaccio/ui/issues/184)) ([8b86ded](https://github.com/verdaccio/ui/commit/8b86ded)) +* linter error fixed ([#143](https://github.com/verdaccio/ui/issues/143)) ([74576bd](https://github.com/verdaccio/ui/commit/74576bd)) +* listItem Component - Introduced ForwardRef ([#183](https://github.com/verdaccio/ui/issues/183)) ([82d7107](https://github.com/verdaccio/ui/commit/82d7107)) +* lock file was corrupted ([7bd9eb7](https://github.com/verdaccio/ui/commit/7bd9eb7)) +* media query ts ignore ([6f52838](https://github.com/verdaccio/ui/commit/6f52838)) +* remove ts ignore from some components ([b1804d7](https://github.com/verdaccio/ui/commit/b1804d7)) +* remove unnecessary ts ignore ([7a8b158](https://github.com/verdaccio/ui/commit/7a8b158)) +* remove unnecessary ts ignore ([32f4389](https://github.com/verdaccio/ui/commit/32f4389)) +* removed tsignore for AppContext ([#188](https://github.com/verdaccio/ui/issues/188)) ([d2c1130](https://github.com/verdaccio/ui/commit/d2c1130)) +* typography Component - Introduced ForwardRef ([#179](https://github.com/verdaccio/ui/issues/179)) ([a8deeb9](https://github.com/verdaccio/ui/commit/a8deeb9)) +* **api:** remove unnecessary ts ignore ([a8eb1f3](https://github.com/verdaccio/ui/commit/a8eb1f3)) +* **App:** ts ignore ([f6eb747](https://github.com/verdaccio/ui/commit/f6eb747)) +* **Developers:** remove compilation warnings ([f4da5e6](https://github.com/verdaccio/ui/commit/f4da5e6)) +* **Footer:** remove unnecessary ts ignore ([1fb0bf9](https://github.com/verdaccio/ui/commit/1fb0bf9)) +* some warnings in console ([#155](https://github.com/verdaccio/ui/issues/155)) ([583ddd5](https://github.com/verdaccio/ui/commit/583ddd5)) +* spinner typings ([3166673](https://github.com/verdaccio/ui/commit/3166673)) +* tarball download not working on Firefox and Edge ([#144](https://github.com/verdaccio/ui/issues/144)) ([f8e3013](https://github.com/verdaccio/ui/commit/f8e3013)) +* warning about modules with names differing in casing ([#148](https://github.com/verdaccio/ui/issues/148)) ([e147290](https://github.com/verdaccio/ui/commit/e147290)) + + +### Features + +* new not found component ([#170](https://github.com/verdaccio/ui/issues/170)) ([fdbdb63](https://github.com/verdaccio/ui/commit/fdbdb63)) +* **eslint-config:** add order rule in import ([ae73772](https://github.com/verdaccio/ui/commit/ae73772)) +* upgraded typescript to 3.6.3 ([#145](https://github.com/verdaccio/ui/issues/145)) ([f8a1f2c](https://github.com/verdaccio/ui/commit/f8a1f2c)) +* use React.lazy for loading components ([#158](https://github.com/verdaccio/ui/issues/158)) ([a365ec5](https://github.com/verdaccio/ui/commit/a365ec5)) +* version Component - Replaced classes by func. comp ([#129](https://github.com/verdaccio/ui/issues/129)) ([1d705da](https://github.com/verdaccio/ui/commit/1d705da)) + +### [0.3.2](https://github.com/verdaccio/ui/compare/v0.3.1...v0.3.2) (2019-09-30) + + +### Bug Fixes + +* sidebar view on small screens ([#136](https://github.com/verdaccio/ui/issues/136)) ([91d818c](https://github.com/verdaccio/ui/commit/91d818c)) + +### [0.3.1](https://github.com/verdaccio/ui/compare/v0.3.0...v0.3.1) (2019-09-29) + + +### Bug Fixes + +* **ui:** fix the hover effect on the packageItem's author area ([#137](https://github.com/verdaccio/ui/issues/137)) ([2e50981](https://github.com/verdaccio/ui/commit/2e50981)) +* correctly load font files - closes [#128](https://github.com/verdaccio/ui/issues/128) ([#134](https://github.com/verdaccio/ui/issues/134)) ([f61913c](https://github.com/verdaccio/ui/commit/f61913c)) + ## [0.3.0](https://github.com/verdaccio/ui/compare/v0.2.4...v0.3.0) (2019-09-01) diff --git a/README.md b/README.md index 1f5801f..f40b604 100755 --- a/README.md +++ b/README.md @@ -26,21 +26,39 @@ We use `>=yarn@1.13.0`, keep on mind we use lock file. For development run the following command, it will execute `webpack` and `verdaccio` to -``` +```bash yarn dev ``` The configuration file is located on `tools/_config.yaml`. Run linting tooling and test to check your code is clean before commit. -``` +> ⚠️ The development mode just emulate interaction of the UI development with a real verdaccio server, but it is not the real integration. UI is just a theme plugin dependency in the [Verdaccio project](https://github.com/verdaccio/verdaccio). + +### Before commit + +Don't forget run the following commands before commit and push your code, it will save you time. + +```bash yarn lint && yarn test ``` +#### Commits + Remember we follow the [the Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0-beta.4/). 🤓 Feel free to participate in code reviews, let us know if you want to participate in this plugin. +### End to End Testing + +Additionally, we recommend run E2E testing before push and verify your changes do not break anything. These command will run in our CI anyway. + +```bash +yarn build && yarn test:e2e +``` + +> `yarn build` will build with webpack the production files. + ## Open Collective Sponsors @@ -65,7 +83,7 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com ## Contributors -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. +This project exists thanks to all the people who contribute. [![contrubitors](https://opencollective.com/verdaccio/contributors.svg?width=890&button=true)](../../graphs/contributors) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..6311404 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,29 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "80...85" + + status: + project: + default: + target: auto + threshold: 1% + base: auto + patch: no + changes: no + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "diff,flags,tree" + behavior: default + require_changes: no \ No newline at end of file diff --git a/jest/jest.config.js b/jest/jest.config.js index 1658072..7b31e3b 100644 --- a/jest/jest.config.js +++ b/jest/jest.config.js @@ -11,7 +11,15 @@ module.exports = { rootDir: '..', setupFiles: ['/jest/setup.ts'], transformIgnorePatterns: ['/node_modules/(?!react-syntax-highlighter)'], - modulePathIgnorePatterns: ['/coverage', '/scripts', '/.circleci', '/tools', '/build', '/.vscode/'], + modulePathIgnorePatterns: [ + '/coverage', + '/scripts', + '/.circleci', + '/tools', + '/build', + '/.vscode/', + '/test/e2e/', + ], snapshotSerializers: ['enzyme-to-json/serializer', 'jest-emotion'], moduleNameMapper: { '\\.(s?css)$': '/node_modules/identity-obj-proxy', diff --git a/jest/setup.ts b/jest/setup.ts index 8d54e3d..293e0ef 100644 --- a/jest/setup.ts +++ b/jest/setup.ts @@ -15,6 +15,8 @@ global.__APP_VERSION__ = '1.0.0'; // @ts-ignore : Property '__VERDACCIO_BASENAME_UI_OPTIONS' does not exist on type 'Global'. global.__VERDACCIO_BASENAME_UI_OPTIONS = {}; +global.VERDACCIO_API_URL = 'https://verdaccio.tld'; + const customGlobal: GlobalWithFetchMock = global as GlobalWithFetchMock; customGlobal.fetch = require('jest-fetch-mock'); customGlobal.fetchMock = customGlobal.fetch; diff --git a/jest/unit/components/__mocks__/token.ts b/jest/unit/components/__mocks__/token.ts index 0f350c8..bed5d39 100644 --- a/jest/unit/components/__mocks__/token.ts +++ b/jest/unit/components/__mocks__/token.ts @@ -3,7 +3,7 @@ */ import { Base64 } from 'js-base64'; -import addHours from 'date-fns/add_hours'; +import addHours from 'date-fns/addHours'; export function generateTokenWithTimeRange(limit = 0) { const payload = { @@ -15,6 +15,11 @@ export function generateTokenWithTimeRange(limit = 0) { export function generateTokenWithExpirationAsString() { const payload = { username: 'verdaccio', exp: 'I am not a number' }; + return `xxxxxx.${Base64.encode(JSON.stringify(payload))}.xxxxxx`; +} + +export function generateInvalidToken() { + const payload = `invalidtoken`; return `xxxxxx.${Base64.encode(payload)}.xxxxxx`; } diff --git a/package.json b/package.json index 01a2bc2..5408053 100644 --- a/package.json +++ b/package.json @@ -1,64 +1,77 @@ { "name": "@verdaccio/ui-theme", - "version": "0.3.0", + "version": "0.3.6", "description": "Verdaccio User Interface", "author": { - "name": "Verdaccio Core Team" + "name": "Verdaccio Core Team", + "email": "verdaccio.npm@gmail.com" }, "repository": { "type": "git", "url": "git://github.com/verdaccio/ui" }, + "homepage": "https://verdaccio.org", "main": "index.js", "devDependencies": { - "@commitlint/cli": "8.1.0", - "@commitlint/config-conventional": "8.1.0", - "@material-ui/core": "4.3.3", - "@material-ui/icons": "4.2.1", - "@material-ui/styles": "4.3.3", - "@octokit/rest": "16.28.7", - "@testing-library/react": "9.1.3", + "@commitlint/cli": "8.2.0", + "@commitlint/config-conventional": "8.2.0", + "@emotion/core": "10.0.22", + "@emotion/styled": "10.0.23", + "@material-ui/core": "4.6.1", + "@material-ui/icons": "4.5.1", + "@octokit/rest": "16.35.0", + "@testing-library/react": "9.3.2", + "@types/autosuggest-highlight": "3.1.0", "@types/enzyme": "3.10.3", - "@types/jest": "24.0.18", - "@types/lodash": "4.14.138", - "@types/node": "12.7.3", - "@types/react": "16.9.2", - "@types/react-dom": "16.9.0", - "@types/react-router-dom": "4.3.5", - "@types/validator": "10.11.3", - "@verdaccio/babel-preset": "2.0.0", - "@verdaccio/eslint-config": "2.0.0", - "@verdaccio/types": "8.0.0", + "@types/jest": "24.0.23", + "@types/js-base64": "2.3.1", + "@types/lodash": "4.14.149", + "@types/node": "12.12.11", + "@types/react": "16.9.11", + "@types/react-autosuggest": "9.3.13", + "@types/react-dom": "16.9.4", + "@types/react-router-dom": "5.1.2", + "@types/request": "2.48.3", + "@types/validator": "12.0.0", + "@types/webpack-env": "1.14.1", + "@typescript-eslint/parser": "2.8.0", + "@verdaccio/babel-preset": "8.2.0", + "@verdaccio/commons-api": "8.3.0", + "@verdaccio/eslint-config": "8.2.0", + "@verdaccio/types": "8.3.0", "autosuggest-highlight": "3.1.1", "babel-loader": "8.0.6", "bundlesize": "0.18.0", - "codeceptjs": "2.2.1", - "codecov": "3.5.0", - "concurrently": "4.1.2", - "cross-env": "5.2.0", + "codeceptjs": "2.3.5", + "codecov": "3.6.1", + "concurrently": "5.0.0", + "cross-env": "6.0.3", "css-loader": "3.2.0", - "date-fns": "1.30.1", - "emotion": "9.2.12", + "date-fns": "2.8.1", + "detect-secrets": "1.0.5", + "emotion": "10.0.23", + "emotion-theming": "10.0.19", "enzyme": "3.10.0", - "enzyme-adapter-react-16": "1.14.0", - "enzyme-to-json": "3.4.0", - "eslint": "5.16.0", - "eslint-plugin-codeceptjs": "1.1.0", + "enzyme-adapter-react-16": "1.15.1", + "enzyme-to-json": "3.4.3", + "eslint": "6.6.0", + "eslint-plugin-codeceptjs": "1.2.0", + "eslint-plugin-import": "2.18.2", "eslint-plugin-jsx-a11y": "6.2.3", - "eslint-plugin-prettier": "3.1.0", - "eslint-plugin-react": "7.14.3", - "eslint-plugin-react-hooks": "2.0.1", - "eslint-plugin-verdaccio": "2.0.0", - "file-loader": "4.2.0", + "eslint-plugin-prettier": "3.1.1", + "eslint-plugin-react": "7.16.0", + "eslint-plugin-react-hooks": "2.3.0", + "eslint-plugin-verdaccio": "8.2.0", + "file-loader": "4.3.0", "friendly-errors-webpack-plugin": "1.7.0", - "get-stdin": "6.0.0", + "get-stdin": "7.0.0", "github-markdown-css": "3.0.1", "html-webpack-plugin": "3.2.0", - "husky": "3.0.4", + "husky": "3.1.0", "identity-obj-proxy": "3.0.0", "in-publish": "2.0.0", "jest": "24.9.0", - "jest-emotion": "10.0.14", + "jest-emotion": "10.0.17", "jest-environment-jsdom": "24.9.0", "jest-environment-jsdom-global": "1.2.0", "jest-environment-node": "24.9.0", @@ -67,45 +80,47 @@ "js-yaml": "3.13.1", "lint-staged": "8.2.1", "localstorage-memory": "1.0.3", + "lockfile-lint": "2.2.0", + "lodash": "^4.17.15", "mini-css-extract-plugin": "0.8.0", - "node-mocks-http": "1.7.6", + "node-mocks-http": "1.8.0", "normalize.css": "8.0.1", "optimize-css-assets-webpack-plugin": "5.0.3", - "ora": "3.4.0", - "prettier": "1.18.2", + "ora": "4.0.3", + "prettier": "1.19.1", "prop-types": "15.7.2", - "puppeteer": "1.17.0", - "react": "16.9.0", + "puppeteer": "2.0.0", + "react": "16.12.0", "react-autosuggest": "9.4.3", - "react-dom": "16.9.0", - "react-emotion": "9.2.12", - "react-hot-loader": "4.12.11", - "react-router": "5.0.1", - "react-router-dom": "5.0.1", - "resolve-url-loader": "3.1.0", - "rimraf": "2.6.3", + "react-dom": "16.12.0", + "react-hot-loader": "4.12.18", + "react-router-dom": "5.1.2", + "request": "2.88.0", + "resolve-url-loader": "3.1.1", + "rimraf": "3.0.0", "source-map-loader": "0.2.4", - "standard-version": "7.0.0", + "standard-version": "7.0.1", "style-loader": "1.0.0", - "stylelint": "10.1.0", - "stylelint-config-recommended": "2.2.0", + "stylelint": "12.0.0", + "stylelint-config-recommended": "3.0.0", "stylelint-config-styled-components": "0.1.1", "stylelint-processor-styled-components": "1.8.0", - "stylelint-webpack-plugin": "0.10.5", + "stylelint-webpack-plugin": "1.1.0", "supertest": "4.0.2", "typeface-roboto": "0.0.75", - "typescript": "3.5.3", + "typescript": "3.7.2", "uglifyjs-webpack-plugin": "2.2.0", - "url-loader": "2.1.0", - "validator": "11.1.0", - "verdaccio": "4.2.2", - "verdaccio-auth-memory": "8.0.0", - "verdaccio-memory": "8.0.0", - "webpack": "4.39.3", - "webpack-bundle-analyzer": "3.4.1", - "webpack-bundle-size-analyzer": "3.0.0", - "webpack-cli": "3.3.7", - "webpack-dev-server": "3.8.0", + "url-loader": "2.3.0", + "validator": "12.1.0", + "verdaccio": "4.3.5", + "verdaccio-auth-memory": "8.3.0", + "verdaccio-memory": "8.3.0", + "wait-on": "3.3.0", + "webpack": "4.41.2", + "webpack-bundle-analyzer": "3.6.0", + "webpack-bundle-size-analyzer": "3.1.0", + "webpack-cli": "3.3.10", + "webpack-dev-server": "3.9.0", "webpack-merge": "4.2.2", "whatwg-fetch": "3.0.0", "xss": "1.0.6" @@ -142,20 +157,22 @@ } ], "scripts": { - "type-check": "tsc --noEmit", + "type-check": "tsc --noEmit --pretty", "type-check:watch": "npm run type-check -- --watch", + "type-check-strict:watch": "tsc --project ./tsconfig.strict.json --noEmit --pretty --watch", "release": "standard-version -a", "test:clean": "npx jest --clearCache", "test:acceptance": "codeceptjs run --steps", "test:acceptance:server": "concurrently --kill-others \"npm run verdaccio:server\" \"npm run test:acceptance\"", + "test:e2e": "cross-env BABEL_ENV=test jest --config ./test/jest.config.e2e.js", "test": "cross-env NODE_ENV=test BABEL_ENV=test TZ=UTC jest --config ./jest/jest.config.js --maxWorkers 2 --passWithNoTests", "test:size": "bundlesize", - "lint": "npm run lint:js && npm run lint:css", + "lint": "npm run lint:js && npm run lint:css && npm run lint:lockfile", "lint:js": "npm run type-check && eslint . --ext .js,.ts,.tsx", "lint:css": "stylelint \"src/**/styles.ts\"", + "lint:lockfile": "lockfile-lint --path yarn.lock --type yarn --validate-https --allowed-hosts verdaccio npm yarn", "coverage:publish": "codecov", "pre:webpack": "rimraf static/*", - "prepublish": "in-publish && npm run build || not-in-publish", "dev:web": "cross-env BABEL_ENV=ui babel-node tools/dev.server.js", "verdaccio:server": "node tools/verdaccio.js", "build": "npm run pre:webpack && cross-env BABEL_ENV=ui webpack --config tools/webpack.prod.config.babel.js", @@ -177,10 +194,11 @@ "relative": true, "linters": { "*.{js,tsx,ts}": [ - "eslint", + "eslint . --ext .js,.ts,.tsx", "prettier --write" ], "*": [ + "detect-secrets-launcher --baseline .secrets-baseline", "git add" ] }, @@ -198,5 +216,6 @@ "type": "opencollective", "url": "https://opencollective.com/verdaccio", "logo": "https://opencollective.com/verdaccio/logo.txt" - } + }, + "dependencies": {} } diff --git a/src/App/App.test.tsx b/src/App/App.test.tsx index 4542e7b..e9a5343 100644 --- a/src/App/App.test.tsx +++ b/src/App/App.test.tsx @@ -1,26 +1,29 @@ import React from 'react'; -import { mount } from 'enzyme'; -import storage from '../utils/storage'; -import App from './App'; +import { ReactWrapper } from 'enzyme'; +import { mount } from '../utils/test-enzyme'; +import storage from '../utils/storage'; import { generateTokenWithTimeRange } from '../../jest/unit/components/__mocks__/token'; +import App from './App'; +import { AppProps } from './AppContext'; + jest.mock('../utils/storage', () => { class LocalStorageMock { - private store: object; + private store: Record; public constructor() { this.store = {}; } public clear(): void { this.store = {}; } - public getItem(key): unknown { + public getItem(key: string): unknown { return this.store[key] || null; } - public setItem(key, value): void { + public setItem(key: string, value: string): void { this.store[key] = value.toString(); } - public removeItem(key): void { + public removeItem(key: string): void { delete this.store[key]; } } @@ -32,7 +35,7 @@ jest.mock('../utils/api', () => ({ })); describe('App', () => { - let wrapper; + let wrapper: ReactWrapper<{}, AppProps, App>; beforeEach(() => { wrapper = mount(); diff --git a/src/App/App.tsx b/src/App/App.tsx index a8bd057..702d5e2 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -3,42 +3,21 @@ import isNil from 'lodash/isNil'; import storage from '../utils/storage'; import { makeLogin, isTokenExpire } from '../utils/login'; - import Loading from '../components/Loading'; import LoginModal from '../components/Login'; import Header from '../components/Header'; import { Container, Content } from '../components/Layout'; -import RouterApp from '../router'; import API from '../utils/api'; -import '../styles/typeface-roboto.css'; -import '../utils/styles/global'; -import 'normalize.css'; import Footer from '../components/Footer'; -import { FormError } from 'src/components/Login/Login'; -export const AppContext = React.createContext<{}>({}); -export const AppContextProvider = AppContext.Provider; -export const AppContextConsumer = AppContext.Consumer; +import AppRoute from './AppRoute'; +import { AppProps, AppContextProvider } from './AppContext'; -export interface AppStateInterface { - error?: FormError; - logoUrl: string; - user: { - username?: string; - }; - scope: string; - showLoginModal: boolean; - isUserLoggedIn: boolean; - packages: []; - isLoading: boolean; -} -export default class App extends Component<{}, AppStateInterface> { - public state: AppStateInterface = { - // @ts-ignore +export default class App extends Component<{}, AppProps> { + public state: AppProps = { logoUrl: window.VERDACCIO_LOGO, user: {}, - // @ts-ignore - scope: window.VERDACCIO_SCOPE ? `${window.VERDACCIO_SCOPE}:` : '', + scope: window.VERDACCIO_SCOPE || '', showLoginModal: false, isUserLoggedIn: false, packages: [], @@ -51,7 +30,7 @@ export default class App extends Component<{}, AppStateInterface> { } // eslint-disable-next-line no-unused-vars - public componentDidUpdate(_, prevState): void { + public componentDidUpdate(_: AppProps, prevState: AppProps): void { const { isUserLoggedIn } = this.state; if (prevState.isUserLoggedIn !== isUserLoggedIn) { this.loadOnHandler(); @@ -64,7 +43,6 @@ export default class App extends Component<{}, AppStateInterface> { const context = { isUserLoggedIn, packages, logoUrl, user, scope }; return ( - // @ts-ignore {isLoading ? : {this.renderContent()}} {this.renderLoginModal()} @@ -75,7 +53,7 @@ export default class App extends Component<{}, AppStateInterface> { public isUserAlreadyLoggedIn = () => { // checks for token validity const token = storage.getItem('token'); - const username = storage.getItem('username'); + const username: string = storage.getItem('username') as string; if (isTokenExpire(token) || isNil(username)) { this.handleLogout(); } else { @@ -88,11 +66,10 @@ export default class App extends Component<{}, AppStateInterface> { public loadOnHandler = async () => { try { - // @ts-ignore - this.req = await API.request('packages', 'GET'); + const packages = await API.request('packages', 'GET'); + // @ts-ignore: FIX THIS TYPE: Type 'any[]' is not assignable to type '[]' this.setState({ - // @ts-ignore - packages: this.req, + packages, isLoading: false, }); } catch (error) { @@ -105,7 +82,7 @@ export default class App extends Component<{}, AppStateInterface> { } }; - public setLoading = isLoading => + public setLoading = (isLoading: boolean) => this.setState({ isLoading, }); @@ -116,7 +93,6 @@ export default class App extends Component<{}, AppStateInterface> { */ public handleToggleLoginModal = () => { this.setState(prevState => ({ - // @ts-ignore showLoginModal: !prevState.showLoginModal, })); }; @@ -125,8 +101,7 @@ export default class App extends Component<{}, AppStateInterface> { * handles login * Required by:
*/ - public handleDoLogin = async (usernameValue, passwordValue) => { - // @ts-ignore + public handleDoLogin = async (usernameValue: string, passwordValue: string) => { const { username, token, error } = await makeLogin(usernameValue, passwordValue); if (username && token) { @@ -143,7 +118,7 @@ export default class App extends Component<{}, AppStateInterface> { } }; - public setLoggedUser = username => { + public setLoggedUser = (username: string) => { this.setState({ user: { username, @@ -168,16 +143,21 @@ export default class App extends Component<{}, AppStateInterface> { public renderLoginModal = (): ReactElement => { const { error, showLoginModal } = this.state; - return ; + return ( + + ); }; public renderContent = (): ReactElement => { return ( <> - - {this.renderHeader()} - + {this.renderHeader()}