Skip to content

Commit

Permalink
test: add system tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ahtrotta committed Dec 6, 2022
1 parent a902b33 commit bbc7da7
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 4 deletions.
18 changes: 17 additions & 1 deletion test/system/src/appMap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Locator, Page } from '@playwright/test';
import FindingDetailsWebview from './findingDetailsWebview';
import FindingsOverviewWebview from './findingsOverviewWebview';
import InstructionsWebview from './instructionsWebview';

export enum InstructionStep {
Expand All @@ -18,7 +20,9 @@ export enum InstructionStepStatus {
export default class AppMap {
constructor(
protected readonly page: Page,
protected readonly instructionsWebview: InstructionsWebview
protected readonly instructionsWebview: InstructionsWebview,
protected readonly findingsOverviewWebview: FindingsOverviewWebview,
protected readonly findingDetailsWebview: FindingDetailsWebview
) {}

get actionPanelButton(): Locator {
Expand Down Expand Up @@ -49,6 +53,10 @@ export default class AppMap {
return this.findingsTree.locator('.pane-body >> [role="treeitem"]').nth(nth || 0);
}

public finding(nth?: number): Locator {
return this.findingsTree.locator('[role="treeitem"][aria-level="3"]').nth(nth || 0);
}

public appMapTreeItem(): Locator {
return this.appMapTree.locator('.pane-body >> [role="treeitem"]:not([aria-expanded])').first();
}
Expand All @@ -59,6 +67,14 @@ export default class AppMap {
}
}

public async openFindingsOverview(): Promise<void> {
this.findingsTreeItem(0).click();
}

public openNthFinding(nth: number): void {
this.finding(nth).click();
}

public async openActionPanel(): Promise<void> {
await this.actionPanelButton.click();
await this.ready();
Expand Down
11 changes: 10 additions & 1 deletion test/system/src/driver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { BrowserContext, ElectronApplication, Locator, Page } from '@playwright/test';
import { glob } from 'glob';
import AppMap from './appMap';
import FindingDetailsWebview from './findingDetailsWebview';
import FindingsOverviewWebview from './findingsOverviewWebview';
import InstructionsWebview from './instructionsWebview';
import Panel from './panel';
import { getOsShortcut } from './util';
Expand All @@ -15,7 +17,14 @@ async function tryClick(elem: Locator, timeout = 5000) {

export default class Driver {
public readonly instructionsWebview = new InstructionsWebview(this.page);
public readonly appMap = new AppMap(this.page, this.instructionsWebview);
public readonly findingsOverviewWebview = new FindingsOverviewWebview(this.page);
public readonly findingDetailsWebview = new FindingDetailsWebview(this.page);
public readonly appMap = new AppMap(
this.page,
this.instructionsWebview,
this.findingsOverviewWebview,
this.findingDetailsWebview
);
public readonly panel = new Panel(this.page);

constructor(
Expand Down
31 changes: 31 additions & 0 deletions test/system/src/findingDetailsWebview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FrameLocator, Page } from '@playwright/test';
import { strictEqual } from 'assert';
import { waitFor } from '../../waitFor';

export default class FindingDetailsWebview {
constructor(protected readonly page: Page) {}

private frameSelector = 'iframe.webview.ready';
private frame?: FrameLocator;
private initializeErrorMsg = 'No frame found. Call initialize() first';

public async assertTitleRenders(expectedTitle: string): Promise<void> {
if (!this.frame) throw Error(this.initializeErrorMsg);

const title = this.frame.locator('[data-cy="title"]');
strictEqual(await title.count(), 1, 'Expected one title element');
strictEqual(await title.innerText(), expectedTitle);
}

public async initialize(expectedFrames: number): Promise<void> {
const checkForIFrames = async () => {
const iframes = await this.page.locator(this.frameSelector).count();
return iframes === expectedFrames;
};

await waitFor('waiting for second iframe', checkForIFrames.bind(this));
const outerFrame = this.page.frameLocator(this.frameSelector).last();
await outerFrame.locator('iframe#active-frame').waitFor();
this.frame = outerFrame.frameLocator('#active-frame');
}
}
49 changes: 49 additions & 0 deletions test/system/src/findingsOverviewWebview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { FrameLocator, Page } from '@playwright/test';
import { strictEqual } from 'assert';
import { waitFor } from '../../waitFor';

export default class FindingsOverviewWebview {
constructor(protected readonly page: Page) {}

private title = 'Runtime Analysis';
private frameSelector = 'iframe.webview.ready';
private frame?: FrameLocator;
private initializeErrorMsg = 'No frame found. Call initialize() first';

public async assertNumberOfFindingsInOverview(expected: number): Promise<void> {
if (!this.frame) throw Error(this.initializeErrorMsg);

const count = await this.frame.locator('[data-cy="finding"]').count();
strictEqual(count, expected, `Expected number of findings to be ${expected}`);
}

public async assertTitleRenders(): Promise<void> {
if (!this.frame) throw Error(this.initializeErrorMsg);

const title = this.frame.locator('[data-cy="title"]');
strictEqual(await title.count(), 1, 'Expected one title element');
strictEqual(await title.innerText(), this.title);
}

public async openFirstFindingDetail(): Promise<void> {
if (!this.frame) throw Error(this.initializeErrorMsg);

this.frame
.locator('[data-cy="finding"]')
.first()
.locator('ul')
.click();
}

public async initialize(expectedFrames: number): Promise<void> {
const checkForIFrames = async () => {
const iframes = await this.page.locator(this.frameSelector).count();
return iframes === expectedFrames;
};

await waitFor('waiting for second iframe', checkForIFrames.bind(this));
const outerFrame = this.page.frameLocator(this.frameSelector).last();
await outerFrame.locator('iframe#active-frame').waitFor();
this.frame = outerFrame.frameLocator('#active-frame');
}
}
84 changes: 82 additions & 2 deletions test/system/tests/findings.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { strictEqual } from 'assert';
import * as path from 'path';

describe('Findings and scanning', function() {
Expand All @@ -19,9 +20,88 @@ describe('Findings and scanning', function() {
await driver.appMap.openActionPanel();
await driver.appMap.expandFindings();
await driver.appMap.findingsTree.click();
await driver.appMap.findingsTreeItem().waitFor({ state: 'hidden' });
await driver.appMap.findingsTreeItem().waitFor();
await project.restoreFiles('**/*.appmap.json');
await driver.waitForFile(path.join(project.workspacePath, 'tmp', '**', 'mtime')); // Wait for the indexer
await driver.appMap.findingsTreeItem().waitFor({ state: 'visible' });
await driver.appMap.findingsTreeItem(1).waitFor();
});

it('shows the findings overview page', async function() {
const { driver, project } = this;

await driver.appMap.openActionPanel();
await driver.appMap.expandFindings();
await driver.appMap.openFindingsOverview();
const expectedFrames = 2;
await driver.appMap.findingsOverviewWebview.initialize(expectedFrames);
await driver.appMap.findingsOverviewWebview.assertTitleRenders();
await driver.appMap.findingsOverviewWebview.assertNumberOfFindingsInOverview(0);
await project.restoreFiles('**/*.appmap.json');
await driver.waitForFile(path.join(project.workspacePath, 'tmp', '**', 'mtime')); // Wait for the indexer
await driver.appMap.findingsTreeItem(1).waitFor();
await driver.appMap.findingsOverviewWebview.assertNumberOfFindingsInOverview(3);
});

it('opens the findings details page from the findings overview page', async function() {
const { driver, project } = this;

await driver.appMap.openActionPanel();
await driver.appMap.expandFindings();
await driver.appMap.openFindingsOverview();

let expectedFrames = 2;
await driver.appMap.findingsOverviewWebview.initialize(expectedFrames);
await driver.appMap.findingsOverviewWebview.assertTitleRenders();
await project.restoreFiles('**/*.appmap.json');
await driver.waitForFile(path.join(project.workspacePath, 'tmp', '**', 'mtime')); // Wait for the indexer
await driver.appMap.findingsTreeItem(1).waitFor();
await driver.appMap.findingsOverviewWebview.openFirstFindingDetail();

expectedFrames = 3;
await driver.appMap.findingDetailsWebview.initialize(expectedFrames);

const expectedTitle = 'N plus 1 SQL query';
await driver.appMap.findingDetailsWebview.assertTitleRenders(expectedTitle);
});

it('opens the findings details page from the runtime analysis tree view', async function() {
const { driver, project } = this;

await driver.appMap.openActionPanel();
await driver.appMap.expandFindings();

await project.restoreFiles('**/*.appmap.json');
await driver.waitForFile(path.join(project.workspacePath, 'tmp', '**', 'mtime')); // Wait for the indexer
await driver.appMap.findingsTreeItem(1).waitFor();

await driver.appMap.openNthFinding(2);
const expectedFrames = 2;
await driver.appMap.findingDetailsWebview.initialize(expectedFrames);

const expectedTitle = 'N plus 1 SQL query';
await driver.appMap.findingDetailsWebview.assertTitleRenders(expectedTitle);
});

it('reuses the finding details webview', async function() {
const { driver, project } = this;

await driver.appMap.openActionPanel();
await driver.appMap.expandFindings();
await driver.appMap.openFindingsOverview();
let expectedFrames = 2;
await driver.appMap.findingsOverviewWebview.initialize(expectedFrames);

await project.restoreFiles('**/*.appmap.json');
await driver.waitForFile(path.join(project.workspacePath, 'tmp', '**', 'mtime')); // Wait for the indexer
await driver.appMap.findingsTreeItem(1).waitFor();

await driver.appMap.findingsOverviewWebview.openFirstFindingDetail();
expectedFrames = 3;
await driver.appMap.findingDetailsWebview.initialize(expectedFrames);
await driver.appMap.openNthFinding(2);
await driver.appMap.findingDetailsWebview.initialize(expectedFrames);

const numTabs = await driver.tabCount();
strictEqual(numTabs, expectedFrames);
});
});

0 comments on commit bbc7da7

Please sign in to comment.