Skip to content

Commit c51ff3b

Browse files
jsjoeiocode-asher
andauthored
refactor: move integration tests to Jest (#5275)
* feat: add installExtension integration test This adds a new helper function called `runCodeServerCommand` along with a test for `--install-extension`. We can use this approach for writing integration tests (i.e. testing a real code-server build, CLI commands, etc). * refactor: s/ test:standalone with test:integration This replaces our integration approach to use Jest instead of a single bash script. By doing this, we will be able to easily maintain and add to our integration test suite. * refactor: filter unit tests Now that our integration tests also use Jest, we need to update our unit test script to ignore `test/integration`. * refactor: add SKIP_SUBMODULE_DEPS to postinstall * refactor: add SKIP_SUBMODULE_DEPS to postinstall * fixup!: skip submod deps * refactor: move runCodeServerCommand into sep. file When Jest runs a test, it loads all the files and imports for that test. This means you might be "requiring" code that's unrelated to your tests. This leads to unexpected errors depending on where the code runs. Moved this file to avoid GLIBC and other errors relaed to argon2 when running integration tests in CI. * fizup: formatting * fizup: increase timeout * refactor: use fixture in installExtension test Instead of relying on a network to install an extension, we use a fixture - vsix file in the repo. This is also faster. * feat: add integration test for listExtensions * chore: ignore integration fixtures * fixup: formatting * fixup: remove custom-hacks.css * fixup: formatting * Update test/integration/installExtension.test.ts Co-authored-by: Asher <[email protected]> * Update test/integration/listExtensions.test.ts Co-authored-by: Asher <[email protected]> * Update test/integration/installExtension.test.ts Co-authored-by: Asher <[email protected]> * Update test/integration/listExtensions.test.ts Co-authored-by: Asher <[email protected]> * fixup: contributing integration tests section * fixup: update ci/readme * fixup: use RELEASE_PATH in test-integration.sh * refactor: unzip vsix for listExtensions * refactor: use exec instead of spawn * Update docs/CONTRIBUTING.md Co-authored-by: Asher <[email protected]> * Update test/integration/listExtensions.test.ts Co-authored-by: Asher <[email protected]> * Update test/integration/listExtensions.test.ts Co-authored-by: Asher <[email protected]> * Update test/integration/listExtensions.test.ts Co-authored-by: Asher <[email protected]> * refactor: use different default binary path * fixup!: formatting Co-authored-by: Asher <[email protected]>
1 parent a879844 commit c51ff3b

15 files changed

+136
-52
lines changed

.github/workflows/ci.yaml

+10-4
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,11 @@ jobs:
288288
- name: Build standalone release
289289
run: source scl_source enable devtoolset-9 && yarn release:standalone
290290

291-
- name: Sanity test standalone release
292-
run: yarn test:standalone-release
291+
- name: Install test dependencies
292+
run: SKIP_SUBMODULE_DEPS=1 yarn install
293+
294+
- name: Run integration tests on standalone release
295+
run: yarn test:integration
293296

294297
- name: Build packages with nfpm
295298
run: yarn package
@@ -421,8 +424,11 @@ jobs:
421424
- name: Build standalone release
422425
run: yarn release:standalone
423426

424-
- name: Sanity test standalone release
425-
run: yarn test:standalone-release
427+
- name: Install test dependencies
428+
run: SKIP_SUBMODULE_DEPS=1 yarn install
429+
430+
- name: Run integration tests on standalone release
431+
run: yarn test:integration
426432

427433
- name: Build packages with nfpm
428434
run: yarn package

.github/workflows/installer.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
run: ./install.sh
3535

3636
- name: Test code-server
37-
run: yarn test:standalone-release code-server
37+
run: CODE_SERVER_PATH="code-server" yarn test:integration
3838

3939
alpine:
4040
name: Test installer on Alpine
@@ -66,4 +66,4 @@ jobs:
6666
run: ./install.sh
6767

6868
- name: Test code-server
69-
run: yarn test:standalone-release code-server
69+
run: CODE_SERVER_PATH="code-server" yarn test:integration

ci/README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ You can disable minification by setting `MINIFY=`.
4545
- Builds vscode into `./lib/vscode/out-vscode`.
4646
- [./ci/build/build-release.sh](./build/build-release.sh) (`yarn release`)
4747
- Bundles the output of the above two scripts into a single node module at `./release`.
48-
- [./ci/build/build-standalone-release.sh](./build/build-standalone-release.sh) (`yarn release:standalone`)
49-
- Requires a node module already built into `./release` with the above script.
50-
- Will build a standalone release with node and node_modules bundled into `./release-standalone`.
5148
- [./ci/build/clean.sh](./build/clean.sh) (`yarn clean`)
5249
- Removes all build artifacts.
5350
- Useful to do a clean build.
@@ -97,6 +94,8 @@ Helps avoid clobbering the CI configuration.
9794
- Runs `yarn lint`.
9895
- [./steps/test-unit.sh](./steps/test-unit.sh)
9996
- Runs `yarn test:unit`.
97+
- [./steps/test-integration.sh](./steps/test-integration.sh)
98+
- Runs `yarn test:integration`.
10099
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
101100
- Runs `yarn test:e2e`.
102101
- [./steps/release.sh](./steps/release.sh)

ci/build/test-standalone-release.sh

-33
This file was deleted.

ci/dev/postinstall.sh

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ main() {
2929

3030
install-deps test
3131
install-deps test/e2e/extensions/test-extension
32-
install-deps lib/vscode
32+
# We don't need these when running the integration tests
33+
# so you can pass SKIP_SUBMODULE_DEPS
34+
if [[ ! ${SKIP_SUBMODULE_DEPS-} ]]; then
35+
install-deps lib/vscode
36+
fi
3337
}
3438

3539
main "$@"

ci/dev/test-integration.sh

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
help() {
5+
echo >&2 " You can build the standalone release with 'yarn release:standalone'"
6+
echo >&2 " Or you can pass in a custom path."
7+
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' yarn test:integration"
8+
}
9+
10+
# Make sure a code-server release works. You can pass in the path otherwise it
11+
# will look for release-standalone in the current directory.
12+
#
13+
# This is to make sure we don't have Node version errors or any other
14+
# compilation-related errors.
15+
main() {
16+
cd "$(dirname "$0")/../.."
17+
18+
source ./ci/lib.sh
19+
20+
local path="$RELEASE_PATH-standalone/bin/code-server"
21+
if [[ ! ${CODE_SERVER_PATH-} ]]; then
22+
echo "Set CODE_SERVER_PATH to test another build of code-server"
23+
else
24+
path="$CODE_SERVER_PATH"
25+
fi
26+
27+
echo "Running tests with code-server binary: '$path'"
28+
29+
if [[ ! -f $path ]]; then
30+
echo >&2 "No code-server build detected"
31+
echo >&2 "Looked in $path"
32+
help
33+
exit 1
34+
fi
35+
36+
CODE_SERVER_PATH="$path" CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
37+
}
38+
39+
main "$@"

ci/dev/test-unit.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ main() {
3030
# We must keep jest in a sub-directory. See ../../test/package.json for more
3131
# information. We must also run it from the root otherwise coverage will not
3232
# include our source files.
33-
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@"
33+
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts" --testPathIgnorePatterns "./test/unit/node/test-plugin"
3434
}
3535

3636
main "$@"

docs/CONTRIBUTING.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ Build the release packages (make sure that you run `yarn release` first):
147147

148148
```shell
149149
yarn release:standalone
150-
yarn test:standalone-release
150+
yarn test:integration
151151
yarn package
152152
```
153153

@@ -188,9 +188,8 @@ We use these to test anything related to our scripts (most of which live under `
188188

189189
### Integration tests
190190

191-
These are a work in progress. We build code-server and run a script called
192-
[test-standalone-release.sh](../ci/build/test-standalone-release.sh), which
193-
ensures that code-server's CLI is working.
191+
These are a work in progress. We build code-server and run tests with `yarn test:integration`, which ensures that code-server builds work on their respective
192+
platforms.
194193

195194
Our integration tests look at components that rely on one another. For example,
196195
testing the CLI requires us to build and package code-server.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"release:github-assets": "./ci/build/release-github-assets.sh",
1919
"release:prep": "./ci/build/release-prep.sh",
2020
"test:e2e": "VSCODE_IPC_HOOK_CLI= ./ci/dev/test-e2e.sh",
21-
"test:standalone-release": "./ci/build/test-standalone-release.sh",
2221
"test:unit": "./ci/dev/test-unit.sh --forceExit --detectOpenHandles",
22+
"test:integration": "./ci/dev/test-integration.sh",
2323
"test:scripts": "./ci/dev/test-scripts.sh",
2424
"package": "./ci/build/build-packages.sh",
2525
"postinstall": "./ci/dev/postinstall.sh",
Binary file not shown.
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { stat } from "fs/promises"
2+
import path from "path"
3+
import { clean, tmpdir } from "../utils/helpers"
4+
import { runCodeServerCommand } from "../utils/runCodeServerCommand"
5+
6+
describe("--install-extension", () => {
7+
const testName = "installExtension"
8+
let tempDir: string
9+
let setupFlags: string[]
10+
11+
beforeEach(async () => {
12+
await clean(testName)
13+
tempDir = await tmpdir(testName)
14+
setupFlags = ["--extensions-dir", tempDir]
15+
})
16+
it("should install an extension", async () => {
17+
const extName = `wesbos.theme-cobalt2-2.1.6`
18+
const vsixFileName = "wesbos.theme-cobalt2-2.1.6.vsix"
19+
const extensionFixture = path.resolve(`./test/integration/fixtures/${vsixFileName}`)
20+
await runCodeServerCommand([...setupFlags, "--install-extension", extensionFixture])
21+
const pathToExtFolder = path.join(tempDir, extName)
22+
const statInfo = await stat(pathToExtFolder)
23+
expect(statInfo.isDirectory()).toBe(true)
24+
}, 20000)
25+
})
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { rename } from "fs/promises"
2+
import path from "path"
3+
import extract from "extract-zip"
4+
import { clean, tmpdir } from "../utils/helpers"
5+
import { runCodeServerCommand } from "../utils/runCodeServerCommand"
6+
7+
describe("--list-extensions", () => {
8+
const testName = "listExtensions"
9+
const extName = `wesbos.theme-cobalt2`
10+
const extVersion = "2.1.6"
11+
const vsixFileName = `${extName}-${extVersion}.vsix`
12+
let tempDir: string
13+
let setupFlags: string[]
14+
15+
beforeEach(async () => {
16+
await clean(testName)
17+
tempDir = await tmpdir(testName)
18+
setupFlags = ["--extensions-dir", tempDir]
19+
const extensionFixture = path.resolve(`./test/integration/fixtures/${vsixFileName}`)
20+
// Make folder because this is where we'll move the extension
21+
const pathToUnpackedExtension = path.join(tempDir, `${extName}-${extVersion}`)
22+
const tempPathToUnpackedExtension = path.join(tempDir, `${extName}-temp`)
23+
await extract(extensionFixture, { dir: tempPathToUnpackedExtension })
24+
await rename(path.join(tempPathToUnpackedExtension, "extension", pathToUnpackedExtension))
25+
})
26+
it("should list installed extensions", async () => {
27+
const { stdout } = await runCodeServerCommand([...setupFlags, "--list-extensions"])
28+
expect(stdout).toMatch(extName)
29+
}, 20000)
30+
})

test/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"@types/supertest": "^2.0.11",
1111
"@types/wtfnode": "^0.7.0",
1212
"argon2": "^0.28.0",
13+
"extract-zip": "^2.0.1",
1314
"jest": "^27.3.1",
1415
"jest-fetch-mock": "^3.0.3",
1516
"jsdom": "^16.4.0",

test/utils/runCodeServerCommand.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { exec } from "child_process"
2+
import path from "path"
3+
import { promisify } from "util"
4+
5+
/**
6+
*
7+
* A helper function for integration tests to run code-server commands.
8+
*/
9+
export async function runCodeServerCommand(argv: string[]): Promise<{ stdout: string; stderr: string }> {
10+
const CODE_SERVER_COMMAND = process.env.CODE_SERVER_PATH || path.resolve("../../release-standalone/bin/code-server")
11+
const { stdout, stderr } = await promisify(exec)(`${CODE_SERVER_COMMAND} ${argv.join(" ")}`)
12+
13+
return { stdout, stderr }
14+
}

test/yarn.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -1690,9 +1690,9 @@ globals@^11.1.0:
16901690
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
16911691

16921692
graceful-fs@^4.2.4:
1693-
version "4.2.9"
1694-
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
1695-
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
1693+
version "4.2.10"
1694+
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
1695+
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
16961696

16971697
has-flag@^3.0.0:
16981698
version "3.0.0"

0 commit comments

Comments
 (0)