Skip to content

Commit

Permalink
Merge pull request #128 from pinanks/fix-release-4.0.3
Browse files Browse the repository at this point in the history
Release v4.0.4
  • Loading branch information
arushsaxena1998 authored Sep 17, 2024
2 parents bc1a5d3 + 682009c commit 17f8186
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 60 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lambdatest/smartui-cli",
"version": "4.0.3",
"version": "4.0.4",
"description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
"files": [
"dist/**/*"
Expand Down
4 changes: 1 addition & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ import pkgJSON from './../package.json'
let log = logger;

try {
let { data: { latestVersion, deprecated, additionalDescription, additionalDescriptionLatestVersion } } = await client.checkUpdate(log);
let { data: { latestVersion, deprecated, additionalDescription } } = await client.checkUpdate(log);
log.info(`\nLambdaTest SmartUI CLI v${pkgJSON.version}`);
log.info(chalk.yellow(`${additionalDescription}`));
if (deprecated){
log.warn(`This version is deprecated. A new version ${latestVersion} is available!`);
log.warn(`${additionalDescriptionLatestVersion}\n`);
}
else if (pkgJSON.version !== latestVersion){
log.info(chalk.green(`A new version ${latestVersion} is available!`));
log.info(chalk.red(`${additionalDescriptionLatestVersion}\n`));
}
else log.info(chalk.gray('https://www.npmjs.com/package/@lambdatest/smartui-cli\n'));
} catch (error) {
Expand Down
113 changes: 57 additions & 56 deletions src/lib/processSnapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class Queue {
private processing: boolean = false;
private processingSnapshot: string = '';
private ctx: Context;

constructor(ctx: Context) {
this.ctx = ctx;
}
Expand All @@ -28,7 +28,7 @@ export default class Queue {
this.processNext();
}
}

private async processNext(): Promise<void> {
if (!this.isEmpty()) {
const snapshot = this.snapshots.shift();
Expand All @@ -37,10 +37,10 @@ export default class Queue {
let { processedSnapshot, warnings } = await processSnapshot(snapshot, this.ctx);
await this.ctx.client.uploadSnapshot(this.ctx, processedSnapshot);
this.ctx.totalSnapshots++;
this.processedSnapshots.push({name: snapshot.name, warnings});
this.processedSnapshots.push({ name: snapshot.name, warnings });
} catch (error: any) {
this.ctx.log.debug(`snapshot failed; ${error}`);
this.processedSnapshots.push({name: snapshot.name, error: error.message});
this.processedSnapshots.push({ name: snapshot.name, error: error.message });
}
// Close open browser contexts and pages
if (this.ctx.browser) {
Expand Down Expand Up @@ -77,8 +77,8 @@ export default class Queue {
}

async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record<string, any>> {
updateLogContext({task: 'discovery'});
ctx.log.debug(`Processing snapshot ${snapshot.name}`);
updateLogContext({ task: 'discovery' });
ctx.log.debug(`Processing snapshot ${snapshot.name} ${snapshot.url}`);

let launchOptions: Record<string, any> = { headless: true }
let contextOptions: Record<string, any> = {
Expand All @@ -92,35 +92,44 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
}
const context = await ctx.browser.newContext(contextOptions);
ctx.log.debug(`Browser context created with options ${JSON.stringify(contextOptions)}`);

// Setting the cookies in playwright context
const domainName = new URL(snapshot.url).hostname;
ctx.log.debug('Setting cookies in context for domain:', domainName);


const cookieArray = snapshot.dom.cookies.split('; ').map(cookie => {
if (!cookie) return null;
const [name, value] = cookie.split('=');
if (!name || !value) return null;

return {
name: name.trim(),
value: value.trim(),
domain: domainName,
path: '/'
};
}).filter(Boolean);


if (cookieArray && Array.isArray(cookieArray) && cookieArray.length > 0) {
await context.addCookies(cookieArray);
ctx.log.debug('Cookies added');
} else {
ctx.log.debug('No valid cookies to add');
if (snapshot.dom.cookies) {
const domainName = new URL(snapshot.url).hostname;
ctx.log.debug(`Setting cookies for domain: ${domainName}`);

const cookieArray = snapshot.dom.cookies.split('; ').map(cookie => {
if (!cookie) return null;
const [name, value] = cookie.split('=');
if (!name || !value) return null;

return {
name: name.trim(),
value: value.trim(),
domain: domainName,
path: '/'
};
}).filter(Boolean);

if (cookieArray.length > 0) {
await context.addCookies(cookieArray);
} else {
ctx.log.debug('No valid cookies to add');
}
}

const page = await context.newPage();

// populate cache with already captured resources
let cache: Record<string, any> = {};
if (snapshot.dom.resources.length) {
for (let resource of snapshot.dom.resources) {
// convert text/css content to base64
let body = resource.mimetype == 'text/css' ? Buffer.from(resource.content).toString('base64') : resource.content;
cache[resource.url] = {
body: body,
type: resource.mimetype
}
}
}

// Use route to intercept network requests and discover resources
await page.route('**/*', async (route, request) => {
Expand All @@ -138,7 +147,7 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
ctx.config.allowedHostnames.push(new URL(snapshot.url).hostname);
if (ctx.config.enableJavaScript) ALLOWED_RESOURCES.push('script');
if (ctx.config.basicAuthorization) {
ctx.log.debug(`Adding basic authorization to the headers for root url`);
ctx.log.debug(`Adding basic authorization to the headers for root url`);
let token = Buffer.from(`${ctx.config.basicAuthorization.username}:${ctx.config.basicAuthorization.password}`).toString('base64');
requestOptions.headers = {
...request.headers(),
Expand All @@ -151,9 +160,15 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
if (requestUrl === snapshot.url) {
response = {
status: () => 200,
headers: () => ({ 'content-type': 'text/html' })
headers: () => ({ 'content-type': 'text/html' })
}
body = snapshot.dom.html;
} else if (cache[requestUrl]) {
response = {
status: () => 200,
headers: () => ({ 'content-type': cache[requestUrl].mimetype })
}
body = snapshot.dom.html
body = cache[requestUrl].body;
} else {
response = await page.request.fetch(request, requestOptions);
body = await response.body();
Expand All @@ -162,7 +177,7 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
// handle response
if (!body) {
ctx.log.debug(`Handling request ${requestUrl}\n - skipping no response`);
} else if (!body.length) {
} else if (!body.length) {
ctx.log.debug(`Handling request ${requestUrl}\n - skipping empty response`);
} else if (requestUrl === snapshot.url) {
ctx.log.debug(`Handling request ${requestUrl}\n - skipping root resource`);
Expand Down Expand Up @@ -204,7 +219,7 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
let ignoreOrSelectBoxes: string;
if (options && Object.keys(options).length) {
ctx.log.debug(`Snapshot options: ${JSON.stringify(options)}`);

const isNotAllEmpty = (obj: Record<string, Array<string>>): boolean => {
for (let key in obj) if (obj[key]?.length) return true;
return false;
Expand Down Expand Up @@ -240,7 +255,7 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
selectors.push(...value);
break;
}
}
}
}
}

Expand All @@ -261,14 +276,14 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
// Update `previousDeviceType` to the current device type for comparison in the next iteration
previousDeviceType = device;

await page.setViewportSize({ width: viewport.width, height: viewport.height || MIN_VIEWPORT_HEIGHT });
ctx.log.debug(`Page resized to ${viewport.width}x${viewport.height || MIN_VIEWPORT_HEIGHT}`);
await page.setViewportSize({ width: viewport.width, height: viewport.height || MIN_VIEWPORT_HEIGHT });
ctx.log.debug(`Page resized to ${viewport.width}x${viewport.height || MIN_VIEWPORT_HEIGHT}`);

// navigate to snapshot url once
if (!navigated) {
try {
// domcontentloaded event is more reliable than load event
await page.goto(snapshot.url, { waitUntil: "domcontentloaded"});
await page.goto(snapshot.url, { waitUntil: "domcontentloaded" });
// adding extra timeout since domcontentloaded event is fired pretty quickly
await new Promise(r => setTimeout(r, 1250));
if (ctx.config.waitForTimeout) await page.waitForTimeout(ctx.config.waitForTimeout);
Expand All @@ -278,7 +293,7 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
ctx.log.debug(`Navigation to discovery page failed; ${error}`)
throw new Error(error.message)
}

}
if (ctx.config.cliEnableJavaScript && fullPage) await page.evaluate(scrollToBottomAndBackToTop, { frequency: 100, timing: ctx.config.scrollTime });

Expand All @@ -289,8 +304,6 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
ctx.log.debug(`Network idle failed due to ${error}`);
}

await new Promise(r => setTimeout(r, 1000));

// snapshot options
if (processedOptions.element) {
let l = await page.locator(processedOptions.element).all()
Expand Down Expand Up @@ -323,18 +336,6 @@ async function processSnapshot(snapshot: Snapshot, ctx: Context): Promise<Record
}
}

// add dom resources to cache
if (snapshot.dom.resources.length) {
for (let resource of snapshot.dom.resources) {
// convert text/css content to base64
let body = resource.mimetype == 'text/css' ? Buffer.from(resource.content).toString('base64') : resource.content;
cache[resource.url] = {
body: body,
type: resource.mimetype
}
}
}

return {
processedSnapshot: {
name: snapshot.name,
Expand Down

0 comments on commit 17f8186

Please sign in to comment.