diff --git a/.codeclimate.yml b/.codeclimate.yml index e7fbbb97..982bc473 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,5 +1,5 @@ --- -version: '2' +version: "2" checks: argument-count: enabled: false @@ -26,7 +26,7 @@ plugins: enabled: true config: config: .eslintrc.json - channel: 'eslint-7' + channel: "eslint-7" # git-legal: # enabled: true duplication: @@ -40,7 +40,7 @@ plugins: # enabled: true exclude_patterns: - dist/ - - '**/node_modules/' + - "**/node_modules/" - coverage/ - test-results/ - scripts/ diff --git a/.eslintignore b/.eslintignore index 6785831a..b6b209ec 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ +.nyc_output/**/* node_modules/**/* target/**/* coverage/** @@ -5,4 +6,5 @@ test-results/** lib/**/* dist/** .env -out \ No newline at end of file +out +report/**/* \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100755 index 00000000..983a05ef --- /dev/null +++ b/.eslintrc @@ -0,0 +1,81 @@ +{ + "parser": "babel-eslint", + "parserOptions": { + "sourceType": "module" + }, + "plugins": [ + "security", + "unicorn", + "promise", + "istanbul", + "jsdoc", + "markdown" + ], + "extends": [ + "standard", + "plugin:security/recommended", + "plugin:unicorn/recommended", + "plugin:jsdoc/recommended", + "plugin:md/recommended", + "plugin:json/recommended" + ], + "env": { + "browser": false, + "node": true + }, + "globals": { + "Promise": true + }, + "rules": { + "node/shebang": [ + "error", + { + "convertPath": { + "bin/**/*.js": ["^bin/(.+?)\\.js$", "lib/bin/$1.js"] + } + } + ], + "node/no-unsupported-features/es-syntax": [ + "error", + { + "ignores": ["modules"] + } + ], + "istanbul/no-ignore-file": "error", + "istanbul/prefer-ignore-reason": "error", + "promise/no-callback-in-promise": "off", + "security/detect-object-injection": "off" + }, + "overrides": [ + { + "files": ["src/test/**", "cucumber.js"], + "plugins": ["chai-friendly"], + "extends": ["plugin:chai-friendly/recommended"], + "globals": { + "expect": true, + "PendingError": true + }, + "rules": { + "security/detect-non-literal-fs-filename": "off", + "jsdoc/require-jsdoc": "off" + } + }, + { + "files": ["scripts/**"], + "parserOptions": { + "sourceType": "module", + "allowImportExportEverywhere": true + }, + "rules": { + "node/shebang": "off" + } + }, + { + "files": ["*.md"], + "parser": "markdown-eslint-parser", + "rules": { + "unicorn/filename-case": "off" + } + } + ] +} diff --git a/.eslintrc.yaml b/.eslintrc.yaml deleted file mode 100755 index 18059da6..00000000 --- a/.eslintrc.yaml +++ /dev/null @@ -1,72 +0,0 @@ ---- -parser: babel-eslint -parserOptions: - sourceType: module -plugins: -- prettier -- security -- unicorn -- promise -- istanbul -- jsdoc -- markdown -extends: -- eslint:recommended -- plugin:security/recommended -- plugin:eslint-comments/recommended -- plugin:unicorn/recommended -- plugin:node/recommended -- plugin:import/errors -- plugin:import/warnings -- plugin:jsdoc/recommended -- plugin:md/recommended -- plugin:json/recommended -- standard -- prettier-standard/prettier-file -env: - browser: false - node: true -globals: - Promise: true -rules: - prettier/prettier: error - node/shebang: - - error - - convertPath: - bin/**/*.js: - - "^bin/(.+?)\\.js$" - - lib/bin/$1.js - node/no-unsupported-features/es-syntax: - - error - - ignores: - - modules - istanbul/no-ignore-file: error - istanbul/prefer-ignore-reason: error - promise/no-callback-in-promise: 'off' - security/detect-object-injection: 'off' -overrides: -- files: - - src/test/** - - cucumber.js - plugins: - - chai-friendly - extends: - - plugin:chai-friendly/recommended - globals: - expect: true - PendingError: true - rules: - security/detect-non-literal-fs-filename: 'off' - jsdoc/require-jsdoc: 'off' -- files: - - scripts/** - parserOptions: - sourceType: module - allowImportExportEverywhere: true - rules: - node/shebang: 'off' -- files: - - "*.md" - parser: markdown-eslint-parser - rules: - unicorn/filename-case: 'off' diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index 419a5012..e916faab 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -9,7 +9,7 @@ on: - main pull_request: branches: - - '**' + - "**" jobs: checksecret: @@ -21,8 +21,8 @@ jobs: env: BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} run: | - echo "SECRETS_SET: ${{ env.BROWSERSTACK_USERNAME != '' }}" - echo "::set-output name=SECRETS_SET::${{ env.BROWSERSTACK_USERNAME != '' }}" + echo "SECRETS_SET: ${{ env.BROWSERSTACK_USERNAME != '' }}" + echo "::set-output name=SECRETS_SET::${{ env.BROWSERSTACK_USERNAME != '' }}" lint: if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" @@ -34,25 +34,25 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run lint + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run lint duplication: if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" @@ -66,31 +66,29 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run duplication - - uses: actions/upload-artifact@v2 - with: - name: duplication-report - path: report - + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run duplication + - uses: actions/upload-artifact@v2 + with: + name: duplication-report + path: report audit: if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" @@ -102,23 +100,23 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - run: npm audit + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + - run: npm audit security: needs: @@ -133,25 +131,25 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run security + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run security build: if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" @@ -163,28 +161,28 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run build + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run build test-node-api: - if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" + if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" runs-on: ubuntu-latest @@ -197,35 +195,35 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run lint - - run: npm run build - - run: npm run cover:node-api - - uses: actions/upload-artifact@v2 - with: - name: code-coverage-report-node-${{ matrix.node-version }} - path: coverage/node-api - - uses: actions/upload-artifact@v2 - with: - name: test-report-node-${{ matrix.node-version }} - path: test-results/node-api + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run lint + - run: npm run build + - run: npm run cover:node-api + - uses: actions/upload-artifact@v2 + with: + name: code-coverage-report-node-${{ matrix.node-version }} + path: coverage/node-api + - uses: actions/upload-artifact@v2 + with: + name: test-report-node-${{ matrix.node-version }} + path: test-results/node-api get-browser-list: needs: @@ -245,40 +243,40 @@ jobs: shell: bash steps: - # wait here so we don't overload our browserstack quota - - uses: softprops/turnstyle@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run --silent json:list-github-actions-browser-matrix:1 > browser-matrix-1.json - - id: set-matrix-1 - run: echo "::set-output name=matrix-1::$(cat browser-matrix-1.json)" - - run: npm run --silent json:list-github-actions-browser-matrix:2 > browser-matrix-2.json - - id: set-matrix-2 - run: echo "::set-output name=matrix-2::$(cat browser-matrix-2.json)" + # wait here so we don't overload our browserstack quota + - uses: softprops/turnstyle@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run --silent json:list-github-actions-browser-matrix:1 > browser-matrix-1.json + - id: set-matrix-1 + run: echo "::set-output name=matrix-1::$(cat browser-matrix-1.json)" + - run: npm run --silent json:list-github-actions-browser-matrix:2 > browser-matrix-2.json + - id: set-matrix-2 + run: echo "::set-output name=matrix-2::$(cat browser-matrix-2.json)" test-browser-api-local: if: | - ! contains(toJSON(github.event.commits.*.message), '[skip-ci]') + ! contains(toJSON(github.event.commits.*.message), '[skip-ci]') runs-on: ubuntu-latest @@ -289,34 +287,34 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - run: npm config set script-shell $(which bash) - - run: npm ci - - run: npm run cover:browser-api:chrome:local - - uses: actions/upload-artifact@v2 - with: - name: code-coverage-report-chrome-local - path: coverage/browser-api-chrome-local - - uses: actions/upload-artifact@v2 - with: - name: test-report-chrome-local - path: test-results/browser-api-chrome-local + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - run: npm config set script-shell $(which bash) + - run: npm ci + - run: npm run cover:browser-api:chrome:local + - uses: actions/upload-artifact@v2 + with: + name: code-coverage-report-chrome-local + path: coverage/browser-api-chrome-local + - uses: actions/upload-artifact@v2 + with: + name: test-report-chrome-local + path: test-results/browser-api-chrome-local test-browser-api-1: needs: @@ -338,52 +336,52 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - run: npm config set script-shell $(which bash) - - run: npm ci - - uses: 'browserstack/github-actions/setup-env@v1.0.1' - with: - username: ${{ secrets.BROWSERSTACK_USERNAME }} - access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} - - uses: 'browserstack/github-actions/setup-local@v1.0.1' - with: - local-testing: start - local-identifier: random - # browserstack can be moody at times, so let - # the pipeline have a few cracks at it - - uses: nick-invision/retry@v2 - with: - timeout_seconds: 600 - max_attempts: 3 - retry_wait_seconds: 30 - command: npm run cover:browser-api:${{ matrix.browser }}:remote - - uses: 'browserstack/github-actions/setup-local@v1.0.1' - with: - local-testing: stop - - uses: actions/upload-artifact@v2 - with: - name: code-coverage-report-${{ matrix.browser }} - path: coverage/browser-api-${{ matrix.browser }}-remote - - uses: actions/upload-artifact@v2 - with: - name: test-report-${{ matrix.browser }} - path: test-results/browser-api-${{ matrix.browser }}-remote + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - run: npm config set script-shell $(which bash) + - run: npm ci + - uses: "browserstack/github-actions/setup-env@v1.0.1" + with: + username: ${{ secrets.BROWSERSTACK_USERNAME }} + access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + - uses: "browserstack/github-actions/setup-local@v1.0.1" + with: + local-testing: start + local-identifier: random + # browserstack can be moody at times, so let + # the pipeline have a few cracks at it + - uses: nick-invision/retry@v2 + with: + timeout_seconds: 600 + max_attempts: 3 + retry_wait_seconds: 30 + command: npm run cover:browser-api:${{ matrix.browser }}:remote + - uses: "browserstack/github-actions/setup-local@v1.0.1" + with: + local-testing: stop + - uses: actions/upload-artifact@v2 + with: + name: code-coverage-report-${{ matrix.browser }} + path: coverage/browser-api-${{ matrix.browser }}-remote + - uses: actions/upload-artifact@v2 + with: + name: test-report-${{ matrix.browser }} + path: test-results/browser-api-${{ matrix.browser }}-remote test-browser-api-2: needs: @@ -405,53 +403,52 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - run: npm config set script-shell $(which bash) - - run: npm ci - - uses: 'browserstack/github-actions/setup-env@v1.0.1' - with: - username: ${{ secrets.BROWSERSTACK_USERNAME }} - access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} - - uses: 'browserstack/github-actions/setup-local@v1.0.1' - with: - local-testing: start - local-identifier: random - # browserstack can be moody at times, so let - # the pipeline have a few cracks at it - - uses: nick-invision/retry@v2 - with: - timeout_seconds: 300 - max_attempts: 3 - retry_wait_seconds: 30 - command: npm run cover:browser-api:${{ matrix.browser }}:remote - - uses: 'browserstack/github-actions/setup-local@v1.0.1' - with: - local-testing: stop - - uses: actions/upload-artifact@v2 - with: - name: code-coverage-report-${{ matrix.browser }} - path: coverage/browser-api-${{ matrix.browser }}-remote - - uses: actions/upload-artifact@v2 - with: - name: test-report-${{ matrix.browser }} - path: test-results/browser-api-${{ matrix.browser }}-remote - + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - run: npm config set script-shell $(which bash) + - run: npm ci + - uses: "browserstack/github-actions/setup-env@v1.0.1" + with: + username: ${{ secrets.BROWSERSTACK_USERNAME }} + access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + - uses: "browserstack/github-actions/setup-local@v1.0.1" + with: + local-testing: start + local-identifier: random + # browserstack can be moody at times, so let + # the pipeline have a few cracks at it + - uses: nick-invision/retry@v2 + with: + timeout_seconds: 300 + max_attempts: 3 + retry_wait_seconds: 30 + command: npm run cover:browser-api:${{ matrix.browser }}:remote + - uses: "browserstack/github-actions/setup-local@v1.0.1" + with: + local-testing: stop + - uses: actions/upload-artifact@v2 + with: + name: code-coverage-report-${{ matrix.browser }} + path: coverage/browser-api-${{ matrix.browser }}-remote + - uses: actions/upload-artifact@v2 + with: + name: test-report-${{ matrix.browser }} + path: test-results/browser-api-${{ matrix.browser }}-remote check-coverage-local: if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" @@ -467,34 +464,33 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - run: npm config set script-shell $(which bash) - - run: npm ci - - uses: actions/download-artifact@v2 - - run: mkdir -p coverage - - run: | - for directory in $(ls -d code-coverage-report-*); do - mv "${directory}" "coverage/." - done - ls -l coverage - - run: npm run report:cover - + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - run: npm config set script-shell $(which bash) + - run: npm ci + - uses: actions/download-artifact@v2 + - run: mkdir -p coverage + - run: | + for directory in $(ls -d code-coverage-report-*); do + mv "${directory}" "coverage/." + done + ls -l coverage + - run: npm run report:cover check-coverage: if: "! contains(toJSON(github.event.commits.*.message), '[skip-ci]')" @@ -511,34 +507,33 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - name: Use Node.js 12.x - uses: actions/setup-node@v1 - with: - node-version: 12.x - - - run: npm config set script-shell $(which bash) - - run: npm ci - - uses: actions/download-artifact@v2 - - run: mkdir -p coverage - - run: | - for directory in $(ls -d code-coverage-report-*); do - mv "${directory}" "coverage/." - done - ls -l coverage - - run: npm run report:cover - + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - run: npm config set script-shell $(which bash) + - run: npm ci + - uses: actions/download-artifact@v2 + - run: mkdir -p coverage + - run: | + for directory in $(ls -d code-coverage-report-*); do + mv "${directory}" "coverage/." + done + ls -l coverage + - run: npm run report:cover report-cover-to-codeclimate: needs: @@ -559,23 +554,23 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - uses: actions/download-artifact@v2 - - run: ls code-coverage-report-chrome - - run: curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - - run: chmod +x ./cc-test-reporter - - run: | - for directory in $(ls -d code-coverage-report-*); do - ./cc-test-reporter format-coverage -t lcov -o ${directory}-codeclimate.json ${directory}/lcov.info - done - - run: ./cc-test-reporter sum-coverage *-codeclimate.json -o code-coverage-report-full-codeclimate.json - - run: ./cc-test-reporter upload-coverage -i code-coverage-report-full-codeclimate.json - env: - CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + - uses: actions/checkout@v2 + - uses: actions/download-artifact@v2 + - run: ls code-coverage-report-chrome + - run: curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + - run: chmod +x ./cc-test-reporter + - run: | + for directory in $(ls -d code-coverage-report-*); do + ./cc-test-reporter format-coverage -t lcov -o ${directory}-codeclimate.json ${directory}/lcov.info + done + - run: ./cc-test-reporter sum-coverage *-codeclimate.json -o code-coverage-report-full-codeclimate.json + - run: ./cc-test-reporter upload-coverage -i code-coverage-report-full-codeclimate.json + env: + CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} publish-reports: if: "false" - + continue-on-error: true needs: @@ -588,25 +583,23 @@ jobs: shell: bash steps: - - - name: Publish Cover Report - uses: JamesIves/github-pages-deploy-action@3.7.1 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages # The branch the action should deploy to. - FOLDER: coverage/full # The folder the action should deploy. - TARGET_FOLDER: /builds/${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}/coverage - CLEAN: true # Automatically remove deleted files from the deploy branch - - - name: Publish Test Results - uses: JamesIves/github-pages-deploy-action@3.7.1 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages # The branch the action should deploy to. - FOLDER: test-results/full # The folder the action should deploy. - TARGET_FOLDER: /builds/${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}/test-results - CLEAN: true # Automatically remove deleted files from the deploy branch - + - name: Publish Cover Report + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages # The branch the action should deploy to. + FOLDER: coverage/full # The folder the action should deploy. + TARGET_FOLDER: /builds/${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}/coverage + CLEAN: true # Automatically remove deleted files from the deploy branch + + - name: Publish Test Results + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages # The branch the action should deploy to. + FOLDER: test-results/full # The folder the action should deploy. + TARGET_FOLDER: /builds/${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}/test-results + CLEAN: true # Automatically remove deleted files from the deploy branch publish: needs: @@ -629,94 +622,93 @@ jobs: shell: bash steps: - - uses: actions/checkout@v2 - - - name: Cache NPM dependencies - uses: actions/cache@v1 - with: - path: | - ~/.npm - node_modules - key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-npm-cache- - - - uses: actions/setup-node@v1 - with: - node-version: 12.x - registry-url: https://registry.npmjs.org/ - - name: Publish and Tag - run: | - npm config set script-shell $(which bash) - PACKAGE_NAME=$(node -p "require('./package.json').name") - CURRENT_VERSION=$(npm --unsafe-perm show "${PACKAGE_NAME}" version) - PACKAGE_VERSION=$(node -p "require('./package.json').version") - echo "CURRENT_VERSION=${CURRENT_VERSION}" - echo "PACKAGE_VERSION=${PACKAGE_VERSION}" - if [ "$CURRENT_VERSION" = "$PACKAGE_VERSION" ]; then - echo "Version ${PACKAGE_VERSION} has already been published" - echo "PACKAGE_VERSION=" >> $GITHUB_ENV - else - npm ci - # need to bump version in README.md to PACKAGE_VERSION - # so that the correct version appears on npmjs.com - npm run sync-readme-version - git config user.name github-actions - git config user.email github-actions@github.com - git add README.md - git commit -m "Updated version in README.md to $PACKAGE_VERSION. [skip-ci]" - npm pack - npm run dopublish + - uses: actions/checkout@v2 + + - name: Cache NPM dependencies + uses: actions/cache@v1 + with: + path: | + ~/.npm + node_modules + key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.OS }}-npm-cache- + + - uses: actions/setup-node@v1 + with: + node-version: 12.x + registry-url: https://registry.npmjs.org/ + - name: Publish and Tag + run: | + npm config set script-shell $(which bash) + PACKAGE_NAME=$(node -p "require('./package.json').name") + CURRENT_VERSION=$(npm --unsafe-perm show "${PACKAGE_NAME}" version) + PACKAGE_VERSION=$(node -p "require('./package.json').version") + echo "CURRENT_VERSION=${CURRENT_VERSION}" + echo "PACKAGE_VERSION=${PACKAGE_VERSION}" + if [ "$CURRENT_VERSION" = "$PACKAGE_VERSION" ]; then + echo "Version ${PACKAGE_VERSION} has already been published" + echo "PACKAGE_VERSION=" >> $GITHUB_ENV + else + npm ci + # need to bump version in README.md to PACKAGE_VERSION + # so that the correct version appears on npmjs.com + npm run sync-readme-version + git config user.name github-actions + git config user.email github-actions@github.com + git add README.md + git commit -m "Updated version in README.md to $PACKAGE_VERSION. [skip-ci]" + npm pack + npm run dopublish + git config user.name github-actions + git config user.email github-actions@github.com + git tag "v${PACKAGE_VERSION}" + git pull --rebase + git push --tags + echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV + fi + PACKAGE_NAME_WITHOUT_AT="${PACKAGE_NAME#@}" + echo "TGZ_NAME=${PACKAGE_NAME_WITHOUT_AT//\//-}" >> $GITHUB_ENV + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} + + - name: Create Release + if: ${{ env.PACKAGE_VERSION != '' }} + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: v${{ env.PACKAGE_VERSION }} + release_name: Release v${{ env.PACKAGE_VERSION }} + draft: false + prerelease: false + + - name: Upload Release Asset + if: ${{ env.PACKAGE_VERSION != '' }} + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./${{ env.TGZ_NAME }}-${{ env.PACKAGE_VERSION }}.tgz + asset_name: ${{ env.TGZ_NAME }}-${{ env.PACKAGE_VERSION }}.tgz + asset_content_type: application/gzip + + - name: Bump Version + run: | git config user.name github-actions git config user.email github-actions@github.com - git tag "v${PACKAGE_VERSION}" + npm --unsafe-perm --no-git-tag-version version minor -m "Version minor to %s." + npm ci + git add package.json + git add package-lock.json + # We don't want to bump the version in the README.md + # otherwise people reading on github will try to + # use the unreleased version. + # instead, we need to update it, just before we pack and tag + NEXT_VERSION=$(node -p "require('./package.json').version") + git commit -m "Version bump to $NEXT_VERSION. [skip-ci]" git pull --rebase - git push --tags - echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV - fi - PACKAGE_NAME_WITHOUT_AT="${PACKAGE_NAME#@}" - echo "TGZ_NAME=${PACKAGE_NAME_WITHOUT_AT//\//-}" >> $GITHUB_ENV - env: - NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} - - - name: Create Release - if: ${{ env.PACKAGE_VERSION != '' }} - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: v${{ env.PACKAGE_VERSION }} - release_name: Release v${{ env.PACKAGE_VERSION }} - draft: false - prerelease: false - - - name: Upload Release Asset - if: ${{ env.PACKAGE_VERSION != '' }} - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./${{ env.TGZ_NAME }}-${{ env.PACKAGE_VERSION }}.tgz - asset_name: ${{ env.TGZ_NAME }}-${{ env.PACKAGE_VERSION }}.tgz - asset_content_type: application/gzip - - - name: Bump Version - run: | - git config user.name github-actions - git config user.email github-actions@github.com - npm --unsafe-perm --no-git-tag-version version minor -m "Version minor to %s." - npm ci - git add package.json - git add package-lock.json - # We don't want to bump the version in the README.md - # otherwise people reading on github will try to - # use the unreleased version. - # instead, we need to update it, just before we pack and tag - NEXT_VERSION=$(node -p "require('./package.json').version") - git commit -m "Version bump to $NEXT_VERSION. [skip-ci]" - git pull --rebase - git push origin HEAD:main - + git push origin HEAD:main diff --git a/.nycrc-browser-api-local.yml b/.nycrc-browser-api-local.yml index a6c8b31e..20228c5f 100644 --- a/.nycrc-browser-api-local.yml +++ b/.nycrc-browser-api-local.yml @@ -1,15 +1,15 @@ -extends: '@istanbuljs/nyc-config-babel' +extends: "@istanbuljs/nyc-config-babel" all: true skip-full: false exclude: - - 'lib/**/*.js' - - 'dist/**/*.js' - - 'scripts/**/*.js' - - 'coverage/**/*.js' - - 'src/test/clients/waychaser-direct.js' - - 'src/test/clients/webdriver-manager-remote.js' - - 'src/test/clients/remote-tunneler.js' - - 'src/util/abstract.js' + - "lib/**/*.js" + - "dist/**/*.js" + - "scripts/**/*.js" + - "coverage/**/*.js" + - "src/test/clients/waychaser-direct.js" + - "src/test/clients/webdriver-manager-remote.js" + - "src/test/clients/remote-tunneler.js" + - "src/util/abstract.js" check-coverage: false reporter: diff --git a/.nycrc-browser-api-remote.yml b/.nycrc-browser-api-remote.yml index 11563953..c1ceb22f 100644 --- a/.nycrc-browser-api-remote.yml +++ b/.nycrc-browser-api-remote.yml @@ -1,14 +1,14 @@ -extends: '@istanbuljs/nyc-config-babel' +extends: "@istanbuljs/nyc-config-babel" all: true skip-full: false exclude: - - 'lib/**/*.js' - - 'dist/**/*.js' - - 'scripts/**/*.js' - - 'coverage/**/*.js' - - 'src/test/clients/waychaser-direct.js' - - 'src/test/clients/webdriver-manager-local.js' - - 'src/util/abstract.js' + - "lib/**/*.js" + - "dist/**/*.js" + - "scripts/**/*.js" + - "coverage/**/*.js" + - "src/test/clients/waychaser-direct.js" + - "src/test/clients/webdriver-manager-local.js" + - "src/util/abstract.js" check-coverage: false reporter: diff --git a/.nycrc-node-api.yml b/.nycrc-node-api.yml index ddceac51..1e6e59a8 100644 --- a/.nycrc-node-api.yml +++ b/.nycrc-node-api.yml @@ -1,15 +1,15 @@ -extends: '@istanbuljs/nyc-config-babel' +extends: "@istanbuljs/nyc-config-babel" all: true skip-full: false exclude: - - 'lib/**/*.js' - - 'dist/**/*.js' - - 'scripts/**/*.js' - - 'coverage/**/*.js' - - 'src/test/clients/remote-tunneler.js' - - 'src/test/clients/waychaser-via-webdriver.js' - - 'src/test/clients/webdriver-*.js' - - 'src/util/abstract.js' + - "lib/**/*.js" + - "dist/**/*.js" + - "scripts/**/*.js" + - "coverage/**/*.js" + - "src/test/clients/remote-tunneler.js" + - "src/test/clients/waychaser-via-webdriver.js" + - "src/test/clients/webdriver-*.js" + - "src/util/abstract.js" check-coverage: false reporter: - text-summary diff --git a/.nycrc.yml b/.nycrc.yml index 1a3d0d70..9409ce26 100644 --- a/.nycrc.yml +++ b/.nycrc.yml @@ -1,11 +1,11 @@ -extends: '@istanbuljs/nyc-config-babel' +extends: "@istanbuljs/nyc-config-babel" all: true skip-full: false exclude: - - 'lib/**/*.js' - - 'dist/**/*.js' - - 'scripts/**/*.js' - - 'coverage/**/*.js' + - "lib/**/*.js" + - "dist/**/*.js" + - "scripts/**/*.js" + - "coverage/**/*.js" check-coverage: true statements: 100 lines: 100 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..ddd8f03e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,12 @@ +.nyc_output +node_modules +target +coverage +test-results +lib +dist +.env +out +report +.vscode +*.js \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index fdc60e2d..00000000 --- a/.prettierrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "prettier-config-standard": true -} diff --git a/.vscode/settings.json b/.vscode/settings.json index 55f1f3b1..df6c2f34 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,5 +13,10 @@ "**/dist": true, "**/lib": true, "**/test-results": true - } + }, + "standard.engine": "standardx", + "standard.usePackageJson": true, + "standard.workingDirectories": [ + + ] } diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 5ee37143..6ae57669 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d43dc98..ede42acd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,3 @@ - # Contributing waychaser is released under the non-restrictive Apache 2.0 licenses and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. Contributions of all form to this repository is acceptable, as long as it follows the prescribed community guidelines enumerated below. @@ -49,11 +48,11 @@ The normal development cycle against a new backend API is: 2. run `npm run watch:test:node-api` 3. write code until the scenario passes 4. commit -5. run `npm run watch:test:browser-api` -6. write code until the scenario passes -7. commit -8. run `npm run test` to make you didn't break anything else along the way -9. run `npm run cover` and remove dead code +5. run `npm run watch:test:browser-api` +6. write code until the scenario passes +7. commit +8. run `npm run test` to make you didn't break anything else along the way +9. run `npm run cover` and remove dead code 10. commit and push ### 🚫💩 @@ -103,18 +102,20 @@ Babel requires plugins to do the transformation. Presets are the set of plugins 1. Install [VSCode](https://code.visualstudio.com/) 2. Install [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) -3. Install [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) -4. Install [Cover extension](https://marketplace.visualstudio.com/items?itemName=hindlemail.cover) +3. Install [StandardJS extension](https://marketplace.visualstudio.com/items?itemName=chenxsan.vscode-standardjs) +4. Install [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) +5. Install [Cover extension](https://marketplace.visualstudio.com/items?itemName=hindlemail.cover) ### Contribution flow A rough outline of an ideal contributors' workflow is as follows: -* Fork the current repository -* Create a topic branch from where to base the contribution. Mostly, it's the main branch. -* Make commits of logical units. -* Push changes in a topic branch to your forked repository. -* Before sending out the pull request, please sync your forked repository with the remote repository to ensure that your PR is elegant, concise. Reference the guide below: +- Fork the current repository +- Create a topic branch from where to base the contribution. Mostly, it's the main branch. +- Make commits of logical units. +- Push changes in a topic branch to your forked repository. +- Before sending out the pull request, please sync your forked repository with the remote repository to ensure that your PR is elegant, concise. Reference the guide below: + ``` git remote add upstream git@github.com:mountain-pass/waychaser.git git fetch upstream @@ -123,13 +124,15 @@ git checkout -b your_awesome_patch ... add some work git push origin your_awesome_patch ``` -* Submit a pull request to mountain-pass/waychaser and wait for the reply. + +- Submit a pull request to mountain-pass/waychaser and wait for the reply. Thanks for contributing! ## Contributor agreement By submitting changes to this repository, you are accepting: + 1. To adhear to our [code of conduct](./CODE_OF_CONDUCT.md), and 2. You are transfering copyright of your change to the waychaser project. diff --git a/README.md b/README.md index 4f35c476..8366bfdf 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ This isomorphic library is compatible with Node.js 10.x, 12.x and 14.x, Chrome, [![JavaScript Style Guide](https://cdn.rawgit.com/standard/standard/master/badge.svg)](https://github.com/standard/standard) - | Node.js
Node.js | [Chrome
Chrome](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22chrome%22}]) | [Firefox
Firefox](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22firefox%22}]) | [Safari
Safari](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22safari%22}]) | [Edge
Edge](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22edge%22}]) | [iOS
iOS](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?oses=[{%22os%22:%22ios%22}]) | [Android
Android](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?oses=[{%22os%22:%22android%22}]) | [IE
IE](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22ie%22}]) | -| --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | -| 10.x, 12.x, 14.x | latest version | latest version| latest version| latest version | latest version | latest version | 11 | +| Node.js
Node.js | [Chrome
Chrome](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22chrome%22}]) | [Firefox
Firefox](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22firefox%22}]) | [Safari
Safari](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22safari%22}]) | [Edge
Edge](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22edge%22}]) | [iOS
iOS](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?oses=[{%22os%22:%22ios%22}]) | [Android
Android](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?oses=[{%22os%22:%22android%22}]) | [IE
IE](https://automate.browserstack.com/dashboard/v2/public-build/M2lUc2Q3VFJicFR2c0N6Y0JvZE5oSXAvYlpUQ1ZPMXgxalpUK2ZtNTdPcz0tLVR3QzU5TXllbEZnemhqK2Z5VEpVQ2c9PQ==--8a61c301655735baed333d4f305980a13ef32c25?browsers=[{%22browser%22:%22ie%22}]) | +| -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 10.x, 12.x, 14.x | latest version | latest version | latest version | latest version | latest version | latest version | 11 | # ToC @@ -98,30 +98,35 @@ try { } catch (error) { // do something with `error` } - ``` ## Browser ```html - + ... ``` -## Requesting linked resources +## Requesting linked resources Level 3 REST APIs are expected to return links to related resources. Waychaser expects to find these links via [RFC 8288](https://tools.ietf.org/html/rfc8288) `link` headers. Waychaser provides methods to simplify requesting these linked resources. For instance, if the `apiResource` loaded above has a `link` with a relationship (`rel`) of `describedby`, then that resource can be retrieve using the following code + ```js const describedByResource = await apiResource.invoke("describedby"); ``` @@ -147,7 +152,7 @@ const describedByResource = await apiResource.invoke("describedby"); - [x] api docs - [x] tags in npm - [x] markdown lint -- [x] switched to JS Standard format +- [x] switched to JS Standard format - [x] split webdriver from waychaser-via - [x] split browser stack tunnel into seperate class - [x] reduce webpacking of node_modules @@ -155,8 +160,11 @@ const describedByResource = await apiResource.invoke("describedby"); - [x] add code duplication checks - [x] clean up logging - [x] add tests for follow to different resource +- [x] fix linting +- [ ] fix husky & lint-staged - [ ] add tests for multiple follows - [ ] add tests for authenticated requests +- [ ] switch to github's builtin dependabot - [ ] upgrade webpack - [ ] investigate mega-lint - [ ] fix struture of package so we get better jsdoc linting @@ -174,7 +182,7 @@ const describedByResource = await apiResource.invoke("describedby"); - [ ] integrate API docs - [ ] lots more 😂 - [ ] help [ -eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) and get better version of `security/detect-object-injectionn` that doesn't flag `for (const index in object) { object[index] = 0; }` + eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) and get better version of `security/detect-object-injectionn` that doesn't flag `for (const index in object) { object[index] = 0; }` - [ ] have a look at using https://github.com/gkouziik/eslint-plugin-security-node - [ ] try to use umd for both node and browser. https://github.com/webpack/webpack/pull/8625 - [ ] investigate using https://rollupjs.org/guide/en/ diff --git a/babel.config.js b/babel.config.js index 0a321c62..28bcb52a 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,48 +1,48 @@ module.exports = { presets: [ [ - "@babel/preset-env", + '@babel/preset-env', { corejs: { - version: "3", - proposals: true, + version: '3', + proposals: true }, - useBuiltIns: "entry", + useBuiltIns: 'entry', targets: { - ie: "11", + ie: '11', browsers: [ - "ie >= 11", - "last 2 versions", - "> 0.2%", - "maintained node versions", - ], - }, - }, - ], + 'ie >= 11', + 'last 2 versions', + '> 0.2%', + 'maintained node versions' + ] + } + } + ] ], plugins: [ - "add-module-exports", - "@babel/plugin-transform-arrow-functions", - "@babel/plugin-proposal-class-properties", + 'add-module-exports', + '@babel/plugin-transform-arrow-functions', + '@babel/plugin-proposal-class-properties', [ - "@babel/transform-runtime", + '@babel/transform-runtime', { - regenerator: true, - }, + regenerator: true + } ], - "dynamic-import-webpack", + 'dynamic-import-webpack', [ - "@babel/plugin-transform-modules-commonjs", + '@babel/plugin-transform-modules-commonjs', { - allowTopLevelThis: true, - }, - ], + allowTopLevelThis: true + } + ] ], env: { test: { - plugins: ["istanbul"], - sourceMaps: "inline", - retainLines: true, - }, - }, -}; + plugins: ['istanbul'], + sourceMaps: 'inline', + retainLines: true + } + } +} diff --git a/cucumber.js b/cucumber.js index 971c21a4..fc80bf9d 100644 --- a/cucumber.js +++ b/cucumber.js @@ -1,47 +1,46 @@ -// eslint-disable-next-line eslint-comments/disable-enable-pair /* eslint-disable security/detect-non-literal-fs-filename */ -const fs = require("fs"); +const fs = require('fs') -const FAIL_FAST = process.env.FAIL_FAST || "--fail-fast"; -const NO_STRICT = process.env.NO_STRICT || ""; +const FAIL_FAST = process.env.FAIL_FAST || '--fail-fast' +const NO_STRICT = process.env.NO_STRICT || '' -const outputDirectory = "test-results"; -fs.mkdirSync(outputDirectory, { recursive: true }); +const outputDirectory = 'test-results' +fs.mkdirSync(outputDirectory, { recursive: true }) -function getFeatureGlob(RERUN, profile) { +function getFeatureGlob (RERUN, profile) { /* istanbul ignore next: RERUN is not set for full test runs */ return fs.existsSync(RERUN) && fs.statSync(RERUN).size !== 0 ? RERUN - : `src/test/**/*.feature --tags 'not(@not-${profile})'`; + : `src/test/**/*.feature --tags 'not(@not-${profile})'` } -function generateConfig() { +function generateConfig () { const profile = process.env.npm_lifecycle_event - .replace("test:", "") - .replace(/:/g, "-"); + .replace('test:', '') + .replace(/:/g, '-') - const resultsDirectory = `${outputDirectory}/${profile}`; - fs.mkdirSync(resultsDirectory, { recursive: true }); + const resultsDirectory = `${outputDirectory}/${profile}` + fs.mkdirSync(resultsDirectory, { recursive: true }) - const RERUN = `${outputDirectory}/@cucumber-${profile}.rerun`; - const FEATURE_GLOB = getFeatureGlob(RERUN, profile); + const RERUN = `${outputDirectory}/@cucumber-${profile}.rerun` + const FEATURE_GLOB = getFeatureGlob(RERUN, profile) const FORMAT_OPTIONS = { - snippetInterface: "async-await", + snippetInterface: 'async-await', snippetSyntax: - "./node_modules/@windyroad/cucumber-js-throwables/lib/custom-cucumber-syntax.js", - }; + './node_modules/@windyroad/cucumber-js-throwables/lib/custom-cucumber-syntax.js' + } const MODULES = - "--require-module @babel/register --require-module @babel/polyfill"; - const REQUIRE_GLOB = "src/test/**/*.js"; + '--require-module @babel/register --require-module @babel/polyfill' + const REQUIRE_GLOB = 'src/test/**/*.js' const CONFIG = `${FEATURE_GLOB} --format-options '${JSON.stringify( FORMAT_OPTIONS - )}' ${MODULES} --require ${REQUIRE_GLOB} ${NO_STRICT} --format rerun:${RERUN} --format json:${resultsDirectory}/results.cucumber -f node_modules/cucumber-junit-formatter:${resultsDirectory}/results.xml ${FAIL_FAST}`; + )}' ${MODULES} --require ${REQUIRE_GLOB} ${NO_STRICT} --format rerun:${RERUN} --format json:${resultsDirectory}/results.cucumber -f node_modules/cucumber-junit-formatter:${resultsDirectory}/results.xml ${FAIL_FAST}` - return CONFIG; + return CONFIG } module.exports = { - default: generateConfig(), + default: generateConfig() // 'browser-api-chrome-local': generateConfig('browser-api-chrome-local'), // 'browser-api-chrome-remote': generateConfig( // 'browser-api-chrome-remote', @@ -70,4 +69,4 @@ module.exports = { // 'browser-api-remote', // 'internet explorer' // ), -}; +} diff --git a/package-lock.json b/package-lock.json index 54a7d03b..473227c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2435,14 +2435,38 @@ "dev": true }, "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", + "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", + "es-abstract": "^1.18.0-next.1", + "get-intrinsic": "^1.0.1", "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "array-union": { @@ -2467,13 +2491,36 @@ "dev": true }, "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "arrify": { @@ -4496,6 +4543,16 @@ } } }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", @@ -7420,25 +7477,10 @@ "lodash.zip": "^4.2.0" } }, - "eslint-config-prettier": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", - "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } - }, - "eslint-config-prettier-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-prettier-standard/-/eslint-config-prettier-standard-3.0.1.tgz", - "integrity": "sha512-myiM0WllCOBNYi1gI4AuI128eb7QVOE74H4bUVqS7oChRzbTIyHPwJwvrt/7QF++2NDNiDHAjsDVhdXtOrJyag==", - "dev": true - }, "eslint-config-standard": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.1.tgz", - "integrity": "sha512-WBBiQQZdaPyL+4sPkGWhWrHCDtvJoU195B9j8yXE9uFQnX34gMXI5CeBRm95gx3PMEZPM5OpwET10hH4F4SxCA==", + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", + "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", "dev": true }, "eslint-import-resolver-node": { @@ -7722,15 +7764,6 @@ } } }, - "eslint-plugin-prettier": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", - "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, "eslint-plugin-promise": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", @@ -7746,6 +7779,12 @@ "safe-regex": "^1.1.0" } }, + "eslint-plugin-standard": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-5.0.0.tgz", + "integrity": "sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg==", + "dev": true + }, "eslint-plugin-unicorn": { "version": "23.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-23.0.0.tgz", @@ -9069,6 +9108,17 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-own-enumerable-property-symbols": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", @@ -9090,12 +9140,6 @@ "npm-conf": "^1.1.0" } }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -15777,12 +15821,6 @@ "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", "dev": true }, - "prettier-config-standard": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prettier-config-standard/-/prettier-config-standard-1.0.1.tgz", - "integrity": "sha512-S0zuixvAFlc0zruhYEDMsjt2VG/e5S5hSbqGuxTMWA0ygjII8EP9U7c/wsCQyjjAoaYG82bUsVmaSQ6veQ+u6g==", - "dev": true - }, "prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", diff --git a/package.json b/package.json index bfd57134..8ca1e023 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,8 @@ "lint:sh": "shellcheck **/*.sh", "lint:js": "eslint .", "lint:js:fix": "npm run ${npm_lifecycle_event%:fix} -- --fix", + "lint:json+": "prettier --check .", + "lint:json+:fix": "npm run ${npm_lifecycle_event%:fix} -- --write", "lint": "npm-run-all --sequential ${npm_lifecycle_event}:*", "test:node-api": "scripts/test-node.sh", "headless:test:browser-api:chrome:local": "CI=1 npm run ${npm_lifecycle_event#headless:}", @@ -93,8 +95,7 @@ "json:list-github-actions-browser-matrix:1": "scripts/list-cover-browsers.js", "json:list-github-actions-browser-matrix:2": "scripts/list-cover-browsers.js", "sync-readme-version": "scripts/sync-readme-version.sh", - "eslint-check": "eslint --print-config src/server/index.js | eslint-config-prettier-check", - "precommit": "lint-staged && npm run test:node-api && npm run duplication", + "pre-push": "lint-staged && npm run test:node-api && npm run duplication", "npm-check-unused": "depcheck", "dopublish": "npm publish mountainpass-waychaser-${npm_package_version}.tgz --access public", "duplication": "jscpd", @@ -146,9 +147,7 @@ "dateformat": "^3.0.3", "depcheck": "^1.2.0", "eslint": "^7.13.0", - "eslint-config-prettier": "^6.5.0", - "eslint-config-prettier-standard": "^3.0.1", - "eslint-config-standard": "^16.0.1", + "eslint-config-standard": "^16.0.2", "eslint-plugin-chai-friendly": "^0.6.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.22.1", @@ -158,16 +157,16 @@ "eslint-plugin-markdown": "^1.0.2", "eslint-plugin-md": "^1.0.19", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.1.1", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-security": "^1.4.0", + "eslint-plugin-standard": "^5.0.0", "eslint-plugin-unicorn": "^23.0.0", "express": "^4.16.3", "fs-extra": "^9.0.1", "geckodriver": "^1.20.0", "html-webpack-plugin": "^4.5.0", "humanize-duration": "^3.24.0", - "husky": "^4.2.5", + "husky": "^4.3.0", "imagemin-lint-staged": "^0.4.0", "istanbul": "^0.4.5", "jscpd": "^3.3.21", @@ -181,7 +180,6 @@ "npm-run-all": "^4.1.5", "nyc": "^15.1.0", "prettier": "^2.1.0", - "prettier-config-standard": "^1.0.1", "selenium-webdriver": "^4.0.0-alpha.5", "shellcheck": "^0.4.4", "snyk": "^1.431.1", @@ -202,7 +200,7 @@ "shellcheck", "git add" ], - "*.{json,css,md}": [ + "*.{json,css,md,yaml,yml,html,less,scss}": [ "prettier --write", "git add" ], @@ -213,7 +211,7 @@ }, "husky": { "hooks": { - "pre-commit": "npm run precommit" + "pre-push": "npm run pre-push" } } } diff --git a/public/index.html b/public/index.html index bb829a15..a333b863 100755 --- a/public/index.html +++ b/public/index.html @@ -5,9 +5,12 @@ Waychaser - + diff --git a/scripts/development-server.js b/scripts/development-server.js index 96941a15..6246cea2 100644 --- a/scripts/development-server.js +++ b/scripts/development-server.js @@ -1,9 +1,9 @@ -import { getNewRouter, startServer } from "../src/test/fakes/server"; +import { getNewRouter, startServer } from '../src/test/fakes/server' -console.log("DEVELOPMENT SERVER STARTED"); +console.log('DEVELOPMENT SERVER STARTED') -startServer(); -const router = getNewRouter(); -router.route("/api").get(async (request, response) => { - response.status(200).send({ status: 200 }); -}); +startServer() +const router = getNewRouter() +router.route('/api').get(async (request, response) => { + response.status(200).send({ status: 200 }) +}) diff --git a/scripts/list-cover-browsers.js b/scripts/list-cover-browsers.js index 61ab3888..7b39fe41 100755 --- a/scripts/list-cover-browsers.js +++ b/scripts/list-cover-browsers.js @@ -1,29 +1,28 @@ #!/usr/bin/env babel-node -/* eslint-disable eslint-comments/disable-enable-pair */ /* eslint-disable security/detect-non-literal-fs-filename */ -import { scripts } from "../package.json"; +import { scripts } from '../package.json' -const BATCH_SIZE = 4; +const BATCH_SIZE = 4 const start = - (process.env.npm_lifecycle_event.replace(/.*:/, "") - 1) * BATCH_SIZE; -const end = start + BATCH_SIZE; + (process.env.npm_lifecycle_event.replace(/.*:/, '') - 1) * BATCH_SIZE +const end = start + BATCH_SIZE console.log( JSON.stringify({ include: Object.keys(scripts) // filter the scritps to just the remote ones - .filter((script) => { - return script.match(/cover:browser-api:.*:remote/); + .filter(script => { + return script.match(/cover:browser-api:.*:remote/) }) // limit the number of items returned because browser stack queue limits .slice(start, end) // extract the browser name - .map((script) => { + .map(script => { return { - browser: script.replace(/cover:browser-api:(.*):remote/, "$1"), - }; - }), + browser: script.replace(/cover:browser-api:(.*):remote/, '$1') + } + }) }) -); +) diff --git a/scripts/merge-coverage.js b/scripts/merge-coverage.js index 0ae9d901..f0d38d5f 100755 --- a/scripts/merge-coverage.js +++ b/scripts/merge-coverage.js @@ -1,26 +1,25 @@ #!/usr/bin/env babel-node -/* eslint-disable eslint-comments/disable-enable-pair */ /* eslint-disable security/detect-non-literal-fs-filename */ -import fs from "fs"; -import fsExtra from "fs-extra"; +import fs from 'fs' +import fsExtra from 'fs-extra' -const RESULTS_DIR = "coverage"; -const FULL_DIRNAME = "full"; -const FULL_DIRPATH = ".nyc_output"; +const RESULTS_DIR = 'coverage' +const FULL_DIRNAME = 'full' +const FULL_DIRPATH = '.nyc_output' -console.log(`cleaning ${FULL_DIRPATH} ...`); -fs.mkdirSync(FULL_DIRPATH, { recursive: true }); -fsExtra.emptyDirSync(FULL_DIRPATH); +console.log(`cleaning ${FULL_DIRPATH} ...`) +fs.mkdirSync(FULL_DIRPATH, { recursive: true }) +fsExtra.emptyDirSync(FULL_DIRPATH) -console.log(`copying files to ${FULL_DIRPATH} ...`); +console.log(`copying files to ${FULL_DIRPATH} ...`) fs.readdirSync(RESULTS_DIR) - .filter((n) => n !== FULL_DIRNAME) - .map((n) => `${RESULTS_DIR}/${n}/.nyc_output/`) - .filter((n) => fs.existsSync(n)) - .forEach((n) => { - fsExtra.copySync(n, FULL_DIRPATH); - }); + .filter(n => n !== FULL_DIRNAME) + .map(n => `${RESULTS_DIR}/${n}/.nyc_output/`) + .filter(n => fs.existsSync(n)) + .forEach(n => { + fsExtra.copySync(n, FULL_DIRPATH) + }) -console.log("... done"); +console.log('... done') diff --git a/src/test/clients/build-info.js b/src/test/clients/build-info.js index b37cc0af..12ea1091 100644 --- a/src/test/clients/build-info.js +++ b/src/test/clients/build-info.js @@ -1,13 +1,12 @@ -import dateFormat from "dateformat"; -import moment from "moment-timezone"; +import dateFormat from 'dateformat' +import moment from 'moment-timezone' const RUN = dateFormat(new Date(), "yyyy-MM-dd'T'hh:mm:ss.l ") + - moment().tz(Intl.DateTimeFormat().resolvedOptions().timeZone).zoneAbbr(); -export const BUILD = `${ - process.env.GITHUB_RUN_ID || - /* istanbul ignore next: only gets executed locally */ "LOCAL" -}-${ - process.env.GITHUB_RUN_NUMBER || - /* istanbul ignore next: only gets executed locally */ RUN -}`; + moment() + .tz(Intl.DateTimeFormat().resolvedOptions().timeZone) + .zoneAbbr() +export const BUILD = `${process.env.GITHUB_RUN_ID || + /* istanbul ignore next: only gets executed locally */ 'LOCAL'}-${process.env + .GITHUB_RUN_NUMBER || + /* istanbul ignore next: only gets executed locally */ RUN}` diff --git a/src/test/clients/remote-tunneler.js b/src/test/clients/remote-tunneler.js index a9bc2040..759b7069 100644 --- a/src/test/clients/remote-tunneler.js +++ b/src/test/clients/remote-tunneler.js @@ -1,45 +1,45 @@ -import logger from "../../util/logger"; -import browserstack from "browserstack-local"; -import assert from "assert"; +import logger from '../../util/logger' +import browserstack from 'browserstack-local' +import assert from 'assert' class RemoteTunneler { - async startTunnel() { + async startTunnel () { /* istanbul ignore next: does not get executed on CI */ if (!process.env.BROWSERSTACK_LOCAL_IDENTIFIER) { assert( process.env.BROWSERSTACK_ACCESS_KEY, - "process.env.BROWSERSTACK_ACCESS_KEY not set" - ); + 'process.env.BROWSERSTACK_ACCESS_KEY not set' + ) this.tunnel = new browserstack.Local({ key: process.env.BROWSERSTACK_ACCESS_KEY, - verbose: true, - }); + verbose: true + }) await new Promise((resolve, reject) => { - this.tunnel.start({}, (error) => { + this.tunnel.start({}, error => { /* istanbul ignore if: only get's executed on tunnel setup failure */ if (error) { - logger.error("error starting tunnel", error); - reject(error); + logger.error('error starting tunnel', error) + reject(error) } - logger.info("tunnel started"); - resolve(); - }); - }); - logger.info("Browserstack tunnel started"); + logger.info('tunnel started') + resolve() + }) + }) + logger.info('Browserstack tunnel started') } } - async stopTunnel() { + async stopTunnel () { /* istanbul ignore next: does not get executed on CI */ if (this.tunnel) { - await new Promise((resolve) => { - this.tunnel.stop(resolve); - }); - delete this.tunnel; + await new Promise(resolve => { + this.tunnel.stop(resolve) + }) + delete this.tunnel } } } -const instance = new RemoteTunneler(); +const instance = new RemoteTunneler() -export { instance as remoteTunneler }; +export { instance as remoteTunneler } diff --git a/src/test/clients/waychaser-direct.js b/src/test/clients/waychaser-direct.js index bc0e911f..35e63692 100644 --- a/src/test/clients/waychaser-direct.js +++ b/src/test/clients/waychaser-direct.js @@ -1,40 +1,40 @@ -import logger from "../../util/logger"; -import { waychaser } from "../../waychaser"; -import { WaychaserProxy } from "./waychaser-proxy"; +import logger from '../../util/logger' +import { waychaser } from '../../waychaser' +import { WaychaserProxy } from './waychaser-proxy' -async function handleResponse(promise) { +async function handleResponse (promise) { try { - const resource = await promise; - return { success: true, resource }; + const resource = await promise + return { success: true, resource } } catch (error) { - logger.error("error loading %s", error); - return { success: false, error }; + logger.error('error loading %s', error) + return { success: false, error } } } class WaychaserDirect extends WaychaserProxy { - async load(url) { - return handleResponse(waychaser.load(url)); + async load (url) { + return handleResponse(waychaser.load(url)) } - async getOCount(property, result) { - return result.resource[property].count(); + async getOCount (property, result) { + return result.resource[property].count() } - async findOneO(property, result, relationship) { - return result.resource[property].findOne(relationship); + async findOneO (property, result, relationship) { + return result.resource[property].findOne(relationship) } - async invokeO(property, result, relationship) { - return handleResponse(result.resource[property].invoke(relationship)); + async invokeO (property, result, relationship) { + return handleResponse(result.resource[property].invoke(relationship)) } - async invoke(result, relationship) { - return handleResponse(result.resource.invoke(relationship)); + async invoke (result, relationship) { + return handleResponse(result.resource.invoke(relationship)) } - async getUrl(result) { - return result.resource.url; + async getUrl (result) { + return result.resource.url } } -export { WaychaserDirect }; +export { WaychaserDirect } diff --git a/src/test/clients/waychaser-proxy.js b/src/test/clients/waychaser-proxy.js index 8893b77c..2c74fb36 100644 --- a/src/test/clients/waychaser-proxy.js +++ b/src/test/clients/waychaser-proxy.js @@ -1,59 +1,59 @@ -import { abstract } from "../../util/abstract"; +import { abstract } from '../../util/abstract' class WaychaserProxy { /* istanbul ignore next: only get's executed if we didn't overload this method */ - async load(url) { - abstract(); + async load (url) { + abstract() } /* istanbul ignore next: only get's executed if we didn't overload this method */ - async getOCount(property, result) { - abstract(); + async getOCount (property, result) { + abstract() } - async getOperationsCount(result) { - return this.getOCount("operations", result); + async getOperationsCount (result) { + return this.getOCount('operations', result) } - async getOpsCount(result) { - return this.getOCount("ops", result); + async getOpsCount (result) { + return this.getOCount('ops', result) } /* istanbul ignore next: only get's executed if we didn't overload this method */ - async findOneO(property, result, relationship) { - abstract(); + async findOneO (property, result, relationship) { + abstract() } - async findOneOperation(result, relationship) { - return this.findOneO("operations", result, relationship); + async findOneOperation (result, relationship) { + return this.findOneO('operations', result, relationship) } - async findOneOp(result, relationship) { - return this.findOneO("ops", result, relationship); + async findOneOp (result, relationship) { + return this.findOneO('ops', result, relationship) } /* istanbul ignore next: only get's executed if we didn't overload this method */ - async invokeO(property, result, relationship) { - abstract(); + async invokeO (property, result, relationship) { + abstract() } - async invokeOperation(result, relationship) { - return this.invokeO("operations", result, relationship); + async invokeOperation (result, relationship) { + return this.invokeO('operations', result, relationship) } - async invokeOp(result, relationship) { - return this.invokeO("ops", result, relationship); + async invokeOp (result, relationship) { + return this.invokeO('ops', result, relationship) } /* istanbul ignore next: only get's executed if we didn't overload this method */ - async invoke(result, relationship) { - abstract(); + async invoke (result, relationship) { + abstract() } /* istanbul ignore next: only get's executed if we didn't overload this method */ - async getUrl(result) { - abstract(); + async getUrl (result) { + abstract() } } -export { WaychaserProxy }; +export { WaychaserProxy } diff --git a/src/test/clients/waychaser-via-webdriver.js b/src/test/clients/waychaser-via-webdriver.js index 0a33248c..d5a3d91f 100644 --- a/src/test/clients/waychaser-via-webdriver.js +++ b/src/test/clients/waychaser-via-webdriver.js @@ -1,108 +1,108 @@ -import logger from "../../util/logger"; -import { WaychaserProxy } from "./waychaser-proxy"; +import logger from '../../util/logger' +import { WaychaserProxy } from './waychaser-proxy' class WaychaserViaWebdriver extends WaychaserProxy { - constructor(manager) { - super(); - this.manager = manager; + constructor (manager) { + super() + this.manager = manager } - async load(url) { + async load (url) { const rval = await this.manager.executeAsyncScript( /* istanbul ignore next: won't work in browser otherwise */ function (url, done) { - window.testLogger(`loading ${url}`); + window.testLogger(`loading ${url}`) window.waychaser .load(url) .then(function (resource) { - window.testLogger("success"); - window.testResults.push(resource); - window.testLogger("calling back"); - done({ success: true, id: window.testResults.length - 1 }); + window.testLogger('success') + window.testResults.push(resource) + window.testLogger('calling back') + done({ success: true, id: window.testResults.length - 1 }) + }) + .catch(error => { + window.callbackWithError(done, error) }) - .catch((error) => { - window.callbackWithError(done, error); - }); }, url - ); - logger.debug({ rval }); + ) + logger.debug({ rval }) await this.manager.driver.executeScript( /* istanbul ignore next: won't work in browser otherwise */ function () { - window.testLogger("after"); + window.testLogger('after') } - ); - return rval; + ) + return rval } - async getOCount(property, result) { + async getOCount (property, result) { return this.manager.driver.executeAsyncScript( /* istanbul ignore next: won't work in browser otherwise */ function (id, property, done) { - done(window.testResults[id][property].count()); + done(window.testResults[id][property].count()) }, result.id, property - ); + ) } - async findOneO(property, result, relationship) { + async findOneO (property, result, relationship) { return this.manager.driver.executeAsyncScript( /* istanbul ignore next: won't work in browser otherwise */ function (property, id, relationship, done) { - done(window.testResults[id][property].findOne(relationship)); + done(window.testResults[id][property].findOne(relationship)) }, property, result.id, relationship - ); + ) } - async invokeO(property, result, relationship) { + async invokeO (property, result, relationship) { return this.manager.executeAsyncScript( /* istanbul ignore next: won't work in browser otherwise */ function (id, relationship, property, done) { - window.testLogger("invokeOperation"); - window.testLogger(JSON.stringify(arguments, undefined, 2)); - const ops = window.testResults[id][property]; - window.testLogger(JSON.stringify(ops, undefined, 2)); - window.handleResponse(ops.invoke(relationship), done); + window.testLogger('invokeOperation') + window.testLogger(JSON.stringify(arguments, undefined, 2)) + const ops = window.testResults[id][property] + window.testLogger(JSON.stringify(ops, undefined, 2)) + window.handleResponse(ops.invoke(relationship), done) }, result.id, relationship, property - ); + ) } - async invoke(result, relationship) { + async invoke (result, relationship) { return this.manager.driver.executeAsyncScript( /* istanbul ignore next: won't work in browser otherwise */ function (id, relationship, done) { window.testResults[id] .invoke(relationship) .then(function (resource) { - window.testResults.push(resource); - done({ success: true, id: window.testResults.length - 1 }); + window.testResults.push(resource) + done({ success: true, id: window.testResults.length - 1 }) }) .catch(function (error) { - window.callbackWithError(done, error); - }); + window.callbackWithError(done, error) + }) }, result.id, relationship - ); + ) } - async getUrl(result) { + async getUrl (result) { return this.manager.driver.executeAsyncScript( /* istanbul ignore next: won't work in browser otherwise */ function (id, done) { - done(window.testResults[id].url); + done(window.testResults[id].url) }, result.id - ); + ) } } -export { WaychaserViaWebdriver }; +export { WaychaserViaWebdriver } diff --git a/src/test/clients/webdriver-manager-local.js b/src/test/clients/webdriver-manager-local.js index 5b69909c..463e7e71 100644 --- a/src/test/clients/webdriver-manager-local.js +++ b/src/test/clients/webdriver-manager-local.js @@ -1,53 +1,53 @@ -import { WebdriverManager } from "./webdriver-manager"; -import { Builder, Capabilities } from "selenium-webdriver"; -import logging from "selenium-webdriver/lib/logging"; -import chrome from "selenium-webdriver/chrome"; -import logger from "../../util/logger"; +import { WebdriverManager } from './webdriver-manager' +import { Builder, Capabilities } from 'selenium-webdriver' +import logging from 'selenium-webdriver/lib/logging' +import chrome from 'selenium-webdriver/chrome' +import logger from '../../util/logger' class WebdriverManagerLocal extends WebdriverManager { - async beforeAllTests() { - this.driver = await this.buildDriver(); - await this.loadWaychaserTestPage(); - await super.beforeAllTests(); + async beforeAllTests () { + this.driver = await this.buildDriver() + await this.loadWaychaserTestPage() + await super.beforeAllTests() } - async afterTest(scenario) { - await super.afterTest(scenario); + async afterTest (scenario) { + await super.afterTest(scenario) /* istanbul ignore next: only get's executed on test failure */ if ( - scenario.result.status === "failed" || - scenario.result.status === "pending" + scenario.result.status === 'failed' || + scenario.result.status === 'pending' ) { - logger.debug("waiting for browser debugging to complete..."); - await this.allowDebug(600000); + logger.debug('waiting for browser debugging to complete...') + await this.allowDebug(600000) } } /* istanbul ignore next: only get's executed on test failure */ - async allowDebug(timeout) { + async allowDebug (timeout) { if (this.driver && process.env.CI === undefined) { this.executeScript( /* istanbul ignore next: only get's executed on test failure */ function () { window.alert( `Window will remain for ${arguments[0]}ms for debugging purposes` - ); + ) }, timeout - ); + ) await this.driver.wait( () => - this.driver.getAllWindowHandles().then((handles) => { + this.driver.getAllWindowHandles().then(handles => { // logger.debug(`${handles.length} handles still open`); - return handles.length === 0; + return handles.length === 0 }), timeout - ); + ) } } - async afterAllTests() { + async afterAllTests () { // we should call this.driver.quit() here, but // doing so cause the tests to hang on my machine, waiting for // firefox to quit. @@ -56,34 +56,34 @@ class WebdriverManagerLocal extends WebdriverManager { /* istanbul ignore else: only happens on test setup failure */ if (this.driver) { /* istanbul ignore next: only firefox */ - if (this.browser !== "firefox") { - await this.driver.quit(); + if (this.browser !== 'firefox') { + await this.driver.quit() } } - await super.afterAllTests(); + await super.afterAllTests() } - async doBuildDriver() { - const prefs = new logging.Preferences(); - prefs.setLevel(logging.Type.BROWSER, logging.Level.DEBUG); + async doBuildDriver () { + const prefs = new logging.Preferences() + prefs.setLevel(logging.Type.BROWSER, logging.Level.DEBUG) - const caps = Capabilities[this.browser](); - caps.setLoggingPrefs(prefs); + const caps = Capabilities[this.browser]() + caps.setLoggingPrefs(prefs) const builder = new Builder() .withCapabilities(caps) - .forBrowser(this.browser); + .forBrowser(this.browser) /* istanbul ignore next: only get's executed on CI server */ if (process.env.CI) { - builder.setChromeOptions(new chrome.Options().headless()); + builder.setChromeOptions(new chrome.Options().headless()) } - this.driver = builder.build(); + this.driver = builder.build() - return this.driver; + return this.driver } } -const instance = new WebdriverManagerLocal(); +const instance = new WebdriverManagerLocal() -export { instance as webdriverManagerLocal }; +export { instance as webdriverManagerLocal } diff --git a/src/test/clients/webdriver-manager-remote.js b/src/test/clients/webdriver-manager-remote.js index 342fa917..e13a5ed7 100644 --- a/src/test/clients/webdriver-manager-remote.js +++ b/src/test/clients/webdriver-manager-remote.js @@ -1,107 +1,106 @@ -import webdriver from "selenium-webdriver"; +import webdriver from 'selenium-webdriver' // eslint-disable-next-line no-unused-vars -import logger from "../../util/logger"; -import { WebdriverManager } from "./webdriver-manager"; -import assert from "assert"; -import { remoteTunneler } from "./remote-tunneler"; -import { BUILD } from "./build-info"; +import logger from '../../util/logger' +import { WebdriverManager } from './webdriver-manager' +import assert from 'assert' +import { remoteTunneler } from './remote-tunneler' +import { BUILD } from './build-info' class WebdriverManagerRemote extends WebdriverManager { - constructor() { - super(); - this.tunneler = remoteTunneler; + constructor () { + super() + this.tunneler = remoteTunneler } - async beforeAllTests() { - await this.tunneler.startTunnel(); - await super.beforeAllTests(); + async beforeAllTests () { + await this.tunneler.startTunnel() + await super.beforeAllTests() } - async beforeTest(scenario) { - this.driver = await this.buildDriver(scenario.pickle.name); - logger.debug("driver built"); - await this.loadWaychaserTestPage(); + async beforeTest (scenario) { + this.driver = await this.buildDriver(scenario.pickle.name) + logger.debug('driver built') + await this.loadWaychaserTestPage() - await super.beforeTest(scenario); + await super.beforeTest(scenario) } - async afterTest(scenario) { - await super.afterTest(scenario); + async afterTest (scenario) { + await super.afterTest(scenario) try { - logger.debug("sending test results...", scenario.result.status); - await this.sendTestResult(scenario.result.status); + logger.debug('sending test results...', scenario.result.status) + await this.sendTestResult(scenario.result.status) } catch (error) { /* istanbul ignore next: only get's executed on test framework failure */ - logger.error("coverage", error); + logger.error('coverage', error) } - logger.debug("...sent"); + logger.debug('...sent') - await this.driver.quit(); - delete this.driver; + await this.driver.quit() + delete this.driver } - async doBuildDriver(name) { + async doBuildDriver (name) { assert( process.env.BROWSERSTACK_USERNAME, - "process.env.BROWSERSTACK_USERNAME not set" - ); + 'process.env.BROWSERSTACK_USERNAME not set' + ) assert( process.env.BROWSERSTACK_ACCESS_KEY, - "process.env.BROWSERSTACK_ACCESS_KEY not set" - ); + 'process.env.BROWSERSTACK_ACCESS_KEY not set' + ) /* istanbul ignore next: branching depends on if running on CI or not */ const projectName = - process.env.npm_package_name + - (process.env.GITHUB_RUN_ID ? "" : "-LOCAL"); + process.env.npm_package_name + (process.env.GITHUB_RUN_ID ? '' : '-LOCAL') /* istanbul ignore next: branching depends on if running on CI or not */ - const localIdentifier = process.env.BROWSERSTACK_LOCAL_IDENTIFIER; + const localIdentifier = process.env.BROWSERSTACK_LOCAL_IDENTIFIER const capabilities = { - "bstack:options": { - os: "Any", + 'bstack:options': { + os: 'Any', projectName, buildName: BUILD, sessionName: name, - local: "true", + local: 'true', ...(localIdentifier && { - localIdentifier, + localIdentifier }), - debug: "true", - consoleLogs: "verbose", - networkLogs: "true", - seleniumVersion: "3.14.0", + debug: 'true', + consoleLogs: 'verbose', + networkLogs: 'true', + seleniumVersion: '3.14.0', userName: process.env.BROWSERSTACK_USERNAME, - accessKey: process.env.BROWSERSTACK_ACCESS_KEY, + accessKey: process.env.BROWSERSTACK_ACCESS_KEY }, browserName: this.browser, - ...(this.browser !== "iphone" && - this.browser !== "android" && { browserVersion: "latest" }), - }; + ...(this.browser !== 'iphone' && + this.browser !== 'android' && { browserVersion: 'latest' }) + } this.driver = new webdriver.Builder() - .usingServer("https://hub-cloud.browserstack.com/wd/hub") + .usingServer('https://hub-cloud.browserstack.com/wd/hub') .withCapabilities(capabilities) - .build(); - await this.driver.manage().setTimeouts({ script: 40000 }); - return this.driver; + .build() + await this.driver.manage().setTimeouts({ script: 40000 }) + return this.driver } - async sendTestResult(status) { + async sendTestResult (status) { /* istanbul ignore else: only get's executed on driver setup failure */ if (this.driver) { await this.driver.executeScript( `browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"${status}"}}` - ); + ) } } - async afterAllTests() { - super.afterAllTests(); - await this.tunneler.stopTunnel(); + async afterAllTests () { + super.afterAllTests() + await this.tunneler.stopTunnel() } } -const instance = new WebdriverManagerRemote(); +const instance = new WebdriverManagerRemote() -export { instance as webdriverManagerRemote }; +export { instance as webdriverManagerRemote } diff --git a/src/test/clients/webdriver-manager.js b/src/test/clients/webdriver-manager.js index f1d27bfb..21e11bce 100644 --- a/src/test/clients/webdriver-manager.js +++ b/src/test/clients/webdriver-manager.js @@ -1,234 +1,234 @@ -import logger from "../../util/logger"; -import logging from "selenium-webdriver/lib/logging"; -import { BROWSER_PORT, BROWSER_HOST } from "../config"; -import { utils } from "istanbul"; -import * as babel from "@babel/core"; -import babelConfig from "../../../babel.config"; -import { abstract } from "../../util/abstract"; +import logger from '../../util/logger' +import logging from 'selenium-webdriver/lib/logging' +import { BROWSER_PORT, BROWSER_HOST } from '../config' +import { utils } from 'istanbul' +import * as babel from '@babel/core' +import babelConfig from '../../../babel.config' +import { abstract } from '../../util/abstract' -delete babelConfig.env.test; +delete babelConfig.env.test /* global __coverage__ */ // based on https://github.com/gotwarlost/istanbul-middleware/blob/dfbca20f361b9c2b79934e395fd266d95d9c5af5/lib/core.js#L217 -function mergeClientCoverage(object) { +function mergeClientCoverage (object) { /* istanbul ignore else: else is only taken if coverage is off */ if (process.env.COVERAGE) { for (const [filePath, added] of Object.entries(object)) { - const original = __coverage__[filePath.toString()]; + const original = __coverage__[filePath.toString()] /* istanbul ignore if: needed for IE but IE doesn't give is coverage */ if (added.s === null) { - added.s = {}; + added.s = {} } /* istanbul ignore if: needed for IE but IE doesn't give is coverage */ if (added.f === null) { - added.f = {}; + added.f = {} } /* istanbul ignore if: needed for IE but IE doesn't give is coverage */ if (added.b === null) { - added.b = {}; + added.b = {} } __coverage__[filePath.toString()] = utils.mergeFileCoverage( original, added - ); + ) } } } class WebdriverManager { - async loadWaychaserTestPage() { - logger.debug("loading page..."); - await this.driver.get(`http://${BROWSER_HOST}:${BROWSER_PORT}`); - logger.debug("...page loaded"); + async loadWaychaserTestPage () { + logger.debug('loading page...') + await this.driver.get(`http://${BROWSER_HOST}:${BROWSER_PORT}`) + logger.debug('...page loaded') - logger.debug("waiting for waychaser..."); + logger.debug('waiting for waychaser...') await this.driver.wait(() => { return this.executeScript( /* istanbul ignore next: won't work in browser otherwise */ function () { - return window.waychaser !== undefined; + return window.waychaser !== undefined } - ); - }, 40000); + ) + }, 40000) - logger.debug("setting up logger function..."); + logger.debug('setting up logger function...') await this.executeScript( /* istanbul ignore next: won't work in browser otherwise */ function () { - window.testResults = []; - window.testLogs = []; + window.testResults = [] + window.testLogs = [] window.testLogger = function (arguments_) { - console.log(arguments_); - window.testLogs.push(arguments_); + console.log(arguments_) + window.testLogs.push(arguments_) // eslint-disable-next-line unicorn/prefer-query-selector - var logsElement = document.getElementById("logs"); // eslint-disable-line no-var - logsElement.textContent += arguments_; - logsElement.textContent += "\n"; - }; + var logsElement = document.getElementById('logs') // eslint-disable-line no-var + logsElement.textContent += arguments_ + logsElement.textContent += '\n' + } window.callbackWithError = (done, error) => { - window.testLogger("error: " + error.toString()); - window.testResults.push(error); + window.testLogger('error: ' + error.toString()) + window.testResults.push(error) done({ success: false, - id: window.testResults.length - 1, + id: window.testResults.length - 1 // uncomenting these causes the andriod tests to fail // error: error.toString(), // stackTrace: error.stack, - }); - }; + }) + } window.handleResponse = function (promise, done) { return promise .then(function (resource) { - window.testLogger("huzzah!"); - window.testResults.push(resource); - done({ success: true, id: window.testResults.length - 1 }); + window.testLogger('huzzah!') + window.testResults.push(resource) + done({ success: true, id: window.testResults.length - 1 }) }) .catch(function (error) { - window.callbackWithError(done, error); - }); - }; + window.callbackWithError(done, error) + }) + } } - ); + ) } - async beforeAllTests() {} + async beforeAllTests () {} - async executeScript(script, ...arguments_) { - const code = `(${script}).apply(window, arguments)`; + async executeScript (script, ...arguments_) { + const code = `(${script}).apply(window, arguments)` const transformed = await ( await babel.transformAsync(code, babelConfig) - ).code.replace('"use strict";\n\n', "return "); - return this.driver.executeScript(transformed, ...arguments_); + ).code.replace('"use strict";\n\n', 'return ') + return this.driver.executeScript(transformed, ...arguments_) } - async executeAsyncScript(script, ...arguments_) { - const code = `(${script}).apply(window, arguments)`; + async executeAsyncScript (script, ...arguments_) { + const code = `(${script}).apply(window, arguments)` // logger.debug({ code }); const transformed = await ( await babel.transformAsync(code, babelConfig) - ).code.replace('"use strict";\n\n', "return "); - logger.debug({ transformed }); + ).code.replace('"use strict";\n\n', 'return ') + logger.debug({ transformed }) const returnedFromBrowser = await this.driver.executeAsyncScript( transformed, ...arguments_ - ); - logger.debug({ returnedFromBrowser }); - return returnedFromBrowser; + ) + logger.debug({ returnedFromBrowser }) + return returnedFromBrowser } - async beforeTest(scenario) { + async beforeTest (scenario) { await this.executeScript( /* istanbul ignore next: won't work in browser otherwise */ function () { - window.testResults = []; - const element = document.querySelector("#test-name"); - element.textContent = arguments[0].pickle.name; + window.testResults = [] + const element = document.querySelector('#test-name') + element.textContent = arguments[0].pickle.name }, scenario - ); + ) - logger.debug("set test name to '%s'", scenario.pickle.name); + logger.debug("set test name to '%s'", scenario.pickle.name) } - async afterTest() { - await this.getBrowserLogs(); + async afterTest () { + await this.getBrowserLogs() - logger.debug("downloading coverage from browser..."); + logger.debug('downloading coverage from browser...') try { - await this.loadCoverage(); + await this.loadCoverage() } catch (error) { /* istanbul ignore next: only get's executed on test framework failure */ - logger.error("coverage", error); + logger.error('coverage', error) } - logger.debug("...coverage downloaded"); + logger.debug('...coverage downloaded') } - async getBrowserLogs() { + async getBrowserLogs () { // getting logs appears to be only possible wtih chrome /* istanbul ignore else: doesn't get executed on CI */ - if (this.browser === "chrome") { + if (this.browser === 'chrome') { await this.driver .manage() .logs() .get(logging.Type.BROWSER) - .then((entries) => { - entries.forEach((entry) => { - logger.browser("[%s] %s", entry.level.name, entry.message); - }); - }); + .then(entries => { + entries.forEach(entry => { + logger.browser('[%s] %s', entry.level.name, entry.message) + }) + }) } } - async afterAllTests() {} + async afterAllTests () {} - async clearRemoteCoverage() { + async clearRemoteCoverage () { /* istanbul ignore else: else is only taken if coverage is off */ if (process.env.COVERAGE) { await this.executeScript( /* istanbul ignore next: won't work in browser otherwise */ function () { if ( - typeof window.__coverage__ !== "undefined" && + typeof window.__coverage__ !== 'undefined' && window.__coverage__ !== null ) { for (const f in window.__coverage__) { - const coverage = window.__coverage__[f]; + const coverage = window.__coverage__[f] for (const index in coverage.b) { - coverage.b[index] = [0, 0]; + coverage.b[index] = [0, 0] } for (const index in coverage.f) { - coverage.f[index] = 0; + coverage.f[index] = 0 } for (const index in coverage.s) { - coverage.s[index] = 0; + coverage.s[index] = 0 } } } } - ); + ) } } - async loadCoverage() { + async loadCoverage () { /* istanbul ignore else: only get's executed when there are fatal web driver issues */ if (this.driver && process.env.COVERAGE) { try { const remoteCoverage = await this.executeScript( /* istanbul ignore next: won't work in browser otherwise */ function () { - return window.__coverage__; + return window.__coverage__ } - ); - mergeClientCoverage(remoteCoverage); + ) + mergeClientCoverage(remoteCoverage) // clear coverage - await this.clearRemoteCoverage(); + await this.clearRemoteCoverage() } catch (error) { /* istanbul ignore next: only get's executed when there are instanbul issues */ - logger.error(error); + logger.error(error) /* istanbul ignore next: only get's executed when there are instanbul issues */ - throw error; + throw error } } } /* istanbul ignore next: only get's executed if we didn't overload this method */ - async doBuildDriver() { - abstract(); + async doBuildDriver () { + abstract() } - async buildDriver() { + async buildDriver () { try { - return this.doBuildDriver(); + return this.doBuildDriver() } catch (error) { /* istanbul ignore next: only get's executed when there are web driver issues */ - logger.error("error getting browser", error); + logger.error('error getting browser', error) /* istanbul ignore next: only get's executed when there are web driver issues */ - throw error; + throw error } } } -export { WebdriverManager }; +export { WebdriverManager } diff --git a/src/test/config.js b/src/test/config.js index a7d1ce31..fb4317e0 100644 --- a/src/test/config.js +++ b/src/test/config.js @@ -1,24 +1,25 @@ -import assert from "assert"; +import assert from 'assert' -export const BROWSER_PORT = Number.parseInt(process.env.BROWSER_PORT); +export const BROWSER_PORT = Number.parseInt(process.env.BROWSER_PORT) -assert(process.env.API_PORT, "'API_PORT' environment variable must be set"); -export const API_PORT = Number.parseInt(process.env.API_PORT); +assert(process.env.API_PORT, "'API_PORT' environment variable must be set") +export const API_PORT = Number.parseInt(process.env.API_PORT) // nodejs tests access the API directly via the API_PORT // browser tests access the API via the BROWSER_PORT, which proxies the API_PORT // doing it this way means we don't have to dick around with cors export const API_ACCESS_PORT = - process.env.npm_lifecycle_event === "test:node-api" ? API_PORT : BROWSER_PORT; + process.env.npm_lifecycle_event === 'test:node-api' ? API_PORT : BROWSER_PORT assert( - !process.env.npm_lifecycle_event.startsWith("test:browser-api") || + !process.env.npm_lifecycle_event.startsWith('test:browser-api') || process.env.BROWSER_PORT, "'BROWSER_PORT' environment variable must be set when testing browser api" -); +) -export const BROWSER_HOST = process.env.npm_lifecycle_event.includes("iphone") - ? /* istanbul ignore next: only get's executed on CI server */ - "bs-local.com" - : "localhost"; +export const BROWSER_HOST = process.env.npm_lifecycle_event.includes( + 'iphone' +) /* istanbul ignore next: only get's executed on CI server */ + ? 'bs-local.com' + : 'localhost' -export const API_ACCESS_HOST = BROWSER_HOST; +export const API_ACCESS_HOST = BROWSER_HOST diff --git a/src/test/fakes/server.js b/src/test/fakes/server.js index f65b9448..74f8248d 100644 --- a/src/test/fakes/server.js +++ b/src/test/fakes/server.js @@ -1,39 +1,39 @@ -import logger from "../../util/logger"; -import { createServer } from "http"; -import { API_PORT } from "../config"; +import logger from '../../util/logger' +import { createServer } from 'http' +import { API_PORT } from '../config' -import express from "express"; +import express from 'express' -export const app = express(); +export const app = express() -let router; +let router -export function getNewRouter() { - router = express.Router(); - return router; +export function getNewRouter () { + router = express.Router() + return router } app.use(function (request, response, next) { - router(request, response, next); -}); + router(request, response, next) +}) -export let server; +export let server -export function stopServer() { +export function stopServer () { if (server !== undefined) { - server.close(); + server.close() } } -export function startServer() { - stopServer(); - server = createServer(app); +export function startServer () { + stopServer() + server = createServer(app) server.listen(API_PORT, function () { logger.info( - "📡 Server is listening on port %d ( http://localhost:%d ) ", + '📡 Server is listening on port %d ( http://localhost:%d ) ', API_PORT, API_PORT - ); - }); - return app; + ) + }) + return app } diff --git a/src/test/load-resource.steps.js b/src/test/load-resource.steps.js index cc8954af..dc151df1 100644 --- a/src/test/load-resource.steps.js +++ b/src/test/load-resource.steps.js @@ -1,47 +1,47 @@ -import { expect } from "chai"; -import { When, Then, Before } from "cucumber"; -import logger from "../util/logger"; -import { API_ACCESS_PORT, API_ACCESS_HOST } from "./config"; +import { expect } from 'chai' +import { When, Then, Before } from 'cucumber' +import logger from '../util/logger' +import { API_ACCESS_PORT, API_ACCESS_HOST } from './config' -When("waychaser loads that resource", async function () { - await this.loadCurrentResource(); -}); +When('waychaser loads that resource', async function () { + await this.loadCurrentResource() +}) When("waychaser loads a resource that's not available", async function () { - await this.loadResourceByUrl(`http://${API_ACCESS_HOST}:33556/api`); -}); + await this.loadResourceByUrl(`http://${API_ACCESS_HOST}:33556/api`) +}) -Then("it will have loaded successfully", async function () { - expect(this.result.success).to.be.true; -}); +Then('it will have loaded successfully', async function () { + expect(this.result.success).to.be.true +}) -Then("it will NOT have loaded successfully", async function () { - expect(this.result.success).to.be.false; -}); +Then('it will NOT have loaded successfully', async function () { + expect(this.result.success).to.be.false +}) -When("waychaser successfully loads that resource", async function () { - await this.loadCurrentResource(); - expect(this.result.success).to.be.true; -}); +When('waychaser successfully loads that resource', async function () { + await this.loadCurrentResource() + expect(this.result.success).to.be.true +}) -When("waychaser successfully loads the latter resource", async function () { - await this.loadCurrentResource(); - expect(this.result.success).to.be.true; -}); +When('waychaser successfully loads the latter resource', async function () { + await this.loadCurrentResource() + expect(this.result.success).to.be.true +}) Before(async function () { this.loadCurrentResource = async function () { - return this.loadResourceByPath(this.currentResourceRoute); - }; + return this.loadResourceByPath(this.currentResourceRoute) + } this.loadResourceByPath = async function (path) { return this.loadResourceByUrl( `http://${API_ACCESS_HOST}:${API_ACCESS_PORT}${path}` - ); - }; + ) + } this.loadResourceByUrl = async function (url) { - logger.debug(`loading ${url}`); - this.result = await this.waychaserProxy.load(url); - }; -}); + logger.debug(`loading ${url}`) + this.result = await this.waychaserProxy.load(url) + } +}) diff --git a/src/test/operations.steps.js b/src/test/operations.steps.js index bc8457e5..3fb4d935 100644 --- a/src/test/operations.steps.js +++ b/src/test/operations.steps.js @@ -1,168 +1,165 @@ -import { assert, expect } from "chai"; -import { When, Then } from "cucumber"; -import logger from "../util/logger"; +import { assert, expect } from 'chai' +import { When, Then } from 'cucumber' +import logger from '../util/logger' -Then("the loaded resource will have no operations", async function () { +Then('the loaded resource will have no operations', async function () { const operationsCount = await this.waychaserProxy.getOperationsCount( this.result - ); - expect(operationsCount).to.equal(0); - const opsCount = await this.waychaserProxy.getOpsCount(this.result); - expect(opsCount).to.equal(0); -}); + ) + expect(operationsCount).to.equal(0) + const opsCount = await this.waychaserProxy.getOpsCount(this.result) + expect(opsCount).to.equal(0) +}) -Then("the loaded resource will have {int} operation(s)", async function ( +Then('the loaded resource will have {int} operation(s)', async function ( expected ) { const operationsCount = await this.waychaserProxy.getOperationsCount( this.result - ); - expect(operationsCount).to.equal(expected); - const opsCount = await this.waychaserProxy.getOpsCount(this.result); - expect(opsCount).to.equal(expected); -}); + ) + expect(operationsCount).to.equal(expected) + const opsCount = await this.waychaserProxy.getOpsCount(this.result) + expect(opsCount).to.equal(expected) +}) -Then("the loaded resource will have {string} operation", async function ( +Then('the loaded resource will have {string} operation', async function ( relationship ) { - await expectFindOne.bind(this)(relationship, assert.isNotNull); -}); + await expectFindOne.bind(this)(relationship, assert.isNotNull) +}) Then("it won't have a(n) {string} operation", async function (relationship) { - await expectFindOne.bind(this)(relationship, assert.isNull); -}); + await expectFindOne.bind(this)(relationship, assert.isNull) +}) -When("we successfully invoke the {string} operation", async function ( +When('we successfully invoke the {string} operation', async function ( relationship ) { - this.previousResult = this.result; + this.previousResult = this.result this.operationResult = await this.waychaserProxy.invokeOperation( this.result, relationship - ); - expect(this.operationResult.success).to.be.true; + ) + expect(this.operationResult.success).to.be.true this.operationResultLokiStyle = await this.waychaserProxy.invokeOperation( this.result, { rel: relationship } - ); - expect(this.operationResultLokiStyle.success).to.be.true; + ) + expect(this.operationResultLokiStyle.success).to.be.true - this.opResult = await this.waychaserProxy.invokeOp(this.result, relationship); - logger.debug("this.opResult", this.opResult); - expect(this.opResult.success).to.be.true; + this.opResult = await this.waychaserProxy.invokeOp(this.result, relationship) + logger.debug('this.opResult', this.opResult) + expect(this.opResult.success).to.be.true this.opResultLokiStyle = await this.waychaserProxy.invokeOp(this.result, { - rel: relationship, - }); - expect(this.opResultLokiStyle.success).to.be.true; + rel: relationship + }) + expect(this.opResultLokiStyle.success).to.be.true this.resultLokiStyle = await this.waychaserProxy.invoke(this.result, { - rel: relationship, - }); - expect(this.resultLokiStyle.success).to.be.true; + rel: relationship + }) + expect(this.resultLokiStyle.success).to.be.true - this.result = await this.waychaserProxy.invoke(this.result, relationship); - expect(this.result.success).to.be.true; -}); + this.result = await this.waychaserProxy.invoke(this.result, relationship) + expect(this.result.success).to.be.true +}) -When("we invoke the {string} operation", async function (relationship) { - this.previousResult = this.result; +When('we invoke the {string} operation', async function (relationship) { + this.previousResult = this.result this.operationResult = await this.waychaserProxy.invokeOperation( this.previousResult, relationship - ); + ) this.operationResultLokiStyle = await this.waychaserProxy.invokeOperation( this.previousResult, { rel: relationship } - ); + ) this.opResult = await this.waychaserProxy.invokeOp( this.previousResult, relationship - ); + ) this.opResultLokiStyle = await this.waychaserProxy.invokeOp( this.previousResult, { - rel: relationship, + rel: relationship } - ); + ) this.result = await this.waychaserProxy.invoke( this.previousResult, relationship - ); + ) this.resultLokiStyle = await this.waychaserProxy.invoke(this.previousResult, { - rel: relationship, - }); -}); + rel: relationship + }) +}) -Then("the same resource will be returned", async function () { - await checkUrls.bind(this)(); -}); +Then('the same resource will be returned', async function () { + await checkUrls.bind(this)() +}) -Then("the former resource will be returned", async function () { - await checkUrls.bind(this)(); -}); +Then('the former resource will be returned', async function () { + await checkUrls.bind(this)() +}) -async function checkUrls() { +async function checkUrls () { const previousResultUrl = await this.waychaserProxy.getUrl( this.previousResult - ); + ) const operationResultUrl = await this.waychaserProxy.getUrl( this.operationResult - ); + ) const operationResultLokiStyleUrl = await this.waychaserProxy.getUrl( this.operationResultLokiStyle - ); - const opResultUrl = await this.waychaserProxy.getUrl(this.opResult); - const opResultLokiStyleUrl = await this.waychaserProxy.getUrl(this.opResult); - const resultUrl = await this.waychaserProxy.getUrl(this.result); - const resultLokiStyleUrl = await this.waychaserProxy.getUrl(this.result); - expect(operationResultUrl).to.deep.equal(previousResultUrl); - expect(operationResultLokiStyleUrl).to.deep.equal(previousResultUrl); - expect(opResultUrl).to.deep.equal(previousResultUrl); - expect(opResultLokiStyleUrl).to.deep.equal(previousResultUrl); - expect(resultUrl).to.deep.equal(previousResultUrl); - expect(resultLokiStyleUrl).to.deep.equal(previousResultUrl); + ) + const opResultUrl = await this.waychaserProxy.getUrl(this.opResult) + const opResultLokiStyleUrl = await this.waychaserProxy.getUrl(this.opResult) + const resultUrl = await this.waychaserProxy.getUrl(this.result) + const resultLokiStyleUrl = await this.waychaserProxy.getUrl(this.result) + expect(operationResultUrl).to.deep.equal(previousResultUrl) + expect(operationResultLokiStyleUrl).to.deep.equal(previousResultUrl) + expect(opResultUrl).to.deep.equal(previousResultUrl) + expect(opResultLokiStyleUrl).to.deep.equal(previousResultUrl) + expect(resultUrl).to.deep.equal(previousResultUrl) + expect(resultLokiStyleUrl).to.deep.equal(previousResultUrl) } -async function expectFindOne(relationship, expectation) { +async function expectFindOne (relationship, expectation) { const { foundOperation, foundOperationLokiStyle, foundOp, - foundOpLokiStyle, - } = await findOne.bind(this)(relationship); - expectation(foundOperation); - expectation(foundOperationLokiStyle); - expectation(foundOp); - expectation(foundOpLokiStyle); + foundOpLokiStyle + } = await findOne.bind(this)(relationship) + expectation(foundOperation) + expectation(foundOperationLokiStyle) + expectation(foundOp) + expectation(foundOpLokiStyle) } -async function findOne(relationship) { +async function findOne (relationship) { const foundOperation = await this.waychaserProxy.findOneOperation( this.result, relationship - ); + ) const foundOperationLokiStyle = await this.waychaserProxy.findOneOperation( this.result, { rel: relationship } - ); + ) - const foundOp = await this.waychaserProxy.findOneOp( - this.result, - relationship - ); + const foundOp = await this.waychaserProxy.findOneOp(this.result, relationship) const foundOpLokiStyle = await this.waychaserProxy.findOneOp(this.result, { - rel: relationship, - }); - return { foundOperation, foundOperationLokiStyle, foundOp, foundOpLokiStyle }; + rel: relationship + }) + return { foundOperation, foundOperationLokiStyle, foundOp, foundOpLokiStyle } } diff --git a/src/test/resource.steps.js b/src/test/resource.steps.js index 59c19b47..975b7016 100644 --- a/src/test/resource.steps.js +++ b/src/test/resource.steps.js @@ -1,110 +1,113 @@ -import { Given, Before } from "cucumber"; -import LinkHeader from "http-link-header"; -import { API_ACCESS_HOST } from "./config"; +import { Given, Before } from 'cucumber' +import LinkHeader from 'http-link-header' +import { API_ACCESS_HOST } from './config' import { uniqueNamesGenerator, adjectives, colors, - animals, -} from "unique-names-generator"; + animals +} from 'unique-names-generator' const randomApiPath = () => { return ( - "/api/" + + '/api/' + uniqueNamesGenerator({ - dictionaries: [adjectives, colors, animals], + dictionaries: [adjectives, colors, animals] }) - ); -}; + ) +} -Given("a resource returning status code {int}", async function (status) { - this.currentResourceRoute = await this.createRoute(randomApiPath(), status); -}); +Given('a resource returning status code {int}', async function (status) { + this.currentResourceRoute = await this.createRoute(randomApiPath(), status) +}) -Given("a resource with no operations", async function () { - this.currentResourceRoute = randomApiPath(); +Given('a resource with no operations', async function () { + this.currentResourceRoute = randomApiPath() await this.router .route(this.currentResourceRoute) .get(async (request, response) => { - response.status(200).send({ status: 200 }); - }); -}); + response.status(200).send({ status: 200 }) + }) +}) -Given("a resource with a {string} operation", async function (relationship) { +Given('a resource with a {string} operation', async function (relationship) { this.currentResourceRoute = await this.createRoute( randomApiPath(), 200, relationship - ); -}); + ) +}) Given( - "a resource with a {string} operation that returns itself", + 'a resource with a {string} operation that returns itself', async function (relationship) { - this.currentResourceRoute = randomApiPath(); + this.currentResourceRoute = randomApiPath() await this.createRoute( this.currentResourceRoute, 200, relationship, this.currentResourceRoute - ); + ) } -); +) Given( - "a resource with a {string} operation that returns an error", + 'a resource with a {string} operation that returns an error', async function (relationship) { this.currentResourceRoute = await this.createRoute( randomApiPath(), 200, relationship, `http://${API_ACCESS_HOST}:33556/api` - ); + ) } -); +) Given( - "a resource with a {string} operation that returns that resource", + 'a resource with a {string} operation that returns that resource', async function (relationship) { this.currentResourceRoute = await this.createRoute( randomApiPath(), 200, relationship, this.currentResourceRoute - ); + ) } -); +) Before(async function () { this.createRoute = async function (route, status, relationship, linkPath) { if (relationship) { - const links = this.createLinks(relationship, linkPath); + const links = this.createLinks(relationship, linkPath) await this.router.route(route).get(async (request, response) => { - this.sendResponse(response, status, links); - }); + this.sendResponse(response, status, links) + }) } else { await this.router.route(route).get(async (request, response) => { - this.sendResponse(response, status); - }); + this.sendResponse(response, status) + }) } - return route; - }; + return route + } this.createLinks = function (relationship, uri) { - const links = new LinkHeader(); + const links = new LinkHeader() links.set({ rel: relationship, - uri: uri, - }); - return links; - }; + uri: uri + }) + return links + } this.sendResponse = function (response, status, links) { if (links) { - response.header("link", links.toString()).status(200).send({ status }); + response + .header('link', links.toString()) + .status(200) + .send({ status }) } else { - response.status(status).send({ status }); + response.status(status).send({ status }) } - }; -}); + } +}) diff --git a/src/test/world.js b/src/test/world.js index 6660a587..daa59aca 100644 --- a/src/test/world.js +++ b/src/test/world.js @@ -1,7 +1,7 @@ import { PendingError, - stepDefinitionWrapper, -} from "@windyroad/cucumber-js-throwables"; + stepDefinitionWrapper +} from '@windyroad/cucumber-js-throwables' import { setDefinitionFunctionWrapper, setWorldConstructor, @@ -9,103 +9,103 @@ import { BeforeAll, After, AfterAll, - setDefaultTimeout, -} from "cucumber"; -import chai from "chai"; -import logger from "../util/logger"; -import chaiAsPromised from "chai-as-promised"; + setDefaultTimeout +} from 'cucumber' +import chai from 'chai' +import logger from '../util/logger' +import chaiAsPromised from 'chai-as-promised' -import { WaychaserDirect } from "./clients/waychaser-direct"; -import { WaychaserViaWebdriver } from "./clients/waychaser-via-webdriver"; -import { webdriverManagerLocal } from "./clients/webdriver-manager-local"; -import { webdriverManagerRemote } from "./clients/webdriver-manager-remote"; +import { WaychaserDirect } from './clients/waychaser-direct' +import { WaychaserViaWebdriver } from './clients/waychaser-via-webdriver' +import { webdriverManagerLocal } from './clients/webdriver-manager-local' +import { webdriverManagerRemote } from './clients/webdriver-manager-remote' -import { startServer, app, stopServer, getNewRouter } from "./fakes/server"; +import { startServer, app, stopServer, getNewRouter } from './fakes/server' -chai.use(chaiAsPromised); +chai.use(chaiAsPromised) -global.expect = chai.expect; -global.PendingError = PendingError; +global.expect = chai.expect +global.PendingError = PendingError const profile = process.env.npm_lifecycle_event - .replace("test:", "") - .replace(/:/g, "-"); + .replace('test:', '') + .replace(/:/g, '-') -let waychaserProxy, webdriverManager; +let waychaserProxy, webdriverManager // if testing via browser, setup web-driver -if (profile.startsWith("browser-api")) { - const mode = profile.replace(/browser-api-.*-(.*)/, "$1"); +if (profile.startsWith('browser-api')) { + const mode = profile.replace(/browser-api-.*-(.*)/, '$1') const clients = { local: webdriverManagerLocal, - remote: webdriverManagerRemote, - }; - webdriverManager = clients[mode.toString()]; + remote: webdriverManagerRemote + } + webdriverManager = clients[mode.toString()] /* istanbul ignore next: only get's executed when there are test config issues */ if (webdriverManager === undefined) { - throw new Error(`unknown mode: ${mode}`); + throw new Error(`unknown mode: ${mode}`) } - webdriverManager.browser = profile.replace(/browser-api-(.*)-.*/, "$1"); - waychaserProxy = new WaychaserViaWebdriver(webdriverManager); + webdriverManager.browser = profile.replace(/browser-api-(.*)-.*/, '$1') + waychaserProxy = new WaychaserViaWebdriver(webdriverManager) } else { // otherwise, direct - waychaserProxy = new WaychaserDirect(); + waychaserProxy = new WaychaserDirect() } BeforeAll({ timeout: 240000 }, async function () { - logger.debug("BEGIN BeforeAll", Date.now()); + logger.debug('BEGIN BeforeAll', Date.now()) if (webdriverManager) { - await webdriverManager.beforeAllTests(); + await webdriverManager.beforeAllTests() } - startServer(); -}); + startServer() +}) -function world({ attach }) { - logger.debug("BEGIN world"); +function world ({ attach }) { + logger.debug('BEGIN world') - this.attach = attach; - this.app = app; + this.attach = attach + this.app = app // reset the fake API server, so we can set new routes - this.router = getNewRouter(); + this.router = getNewRouter() - logger.debug("END world"); - return ""; + logger.debug('END world') + return '' } Before({ timeout: 240000 }, async function (scenario) { - logger.debug("BEGIN Before"); - this.router = getNewRouter(); - this.waychaserProxy = waychaserProxy; + logger.debug('BEGIN Before') + this.router = getNewRouter() + this.waychaserProxy = waychaserProxy if (webdriverManager) { - await webdriverManager.beforeTest(scenario); + await webdriverManager.beforeTest(scenario) } - logger.debug("END Before"); -}); + logger.debug('END Before') +}) After({ timeout: 600000 }, async function (scenario) { - logger.debug("BEGIN After"); + logger.debug('BEGIN After') - logger.debug("%s: - %s", scenario.pickle.name, scenario.result.status); + logger.debug('%s: - %s', scenario.pickle.name, scenario.result.status) if (webdriverManager) { - await webdriverManager.afterTest(scenario); + await webdriverManager.afterTest(scenario) } - logger.debug("END After"); -}); + logger.debug('END After') +}) AfterAll({ timeout: 600000 }, async function () { - logger.debug("BEGIN AfterAll"); + logger.debug('BEGIN AfterAll') if (webdriverManager) { - await webdriverManager.afterAllTests(); + await webdriverManager.afterAllTests() } - stopServer(); - logger.debug("END AfterAll"); -}); + stopServer() + logger.debug('END AfterAll') +}) -setWorldConstructor(world); +setWorldConstructor(world) -setDefinitionFunctionWrapper(stepDefinitionWrapper); +setDefinitionFunctionWrapper(stepDefinitionWrapper) -setDefaultTimeout(20 * 1000); +setDefaultTimeout(20 * 1000) diff --git a/src/util/abstract.js b/src/util/abstract.js index 12b30005..b789fdb1 100644 --- a/src/util/abstract.js +++ b/src/util/abstract.js @@ -1,6 +1,6 @@ /** * */ -export function abstract() { - throw new Error("You have to implement the method!"); +export function abstract () { + throw new Error('You have to implement the method!') } diff --git a/src/util/logger.js b/src/util/logger.js index 25e4b7c2..247e58e6 100644 --- a/src/util/logger.js +++ b/src/util/logger.js @@ -1,25 +1,25 @@ -const debug = require("debug"); +const debug = require('debug') const logger = { - debug: debug("debug"), - info: debug("info"), - error: debug("error"), - browser: debug("browser"), - remote: debug("remote"), - waychaser: debug("waychaser"), - test: debug("test"), -}; + debug: debug('debug'), + info: debug('info'), + error: debug('error'), + browser: debug('browser'), + remote: debug('remote'), + waychaser: debug('waychaser'), + test: debug('test') +} -logger.debug.log = console.log.bind(console); -logger.info.log = console.log.bind(console); -logger.error.log = console.log.bind(console); -logger.browser.log = console.log.bind(console); -logger.remote.log = console.log.bind(console); -logger.waychaser.log = console.log.bind(console); -logger.test.log = console.log.bind(console); +logger.debug.log = console.log.bind(console) +logger.info.log = console.log.bind(console) +logger.error.log = console.log.bind(console) +logger.browser.log = console.log.bind(console) +logger.remote.log = console.log.bind(console) +logger.waychaser.log = console.log.bind(console) +logger.test.log = console.log.bind(console) -debug.enable("debug,info,error,browser,remote,waychaser,test"); +debug.enable('debug,info,error,browser,remote,waychaser,test') -export default logger; +export default logger /* import getLogger from "webpack-log"; diff --git a/src/waychaser.js b/src/waychaser.js index 14055825..9e01b841 100644 --- a/src/waychaser.js +++ b/src/waychaser.js @@ -1,9 +1,9 @@ -import fetch from "isomorphic-fetch"; -import { polyfill } from "es6-promise"; -import LinkHeader from "http-link-header"; -import Loki from "lokijs"; -import logger from "./util/logger"; -polyfill(); +import fetch from 'isomorphic-fetch' +import { polyfill } from 'es6-promise' +import LinkHeader from 'http-link-header' +import Loki from 'lokijs' +import logger from './util/logger' +polyfill() /** * Loads the resouce at the provided url using fetch @@ -15,56 +15,56 @@ polyfill(); * * @throws {Error} If the server returns with a status >= 400 */ -function loadResource(url, options) { - logger.waychaser(`loading ${url}`); - return fetch(url, options).then((response) => { +function loadResource (url, options) { + logger.waychaser(`loading ${url}`) + return fetch(url, options).then(response => { if (!response.ok) { - logger.waychaser(`Bad response from server ${JSON.stringify(response)}`); - throw new Error("Bad response from server", response); + logger.waychaser(`Bad response from server ${JSON.stringify(response)}`) + throw new Error('Bad response from server', response) } - logger.waychaser(`Good response from server ${JSON.stringify(response)}`); + logger.waychaser(`Good response from server ${JSON.stringify(response)}`) /* istanbul ignore next: IE fails without this, but IE doesn't report coverage */ - if (response.url === undefined || response.url === "") { + if (response.url === undefined || response.url === '') { // in ie url is not being populated 🤷‍♂️ - response.url = url; + response.url = url } - return new waychaser.ApiResourceObject(response); - }); + return new waychaser.ApiResourceObject(response) + }) } class Operation { - constructor(callingContext) { + constructor (callingContext) { logger.waychaser( `Operation callingContext ${JSON.stringify(this.callingContext)}` - ); - this.callingContext = callingContext; + ) + this.callingContext = callingContext } - async invoke(context, options) { - const contextUrl = this.callingContext.url; - const invokeUrl = new URL(this.uri, contextUrl); - logger.waychaser(`invoking ${invokeUrl}`); - return loadResource(invokeUrl, options); + async invoke (context, options) { + const contextUrl = this.callingContext.url + const invokeUrl = new URL(this.uri, contextUrl) + logger.waychaser(`invoking ${invokeUrl}`) + return loadResource(invokeUrl, options) } } -Loki.Collection.prototype.findOne_ = Loki.Collection.prototype.findOne; +Loki.Collection.prototype.findOne_ = Loki.Collection.prototype.findOne Loki.Collection.prototype.findOne = function (...arguments_) { - return arguments_.length === 1 && typeof arguments_[0] === "string" + return arguments_.length === 1 && typeof arguments_[0] === 'string' ? this.findOne_({ rel: arguments_[0] }) - : this.findOne_(...arguments_); -}; + : this.findOne_(...arguments_) +} Loki.Collection.prototype.invoke = async function ( relationship, context, options ) { - const operation = this.findOne(relationship); - logger.waychaser(JSON.stringify(operation, undefined, 2)); - return operation.invoke(context, options); -}; + const operation = this.findOne(relationship) + logger.waychaser(JSON.stringify(operation, undefined, 2)) + return operation.invoke(context, options) +} /** @namespace */ const waychaser = { @@ -79,39 +79,39 @@ const waychaser = { * @throws {Error} If the server returns with a status >= 400 */ load: async function (url, options) { - return loadResource(url, options); + return loadResource(url, options) }, logger: logger.waychaser, ApiResourceObject: class { - constructor(response) { - logger.waychaser("creating ARO", response); - this.response = response; - const linkHeader = response.headers.get("link"); - const linkDatabase = new Loki(); - this.operations = linkDatabase.addCollection(); + constructor (response) { + logger.waychaser('creating ARO', response) + this.response = response + const linkHeader = response.headers.get('link') + const linkDatabase = new Loki() + this.operations = linkDatabase.addCollection() if (linkHeader) { - const links = LinkHeader.parse(linkHeader); + const links = LinkHeader.parse(linkHeader) this.operations.insert( - links.refs.map((reference) => { - const operation = new Operation(response); - Object.assign(operation, reference); - return operation; + links.refs.map(reference => { + const operation = new Operation(response) + Object.assign(operation, reference) + return operation }) - ); + ) } } - get ops() { - return this.operations; + get ops () { + return this.operations } - async invoke(relationship) { - return this.operations.invoke(relationship); + async invoke (relationship) { + return this.operations.invoke(relationship) } - }, -}; + } +} -export { waychaser }; +export { waychaser } diff --git a/webpack.config.js b/webpack.config.js index afb52866..066e8a87 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,20 +1,20 @@ -const path = require("path"); -const HtmlWebpackPlugin = require("html-webpack-plugin"); +const path = require('path') +const HtmlWebpackPlugin = require('html-webpack-plugin') -module.exports = (environment) => ({ - mode: "development", - entry: ["babel-polyfill", "core-js/web", "./src/waychaser.js"], +module.exports = environment => ({ + mode: 'development', + entry: ['babel-polyfill', 'core-js/web', './src/waychaser.js'], output: { - path: path.resolve(__dirname, "dist"), + path: path.resolve(__dirname, 'dist'), filename: environment.OUTPUT_FILENAME, - libraryTarget: "umd", + libraryTarget: 'umd' }, - devtool: "source-map", + devtool: 'source-map', optimization: { - runtimeChunk: true, + runtimeChunk: true }, node: { - fs: "empty", + fs: 'empty' }, module: { rules: [ @@ -27,14 +27,14 @@ module.exports = (environment) => ({ /out/, /scripts/, /test-results/, - /cucumber\.js/, + /cucumber\.js/ ], - use: ["babel-loader"], - }, - ], + use: ['babel-loader'] + } + ] }, resolve: { - extensions: [".js"], + extensions: ['.js'] }, devServer: { port: environment.BROWSER_PORT, @@ -42,15 +42,15 @@ module.exports = (environment) => ({ liveReload: false, open: true, proxy: { - "/api": { - target: `http://localhost:${environment.API_PORT}`, - }, - }, + '/api': { + target: `http://localhost:${environment.API_PORT}` + } + } }, plugins: [ new HtmlWebpackPlugin({ - template: "./public/index.html", - filename: "./index.html", - }), - ], -}); + template: './public/index.html', + filename: './index.html' + }) + ] +})