Skip to content

Commit

Permalink
chore(tests) add test coverage
Browse files Browse the repository at this point in the history
Signed-off-by: David Edler <david.edler@canonical.com>
  • Loading branch information
edlerd committed Feb 20, 2024
1 parent 625aa55 commit 33cd89f
Show file tree
Hide file tree
Showing 20 changed files with 1,711 additions and 897 deletions.
88 changes: 88 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: PR checks
on: pull_request

permissions:
contents: read

jobs:
e2e-coverage:
name: e2e-test-coverage
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
lxd_channel: ["latest/edge"]
browser: ["chromium"]
outputs:
job_status: ${{job.status}}
steps:
- uses: actions/checkout@v4

- name: Install Dotrun
run: |
sudo pip3 install dotrun
- name: Restore cached keys
uses: actions/cache/restore@v3
with:
path: keys
key: keys-folder

- name: Install LXD-UI dependencies
run: |
set -x
sudo chmod 0777 ../lxd-ui
dotrun install
- name: Run LXD-UI
env:
ENVIRONMENT: devel
PORT: 8407
LXD_UI_BACKEND_IP: 172.17.0.1
run: |
dotrun &
curl --head --fail --retry-delay 2 --retry 100 --retry-connrefused --insecure https://localhost:8407
- name: Set keys permissions
run: |
set -x
sudo chmod -R 0666 keys
sudo chmod 0777 keys
- name: Save keys
uses: actions/cache/save@v3
with:
path: keys
key: keys-folder

- name: Install LXD
uses: canonical/setup-lxd@v0.1.1
with:
channel: ${{ matrix.lxd_channel }}

- name: Setup LXD
shell: bash
run: |
set -x
sudo lxc config set core.https_address "[::]:8443"
sudo lxc config trust add keys/lxd-ui.crt
sudo lxc config set cluster.https_address "127.0.0.1"
sudo lxc cluster enable local
- uses: actions/setup-node@v4
with:
node-version: 18

- name: Install Playwright Browsers
run: npx playwright install --with-deps ${{ matrix.browser }}

- name: Run tests with coverage
run: yarn test-e2e-coverage

- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: lxd-playwright-coverage
path: coverage/playwright-report
retention-days: 1
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ dist/
/test-results/
/playwright-report/
/playwright/.cache/
/coverage

haproxy-local.cfg
haproxy-local.cfg
16 changes: 14 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "LGPL-3.0-only",
"type": "module",
"scripts": {
"clean": "rm -rf node_modules yarn-error.log *.log build/ .jekyll-metadata .bundle playwright-report test-results haproxy-local.cfg",
"clean": "rm -rf node_modules yarn-error.log *.log build/ .jekyll-metadata .bundle playwright-report test-results haproxy-local.cfg coverage",
"build-html": "cp build/ui/index.html build/index.html",
"build": "npx vite build && yarn build-html",
"format-js-eslint": "eslint 'src/**/*.{json,jsx,tsx,ts}' 'tests/**/*.ts' --fix",
Expand All @@ -21,7 +21,12 @@
"serve": "./entrypoint",
"test-js": "vitest --run",
"test-e2e-edge": "npx playwright test --project chromium:lxd-latest-edge firefox:lxd-latest-edge",
"test-e2e-stable": "npx playwright test --project chromium:lxd-5.0-stable firefox:lxd-5.0-stable"
"test-e2e-stable": "npx playwright test --project chromium:lxd-5.0-stable firefox:lxd-5.0-stable",
"test-js-coverage": "vitest --run --coverage",
"test-e2e-coverage": "yarn test-e2e-coverage-pw ; yarn test-e2e-coverage-report-html && yarn test-e2e-coverage-report-cobertura",
"test-e2e-coverage-pw": "rm -rf coverage/playwright* ; PW_TEST_HTML_REPORT_OPEN='never' npx playwright test --project coverage",
"test-e2e-coverage-report-html": "nyc report --reporter html --temp-dir coverage/playwright --report-dir coverage/playwright-report",
"test-e2e-coverage-report-cobertura": "nyc report --reporter cobertura --temp-dir coverage/playwright --report-dir coverage/playwright-report"
},
"dependencies": {
"@canonical/react-components": "0.50.2",
Expand Down Expand Up @@ -54,6 +59,7 @@
"@babel/preset-react": "7.23.3",
"@babel/preset-typescript": "7.23.3",
"@playwright/test": "1.41.0",
"@types/convert-source-map": "2.0.3",
"@types/cytoscape-popper": "2.0.4",
"@types/node-forge": "1.3.11",
"@types/react": "18.2.48",
Expand All @@ -64,15 +70,19 @@
"@typescript-eslint/eslint-plugin": "6.19.0",
"@typescript-eslint/parser": "6.19.0",
"@vitejs/plugin-react": "4.2.1",
"@vitest/coverage-istanbul": "1.2.2",
"autoprefixer": "10.4.16",
"babel-plugin-istanbul": "6.1.1",
"concurrently": "8.2.2",
"convert-source-map": "2.0.0",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-react": "7.33.2",
"husky": "8.0.3",
"lint-staged": "15.2.0",
"monaco-editor": "0.45.0",
"nyc": "^15.1.0",
"postcss": "8.4.33",
"postcss-cli": "11.0.0",
"prettier": "3.2.4",
Expand All @@ -83,7 +93,9 @@
"stylelint-prettier": "5.0.0",
"stylelint-scss": "6.0.0",
"typescript": "5.3.3",
"v8-to-istanbul": "9.2.0",
"vite": "4.5.2",
"vite-plugin-istanbul": "5.0.0",
"vite-tsconfig-paths": "4.3.1",
"vitest": "1.2.1"
},
Expand Down
16 changes: 12 additions & 4 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ import { TestOptions } from "./tests/fixtures/lxd-test";
const config: PlaywrightTestConfig<TestOptions> = {
testDir: "./tests",
/* Maximum time one test can run for. */
timeout: 120 * 1000,
timeout: 120_000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 120 * 1000,
timeout: 120_000,
},
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : 3,
/* Opt out of parallel tests. */
workers: 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: process.env.CI ? "blob" : "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
Expand Down Expand Up @@ -70,6 +70,14 @@ const config: PlaywrightTestConfig<TestOptions> = {
lxdVersion: "latest-edge",
},
},
{
name: "coverage",
use: {
...devices["Desktop Chrome"],
lxdVersion: "latest-edge",
hasCoverage: true,
},
},
],
};

Expand Down
58 changes: 58 additions & 0 deletions tests/fixtures/coverage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Page } from "@playwright/test";
import fs from "fs";
import { fromSource, removeMapFileComments } from "convert-source-map";
import v8ToIstanbul from "v8-to-istanbul";
import * as crypto from "crypto";

export const startCoverage = async (page: Page) => {
await page.coverage.startJSCoverage();
};

export const finishCoverage = async (page: Page) => {
const coverage = await page.coverage.stopJSCoverage();
for (const entry of coverage) {
if (entry.url.endsWith(".css")) {
continue;
}
if (entry.url.includes("@vite")) {
continue;
}
if (entry.url.includes("spice")) {
continue;
}
const fileMatcher = entry.url.match(/http(s)*:\/\/.*:8407\/(?<file>.*)/);
if (!fileMatcher?.groups) {
continue;
}
const path = fileMatcher.groups.file;
const source = removeMapFileComments(entry.source ?? "");
const sourceMap = fromSource(entry.source ?? "");

const converter = v8ToIstanbul(path, 0, {
source,
sourceMap,
});
await converter.load();
converter.applyCoverage(entry.functions);
const istanbulCoverage = converter.toIstanbul();

const generateUUID = (): string => {
return crypto.randomBytes(16).toString("hex");
};

const uuid = generateUUID();

Object.entries(istanbulCoverage).forEach(([key]) => {
istanbulCoverage[key]["_coverageSchema"] = uuid;
});

const outDir = "coverage/playwright";
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir, { recursive: true });
}
fs.writeFileSync(
`${outDir}/playwright_coverage_${uuid}.json`,
JSON.stringify(istanbulCoverage),
);
}
};
17 changes: 17 additions & 0 deletions tests/fixtures/lxd-test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import { test as base } from "@playwright/test";
import { finishCoverage, startCoverage } from "./coverage";

export type LxdVersions = "5.0-stable" | "latest-edge";
export type TestOptions = {
lxdVersion: LxdVersions;
hasCoverage: boolean;
};

export const test = base.extend<TestOptions>({
lxdVersion: ["latest-edge", { option: true }],
hasCoverage: [false, { option: true }],
});

test.beforeEach(async ({ page, hasCoverage }) => {
if (hasCoverage) {
await startCoverage(page);
}
});

test.afterEach(async ({ page, hasCoverage }) => {
if (hasCoverage) {
await finishCoverage(page);
}
});

export const expect = test.expect;
1 change: 1 addition & 0 deletions tests/helpers/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const deleteNetwork = async (page: Page, network: string) => {
};

export const visitNetwork = async (page: Page, network: string) => {
await page.goto("/ui/");
await page.getByTitle("Networks (default)").click();
await page.getByRole("link", { name: network }).first().click();
};
Expand Down
15 changes: 7 additions & 8 deletions tests/instance-panel.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Page } from "@playwright/test";
import { test } from "./fixtures/lxd-test";
import {
createInstance,
deleteInstance,
randomInstanceName,
} from "./helpers/instances";
// eslint-disable-next-line prettier/prettier
import {
closeInstancePanel,
navigateToInstanceDetails,
Expand All @@ -15,31 +13,32 @@ import {
} from "./helpers/instancePanel";

let instance = randomInstanceName();
let page: Page;
test.beforeAll(async ({ browserName, browser }) => {
instance = `${browserName}-${instance}`;
page = await browser.newPage();
const page = await browser.newPage();
await createInstance(page, instance);
await page.close();
});

test.afterAll(async () => {
test.afterAll(async ({ browser }) => {
const page = await browser.newPage();
await deleteInstance(page, instance);
await page.close();
});

test("instance panel open and close", async () => {
test("instance panel open and close", async ({ page }) => {
await openInstancePanel(page, instance);
await closeInstancePanel(page);
});

test("start and stop instance from panel", async () => {
test("start and stop instance from panel", async ({ page }) => {
await openInstancePanel(page, instance);
await startInstanceFromPanel(page, instance);
await stopInstanceFromPanel(page, instance);
await closeInstancePanel(page);
});

test("navigate to instance details from panel", async () => {
test("navigate to instance details from panel", async ({ page }) => {
await openInstancePanel(page, instance);
await navigateToInstanceDetails(page, instance);
});
Loading

0 comments on commit 33cd89f

Please sign in to comment.