This commit is contained in:
2025-08-18 21:51:28 -04:00
parent 1eb0637d38
commit f3ecb8c35b
19 changed files with 179 additions and 646 deletions

View File

@@ -1,27 +1,27 @@
import SupportedBrowser from "./SupportedBrowser";
import SupportedBrowser from './SupportedBrowser';
// Source: https://github.com/browserstack/api
export class BrowserstackApi {
private readonly _baseUrl: string = 'https://api.browserstack.com/5';
private readonly _authorizationHeader: string;
private readonly _baseUrl: string = 'https://api.browserstack.com/5';
private readonly _authorizationHeader: string;
constructor(username: string, accessKey: string) {
this._authorizationHeader = `Basic ${Buffer.from(`${username}:${accessKey}`).toString('base64')}`;
constructor(username: string, accessKey: string) {
this._authorizationHeader = `Basic ${Buffer.from(`${username}:${accessKey}`).toString('base64')}`;
}
public async getSupportedBrowsers(): Promise<SupportedBrowser[]> {
const endpoint = `${this._baseUrl}/browsers?flat=true`;
const headers = {
Authorization: this._authorizationHeader
};
const response = await fetch(endpoint, {headers});
if (!response.ok) {
throw new Error(`Failed to fetch BrowserStack supported browsers due to [ ${response.statusText}]`);
}
public async getSupportedBrowsers(): Promise<SupportedBrowser[]> {
const endpoint = `${this._baseUrl}/browsers?flat=true`;
const headers = {
'Authorization': this._authorizationHeader
};
const response = await fetch(endpoint, { headers });
if (!response.ok) {
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,10 +1,10 @@
type SupportedBrowser = {
os: string;
os_version: string;
browser: string;
device: string;
browser_version: string | null;
real_mobile: boolean;
}
os: string;
os_version: string;
browser: string;
device: string;
browser_version: string | null;
real_mobile: boolean;
};
export default SupportedBrowser;
export default SupportedBrowser;

View File

@@ -27,43 +27,61 @@ const defaultUseBrowserstack = false;
const defaultUseBrowserstackLocal = false;
export default class CommandLine {
private static readonly _program: Command = new Command();
private static readonly _program: Command = new Command();
public static parse(args: string[]): CommandLineOptions {
CommandLine._program.parse(args);
return CommandLine._program.opts<CommandLineOptions>();
const rawOptions = CommandLine._program.opts();
// Convert the string log level back to LoggingLevel enum
const logLevel = rawOptions.logLevel ? LoggingLevelMapping.convertLoggingLevelTypeToLoggingLevel(rawOptions.logLevel) : defaultLogLevel;
return {
...rawOptions,
logLevel
} as CommandLineOptions;
}
static {
CommandLine._program.version(PackageJson.version);
const setupProgramOptions = (): void => {
const handleArrayOption = (value: string, previousValue: string[]) => {
if (previousValue) {
return previousValue.concat(value);
}
return [value];
};
// Required options
CommandLine._program.requiredOption('--application-id <applicationId>', 'The application ID to use');
CommandLine._program.requiredOption('--secret <secret>', 'The secret to use');
CommandLine._program.requiredOption('--pcast-uri <pcastUri>', 'The pcast URI to use');
CommandLine._program.requiredOption('--channel-uri <channelUri>', 'The channel URI to use');
CommandLine._program.option('--ingest-uri <ingestUri>', 'The ingest URI to use');
CommandLine._program.option('--publisher-uri <publisherUri>', 'The publisher URI to use');
CommandLine._program.option('--viewer <browser@version:OS@OSVersion...>', 'The browser and OS for simulating a viewer to use', handleArrayOption, defaultViewers);
CommandLine._program.option('--publisher <browser@version:OS@OSVersion...>', 'The browser and OS for simulating a publisher to use', handleArrayOption, defaultPublishers);
CommandLine._program.option(
'--viewer <browser@version:OS@OSVersion...>',
'The browser and OS for simulating a viewer to use',
handleArrayOption,
defaultViewers
);
CommandLine._program.option(
'--publisher <browser@version:OS@OSVersion...>',
'The browser and OS for simulating a publisher to use',
handleArrayOption,
defaultPublishers
);
CommandLine._program.option('-t, --test <test...>', 'The test to run', handleArrayOption, defaultTests);
CommandLine._program.option('--use-browserstack', 'Run tests using BrowserStack', defaultUseBrowserstack);
CommandLine._program.option('--use-browserstack-local', 'Run tests using BrowserStack Local', defaultUseBrowserstackLocal);
CommandLine._program.option('--browserstack-user <username>', 'The BrowserStack username to use', process.env.BROWSERSTACK_USER || '');
CommandLine._program.option('--browserstack-key <key>', 'The BrowserStack key to use', process.env.BROWSERSTACK_KEY || '');
CommandLine._program.option('--log-level <logLevel>', 'The log level to use', LoggingLevelMapping.convertLoggingLevelToLoggingLevelType(defaultLogLevel));
}
};
setupProgramOptions();
}

View File

@@ -1,78 +1,77 @@
import CommandLine, { CommandLineOptions } from './CommandLine';
import type {CommandLineOptions} from './CommandLine';
type ApplicationCredentials = {
applicationId: string;
secret: string;
}
applicationId: string;
secret: string;
};
type Uri = {
pcast: string;
ingest: string | undefined;
channel: string | undefined;
publisher: string | undefined;
}
pcast: string;
ingest: string | undefined;
channel: string | undefined;
publisher: string | undefined;
};
type BrowserstackConfiguration = {
enabled: boolean;
local: boolean;
user: string;
key: string;
}
enabled: boolean;
local: boolean;
user: string;
key: string;
};
export default class TestConfiguration {
private readonly _applicationCredentials: ApplicationCredentials;
private readonly _uri: Uri;
private readonly _viewers: string[];
private readonly _publishers: string[];
private readonly _tests: string[];
private readonly _browserstack: BrowserstackConfiguration;
private readonly _applicationCredentials: ApplicationCredentials;
private readonly _uri: Uri;
private readonly _viewers: string[];
private readonly _publishers: string[];
private readonly _tests: string[];
private readonly _browserstack: BrowserstackConfiguration;
constructor(commandLineOptions: CommandLineOptions) {
this._applicationCredentials = {
applicationId: commandLineOptions.applicationId,
secret: commandLineOptions.secret,
};
constructor(commandLineOptions: CommandLineOptions) {
this._applicationCredentials = {
applicationId: commandLineOptions.applicationId,
secret: commandLineOptions.secret
};
this._uri = {
pcast: commandLineOptions.pcastUri,
ingest: commandLineOptions.ingestUri,
channel: commandLineOptions.channelUri,
publisher: commandLineOptions.publisherUri,
};
this._uri = {
pcast: commandLineOptions.pcastUri,
ingest: commandLineOptions.ingestUri,
channel: commandLineOptions.channelUri,
publisher: commandLineOptions.publisherUri
};
this._viewers = commandLineOptions.viewers;
this._publishers = commandLineOptions.publishers;
this._tests = commandLineOptions.tests;
this._browserstack = {
enabled: commandLineOptions.useBrowserstack,
local: commandLineOptions.useBrowserstackLocal,
user: commandLineOptions.browserstackUser,
key: commandLineOptions.browserstackKey,
};
}
this._viewers = commandLineOptions.viewers;
this._publishers = commandLineOptions.publishers;
this._tests = commandLineOptions.tests;
this._browserstack = {
enabled: commandLineOptions.useBrowserstack,
local: commandLineOptions.useBrowserstackLocal,
user: commandLineOptions.browserstackUser,
key: commandLineOptions.browserstackKey
};
}
get applicationCredentials(): ApplicationCredentials {
return this._applicationCredentials;
}
get applicationCredentials(): ApplicationCredentials {
return this._applicationCredentials;
}
get uri(): Uri {
return this._uri;
}
get uri(): Uri {
return this._uri;
}
get viewers(): string[] {
return this._viewers;
}
get viewers(): string[] {
return this._viewers;
}
get publishers(): string[] {
return this._publishers;
}
get publishers(): string[] {
return this._publishers;
}
get tests(): string[] {
return this._tests;
}
get tests(): string[] {
return this._tests;
}
get browserstack(): BrowserstackConfiguration {
return this._browserstack;
}
}
get browserstack(): BrowserstackConfiguration {
return this._browserstack;
}
}