Skip to content

Commit 5ec08f2

Browse files
committed
fix issues
1 parent 9ad4707 commit 5ec08f2

File tree

4 files changed

+21
-63
lines changed

4 files changed

+21
-63
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": "4.1.37",
3+
"version": "4.1.39",
44
"description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
55
"files": [
66
"dist/**/*"

src/commander/capture.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ command
3838
}
3939
try {
4040
ctx.webStaticConfig = JSON.parse(fs.readFileSync(file, 'utf8'));
41+
ctx.log.info({config : ctx.webStaticConfig})
4142
if (!validateWebStaticConfig(ctx.webStaticConfig)){
4243
ctx.log.debug(JSON.stringify(validateWebStaticConfig.errors, null, 2));
4344
// Iterate and add warning for "additionalProperties"

src/lib/processSnapshot.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,11 @@ export async function prepareSnapshot(snapshot: Snapshot, ctx: Context): Promise
159159
if (options?.customCSS) {
160160
const resolvedCSS = resolveCustomCSS(options.customCSS, '', ctx.log);
161161
processedOptions.customCSS = resolvedCSS;
162-
ctx.log.debug('Using per-snapshot customCSS (overriding config)');
163162
} else if (ctx.config.customCSS) {
164163
processedOptions.customCSS = ctx.config.customCSS;
165-
ctx.log.debug('Using config customCSS');
166164
}
167165
} catch (error: any) {
168-
ctx.log.warn(`customCSS warning: ${error.message}`);
169-
chalk.yellow(`[SmartUI] warning: ${error.message}`);
166+
optionWarnings.add(`${error.message}`);
170167
}
171168

172169
processedOptions.allowedAssets = ctx.config.allowedAssets;
@@ -603,8 +600,6 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
603600
optionWarnings.add(`${error.message}`);
604601
}
605602

606-
ctx.log.debug(`Processed options: ${JSON.stringify(processedOptions)}`);
607-
608603
// process for every viewport
609604
let navigated: boolean = false;
610605
let previousDeviceType: string | null = null;

src/lib/utils.ts

Lines changed: 18 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -891,50 +891,7 @@ export async function startSSEListener(ctx: Context) {
891891
}
892892
}
893893

894-
/**
895-
* Validates if a string contains valid CSS syntax
896-
* @param cssString - The CSS string to validate
897-
* @returns true if valid CSS, false otherwise
898-
*/
899-
export function isValidCSS(cssString: string): boolean {
900-
if (!cssString || typeof cssString !== 'string' || cssString.trim().length === 0) {
901-
return false;
902-
}
903-
904-
const trimmed = cssString.trim();
905-
906-
// Basic CSS validation patterns
907-
// Check for balanced braces
908-
const openBraces = (trimmed.match(/\{/g) || []).length;
909-
const closeBraces = (trimmed.match(/\}/g) || []).length;
910-
911-
if (openBraces !== closeBraces) {
912-
return false;
913-
}
914-
915-
// Check for basic CSS structure (selector { property: value; })
916-
// Allow comments /* */ and media queries
917-
const cssPattern = /^[\s\S]*[\{\}][\s\S]*$/;
918-
919-
// Must contain at least one CSS rule or be empty
920-
if (trimmed.length > 0 && !cssPattern.test(trimmed)) {
921-
// Allow single-line rules without newlines
922-
const singleRulePattern = /^[^{]+\{[^}]+\}$/;
923-
if (!singleRulePattern.test(trimmed)) {
924-
return false;
925-
}
926-
}
927894

928-
return true;
929-
}
930-
931-
/**
932-
* Resolves customCSS from either a file path or inline CSS string
933-
* @param cssValue - The CSS value from config (file path or inline CSS)
934-
* @param configPath - The path to the config file (for resolving relative paths)
935-
* @param logger - Logger instance for debug messages
936-
* @returns Resolved CSS string or throws error if invalid
937-
*/
938895
export function resolveCustomCSS(cssValue: string, configPath: string, logger: any): string {
939896
if (!cssValue || typeof cssValue !== 'string') {
940897
throw new Error('customCSS must be a non-empty string');
@@ -948,11 +905,13 @@ export function resolveCustomCSS(cssValue: string, configPath: string, logger: a
948905
// Check if it looks like a file path
949906
const path = require('path');
950907
const isLikelyFilePath =
951-
trimmed.endsWith('.css') ||
952-
trimmed.startsWith('./') ||
953-
trimmed.startsWith('../') ||
954-
trimmed.startsWith('/') ||
955-
path.isAbsolute(trimmed);
908+
trimmed.includes('.') && (
909+
trimmed.startsWith('./') ||
910+
trimmed.startsWith('../') ||
911+
trimmed.startsWith('/') ||
912+
path.isAbsolute(trimmed) ||
913+
/\.(css|json|js|txt|html)$/i.test(trimmed)
914+
);
956915

957916
if (isLikelyFilePath) {
958917
logger.debug(`customCSS appears to be a file path: ${trimmed}`);
@@ -962,6 +921,10 @@ export function resolveCustomCSS(cssValue: string, configPath: string, logger: a
962921
if (ext && ext !== '.css') {
963922
throw new Error(`Invalid customCSS file type: ${ext}. Only .css files are supported.`);
964923
}
924+
// If no extension at all, also reject
925+
if (!ext) {
926+
throw new Error('Invalid file provided in customCSS. Expected .css file.');
927+
}
965928

966929
// Resolve the file path
967930
const baseDir = path.dirname(configPath);
@@ -971,7 +934,6 @@ export function resolveCustomCSS(cssValue: string, configPath: string, logger: a
971934

972935
logger.debug(`Resolved customCSS file path: ${resolvedPath}`);
973936

974-
// Check if file exists
975937
if (!fs.existsSync(resolvedPath)) {
976938
throw new Error(`customCSS file not found: ${resolvedPath}`);
977939
}
@@ -982,7 +944,6 @@ export function resolveCustomCSS(cssValue: string, configPath: string, logger: a
982944
throw new Error(`customCSS path is not a file: ${resolvedPath}`);
983945
}
984946

985-
// Read the file
986947
try {
987948
const cssContent = fs.readFileSync(resolvedPath, 'utf-8');
988949
logger.debug(`Read ${cssContent.length} characters from customCSS file`);
@@ -995,18 +956,12 @@ export function resolveCustomCSS(cssValue: string, configPath: string, logger: a
995956
throw new Error(`Failed to read customCSS file: ${error.message}`);
996957
}
997958
} else {
998-
// Treat as inline CSS
999959
logger.debug('customCSS appears to be inline CSS');
1000960
return trimmed;
1001961
}
1002962
}
1003963

1004964

1005-
/**
1006-
* Parse CSS content and extract selectors with their rules
1007-
* @param cssContent - The CSS content to parse
1008-
* @returns Array of parsed CSS rules with selectors
1009-
*/
1010965
export function parseCSSFile(cssContent: string): Array<{
1011966
selector: string;
1012967
declarations: Array<{ property: string; value: string; important: boolean }>;
@@ -1022,6 +977,13 @@ export function parseCSSFile(cssContent: string): Array<{
1022977
const ast = postcss.parse(cssContent);
1023978

1024979
ast.walkRules((rule: any) => {
980+
981+
// Skip rules inside @keyframes, @media, and other at-rules
982+
// by checking if the parent is an AtRule
983+
if (rule.parent && rule.parent.type === 'atrule') {
984+
return; // Skip this rule
985+
}
986+
1025987
const declarations: Array<{ property: string; value: string; important: boolean }> = [];
1026988

1027989
rule.walkDecls((decl: any) => {

0 commit comments

Comments
 (0)