From deb4bf2f7b97617f4a036912d66ca54c45a2fea8 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Tue, 9 Jun 2020 13:18:24 +0300 Subject: [PATCH] Integration tests using spectron (#410) Signed-off-by: Jari Kolehmainen --- .azure-pipelines.yml | 13 +- Makefile | 12 + package.json | 11 +- spec/integration/helpers/utils.ts | 34 ++ spec/integration/specs/app_spec.ts | 56 +++ src/main/window-manager.ts | 5 +- src/renderer/components/AddClusterPage.vue | 1 + src/renderer/components/LandingPage.vue | 10 +- yarn.lock | 400 ++++++++++++++++++++- 9 files changed, 513 insertions(+), 29 deletions(-) create mode 100644 spec/integration/helpers/utils.ts create mode 100644 spec/integration/specs/app_spec.ts diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 05d7117e19..2a4751ff33 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -44,7 +44,6 @@ jobs: WIN_CSC_KEY_PASSWORD: $(WIN_CSC_KEY_PASSWORD) GH_TOKEN: $(GH_TOKEN) - job: macOS - condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))" pool: vmImage: macOS-10.14 strategy: @@ -75,7 +74,10 @@ jobs: displayName: Lint - script: make test displayName: Run tests + - script: make integration-mac + displayName: Run integration tests - script: make build + condition: "and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))" displayName: Build env: APPLEID: $(APPLEID) @@ -119,6 +121,15 @@ jobs: displayName: Lint - script: make test displayName: Run tests + - bash: | + sudo apt-get update + sudo apt-get install libgconf-2-4 conntrack -y + curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 + sudo install minikube-linux-amd64 /usr/local/bin/minikube + sudo minikube start --driver=none + displayName: Install integration test dependencies + - script: xvfb-run --auto-servernum --server-args='-screen 0, 1600x900x24' make integration-linux + displayName: Run integration tests - bash: | sudo chown root:root / sudo apt-get update && sudo apt-get install -y snapd diff --git a/Makefile b/Makefile index dfab88c228..6139afdfba 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,18 @@ dev: app-deps dashboard-deps test: test-app test-dashboard +integration-linux: + yarn build:linux + yarn integration + +integration-mac: + yarn build:mac + yarn integration + +integration-win: + yarn build:win + yarn integration + lint: yarn lint diff --git a/package.json b/package.json index 007bb9cca6..82906dce0b 100644 --- a/package.json +++ b/package.json @@ -109,16 +109,17 @@ "dev-dashboard": "cd dashboard && yarn dev", "dev-electron": "electron-webpack dev", "compile": "yarn download:bins && electron-webpack", - "build:linux": "yarn compile && electron-builder --linux --dir", - "build:mac": "yarn compile && electron-builder --mac --dir", - "build:win": "yarn compile && electron-builder --win --dir", + "build:linux": "yarn compile && electron-builder --linux --dir -c.productName=LensDev", + "build:mac": "yarn compile && electron-builder --mac --dir -c.productName=LensDev", + "build:win": "yarn compile && electron-builder --win --dir -c.productName=LensDev", "dist": "yarn compile && electron-builder -p onTag", "dist:win": "yarn compile && electron-builder -p onTag --x64 --ia32", "dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null", "lint": "eslint $@ --ext js,ts,vue --max-warnings=0 src/", "lint-dashboard": "eslint $@ --ext js,ts,tsx --max-warnings=0 dashboard/client dashboard/server", "postinstall": "patch-package", - "test": "node_modules/.bin/jest", + "test": "node_modules/.bin/jest spec/src/", + "integration": "node_modules/.bin/jest spec/integration/", "download:bins": "concurrently \"yarn download:kubectl\" \"yarn download:helm\"", "download:kubectl": "yarn run ts-node build/download_kubectl.ts", "download:helm": "yarn run ts-node build/download_helm.ts" @@ -184,6 +185,7 @@ "@types/tempy": "0.1.0", "@types/universal-analytics": "^0.4.3", "@types/uuid": "^3.4.5", + "@types/webdriverio": "^4.13.0", "@typescript-eslint/eslint-plugin": "^2.7.0", "@typescript-eslint/parser": "^2.7.0", "bootstrap": "^4.3.1", @@ -211,6 +213,7 @@ "postinstall-postinstall": "^2.0.0", "prismjs": "^1.17.1", "sass-loader": "^8.0.0", + "spectron": "^8.0.0", "ts-jest": "^24.1.0", "ts-loader": "^6.0.4", "ts-node": "^8.4.1", diff --git a/spec/integration/helpers/utils.ts b/spec/integration/helpers/utils.ts new file mode 100644 index 0000000000..ee138be56e --- /dev/null +++ b/spec/integration/helpers/utils.ts @@ -0,0 +1,34 @@ +import { Application } from "spectron"; + +let appPath = "" +switch(process.platform) { +case "win32": + appPath = "./dist/win-unpacked/Lens.exe" + break +case "linux": + appPath = "./dist/linux-unpacked/kontena-lens" + break +case "darwin": + appPath = "./dist/mac/LensDev.app/Contents/MacOS/LensDev" + break +} + +export function setup() { + return new Application({ + // path to electron app + args: [], + path: appPath, + startTimeout: 30000, + waitTimeout: 30000, + }) +} + +export async function tearDown(app: Application) { + const pid = app.mainProcess.pid + await app.stop() + try { + process.kill(pid, 0); + } catch(e) { + return + } +} diff --git a/spec/integration/specs/app_spec.ts b/spec/integration/specs/app_spec.ts new file mode 100644 index 0000000000..414c3288bd --- /dev/null +++ b/spec/integration/specs/app_spec.ts @@ -0,0 +1,56 @@ +import { Application } from "spectron" +import * as util from "../helpers/utils" +import { spawnSync } from "child_process" +import { stat } from "fs" + +jest.setTimeout(20000) + +describe("app start", () => { + let app: Application + const clickWhatsNew = async (app: Application) => { + await app.client.waitUntilTextExists("h1", "What's new") + await app.client.click("button.btn-primary") + await app.client.waitUntilTextExists("h1", "Welcome") + } + + beforeEach(async () => { + app = util.setup() + await app.start() + const windowCount = await app.client.getWindowCount() + await app.client.windowByIndex(windowCount - 1) + await app.client.waitUntilWindowLoaded() + }, 20000) + + it('shows "whats new"', async () => { + await clickWhatsNew(app) + }) + + it('allows to add a cluster', async () => { + const status = spawnSync("minikube status", {shell: true}) + if (status.status !== 0) { + console.warn("minikube not running, skipping test") + return + } + await clickWhatsNew(app) + await app.client.click("a#add-cluster") + await app.client.waitUntilTextExists("legend", "Choose config:") + await app.client.selectByVisibleText("select#kubecontext-select", "minikube (new)") + await app.client.click("button.btn-primary") + await app.client.waitUntilTextExists("pre.auth-output", "Authentication proxy started") + let windowCount = await app.client.getWindowCount() + // wait for webview to appear on window count + while (windowCount == 1) { + windowCount = await app.client.getWindowCount() + } + await app.client.windowByIndex(windowCount - 1) + await app.client.waitUntilTextExists("span.link-text", "Cluster") + await app.client.click('a[href="/nodes"]') + await app.client.waitUntilTextExists("div.TableCell", "minikube") + }) + + afterEach(async () => { + if (app && app.isRunning()) { + return util.tearDown(app) + } + }) +}) diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index b585f69761..9baa5e1d4e 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -27,7 +27,10 @@ export class WindowManager { center: true, frame: false, resizable: false, - show: false + show: false, + webPreferences: { + nodeIntegration: true + } }) if (showSplash) { this.splashWindow.loadFile(path.join(__static, "/splash.html")) diff --git a/src/renderer/components/AddClusterPage.vue b/src/renderer/components/AddClusterPage.vue index 6f105a3950..74811a35b2 100644 --- a/src/renderer/components/AddClusterPage.vue +++ b/src/renderer/components/AddClusterPage.vue @@ -11,6 +11,7 @@ label="Choose config:" >