Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: write e2e testcases as bdd scenarios #557

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .devcontainer/cpp/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@
"customizations": {
"vscode": {
"settings": {
"cucumberautocomplete.steps": [".devcontainer/cpp/e2e/features/steps/*.steps.ts"],
"cucumberautocomplete.strictGherkinCompletion": false,
"cucumberautocomplete.strictGherkinValidation": false,
"cucumberautocomplete.smartSnippets": true,
"cucumberautocomplete.onTypeFormat": true,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true
},
"extensions": [
"alexkrechik.cucumberautocomplete@3.0.5",
"github.copilot@1.208.0",
"github.vscode-github-actions@0.26.3",
"github.vscode-pull-request-github@0.90.0",
Expand Down
6 changes: 6 additions & 0 deletions .devcontainer/cpp/e2e/features/compilation.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Feature: Compilation

Scenario: Build default configuration
Given I select the default build configuration
When I build configuration "host"
Then the output should contain "Build finished with exit code 0"
37 changes: 37 additions & 0 deletions .devcontainer/cpp/e2e/features/pages/authentication.pom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { type Page } from '@playwright/test';
import * as OTPAuth from 'otpauth';
import { STORAGE_STATE } from '../../playwright.config';

export class AuthenticationPage {
readonly page: Page;

constructor(page: Page) {
this.page = page;
}

async authenticate() {
await this.page.goto('https://github.com/login');
await this.page.getByLabel('Username or email address').fill(process.env.GITHUB_USER!);
await this.page.getByLabel('Password').fill(process.env.GITHUB_PASSWORD!);
await this.page.getByRole('button', { name: 'Sign in', exact: true }).click();

let totp = new OTPAuth.TOTP({
issuer: 'GitHub',
label: 'GitHub',
algorithm: 'SHA1',
digits: 6,
period: 30,
secret: process.env.GITHUB_TOTP_SECRET!
});

let code = totp.generate();
await this.page.getByPlaceholder('XXXXXX').fill(code);

// Wait until the page receives the cookies.
//
// Sometimes login flow sets cookies in the process of several redirects.
// Wait for the final URL to ensure that the cookies are actually set.
await this.page.waitForURL('https://github.com/');
await this.page.context().storageState({ path: STORAGE_STATE });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,8 @@ export class CodespacePage {
await this.page.getByRole('treeitem', { name: name }).locator('a').click();
await expect(this.page.locator('[id="workbench.parts.editor"]')).toContainText(name);
}

async buildSelectedTarget() {
await this.page.getByRole('button', { name: 'Build the selected target' }).click();
}
}
15 changes: 15 additions & 0 deletions .devcontainer/cpp/e2e/features/steps/compilation.steps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect } from "@playwright/test";
import { Given, When, Then } from "./fixtures";

Given("I select the default build configuration", async () => {
// No-op
});

When("I build configuration {string}", async ({ codespacePage }, configuration: string) => {
await codespacePage.page.getByRole('button', { name: 'Build the selected target' }).click();
await codespacePage.page.getByLabel(configuration).locator('a').click();
});

Then("the output should contain {string}", async ({ codespacePage }, expectedOutput: string) => {
await expect(codespacePage.outputPanel).toContainText(expectedOutput, { timeout: 5 * 60 * 1000 });
});
24 changes: 24 additions & 0 deletions .devcontainer/cpp/e2e/features/steps/fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AuthenticationPage } from '../pages/authentication.pom';
import { CodespacePage } from '../pages/codespace.pom';
import { test as base, createBdd } from 'playwright-bdd';

export const test = base.extend<{ codespacePage: CodespacePage }, { authenticationPage: AuthenticationPage }>({
authenticationPage: [async ({ browser }, use) => {
let authenticationPage = new AuthenticationPage(await browser.newPage());
await authenticationPage.authenticate();

await use(authenticationPage);
}, { scope: 'worker', auto: true }
],
codespacePage: async ({ page }, use) => {
const codespacePage = new CodespacePage(page);
await codespacePage.goto();
await codespacePage.areExtensionsActive(['Testing', 'SonarLint', 'CMake', 'Live Share', 'GitHub Pull Requests']);

await use(codespacePage);

await codespacePage.executeInTerminal('git clean -fdx');
},
});

export const { Given, When, Then } = createBdd(test);
14 changes: 9 additions & 5 deletions .devcontainer/cpp/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { defineConfig, devices } from '@playwright/test';
import { defineBddConfig } from "playwright-bdd";
import path from 'path';

require('dotenv').config();
require('dotenv').config({ path: path.join(__dirname, '..', '..', '..', '.env') });

export const STORAGE_STATE = path.join(__dirname, 'playwright/.auth/user.json');

const testDir = defineBddConfig({
features: "features/*.feature",
steps: ["features/steps/*.ts"],
});

export default defineConfig({
testDir: './tests',
testDir,
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
Expand All @@ -16,14 +22,12 @@ export default defineConfig({
trace: 'on-first-retry'
},
projects: [
{ name: 'setup', testMatch: '**/*.setup.ts' },
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
storageState: STORAGE_STATE
},
dependencies: ['setup']
}
}
]
});
29 changes: 0 additions & 29 deletions .devcontainer/cpp/e2e/tests/authentication.setup.ts

This file was deleted.

20 changes: 0 additions & 20 deletions .devcontainer/cpp/e2e/tests/smoke.spec.ts

This file was deleted.

2 changes: 0 additions & 2 deletions .devcontainer/cpp/e2e/workspace/CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
},
{
"name": "host",
"displayName": "host",
"description": "Build for host",
"inherits": "defaults"
}
],
Expand Down
23 changes: 23 additions & 0 deletions .github/linters/.gherkin-lintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"file-name": ["on", {"style": "PascalCase"}],
"indentation": ["on", {"Step": 4, "example": 4}],
"new-line-at-eof": ["on", "yes"],
"no-background-only-scenario": "off",
"no-dupe-feature-names": "on",
"no-dupe-scenario-names": ["on", "in-feature"],
"no-duplicate-tags": "on",
"no-empty-background": "on",
"no-empty-file": "on",
"no-files-without-scenarios" : "on",
"no-multiple-empty-lines": "on",
"no-partially-commented-tag-lines": "on",
"no-scenario-outlines-without-examples": "on",
"no-superfluous-tags": "on",
"no-trailing-spaces": "on",
"no-unnamed-features": "on",
"no-unnamed-scenarios": "on",
"no-unused-variables": "on",
"one-space-between-tags": "on",
"scenario-size": ["on", { "steps-length": {"Background": 5}}],
"use-and": "on"
}
2 changes: 1 addition & 1 deletion .github/workflows/linting-formatting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
- uses: oxsecurity/megalinter/flavors/documentation@c217fe8f7bc9207062a084e989bd97efd56e7b9a # v8.0.0
- uses: oxsecurity/megalinter@c217fe8f7bc9207062a084e989bd97efd56e7b9a # v8.0.0
env:
APPLY_FIXES: all
VALIDATE_ALL_CODEBASE: true
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.features-gen/
.xwin-cache/
.xwin-hash/
build/
Expand Down
3 changes: 2 additions & 1 deletion .mega-linter.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ENABLE:
- ACTION
- DOCKERFILE
- GHERKIN
- JSON
- MARKDOWN
- REPOSITORY
Expand All @@ -16,7 +17,7 @@ DISABLE_LINTERS:
SARIF_REPORTER: true
PRINT_ALPACA: false
SHOW_SKIPPED_LINTERS: false
FILTER_REGEX_EXCLUDE: (CHANGELOG.md)
FILTER_REGEX_EXCLUDE: (CHANGELOG.md|package-lock.json)
# tasks.json is wrongfully matched against another schema,
# and schemas for .vscode/[tasks.json|launch.json] are built
# dynamically based upon context (e.g. installed extensions)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ A test task is available to run the included `bats` tests. Choose `Tasks: Run Te

#### Running the Acceptance Tests

Create an .env file with the following contents, this assumes a GitHub account that has rights to create a Codespace on this repository and is configured for time-based one-time password (TOTP) two-factor authentication (2FA).
Create a .env file in the root of the workspace with the following contents, this assumes a GitHub account that has rights to create a Codespace on this repository and is configured for time-based one-time password (TOTP) two-factor authentication (2FA).

```dotenv
GITHUB_USER=
Expand Down
Loading
Loading