Skip to content

Commit

Permalink
[ftr] migrate screenshots and snapshots services to FtrService class (e…
Browse files Browse the repository at this point in the history
…lastic#100514)

Co-authored-by: spalger <spalger@users.noreply.github.com>
  • Loading branch information
2 people authored and ecezalp committed May 26, 2021
1 parent 6815d3f commit af50418
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 110 deletions.
4 changes: 2 additions & 2 deletions test/functional/services/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
export { BrowserProvider, Browser } from './browser';
export { FailureDebuggingProvider } from './failure_debugging';
export { FindProvider } from './find';
export { ScreenshotsProvider } from './screenshots';
export { SnapshotsProvider } from './snapshots';
export { ScreenshotsService } from './screenshots';
export { SnapshotsService } from './snapshots';
export { TestSubjects } from './test_subjects';
123 changes: 67 additions & 56 deletions test/functional/services/common/screenshots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,77 +13,88 @@ import { promisify } from 'util';
import del from 'del';

import { comparePngs } from '../lib/compare_pngs';
import { FtrProviderContext } from '../../ftr_provider_context';
import { FtrProviderContext, FtrService } from '../../ftr_provider_context';
import { WebElementWrapper } from '../lib/web_element_wrapper';

const mkdirAsync = promisify(mkdir);
const writeFileAsync = promisify(writeFile);

export async function ScreenshotsProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const config = getService('config');
const failureMetadata = getService('failureMetadata');
const browser = getService('browser');
export class ScreenshotsService extends FtrService {
private readonly log = this.ctx.getService('log');
private readonly config = this.ctx.getService('config');
private readonly failureMetadata = this.ctx.getService('failureMetadata');
private readonly browser = this.ctx.getService('browser');

const SESSION_DIRECTORY = resolve(config.get('screenshots.directory'), 'session');
const FAILURE_DIRECTORY = resolve(config.get('screenshots.directory'), 'failure');
const BASELINE_DIRECTORY = resolve(config.get('screenshots.directory'), 'baseline');
private readonly SESSION_DIRECTORY = resolve(this.config.get('screenshots.directory'), 'session');
private readonly FAILURE_DIRECTORY = resolve(this.config.get('screenshots.directory'), 'failure');
private readonly BASELINE_DIRECTORY = resolve(
this.config.get('screenshots.directory'),
'baseline'
);

if (process.env.CI !== 'true' && !process.env.stack_functional_integration) {
await del([SESSION_DIRECTORY, FAILURE_DIRECTORY]);
constructor(ctx: FtrProviderContext) {
super(ctx);

if (process.env.CI !== 'true' && !process.env.stack_functional_integration) {
ctx.getService('lifecycle').beforeTests.add(async () => {
await del([this.SESSION_DIRECTORY, this.FAILURE_DIRECTORY]);
});
}
}

class Screenshots {
/**
*
* @param name {string} name of the file to use for comparison
* @param updateBaselines {boolean} optional, pass true to update the baseline snapshot.
* @return {Promise.<number>} Percentage difference between the baseline and the current snapshot.
*/
async compareAgainstBaseline(name: string, updateBaselines: boolean, el?: WebElementWrapper) {
log.debug('compareAgainstBaseline');
const sessionPath = resolve(SESSION_DIRECTORY, `${name}.png`);
await this._take(sessionPath, el);
/**
*
* @param name {string} name of the file to use for comparison
* @param updateBaselines {boolean} optional, pass true to update the baseline snapshot.
* @return {Promise.<number>} Percentage difference between the baseline and the current snapshot.
*/
async compareAgainstBaseline(name: string, updateBaselines: boolean, el?: WebElementWrapper) {
this.log.debug('compareAgainstBaseline');
const sessionPath = resolve(this.SESSION_DIRECTORY, `${name}.png`);
await this.capture(sessionPath, el);

const baselinePath = resolve(BASELINE_DIRECTORY, `${name}.png`);
const failurePath = resolve(FAILURE_DIRECTORY, `${name}.png`);
const baselinePath = resolve(this.BASELINE_DIRECTORY, `${name}.png`);
const failurePath = resolve(this.FAILURE_DIRECTORY, `${name}.png`);

if (updateBaselines) {
log.debug('Updating baseline snapshot');
// Make the directory if it doesn't exist
await mkdirAsync(dirname(baselinePath), { recursive: true });
await writeFileAsync(baselinePath, readFileSync(sessionPath));
return 0;
} else {
await mkdirAsync(FAILURE_DIRECTORY, { recursive: true });
return await comparePngs(sessionPath, baselinePath, failurePath, SESSION_DIRECTORY, log);
}
if (updateBaselines) {
this.log.debug('Updating baseline snapshot');
// Make the directory if it doesn't exist
await mkdirAsync(dirname(baselinePath), { recursive: true });
await writeFileAsync(baselinePath, readFileSync(sessionPath));
return 0;
} else {
await mkdirAsync(this.FAILURE_DIRECTORY, { recursive: true });
return await comparePngs(
sessionPath,
baselinePath,
failurePath,
this.SESSION_DIRECTORY,
this.log
);
}
}

async take(name: string, el?: WebElementWrapper) {
const path = resolve(SESSION_DIRECTORY, `${name}.png`);
await this._take(path, el);
failureMetadata.addScreenshot(name, path);
}
async take(name: string, el?: WebElementWrapper) {
const path = resolve(this.SESSION_DIRECTORY, `${name}.png`);
await this.capture(path, el);
this.failureMetadata.addScreenshot(name, path);
}

async takeForFailure(name: string, el?: WebElementWrapper) {
const path = resolve(FAILURE_DIRECTORY, `${name}.png`);
await this._take(path, el);
failureMetadata.addScreenshot(`failure[${name}]`, path);
}
async takeForFailure(name: string, el?: WebElementWrapper) {
const path = resolve(this.FAILURE_DIRECTORY, `${name}.png`);
await this.capture(path, el);
this.failureMetadata.addScreenshot(`failure[${name}]`, path);
}

async _take(path: string, el?: WebElementWrapper) {
try {
log.info(`Taking screenshot "${path}"`);
const screenshot = await (el ? el.takeScreenshot() : browser.takeScreenshot());
await mkdirAsync(dirname(path), { recursive: true });
await writeFileAsync(path, screenshot, 'base64');
} catch (err) {
log.error('SCREENSHOT FAILED');
log.error(err);
}
private async capture(path: string, el?: WebElementWrapper) {
try {
this.log.info(`Taking screenshot "${path}"`);
const screenshot = await (el ? el.takeScreenshot() : this.browser.takeScreenshot());
await mkdirAsync(dirname(path), { recursive: true });
await writeFileAsync(path, screenshot, 'base64');
} catch (err) {
this.log.error('SCREENSHOT FAILED');
this.log.error(err);
}
}

return new Screenshots();
}
97 changes: 49 additions & 48 deletions test/functional/services/common/snapshots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,67 +12,68 @@ import { promisify } from 'util';

import expect from '@kbn/expect';
import del from 'del';
import { FtrProviderContext } from '../../ftr_provider_context';
import { FtrProviderContext, FtrService } from '../../ftr_provider_context';

const mkdirAsync = promisify(mkdir);
const writeFileAsync = promisify(writeFile);

export async function SnapshotsProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const config = getService('config');
export class SnapshotsService extends FtrService {
private readonly log = this.ctx.getService('log');
private readonly config = this.ctx.getService('config');

const SESSION_DIRECTORY = resolve(config.get('snapshots.directory'), 'session');
const BASELINE_DIRECTORY = resolve(config.get('snapshots.directory'), 'baseline');
private readonly SESSION_DIRECTORY = resolve(this.config.get('snapshots.directory'), 'session');
private readonly BASELINE_DIRECTORY = resolve(this.config.get('snapshots.directory'), 'baseline');

if (process.env.CI !== 'true' && !process.env.stack_functional_integration) {
await del([SESSION_DIRECTORY]);
}

class Snapshots {
/**
*
* @param name {string} name of the file to use for comparison
* @param value {object} value to compare to baseline.
* @param updateBaselines {boolean} optional, pass true to update the baseline snapshot.
* @return {Promise.<number>} returns 0 if successful.
*/
public async compareAgainstBaseline(name: string, value: object, updateBaselines?: boolean) {
log.debug('compareAgainstBaseline');
const sessionPath = resolve(SESSION_DIRECTORY, `${name}.json`);
await this._take(sessionPath, value);

const baselinePath = resolve(BASELINE_DIRECTORY, `${name}.json`);
constructor(ctx: FtrProviderContext) {
super(ctx);

if (updateBaselines) {
await writeFileAsync(baselinePath, readFileSync(sessionPath));
return 0;
} else {
log.debug('comparing');
return this.compare(sessionPath, baselinePath);
}
if (process.env.CI !== 'true' && !process.env.stack_functional_integration) {
ctx.getService('lifecycle').beforeTests.add(async () => {
await del([this.SESSION_DIRECTORY]);
});
}
}
/**
*
* @param name {string} name of the file to use for comparison
* @param value {object} value to compare to baseline.
* @param updateBaselines {boolean} optional, pass true to update the baseline snapshot.
* @return {Promise.<number>} returns 0 if successful.
*/
public async compareAgainstBaseline(name: string, value: object, updateBaselines?: boolean) {
this.log.debug('compareAgainstBaseline');
const sessionPath = resolve(this.SESSION_DIRECTORY, `${name}.json`);
await this._take(sessionPath, value);

const baselinePath = resolve(this.BASELINE_DIRECTORY, `${name}.json`);

private compare(sessionPath: string, baselinePath: string) {
const currentObject = readFileSync(sessionPath, { encoding: 'utf8' });
const baselineObject = readFileSync(baselinePath, { encoding: 'utf8' });
expect(currentObject).to.eql(baselineObject);
if (updateBaselines) {
await writeFileAsync(baselinePath, readFileSync(sessionPath));
return 0;
} else {
this.log.debug('comparing');
return this.compare(sessionPath, baselinePath);
}
}

public async take(name: string) {
return await this._take(resolve(SESSION_DIRECTORY, `${name}.json`));
}
private compare(sessionPath: string, baselinePath: string) {
const currentObject = readFileSync(sessionPath, { encoding: 'utf8' });
const baselineObject = readFileSync(baselinePath, { encoding: 'utf8' });
expect(currentObject).to.eql(baselineObject);
return 0;
}

private async _take(path: string, snapshot?: object) {
try {
await mkdirAsync(dirname(path), { recursive: true });
await writeFileAsync(path, JSON.stringify(snapshot), 'utf8');
} catch (err) {
log.error('SNAPSHOT FAILED');
log.error(err);
}
}
public async take(name: string) {
return await this._take(resolve(this.SESSION_DIRECTORY, `${name}.json`));
}

return new Snapshots();
private async _take(path: string, snapshot?: object) {
try {
await mkdirAsync(dirname(path), { recursive: true });
await writeFileAsync(path, JSON.stringify(snapshot), 'utf8');
} catch (err) {
this.log.error('SNAPSHOT FAILED');
this.log.error(err);
}
}
}
8 changes: 4 additions & 4 deletions test/functional/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
BrowserProvider,
FailureDebuggingProvider,
FindProvider,
ScreenshotsProvider,
SnapshotsProvider,
ScreenshotsService,
SnapshotsService,
TestSubjects,
} from './common';
import { ComboBoxProvider } from './combo_box';
Expand Down Expand Up @@ -58,8 +58,8 @@ export const services = {
find: FindProvider,
testSubjects: TestSubjects,
docTable: DocTableService,
screenshots: ScreenshotsProvider,
snapshots: SnapshotsProvider,
screenshots: ScreenshotsService,
snapshots: SnapshotsService,
dashboardVisualizations: DashboardVisualizationProvider,
dashboardExpect: DashboardExpectProvider,
failureDebugging: FailureDebuggingProvider,
Expand Down

0 comments on commit af50418

Please sign in to comment.