Skip to content

Commit 15a2679

Browse files
authored
Merge pull request #89 from LambdaTest/stage
Release v3.0.7
2 parents d46ff99 + 4a95045 commit 15a2679

File tree

14 files changed

+281
-12
lines changed

14 files changed

+281
-12
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@lambdatest/smartui-cli",
3-
"version": "3.0.6",
3+
"version": "3.0.7",
44
"description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
55
"files": [
66
"dist/**/*"

src/commander/commander.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Command } from 'commander'
22
import exec from './exec.js'
3-
import { configWeb, configStatic } from './config.js'
3+
import { configWeb, configStatic, configFigma} from './config.js'
44
import capture from './capture.js'
55
import { version } from '../../package.json'
6+
import uploadFigma from './uploadFigma.js'
67

78
const program = new Command();
89

@@ -15,6 +16,8 @@ program
1516
.addCommand(capture)
1617
.addCommand(configWeb)
1718
.addCommand(configStatic)
18-
19+
.addCommand(configFigma)
20+
.addCommand(uploadFigma)
21+
1922

2023
export default program;

src/commander/config.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Command } from 'commander'
2-
import { createConfig, createWebStaticConfig } from '../lib/config.js'
2+
import { createConfig, createWebStaticConfig, createFigmaConfig } from '../lib/config.js'
33

44
export const configWeb = new Command();
55
export const configStatic = new Command();
6+
export const configFigma = new Command();
67

78
configWeb
89
.name('config:create')
@@ -19,3 +20,13 @@ configStatic
1920
.action(async function(filepath, options) {
2021
createWebStaticConfig(filepath);
2122
})
23+
24+
configFigma
25+
.name('config:create-figma')
26+
.description('Create figma designs config file')
27+
.argument('[filepath]', 'Optional config filepath')
28+
.action(async function(filepath, options) {
29+
createFigmaConfig(filepath);
30+
})
31+
32+

src/commander/uploadFigma.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import fs from 'fs'
2+
import { Command } from 'commander'
3+
import { Context } from '../types.js'
4+
import { color , Listr, ListrDefaultRendererLogLevels, LoggerFormat } from 'listr2'
5+
import auth from '../tasks/auth.js'
6+
import ctxInit from '../lib/ctx.js'
7+
import getGitInfo from '../tasks/getGitInfo.js'
8+
import createBuild from '../tasks/createBuild.js'
9+
import captureScreenshots from '../tasks/captureScreenshots.js'
10+
import finalizeBuild from '../tasks/finalizeBuild.js'
11+
import { validateFigmaDesignConfig } from '../lib/schemaValidation.js'
12+
import uploadFigmaDesigns from '../tasks/uploadFigmaDesigns.js'
13+
14+
const command = new Command();
15+
16+
command
17+
.name('upload-figma')
18+
.description('Capture screenshots of static sites')
19+
.argument('<file>', 'figma design config file')
20+
.option('--markBaseline', 'Mark the uploaded images as baseline')
21+
.option('--buildName <buildName>' , 'Name of the build')
22+
.action(async function(file, _, command) {
23+
let ctx: Context = ctxInit(command.optsWithGlobals());
24+
25+
if (!fs.existsSync(file)) {
26+
console.log(`Error: Figma Config file ${file} not found.`);
27+
return;
28+
}
29+
try {
30+
ctx.figmaDesignConfig = JSON.parse(fs.readFileSync(file, 'utf8'));
31+
if (!validateFigmaDesignConfig(ctx.figmaDesignConfig)) {
32+
const validationError = validateFigmaDesignConfig.errors?.[0]?.message;
33+
throw new Error(validationError || 'Invalid figma design Config');
34+
}
35+
} catch (error: any) {
36+
console.log(`[smartui] Error: Invalid figma design Config; ${error.message}`);
37+
return;
38+
}
39+
40+
let tasks = new Listr<Context>(
41+
[
42+
auth(ctx),
43+
uploadFigmaDesigns(ctx)
44+
],
45+
{
46+
rendererOptions: {
47+
icon: {
48+
[ListrDefaultRendererLogLevels.OUTPUT]: `→`
49+
},
50+
color: {
51+
[ListrDefaultRendererLogLevels.OUTPUT]: color.gray as LoggerFormat
52+
}
53+
}
54+
}
55+
)
56+
57+
try {
58+
await tasks.run(ctx);
59+
} catch (error) {
60+
console.log('\nRefer docs: https://www.lambdatest.com/support/docs/smart-visual-regression-testing/');
61+
}
62+
63+
})
64+
65+
export default command;

src/lib/config.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,25 @@ export function createWebStaticConfig(filepath: string) {
4545
fs.writeFileSync(filepath, JSON.stringify(constants.DEFAULT_WEB_STATIC_CONFIG, null, 2) + '\n');
4646
console.log(`Created web-static config: ${filepath}`);
4747
};
48+
49+
export function createFigmaConfig(filepath: string) {
50+
// default filepath
51+
filepath = filepath || 'designs.json';
52+
let filetype = path.extname(filepath);
53+
if (filetype != '.json') {
54+
console.log('Error: designs config file must have .json extension');
55+
return
56+
}
57+
58+
// verify the file does not already exist
59+
if (fs.existsSync(filepath)) {
60+
console.log(`Error: designs config already exists: ${filepath}`);
61+
console.log(`To create a new file, please specify the file name like: 'smartui config:figma-config designs.json'`);
62+
return
63+
}
64+
65+
// write stringified default config options to the filepath
66+
fs.mkdirSync(path.dirname(filepath), { recursive: true });
67+
fs.writeFileSync(filepath, JSON.stringify(constants.DEFAULT_FIGMA_CONFIG, null, 2) + '\n');
68+
console.log(`Created designs config: ${filepath}`);
69+
};

src/lib/constants.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,5 +235,19 @@ export default {
235235
'iPhone XR': { os: 'ios', viewport: {width: 414, height: 896}},
236236
'iPhone XS': { os: 'ios', viewport: {width: 375, height: 812}},
237237
'iPhone XS Max': { os: 'ios', viewport: {width: 414, height: 896}},
238+
},
239+
240+
FIGMA_API : 'https://api.figma.com/v1/',
241+
DEFAULT_FIGMA_CONFIG: {
242+
"depth": 2,
243+
"figma_config": [
244+
{
245+
"figma_file_token": "token_for_first_figma_file",
246+
"figma_ids": [
247+
"id1",
248+
"id2"
249+
]
250+
}
251+
]
238252
}
239253
}

src/lib/ctx.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ export default (options: Record<string, string>): Context => {
7373
},
7474
args: {},
7575
options: {
76-
parallel: options.parallel ? true : false
76+
parallel: options.parallel ? true : false,
77+
markBaseline: options.markBaseline ? true : false,
78+
buildName: options.buildName || ''
7779
},
7880
cliVersion: version,
7981
totalSnapshots: -1

src/lib/env.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ export default (): Env => {
99
SMARTUI_GIT_INFO_FILEPATH,
1010
HTTP_PROXY,
1111
HTTPS_PROXY,
12-
GITHUB_ACTIONS
12+
GITHUB_ACTIONS,
13+
FIGMA_TOKEN,
14+
LT_USERNAME,
15+
LT_ACCESS_KEY
1316
} = process.env
1417

1518
return {
@@ -20,6 +23,9 @@ export default (): Env => {
2023
SMARTUI_GIT_INFO_FILEPATH,
2124
HTTP_PROXY,
2225
HTTPS_PROXY,
23-
GITHUB_ACTIONS
26+
GITHUB_ACTIONS,
27+
FIGMA_TOKEN,
28+
LT_USERNAME,
29+
LT_ACCESS_KEY
2430
}
2531
}

src/lib/httpClient.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'fs';
22
import FormData from 'form-data';
33
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
4-
import { Env, ProcessedSnapshot, Git, Build } from '../types.js';
4+
import { Env, ProcessedSnapshot, Git, Build, Context } from '../types.js';
55
import constants from './constants.js';
66
import type { Logger } from 'winston'
77
import pkgJSON from './../../package.json'
@@ -136,4 +136,25 @@ export default class httpClient {
136136
}
137137
}, log)
138138
}
139+
140+
getFigmaFilesAndImages(figmaFileToken: string, figmaToken: String | undefined, queryParams: string, authToken: string, depth: number, markBaseline: boolean, buildName: string, log: Logger) {
141+
const requestBody = {
142+
figma_file_token: figmaFileToken,
143+
figma_token: figmaToken,
144+
query_params: queryParams,
145+
auth: authToken,
146+
depth: depth,
147+
mark_base_line: markBaseline,
148+
build_name: buildName
149+
};
150+
151+
return this.request({
152+
url: "/uploadfigma",
153+
method: "POST",
154+
headers: {
155+
"Content-Type": "application/json",
156+
},
157+
data: JSON.stringify(requestBody)
158+
}, log);
159+
}
139160
}

src/lib/processSnapshot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { scrollToBottomAndBackToTop, getRenderViewports } from "./utils.js"
33
import { chromium, Locator } from "@playwright/test"
44
import constants from "./constants.js";
55

6-
const MAX_RESOURCE_SIZE = 10 * (1024 ** 2); // 10MB
6+
const MAX_RESOURCE_SIZE = 15 * (1024 ** 2); // 15MB
77
var ALLOWED_RESOURCES = ['document', 'stylesheet', 'image', 'media', 'font', 'other'];
88
const ALLOWED_STATUSES = [200, 201];
99
const REQUEST_TIMEOUT = 10000;
@@ -50,7 +50,7 @@ export default async (snapshot: Snapshot, ctx: Context): Promise<Record<string,
5050
} else if (cache[requestUrl]) {
5151
ctx.log.debug(`Handling request ${requestUrl}\n - skipping already cached resource`);
5252
} else if (body.length > MAX_RESOURCE_SIZE) {
53-
ctx.log.debug(`Handling request ${requestUrl}\n - skipping resource larger than 5MB`);
53+
ctx.log.debug(`Handling request ${requestUrl}\n - skipping resource larger than 15MB`);
5454
} else if (!ALLOWED_STATUSES.includes(response.status())) {
5555
ctx.log.debug(`Handling request ${requestUrl}\n - skipping disallowed status [${response.status()}]`);
5656
} else if (!ALLOWED_RESOURCES.includes(request.resourceType())) {

0 commit comments

Comments
 (0)