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

Feat: Send domInfoSha & PoA optimizations #1270

Merged
merged 21 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 2 additions & 0 deletions packages/cli-exec/src/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export const exec = command('exec', {
log.warn('Percy is disabled');
} else {
try {
percy.projectType = percy?.tokenType();
percy.skipDiscovery = percy.projectType === 'web';
itsjwala marked this conversation as resolved.
Show resolved Hide resolved
yield* percy.yield.start();
} catch (error) {
if (error.name === 'AbortError') throw error;
Expand Down
11 changes: 7 additions & 4 deletions packages/client/src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,9 @@ export class PercyClient {
return snapshot;
}

async createComparison(snapshotId, { tag, tiles = [], externalDebugUrl, ignoredElementsData } = {}) {
async createComparison(snapshotId, { tag, tiles = [], externalDebugUrl, ignoredElementsData, domSha } = {}) {
itsjwala marked this conversation as resolved.
Show resolved Hide resolved
validateId('snapshot', snapshotId);

// Remove post percy api deploy
this.log.debug(`Creating comparision: ${tag.name}...`);

for (let tile of tiles) {
Expand All @@ -386,7 +386,8 @@ export class PercyClient {
type: 'comparisons',
attributes: {
'external-debug-url': externalDebugUrl || null,
'ignore-elements-data': ignoredElementsData || null
'ignore-elements-data': ignoredElementsData || null,
'dom-info-sha': domSha || null
},
relationships: {
tag: {
Expand All @@ -398,7 +399,9 @@ export class PercyClient {
height: tag.height || null,
'os-name': tag.osName || null,
'os-version': tag.osVersion || null,
orientation: tag.orientation || null
orientation: tag.orientation || null,
browser_name: tag.browserName || null,
browser_version: tag.browserVersion || null
}
}
},
Expand Down
28 changes: 20 additions & 8 deletions packages/client/test/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,9 @@ describe('PercyClient', () => {
height: 1024,
osName: 'fooOS',
osVersion: '0.1.0',
orientation: 'portrait'
orientation: 'portrait',
browserName: 'chrome',
browserVersion: '111.0.0'
},
tiles: [{
statusBarHeight: 40,
Expand All @@ -835,15 +837,17 @@ describe('PercyClient', () => {
sha: sha256hash('somesha')
}],
externalDebugUrl: 'http://debug.localhost',
ignoredElementsData: ignoredElementsData
ignoredElementsData: ignoredElementsData,
domSha: 'abcd='
})).toBeResolved();

expect(api.requests['/snapshots/4567/comparisons'][0].body).toEqual({
data: {
type: 'comparisons',
attributes: {
'external-debug-url': 'http://debug.localhost',
'ignore-elements-data': ignoredElementsData
'ignore-elements-data': ignoredElementsData,
'dom-info-sha': 'abcd='
},
relationships: {
tag: {
Expand All @@ -855,7 +859,9 @@ describe('PercyClient', () => {
height: 1024,
'os-name': 'fooOS',
'os-version': '0.1.0',
orientation: 'portrait'
orientation: 'portrait',
browser_name: 'chrome',
browser_version: '111.0.0'
}
}
},
Expand Down Expand Up @@ -907,7 +913,8 @@ describe('PercyClient', () => {
type: 'comparisons',
attributes: {
'external-debug-url': null,
'ignore-elements-data': null
'ignore-elements-data': null,
'dom-info-sha': null
},
relationships: {
tag: {
Expand All @@ -919,7 +926,9 @@ describe('PercyClient', () => {
height: null,
'os-name': null,
'os-version': null,
orientation: null
orientation: null,
browser_name: null,
browser_version: null
}
}
},
Expand Down Expand Up @@ -1156,7 +1165,8 @@ describe('PercyClient', () => {
type: 'comparisons',
attributes: {
'external-debug-url': null,
'ignore-elements-data': null
'ignore-elements-data': null,
'dom-info-sha': null
},
relationships: {
tag: {
Expand All @@ -1168,7 +1178,9 @@ describe('PercyClient', () => {
height: null,
'os-name': null,
'os-version': null,
orientation: null
orientation: null,
browser_name: null,
browser_version: null
}
}
},
Expand Down
14 changes: 9 additions & 5 deletions packages/core/src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { createRequire } from 'module';
import logger from '@percy/logger';
import { normalize } from '@percy/config/utils';
import { getPackageJSON, Server } from './utils.js';
import { getPackageJSON, Server, percyAutomateRequestHandler } from './utils.js';
// TODO Remove below esline disable once we publish webdriver-util
import WebdriverUtils from '@percy/webdriver-utils'; // eslint-disable-line import/no-extraneous-dependencies

Expand Down Expand Up @@ -63,7 +63,8 @@ export function createPercyServer(percy, port) {
build: percy.testing?.build ?? percy.build,
loglevel: percy.loglevel(),
config: percy.config,
success: true
success: true,
type: percy.tokenType()
}))
// get or set config options
.route(['get', 'post'], '/percy/config', async (req, res) => res.json(200, {
Expand Down Expand Up @@ -117,9 +118,12 @@ export function createPercyServer(percy, port) {
.route('post', '/percy/flush', async (req, res) => res.json(200, {
success: await percy.flush(req.body).then(() => true)
}))
.route('post', '/percy/automateScreenshot', async (req, res) => res.json(200, {
success: await (percy.upload(await new WebdriverUtils(req.body).automateScreenshot())).then(() => true)
}))
.route('post', '/percy/automateScreenshot', async (req, res) => {
req = percyAutomateRequestHandler(req);
res.json(200, {
success: await (percy.upload(await new WebdriverUtils(req.body).automateScreenshot())).then(() => true)
});
})
// stops percy at the end of the current event loop
.route('/percy/stop', (req, res) => {
setImmediate(() => percy.stop());
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ export const comparisonSchema = {
properties: {
name: { type: 'string' },
externalDebugUrl: { type: 'string' },
domSha: { type: 'string' },
itsjwala marked this conversation as resolved.
Show resolved Hide resolved
tag: {
type: 'object',
additionalProperties: false,
Expand All @@ -418,7 +419,9 @@ export const comparisonSchema = {
orientation: {
type: 'string',
enum: ['portrait', 'landscape']
}
},
browserName: { type: 'string' },
browserVersion: { type: 'string' }
}
},
tiles: {
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/percy.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,25 @@ export class Percy {
}
}.call(this));
}

// decides project type
itsjwala marked this conversation as resolved.
Show resolved Hide resolved
tokenType() {
if (!process.env.PERCY_TOKEN || typeof process.env.PERCY_TOKEN !== 'string') { throw new Error('Missing Percy token'); }

const type = process.env.PERCY_TOKEN?.split('_')[0];
itsjwala marked this conversation as resolved.
Show resolved Hide resolved
switch (type) {
case 'auto':
return 'automate';
case 'web':
return 'web';
case 'app':
return 'app';
case 'ss':
return 'generic';
default:
return 'web';
}
}
}

export default Percy;
14 changes: 14 additions & 0 deletions packages/core/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ export function normalizeURL(url) {
return `${protocol}//${host}${pathname}${search}`;
}

// Returns the body for automateScreenshot in structure
export function percyAutomateRequestHandler(req) {
if (req.body.client_info) {
req.body.clientInfo = req.body.client_info;
}
if (req.body.environment_info) {
req.body.environmentInfo = req.body.environment_info;
}
if (!req.body.options) {
req.body.options = {};
}
return req;
}

// Creates a local resource object containing the resource URL, mimetype, content, sha, and any
// other additional resources attributes.
export function createResource(url, content, mimetype, attrs) {
Expand Down
3 changes: 2 additions & 1 deletion packages/core/test/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ describe('API Server', () => {
id: '123',
number: 1,
url: 'https://percy.io/test/test/123'
}
},
type: percy.tokenType()
});
});

Expand Down
41 changes: 41 additions & 0 deletions packages/core/test/percy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -843,4 +843,45 @@ describe('Percy', () => {
expect(api.requests['/builds/123/snapshots']).toBeUndefined();
});
});

describe('#tokenType', () => {
afterEach(() => {
delete process.env.PERCY_TOKEN;
});

it('should return web for default token', () => {
process.env.PERCY_TOKEN = '<<PERCY_TOKEN>>';
expect(percy.tokenType()).toBe('web');
});

it('should return web for web tokens', () => {
process.env.PERCY_TOKEN = 'web_abc';
expect(percy.tokenType()).toBe('web');
});

it('should return app for app tokens', () => {
process.env.PERCY_TOKEN = 'app_abc';
expect(percy.tokenType()).toBe('app');
});

it('should return automate for auto tokens', () => {
process.env.PERCY_TOKEN = 'auto_abc';
expect(percy.tokenType()).toBe('automate');
});

it('should return generic for ss tokens', () => {
process.env.PERCY_TOKEN = 'ss_abc';
expect(percy.tokenType()).toBe('generic');
});

it('should return web for default token', () => {
process.env.PERCY_TOKEN = 'abcdef123';
expect(percy.tokenType()).toBe('web');
});

it('should throw error for no token', () => {
process.env.PERCY_TOKEN = '';
expect(() => { percy.tokenType(); }).toThrowError('Missing Percy token');
});
});
});
31 changes: 30 additions & 1 deletion packages/core/test/unit/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
generatePromise,
AbortController,
yieldTo,
yieldAll
yieldAll,
percyAutomateRequestHandler
} from '../../src/utils.js';

describe('Unit / Utils', () => {
Expand Down Expand Up @@ -165,4 +166,32 @@ describe('Unit / Utils', () => {
{ done: true, value: [2, 4, null, 3, 6] });
});
});

describe('percyAutomateRequestHandler', () => {
let req;
beforeAll(() => {
req = {
body: {
name: 'abc',
client_info: 'client',
environment_info: 'environment'
}
};
});

it('converts client_info to clientInfo', () => {
const nreq = percyAutomateRequestHandler(req);
expect(nreq.body.clientInfo).toBe('client');
});

it('converts environment_info to environmentInfo', () => {
const nreq = percyAutomateRequestHandler(req);
expect(nreq.body.environmentInfo).toBe('environment');
});

it('adds options', () => {
const nreq = percyAutomateRequestHandler(req);
expect(nreq.body.options).toEqual({});
});
});
});
16 changes: 14 additions & 2 deletions packages/webdriver-utils/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ import { camelcase } from '@percy/config/utils';

export default class WebdriverUtils {
log = utils.logger('webdriver-utils:main');
constructor({ sessionId, commandExecutorUrl, capabilities, sessionCapabilites, snapshotName, options = {} }) {
constructor(
{
sessionId,
commandExecutorUrl,
capabilities,
sessionCapabilites,
snapshotName,
clientInfo,
environmentInfo,
options = {}
}) {
this.sessionId = sessionId;
this.commandExecutorUrl = commandExecutorUrl;
this.capabilities = capabilities;
Expand All @@ -16,11 +26,13 @@ export default class WebdriverUtils {
camelCasedOptions[newKey] = options[key];
});
this.options = camelCasedOptions;
this.clientInfo = clientInfo;
this.environmentInfo = environmentInfo;
}

async automateScreenshot() {
this.log.info('Starting automate screenshot');
const automate = ProviderResolver.resolve(this.sessionId, this.commandExecutorUrl, this.capabilities, this.sessionCapabilites);
const automate = ProviderResolver.resolve(this.sessionId, this.commandExecutorUrl, this.capabilities, this.sessionCapabilites, this.clientInfo, this.environmentInfo, this.options);
await automate.createDriver();
return await automate.screenshot(this.snapshotName, this.options);
}
Expand Down
13 changes: 9 additions & 4 deletions packages/webdriver-utils/src/metadata/desktopMetaData.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,26 @@ export default class DesktopMetaData {
return this.capabilities.browserName.toLowerCase();
}

browserVersion() {
return this.capabilities.browserVersion.split('.')[0];
}

osName() {
let osName = this.capabilities.osVersion;
let osName = this.capabilities.os;
if (osName) return osName.toLowerCase();

osName = this.capabilities.platform;
return osName;
}

// desktop will show this as browser version
// showing major version
osVersion() {
return this.capabilities.version.split('.')[0];
return this.capabilities.osVersion.toLowerCase();
}

// combination of browserName + browserVersion + osVersion + osName
deviceName() {
return this.browserName() + '_' + this.osVersion() + '_' + this.osName();
return this.browserName() + '_' + this.browserVersion() + '_' + this.osVersion() + '_' + this.osName();
}

orientation() {
Expand Down
Loading