Merge branch 'main' into jsjoeio/upgrade-vscode-1.54
This commit is contained in:
commit
d3df963d39
25
.github/dependabot.yml
vendored
Normal file
25
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
time: "11:00"
|
||||||
|
assignees:
|
||||||
|
- "jawnsy"
|
||||||
|
reviewers:
|
||||||
|
- "jawnsy"
|
||||||
|
ignore:
|
||||||
|
# GitHub always delivers the latest versions for each major
|
||||||
|
# release tag, so handle updates manually
|
||||||
|
- dependency-name: "actions/*"
|
||||||
|
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
time: "11:00"
|
||||||
|
assignees:
|
||||||
|
- "jawnsy"
|
||||||
|
reviewers:
|
||||||
|
- "jawnsy"
|
46
.github/workflows/ci.yaml
vendored
46
.github/workflows/ci.yaml
vendored
@ -1,12 +1,18 @@
|
|||||||
name: ci
|
name: ci
|
||||||
|
|
||||||
on: [push]
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
fmt:
|
fmt:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Run ./ci/steps/fmt.sh
|
- name: Run ./ci/steps/fmt.sh
|
||||||
uses: ./ci/images/debian10
|
uses: ./ci/images/debian10
|
||||||
with:
|
with:
|
||||||
@ -15,20 +21,28 @@ jobs:
|
|||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Run ./ci/steps/lint.sh
|
- name: Run ./ci/steps/lint.sh
|
||||||
uses: ./ci/images/debian10
|
uses: ./ci/images/debian10
|
||||||
with:
|
with:
|
||||||
args: ./ci/steps/lint.sh
|
args: ./ci/steps/lint.sh
|
||||||
|
|
||||||
test:
|
test-unit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Run unit tests
|
||||||
|
uses: ./ci/images/debian10
|
||||||
|
with:
|
||||||
|
args: ./ci/steps/test-unit.sh
|
||||||
|
test-e2e:
|
||||||
needs: linux-amd64
|
needs: linux-amd64
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
PASSWORD: e45432jklfdsab
|
PASSWORD: e45432jklfdsab
|
||||||
CODE_SERVER_ADDRESS: http://localhost:8080
|
CODE_SERVER_ADDRESS: http://localhost:8080
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Download release packages
|
- name: Download release packages
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
@ -38,24 +52,24 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd release-packages && tar -xzf code-server*-linux-amd64.tar.gz
|
cd release-packages && tar -xzf code-server*-linux-amd64.tar.gz
|
||||||
- uses: microsoft/playwright-github-action@v1
|
- uses: microsoft/playwright-github-action@v1
|
||||||
- name: Install dependencies and run tests
|
- name: Install dependencies and run end-to-end tests
|
||||||
run: |
|
run: |
|
||||||
./release-packages/code-server*-linux-amd64/bin/code-server &
|
./release-packages/code-server*-linux-amd64/bin/code-server &
|
||||||
yarn --frozen-lockfile
|
yarn --frozen-lockfile
|
||||||
yarn test
|
yarn test:e2e
|
||||||
- name: Upload test artifacts
|
- name: Upload test artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: test-videos
|
name: test-videos
|
||||||
path: ./test/videos
|
path: ./test/e2e/videos
|
||||||
- name: Remove release packages and test artifacts
|
- name: Remove release packages and test artifacts
|
||||||
run: rm -rf ./release-packages ./test/videos
|
run: rm -rf ./release-packages ./test/e2e/videos
|
||||||
|
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Run ./ci/steps/release.sh
|
- name: Run ./ci/steps/release.sh
|
||||||
uses: ./ci/images/debian10
|
uses: ./ci/images/debian10
|
||||||
with:
|
with:
|
||||||
@ -70,7 +84,7 @@ jobs:
|
|||||||
needs: release
|
needs: release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Download npm package
|
- name: Download npm package
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
@ -90,7 +104,7 @@ jobs:
|
|||||||
needs: release
|
needs: release
|
||||||
runs-on: ubuntu-arm64-latest
|
runs-on: ubuntu-arm64-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Download npm package
|
- name: Download npm package
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
@ -111,8 +125,10 @@ jobs:
|
|||||||
macos-amd64:
|
macos-amd64:
|
||||||
needs: release
|
needs: release
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
# This job requires secrets, so can only run on the default branch
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Download npm package
|
- name: Download npm package
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
@ -133,7 +149,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: linux-amd64
|
needs: linux-amd64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Download release package
|
- name: Download release package
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
@ -153,7 +169,7 @@ jobs:
|
|||||||
runs-on: ubuntu-arm64-latest
|
runs-on: ubuntu-arm64-latest
|
||||||
needs: linux-arm64
|
needs: linux-arm64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Download release package
|
- name: Download release package
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -16,5 +16,5 @@ node-*
|
|||||||
.home
|
.home
|
||||||
coverage
|
coverage
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
test/videos
|
test/e2e/videos
|
||||||
test/screenshots
|
test/e2e/screenshots
|
||||||
|
18
ci/README.md
18
ci/README.md
@ -52,7 +52,7 @@ Make sure you have `$GITHUB_TOKEN` set and [hub](https://github.com/github/hub)
|
|||||||
|
|
||||||
Currently, we run a command to manually generate the code coverage shield. Follow these steps:
|
Currently, we run a command to manually generate the code coverage shield. Follow these steps:
|
||||||
|
|
||||||
1. Run `yarn test` and make sure all the tests are passing
|
1. Run `yarn test:unit` and make sure all the tests are passing
|
||||||
2. Run `yarn badges`
|
2. Run `yarn badges`
|
||||||
3. Go into the README and change the color from `red` to `green` in this line:
|
3. Go into the README and change the color from `red` to `green` in this line:
|
||||||
|
|
||||||
@ -72,8 +72,10 @@ This directory contains scripts used for the development of code-server.
|
|||||||
- Runs formatters.
|
- Runs formatters.
|
||||||
- [./ci/dev/lint.sh](./dev/lint.sh) (`yarn lint`)
|
- [./ci/dev/lint.sh](./dev/lint.sh) (`yarn lint`)
|
||||||
- Runs linters.
|
- Runs linters.
|
||||||
- [./ci/dev/test.sh](./dev/test.sh) (`yarn test`)
|
- [./ci/dev/test-unit.sh](./dev/test-unit.sh) (`yarn test:unit`)
|
||||||
- Runs tests.
|
- Runs unit tests.
|
||||||
|
- [./ci/dev/test-e2e.sh](./dev/test-e2e.sh) (`yarn test:e2e`)
|
||||||
|
- Runs end-to-end tests.
|
||||||
- [./ci/dev/ci.sh](./dev/ci.sh) (`yarn ci`)
|
- [./ci/dev/ci.sh](./dev/ci.sh) (`yarn ci`)
|
||||||
- Runs `yarn fmt`, `yarn lint` and `yarn test`.
|
- Runs `yarn fmt`, `yarn lint` and `yarn test`.
|
||||||
- [./ci/dev/watch.ts](./dev/watch.ts) (`yarn watch`)
|
- [./ci/dev/watch.ts](./dev/watch.ts) (`yarn watch`)
|
||||||
@ -142,11 +144,13 @@ This directory contains the scripts used in CI.
|
|||||||
Helps avoid clobbering the CI configuration.
|
Helps avoid clobbering the CI configuration.
|
||||||
|
|
||||||
- [./steps/fmt.sh](./steps/fmt.sh)
|
- [./steps/fmt.sh](./steps/fmt.sh)
|
||||||
- Runs `yarn fmt` after ensuring VS Code is patched.
|
- Runs `yarn fmt`.
|
||||||
- [./steps/lint.sh](./steps/lint.sh)
|
- [./steps/lint.sh](./steps/lint.sh)
|
||||||
- Runs `yarn lint` after ensuring VS Code is patched.
|
- Runs `yarn lint`.
|
||||||
- [./steps/test.sh](./steps/test.sh)
|
- [./steps/test-unit.sh](./steps/test-unit.sh)
|
||||||
- Runs `yarn test` after ensuring VS Code is patched.
|
- Runs `yarn test:unit`.
|
||||||
|
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
|
||||||
|
- Runs `yarn test:e2e`.
|
||||||
- [./steps/release.sh](./steps/release.sh)
|
- [./steps/release.sh](./steps/release.sh)
|
||||||
- Runs the release process.
|
- Runs the release process.
|
||||||
- Generates the npm package at `./release`.
|
- Generates the npm package at `./release`.
|
||||||
|
@ -6,7 +6,7 @@ main() {
|
|||||||
|
|
||||||
yarn fmt
|
yarn fmt
|
||||||
yarn lint
|
yarn lint
|
||||||
yarn test
|
yarn test:unit
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
@ -3,12 +3,9 @@ set -euo pipefail
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/../.."
|
cd "$(dirname "$0")/../.."
|
||||||
cd test/test-plugin
|
|
||||||
make -s out/index.js
|
|
||||||
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
||||||
# information. We must also run it from the root otherwise coverage will not
|
# information. We must also run it from the root otherwise coverage will not
|
||||||
# include our source files.
|
# include our source files.
|
||||||
cd "$OLDPWD"
|
|
||||||
if [[ -z ${PASSWORD-} ]] || [[ -z ${CODE_SERVER_ADDRESS-} ]]; then
|
if [[ -z ${PASSWORD-} ]] || [[ -z ${CODE_SERVER_ADDRESS-} ]]; then
|
||||||
echo "The end-to-end testing suites rely on your local environment"
|
echo "The end-to-end testing suites rely on your local environment"
|
||||||
echo -e "\n"
|
echo -e "\n"
|
||||||
@ -18,7 +15,7 @@ main() {
|
|||||||
echo -e "\n"
|
echo -e "\n"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@"
|
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --config ./test/jest.e2e.config.ts
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
15
ci/dev/test-unit.sh
Executable file
15
ci/dev/test-unit.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
cd test/unit/test-plugin
|
||||||
|
make -s out/index.js
|
||||||
|
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
||||||
|
# information. We must also run it from the root otherwise coverage will not
|
||||||
|
# include our source files.
|
||||||
|
cd "$OLDPWD"
|
||||||
|
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
12
ci/steps/test-e2e.sh
Executable file
12
ci/steps/test-e2e.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
"./release-packages/code-server*-linux-amd64/bin/code-server" --home "$CODE_SERVER_ADDRESS"/healthz &
|
||||||
|
yarn --frozen-lockfile
|
||||||
|
yarn test:e2e
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -6,7 +6,7 @@ main() {
|
|||||||
|
|
||||||
yarn --frozen-lockfile
|
yarn --frozen-lockfile
|
||||||
|
|
||||||
yarn test
|
yarn test:unit
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
@ -3999,7 +3999,7 @@ fsevents@~2.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
|
||||||
integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
|
integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
|
||||||
|
|
||||||
fstream@^1.0.2:
|
fstream@^1.0.12:
|
||||||
version "1.0.12"
|
version "1.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
|
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
|
||||||
integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
|
integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
|
||||||
@ -9290,12 +9290,12 @@ tar-stream@^2.1.4:
|
|||||||
readable-stream "^3.1.1"
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
tar@^2.2.1:
|
tar@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
|
||||||
integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=
|
integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
|
||||||
dependencies:
|
dependencies:
|
||||||
block-stream "*"
|
block-stream "*"
|
||||||
fstream "^1.0.2"
|
fstream "^1.0.12"
|
||||||
inherits "2"
|
inherits "2"
|
||||||
|
|
||||||
tar@^6.0.2:
|
tar@^6.0.2:
|
||||||
|
14
package.json
14
package.json
@ -16,7 +16,9 @@
|
|||||||
"release:standalone": "./ci/build/build-standalone-release.sh",
|
"release:standalone": "./ci/build/build-standalone-release.sh",
|
||||||
"release:github-draft": "./ci/build/release-github-draft.sh",
|
"release:github-draft": "./ci/build/release-github-draft.sh",
|
||||||
"release:github-assets": "./ci/build/release-github-assets.sh",
|
"release:github-assets": "./ci/build/release-github-assets.sh",
|
||||||
|
"test:e2e": "./ci/dev/test-e2e.sh",
|
||||||
"test:standalone-release": "./ci/build/test-standalone-release.sh",
|
"test:standalone-release": "./ci/build/test-standalone-release.sh",
|
||||||
|
"test:unit": "./ci/dev/test-unit.sh",
|
||||||
"package": "./ci/build/build-packages.sh",
|
"package": "./ci/build/build-packages.sh",
|
||||||
"postinstall": "./ci/dev/postinstall.sh",
|
"postinstall": "./ci/dev/postinstall.sh",
|
||||||
"update:vscode": "./ci/dev/update-vscode.sh",
|
"update:vscode": "./ci/dev/update-vscode.sh",
|
||||||
@ -52,7 +54,7 @@
|
|||||||
"@types/wtfnode": "^0.7.0",
|
"@types/wtfnode": "^0.7.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.7.0",
|
"@typescript-eslint/eslint-plugin": "^4.7.0",
|
||||||
"@typescript-eslint/parser": "^4.7.0",
|
"@typescript-eslint/parser": "^4.7.0",
|
||||||
"doctoc": "^1.4.0",
|
"doctoc": "^2.0.0",
|
||||||
"eslint": "^7.7.0",
|
"eslint": "^7.7.0",
|
||||||
"eslint-config-prettier": "^6.0.0",
|
"eslint-config-prettier": "^6.0.0",
|
||||||
"eslint-import-resolver-alias": "^1.1.2",
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
@ -71,7 +73,8 @@
|
|||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "^12.12.7",
|
"@types/node": "^12.12.7",
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"vfile-message": "^2.0.2"
|
"vfile-message": "^2.0.2",
|
||||||
|
"node-forge": "^0.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coder/logger": "1.1.16",
|
"@coder/logger": "1.1.16",
|
||||||
@ -123,7 +126,8 @@
|
|||||||
"testPathIgnorePatterns": [
|
"testPathIgnorePatterns": [
|
||||||
"/node_modules/",
|
"/node_modules/",
|
||||||
"/lib/",
|
"/lib/",
|
||||||
"/out/"
|
"/out/",
|
||||||
|
"test/e2e"
|
||||||
],
|
],
|
||||||
"collectCoverage": true,
|
"collectCoverage": true,
|
||||||
"collectCoverageFrom": [
|
"collectCoverageFrom": [
|
||||||
@ -143,8 +147,6 @@
|
|||||||
"lines": 40
|
"lines": 40
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testTimeout": 30000,
|
|
||||||
"globalSetup": "<rootDir>/test/globalSetup.ts",
|
|
||||||
"modulePathIgnorePatterns": [
|
"modulePathIgnorePatterns": [
|
||||||
"<rootDir>/lib/vscode",
|
"<rootDir>/lib/vscode",
|
||||||
"<rootDir>/release-packages",
|
"<rootDir>/release-packages",
|
||||||
@ -155,7 +157,7 @@
|
|||||||
"<rootDir>/release-images"
|
"<rootDir>/release-images"
|
||||||
],
|
],
|
||||||
"moduleNameMapper": {
|
"moduleNameMapper": {
|
||||||
"^.+\\.(css|less)$": "<rootDir>/test/cssStub.ts"
|
"^.+\\.(css|less)$": "<rootDir>/test/utils/cssStub.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { chromium, Page, Browser } from "playwright"
|
import { chromium, Page, Browser } from "playwright"
|
||||||
import { CODE_SERVER_ADDRESS } from "./constants"
|
import { CODE_SERVER_ADDRESS } from "../utils/constants"
|
||||||
|
|
||||||
let browser: Browser
|
let browser: Browser
|
||||||
let page: Page
|
let page: Page
|
@ -1,5 +1,5 @@
|
|||||||
import { chromium, Page, Browser, BrowserContext } from "playwright"
|
import { chromium, Page, Browser, BrowserContext } from "playwright"
|
||||||
import { CODE_SERVER_ADDRESS, PASSWORD } from "./constants"
|
import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants"
|
||||||
|
|
||||||
describe("login", () => {
|
describe("login", () => {
|
||||||
let browser: Browser
|
let browser: Browser
|
22
test/jest.e2e.config.ts
Normal file
22
test/jest.e2e.config.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// jest.config.ts
|
||||||
|
import type { Config } from "@jest/types"
|
||||||
|
|
||||||
|
const config: Config.InitialOptions = {
|
||||||
|
transform: {
|
||||||
|
"^.+\\.ts$": "<rootDir>/node_modules/ts-jest",
|
||||||
|
},
|
||||||
|
globalSetup: "<rootDir>/utils/globalSetup.ts",
|
||||||
|
testEnvironment: "node",
|
||||||
|
testPathIgnorePatterns: ["node_modules", "lib", "out", "test/unit"],
|
||||||
|
testTimeout: 30000,
|
||||||
|
modulePathIgnorePatterns: [
|
||||||
|
"<rootDir>/../lib/vscode",
|
||||||
|
"<rootDir>/../release-packages",
|
||||||
|
"<rootDir>/../release",
|
||||||
|
"<rootDir>/../release-standalone",
|
||||||
|
"<rootDir>/../release-npm-package",
|
||||||
|
"<rootDir>/../release-gcp",
|
||||||
|
"<rootDir>/../release-images",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
export default config
|
@ -1,91 +0,0 @@
|
|||||||
import { chromium, Page, Browser, BrowserContext, Cookie } from "playwright"
|
|
||||||
import { hash } from "../src/node/util"
|
|
||||||
import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "./constants"
|
|
||||||
import { createCookieIfDoesntExist } from "./helpers"
|
|
||||||
|
|
||||||
describe("Open Help > About", () => {
|
|
||||||
let browser: Browser
|
|
||||||
let page: Page
|
|
||||||
let context: BrowserContext
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
browser = await chromium.launch()
|
|
||||||
// Create a new context with the saved storage state
|
|
||||||
const storageState = JSON.parse(STORAGE) || {}
|
|
||||||
|
|
||||||
const cookieToStore = {
|
|
||||||
sameSite: "Lax" as const,
|
|
||||||
name: "key",
|
|
||||||
value: hash(PASSWORD),
|
|
||||||
domain: "localhost",
|
|
||||||
path: "/",
|
|
||||||
expires: -1,
|
|
||||||
httpOnly: false,
|
|
||||||
secure: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
// For some odd reason, the login method used in globalSetup.ts doesn't always work
|
|
||||||
// I don't know if it's on playwright clearing our cookies by accident
|
|
||||||
// or if it's our cookies disappearing.
|
|
||||||
// This means we need an additional check to make sure we're logged in.
|
|
||||||
// We do this by manually adding the cookie to the browser environment
|
|
||||||
// if it's not there at the time the test starts
|
|
||||||
const cookies: Cookie[] = storageState.cookies || []
|
|
||||||
// If the cookie exists in cookies then
|
|
||||||
// this will return the cookies with no changes
|
|
||||||
// otherwise if it doesn't exist, it will create it
|
|
||||||
// hence the name maybeUpdatedCookies
|
|
||||||
//
|
|
||||||
// TODO(@jsjoeio)
|
|
||||||
// The playwright storage thing sometimes works and sometimes doesn't. We should investigate this further
|
|
||||||
// at some point.
|
|
||||||
// See discussion: https://github.com/cdr/code-server/pull/2648#discussion_r575434946
|
|
||||||
|
|
||||||
const maybeUpdatedCookies = createCookieIfDoesntExist(cookies, cookieToStore)
|
|
||||||
|
|
||||||
context = await browser.newContext({
|
|
||||||
storageState: { cookies: maybeUpdatedCookies },
|
|
||||||
recordVideo: { dir: "./test/videos/" },
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
// Remove password from local storage
|
|
||||||
await context.clearCookies()
|
|
||||||
|
|
||||||
await context.close()
|
|
||||||
await browser.close()
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
page = await context.newPage()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should see a 'Help' then 'About' button in the Application Menu that opens a dialog", async () => {
|
|
||||||
// waitUntil: "domcontentloaded"
|
|
||||||
// In case the page takes a long time to load
|
|
||||||
await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "domcontentloaded" })
|
|
||||||
|
|
||||||
// Make sure the editor actually loaded
|
|
||||||
expect(await page.isVisible("div.monaco-workbench"))
|
|
||||||
|
|
||||||
// Click the Application menu
|
|
||||||
await page.click("[aria-label='Application Menu']")
|
|
||||||
// See the Help button
|
|
||||||
const helpButton = "a.action-menu-item span[aria-label='Help']"
|
|
||||||
expect(await page.isVisible(helpButton))
|
|
||||||
|
|
||||||
// Hover the helpButton
|
|
||||||
await page.hover(helpButton)
|
|
||||||
|
|
||||||
// see the About button and click it
|
|
||||||
const aboutButton = "a.action-menu-item span[aria-label='About']"
|
|
||||||
expect(await page.isVisible(aboutButton))
|
|
||||||
// NOTE: it won't work unless you hover it first
|
|
||||||
await page.hover(aboutButton)
|
|
||||||
await page.click(aboutButton)
|
|
||||||
|
|
||||||
const codeServerText = "text=code-server"
|
|
||||||
expect(await page.isVisible(codeServerText))
|
|
||||||
})
|
|
||||||
})
|
|
@ -3,8 +3,8 @@ import * as fs from "fs-extra"
|
|||||||
import * as net from "net"
|
import * as net from "net"
|
||||||
import * as os from "os"
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { Args, parse, setDefaults, shouldOpenInExistingInstance } from "../src/node/cli"
|
import { Args, parse, setDefaults, shouldOpenInExistingInstance } from "../../src/node/cli"
|
||||||
import { paths, tmpdir } from "../src/node/util"
|
import { paths, tmpdir } from "../../src/node/util"
|
||||||
|
|
||||||
type Mutable<T> = {
|
type Mutable<T> = {
|
||||||
-readonly [P in keyof T]: T[P]
|
-readonly [P in keyof T]: T[P]
|
@ -1,8 +1,8 @@
|
|||||||
import { commit, getPackageJson, version } from "../src/node/constants"
|
import { commit, getPackageJson, version } from "../../src/node/constants"
|
||||||
import { loggerModule } from "./helpers"
|
import { loggerModule } from "../utils/helpers"
|
||||||
|
|
||||||
// jest.mock is hoisted above the imports so we must use `require` here.
|
// jest.mock is hoisted above the imports so we must use `require` here.
|
||||||
jest.mock("@coder/logger", () => require("./helpers").loggerModule)
|
jest.mock("@coder/logger", () => require("../utils/helpers").loggerModule)
|
||||||
|
|
||||||
describe("constants", () => {
|
describe("constants", () => {
|
||||||
describe("getPackageJson", () => {
|
describe("getPackageJson", () => {
|
@ -1,8 +1,8 @@
|
|||||||
// Note: we need to import logger from the root
|
// Note: we need to import logger from the root
|
||||||
// because this is the logger used in logError in ../src/common/util
|
// because this is the logger used in logError in ../src/common/util
|
||||||
import { logger } from "../node_modules/@coder/logger"
|
import { logger } from "../../node_modules/@coder/logger"
|
||||||
|
|
||||||
import { Emitter } from "../src/common/emitter"
|
import { Emitter } from "../../src/common/emitter"
|
||||||
|
|
||||||
describe("emitter", () => {
|
describe("emitter", () => {
|
||||||
let spy: jest.SpyInstance
|
let spy: jest.SpyInstance
|
@ -1,5 +1,5 @@
|
|||||||
import * as httpserver from "./httpserver"
|
import * as httpserver from "../utils/httpserver"
|
||||||
import * as integration from "./integration"
|
import * as integration from "../utils/integration"
|
||||||
|
|
||||||
describe("health", () => {
|
describe("health", () => {
|
||||||
let codeServer: httpserver.HttpServer | undefined
|
let codeServer: httpserver.HttpServer | undefined
|
@ -1,4 +1,4 @@
|
|||||||
import { HttpCode, HttpError } from "../src/common/http"
|
import { HttpCode, HttpError } from "../../src/common/http"
|
||||||
|
|
||||||
describe("http", () => {
|
describe("http", () => {
|
||||||
describe("HttpCode", () => {
|
describe("HttpCode", () => {
|
@ -2,11 +2,11 @@ import { logger } from "@coder/logger"
|
|||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import * as fs from "fs"
|
import * as fs from "fs"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { HttpCode } from "../src/common/http"
|
import { HttpCode } from "../../src/common/http"
|
||||||
import { AuthType } from "../src/node/cli"
|
import { AuthType } from "../../src/node/cli"
|
||||||
import { codeServer, PluginAPI } from "../src/node/plugin"
|
import { codeServer, PluginAPI } from "../../src/node/plugin"
|
||||||
import * as apps from "../src/node/routes/apps"
|
import * as apps from "../../src/node/routes/apps"
|
||||||
import * as httpserver from "./httpserver"
|
import * as httpserver from "../utils/httpserver"
|
||||||
const fsp = fs.promises
|
const fsp = fs.promises
|
||||||
|
|
||||||
// Jest overrides `require` so our usual override doesn't work.
|
// Jest overrides `require` so our usual override doesn't work.
|
@ -1,7 +1,7 @@
|
|||||||
import bodyParser from "body-parser"
|
import bodyParser from "body-parser"
|
||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import * as httpserver from "./httpserver"
|
import * as httpserver from "../utils/httpserver"
|
||||||
import * as integration from "./integration"
|
import * as integration from "../utils/integration"
|
||||||
|
|
||||||
describe("proxy", () => {
|
describe("proxy", () => {
|
||||||
const nhooyrDevServer = new httpserver.HttpServer()
|
const nhooyrDevServer = new httpserver.HttpServer()
|
@ -1,5 +1,5 @@
|
|||||||
import { JSDOM } from "jsdom"
|
import { JSDOM } from "jsdom"
|
||||||
import { loggerModule } from "./helpers"
|
import { loggerModule } from "../utils/helpers"
|
||||||
|
|
||||||
describe("register", () => {
|
describe("register", () => {
|
||||||
describe("when navigator and serviceWorker are defined", () => {
|
describe("when navigator and serviceWorker are defined", () => {
|
||||||
@ -40,7 +40,7 @@ describe("register", () => {
|
|||||||
|
|
||||||
it("should register a ServiceWorker", () => {
|
it("should register a ServiceWorker", () => {
|
||||||
// Load service worker like you would in the browser
|
// Load service worker like you would in the browser
|
||||||
require("../src/browser/register")
|
require("../../src/browser/register")
|
||||||
expect(mockRegisterFn).toHaveBeenCalled()
|
expect(mockRegisterFn).toHaveBeenCalled()
|
||||||
expect(mockRegisterFn).toHaveBeenCalledTimes(1)
|
expect(mockRegisterFn).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
@ -54,7 +54,7 @@ describe("register", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Load service worker like you would in the browser
|
// Load service worker like you would in the browser
|
||||||
require("../src/browser/register")
|
require("../../src/browser/register")
|
||||||
|
|
||||||
expect(mockRegisterFn).toHaveBeenCalled()
|
expect(mockRegisterFn).toHaveBeenCalled()
|
||||||
expect(loggerModule.logger.error).toHaveBeenCalled()
|
expect(loggerModule.logger.error).toHaveBeenCalled()
|
||||||
@ -78,7 +78,7 @@ describe("register", () => {
|
|||||||
|
|
||||||
it("should log an error to the console", () => {
|
it("should log an error to the console", () => {
|
||||||
// Load service worker like you would in the browser
|
// Load service worker like you would in the browser
|
||||||
require("../src/browser/register")
|
require("../../src/browser/register")
|
||||||
expect(spy).toHaveBeenCalled()
|
expect(spy).toHaveBeenCalled()
|
||||||
expect(spy).toHaveBeenCalledTimes(1)
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
expect(spy).toHaveBeenCalledWith("[Service Worker] navigator is undefined")
|
expect(spy).toHaveBeenCalledWith("[Service Worker] navigator is undefined")
|
@ -58,7 +58,7 @@ describe("serviceWorker", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("should add 3 listeners: install, activate and fetch", () => {
|
it("should add 3 listeners: install, activate and fetch", () => {
|
||||||
require("../src/browser/serviceWorker.ts")
|
require("../../src/browser/serviceWorker.ts")
|
||||||
const listenerEventNames = listeners.map((listener) => listener.event)
|
const listenerEventNames = listeners.map((listener) => listener.event)
|
||||||
|
|
||||||
expect(listeners).toHaveLength(3)
|
expect(listeners).toHaveLength(3)
|
||||||
@ -68,20 +68,20 @@ describe("serviceWorker", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("should call the proper callbacks for 'install'", async () => {
|
it("should call the proper callbacks for 'install'", async () => {
|
||||||
require("../src/browser/serviceWorker.ts")
|
require("../../src/browser/serviceWorker.ts")
|
||||||
emit("install")
|
emit("install")
|
||||||
expect(spy).toHaveBeenCalledWith("[Service Worker] installed")
|
expect(spy).toHaveBeenCalledWith("[Service Worker] installed")
|
||||||
expect(spy).toHaveBeenCalledTimes(1)
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should do nothing when 'fetch' is called", async () => {
|
it("should do nothing when 'fetch' is called", async () => {
|
||||||
require("../src/browser/serviceWorker.ts")
|
require("../../src/browser/serviceWorker.ts")
|
||||||
emit("fetch")
|
emit("fetch")
|
||||||
expect(spy).not.toHaveBeenCalled()
|
expect(spy).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should call the proper callbacks for 'activate'", async () => {
|
it("should call the proper callbacks for 'activate'", async () => {
|
||||||
require("../src/browser/serviceWorker.ts")
|
require("../../src/browser/serviceWorker.ts")
|
||||||
emit("activate")
|
emit("activate")
|
||||||
|
|
||||||
// Activate serviceWorker
|
// Activate serviceWorker
|
@ -3,9 +3,9 @@ import * as fs from "fs-extra"
|
|||||||
import * as net from "net"
|
import * as net from "net"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as tls from "tls"
|
import * as tls from "tls"
|
||||||
import { Emitter } from "../src/common/emitter"
|
import { Emitter } from "../../src/common/emitter"
|
||||||
import { SocketProxyProvider } from "../src/node/socket"
|
import { SocketProxyProvider } from "../../src/node/socket"
|
||||||
import { generateCertificate, tmpdir } from "../src/node/util"
|
import { generateCertificate, tmpdir } from "../../src/node/util"
|
||||||
|
|
||||||
describe("SocketProxyProvider", () => {
|
describe("SocketProxyProvider", () => {
|
||||||
const provider = new SocketProxyProvider()
|
const provider = new SocketProxyProvider()
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
@ -44,7 +44,7 @@
|
|||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
||||||
"paths": {
|
"paths": {
|
||||||
"code-server": ["../../typings/pluginapi"]
|
"code-server": ["../../../typings/pluginapi"]
|
||||||
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */,
|
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */,
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
@ -1,9 +1,9 @@
|
|||||||
import * as fs from "fs-extra"
|
import * as fs from "fs-extra"
|
||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { SettingsProvider, UpdateSettings } from "../src/node/settings"
|
import { SettingsProvider, UpdateSettings } from "../../src/node/settings"
|
||||||
import { LatestResponse, UpdateProvider } from "../src/node/update"
|
import { LatestResponse, UpdateProvider } from "../../src/node/update"
|
||||||
import { tmpdir } from "../src/node/util"
|
import { tmpdir } from "../../src/node/util"
|
||||||
|
|
||||||
describe.skip("update", () => {
|
describe.skip("update", () => {
|
||||||
let version = "1.0.0"
|
let version = "1.0.0"
|
@ -10,11 +10,11 @@ import {
|
|||||||
split,
|
split,
|
||||||
trimSlashes,
|
trimSlashes,
|
||||||
normalize,
|
normalize,
|
||||||
} from "../src/common/util"
|
} from "../../src/common/util"
|
||||||
import { Cookie as CookieEnum } from "../src/node/routes/login"
|
import { Cookie as CookieEnum } from "../../src/node/routes/login"
|
||||||
import { hash } from "../src/node/util"
|
import { hash } from "../../src/node/util"
|
||||||
import { PASSWORD } from "./constants"
|
import { PASSWORD } from "../utils/constants"
|
||||||
import { checkForCookie, createCookieIfDoesntExist, loggerModule, Cookie } from "./helpers"
|
import { checkForCookie, createCookieIfDoesntExist, loggerModule, Cookie } from "../utils/helpers"
|
||||||
|
|
||||||
const dom = new JSDOM()
|
const dom = new JSDOM()
|
||||||
global.document = dom.window.document
|
global.document = dom.window.document
|
||||||
@ -22,7 +22,7 @@ global.document = dom.window.document
|
|||||||
type LocationLike = Pick<Location, "pathname" | "origin">
|
type LocationLike = Pick<Location, "pathname" | "origin">
|
||||||
|
|
||||||
// jest.mock is hoisted above the imports so we must use `require` here.
|
// jest.mock is hoisted above the imports so we must use `require` here.
|
||||||
jest.mock("@coder/logger", () => require("./helpers").loggerModule)
|
jest.mock("@coder/logger", () => require("../utils/helpers").loggerModule)
|
||||||
|
|
||||||
describe("util", () => {
|
describe("util", () => {
|
||||||
describe("normalize", () => {
|
describe("normalize", () => {
|
@ -1,3 +1,4 @@
|
|||||||
export const CODE_SERVER_ADDRESS = process.env.CODE_SERVER_ADDRESS || "http://localhost:8080"
|
export const CODE_SERVER_ADDRESS = process.env.CODE_SERVER_ADDRESS || "http://localhost:8080"
|
||||||
export const PASSWORD = process.env.PASSWORD || "e45432jklfdsab"
|
export const PASSWORD = process.env.PASSWORD || "e45432jklfdsab"
|
||||||
export const STORAGE = process.env.STORAGE || ""
|
export const STORAGE = process.env.STORAGE || ""
|
||||||
|
export const E2E_VIDEO_DIR = "./test/e2e/videos"
|
@ -6,7 +6,7 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "./constants"
|
|||||||
import * as wtfnode from "./wtfnode"
|
import * as wtfnode from "./wtfnode"
|
||||||
|
|
||||||
module.exports = async () => {
|
module.exports = async () => {
|
||||||
console.log("\n🚨 Running Global Setup for Jest Tests")
|
console.log("\n🚨 Running Global Setup for Jest End-to-End Tests")
|
||||||
console.log(" Please hang tight...")
|
console.log(" Please hang tight...")
|
||||||
const browser = await chromium.launch()
|
const browser = await chromium.launch()
|
||||||
const context = await browser.newContext()
|
const context = await browser.newContext()
|
||||||
@ -30,5 +30,5 @@ module.exports = async () => {
|
|||||||
await page.close()
|
await page.close()
|
||||||
await browser.close()
|
await browser.close()
|
||||||
await context.close()
|
await context.close()
|
||||||
console.log("✅ Global Setup for Jest Tests is now complete.")
|
console.log("✅ Global Setup for Jest End-to-End Tests is now complete.")
|
||||||
}
|
}
|
@ -3,9 +3,9 @@ import * as http from "http"
|
|||||||
import * as net from "net"
|
import * as net from "net"
|
||||||
import * as nodeFetch from "node-fetch"
|
import * as nodeFetch from "node-fetch"
|
||||||
import Websocket from "ws"
|
import Websocket from "ws"
|
||||||
import * as util from "../src/common/util"
|
import * as util from "../../src/common/util"
|
||||||
import { ensureAddress } from "../src/node/app"
|
import { ensureAddress } from "../../src/node/app"
|
||||||
import { handleUpgrade } from "../src/node/wsRouter"
|
import { handleUpgrade } from "../../src/node/wsRouter"
|
||||||
|
|
||||||
// Perhaps an abstraction similar to this should be used in app.ts as well.
|
// Perhaps an abstraction similar to this should be used in app.ts as well.
|
||||||
export class HttpServer {
|
export class HttpServer {
|
@ -1,7 +1,7 @@
|
|||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import { createApp } from "../src/node/app"
|
import { createApp } from "../../src/node/app"
|
||||||
import { parse, setDefaults, parseConfigFile, DefaultedArgs } from "../src/node/cli"
|
import { parse, setDefaults, parseConfigFile, DefaultedArgs } from "../../src/node/cli"
|
||||||
import { register } from "../src/node/routes"
|
import { register } from "../../src/node/routes"
|
||||||
import * as httpserver from "./httpserver"
|
import * as httpserver from "./httpserver"
|
||||||
|
|
||||||
export async function setup(
|
export async function setup(
|
Reference in New Issue
Block a user