Compare commits

..

2 Commits

Author SHA1 Message Date
e93eb5fe84 Enhance CommandLine and TestConfiguration for improved option validation and logging
* Added validation for required command line options in the `CommandLine` class to ensure necessary parameters are provided.
* Updated `TestConfiguration` to store and expose the logging level from command line options.
* Refactored `BrowserstackApi` to improve method naming and added content type headers for API requests.
* Changed `SupportedBrowser` type to be exported for better accessibility.
* Updated `Page` and `SubscribingPage` classes to use a consistent browser import and improved constructor parameters.
2025-08-18 22:07:37 -04:00
1cf223fd85 Update dependencies and refactor page navigation logic
* Added `@wdio/cli` as a development dependency for improved test command handling.
* Refactored URL construction in the `Page` class to enhance clarity and maintainability.
* Updated import statements in `Subscribing.page.ts` for consistency and removed unnecessary options in the constructor.
2025-08-18 21:55:30 -04:00
8 changed files with 51 additions and 28 deletions

View File

@@ -10,6 +10,7 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "9.33.0", "@eslint/js": "9.33.0",
"@types/bun": "latest", "@types/bun": "latest",
"@wdio/cli": "9.19.1",
"globals": "16.3.0", "globals": "16.3.0",
"typescript-eslint": "8.40.0" "typescript-eslint": "8.40.0"
}, },

View File

@@ -1,4 +1,4 @@
import SupportedBrowser from './SupportedBrowser'; import type {SupportedBrowser} from './SupportedBrowser';
// Source: https://github.com/browserstack/api // Source: https://github.com/browserstack/api
@@ -10,16 +10,18 @@ export class BrowserstackApi {
this._authorizationHeader = `Basic ${Buffer.from(`${username}:${accessKey}`).toString('base64')}`; this._authorizationHeader = `Basic ${Buffer.from(`${username}:${accessKey}`).toString('base64')}`;
} }
public async getSupportedBrowsers(): Promise<SupportedBrowser[]> { public async getListOfSupportedBrowsers(): Promise<SupportedBrowser[]> {
const endpoint = `${this._baseUrl}/browsers?flat=true`; const requestPath = `${this._baseUrl}/browsers?flat=true`;
const headers = { const headers = {
Authorization: this._authorizationHeader Authorization: this._authorizationHeader,
'Content-Type': 'application/json',
Accept: 'application/json'
}; };
const response = await fetch(endpoint, {headers}); const response = await fetch(requestPath, {headers});
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to fetch BrowserStack supported browsers due to [ ${response.statusText}]`); throw new Error(`Failed to fetch BrowserStack supported browsers due to [${response.statusText}]`);
} }
return response.json() as Promise<SupportedBrowser[]>; return response.json() as Promise<SupportedBrowser[]>;

View File

@@ -1,4 +1,4 @@
type SupportedBrowser = { export type SupportedBrowser = {
os: string; os: string;
os_version: string; os_version: string;
browser: string; browser: string;
@@ -6,5 +6,3 @@ type SupportedBrowser = {
browser_version: string | null; browser_version: string | null;
real_mobile: boolean; real_mobile: boolean;
}; };
export default SupportedBrowser;

View File

@@ -37,6 +37,11 @@ export default class CommandLine {
// Convert the string log level back to LoggingLevel enum // Convert the string log level back to LoggingLevel enum
const logLevel = rawOptions.logLevel ? LoggingLevelMapping.convertLoggingLevelTypeToLoggingLevel(rawOptions.logLevel) : defaultLogLevel; const logLevel = rawOptions.logLevel ? LoggingLevelMapping.convertLoggingLevelTypeToLoggingLevel(rawOptions.logLevel) : defaultLogLevel;
// Validate required options are present
if (!rawOptions.applicationId || !rawOptions.secret || !rawOptions.pcastUri || !rawOptions.channelUri) {
throw new Error('Missing required command line options: applicationId, secret, pcastUri, and channelUri are required');
}
return { return {
...rawOptions, ...rawOptions,
logLevel logLevel

View File

@@ -1,4 +1,5 @@
import type {CommandLineOptions} from './CommandLine'; import type {CommandLineOptions} from './CommandLine';
import {LoggingLevel} from '../logger/LoggingLevel';
type ApplicationCredentials = { type ApplicationCredentials = {
applicationId: string; applicationId: string;
@@ -26,6 +27,7 @@ export default class TestConfiguration {
private readonly _publishers: string[]; private readonly _publishers: string[];
private readonly _tests: string[]; private readonly _tests: string[];
private readonly _browserstack: BrowserstackConfiguration; private readonly _browserstack: BrowserstackConfiguration;
private readonly _logLevel: LoggingLevel;
constructor(commandLineOptions: CommandLineOptions) { constructor(commandLineOptions: CommandLineOptions) {
this._applicationCredentials = { this._applicationCredentials = {
@@ -43,6 +45,7 @@ export default class TestConfiguration {
this._viewers = commandLineOptions.viewers; this._viewers = commandLineOptions.viewers;
this._publishers = commandLineOptions.publishers; this._publishers = commandLineOptions.publishers;
this._tests = commandLineOptions.tests; this._tests = commandLineOptions.tests;
this._logLevel = commandLineOptions.logLevel;
this._browserstack = { this._browserstack = {
enabled: commandLineOptions.useBrowserstack, enabled: commandLineOptions.useBrowserstack,
local: commandLineOptions.useBrowserstackLocal, local: commandLineOptions.useBrowserstackLocal,
@@ -74,4 +77,8 @@ export default class TestConfiguration {
get browserstack(): BrowserstackConfiguration { get browserstack(): BrowserstackConfiguration {
return this._browserstack; return this._browserstack;
} }
get logLevel(): LoggingLevel {
return this._logLevel;
}
} }

View File

@@ -1,33 +1,44 @@
import {browser} from '@wdio/globals'; import {browser as wdio} from '@wdio/globals';
export type PageOptions = { export type PageOptions = {
browser?: typeof browser; // MultiRemote usecase browser?: typeof wdio; // MultiRemote usecase
}; };
export type PageOpenOptions = { export type PageOpenOptions = {
queryParameters?: Record<string, string | number>; queryParameters?: Record<string, string | number>;
isNewTabRequest?: boolean; isNewTabRequest?: boolean;
endpoint?: string;
requestPath?: string; requestPath?: string;
}; };
export default class Page { export default class Page {
private readonly _baseUrl: string; private readonly _baseUrl: string;
private readonly _browser: typeof wdio;
constructor(baseUrl: string) { constructor(baseUrl: string, browser: typeof wdio) {
this._baseUrl = baseUrl; this._baseUrl = baseUrl;
this._browser = browser;
} }
public async open(options: PageOpenOptions = {}): Promise<void> { public async open(options: PageOpenOptions = {}): Promise<void> {
const {queryParameters, isNewTabRequest, endpoint, requestPath} = options; const {queryParameters, isNewTabRequest, requestPath} = options;
const pageUrl = `${this._baseUrl}/${endpoint}${requestPath}?${Object.entries(queryParameters ?? {})
.map(([queryParameterName, queryParamterValue]) => `${queryParameterName}=${queryParamterValue}&`) let pageUrl = this._baseUrl;
.join('')}`;
if (requestPath) {
pageUrl += `/${requestPath}`;
}
if (queryParameters && Object.keys(queryParameters).length > 0) {
const queryString = Object.entries(queryParameters)
.map(([queryParameterName, queryParameterValue]) => `${queryParameterName}=${queryParameterValue}`)
.join('&');
pageUrl += `?${queryString}`;
}
if (isNewTabRequest) { if (isNewTabRequest) {
await browser.newWindow(pageUrl); await (this._browser as any).newWindow(pageUrl);
} else { } else {
await browser.url(pageUrl); await (this._browser as any).url(pageUrl);
} }
} }
} }

View File

@@ -1,17 +1,16 @@
import Page, {PageOpenOptions} from './Page.ts'; import {browser as wdio, $} from '@wdio/globals';
import Page, {PageOpenOptions} from './Page';
export type SubscribingPageOptions = {};
export class SubscribingPage extends Page { export class SubscribingPage extends Page {
constructor(baseUri: string, options: SubscribingPageOptions) { constructor(baseUri: string, browser: typeof wdio) {
super(baseUri, options); super(baseUri, browser);
} }
get videoElement() { get videoElement() {
return $('video'); return $('video');
} }
public async open(options?: PageOpenOptions): Promise<void> { public override async open(options?: PageOpenOptions): Promise<void> {
await super.open(options); await super.open(options);
} }
} }

View File

@@ -1 +1 @@
export * from './Subscribing.page.ts'; export * from './Subscribing.page';