Skip to content

Commit 98d63c0

Browse files
author
Alex Plischke
authored
feat: add configuration options (#13)
1 parent 7a70692 commit 98d63c0

File tree

4 files changed

+102
-11
lines changed

4 files changed

+102
-11
lines changed

README.md

+30-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ This is the official Sauce Labs browser provider plugin for [TestCafe](http://de
88
npm install testcafe-browser-provider-sauce
99
```
1010

11+
## Setup
12+
13+
Before using this plugin, you need to set the `SAUCE_USERNAME` and
14+
`SAUCE_ACCESS_KEY` environment variables. Your Sauce Labs Username and Access
15+
Key are available from your [dashboard](https://app.saucelabs.com/user-settings).
16+
17+
Furthermore, a [Sauce Connect](https://docs.saucelabs.com/secure-connections/sauce-connect-5/)
18+
tunnel is required to run tests on Sauce Labs. After launching a tunnel, specify
19+
the tunnel name using the `SAUCE_TUNNEL_NAME` environment variable.
20+
1121
## Usage
1222

1323
You can determine the available browser aliases by running
@@ -19,7 +29,7 @@ testcafe -b sauce
1929
When you run tests from the command line, use the alias when specifying browsers:
2030

2131
```
22-
testcafe sauce:chrome 'path/to/test/file.js'
32+
testcafe "sauce:chrome@latest:Windows 11" 'path/to/test/file.js'
2333
```
2434

2535
When you use API, pass the alias to the `browsers()` method:
@@ -28,10 +38,28 @@ When you use API, pass the alias to the `browsers()` method:
2838
testCafe
2939
.createRunner()
3040
.src('path/to/test/file.js')
31-
.browsers('sauce:chrome')
41+
.browsers('sauce:chrome@latest:Windows 11')
3242
.run();
3343
```
3444

45+
## Configuration
46+
47+
Full overview of the available configuration options.
48+
49+
Mandatory environment variables:
50+
51+
- `SAUCE_USERNAME` - Your Sauce Labs username.
52+
- `SAUCE_ACCESS_KEY` - Your Sauce Labs access key.
53+
- `SAUCE_TUNNEL_NAME` - The Sauce Connect tunnel name.
54+
55+
Optional environment variables:
56+
57+
- `SAUCE_JOB_NAME` - Specify the job name for all jobs. Defaults to `TestCafe via ${browserName}@${browserVersion} on ${platformName}`.
58+
- `SAUCE_BUILD` - All jobs will be associated with this build. The default value is randomly generated.
59+
- `SAUCE_TAGS` - A comma separated list of tags to apply to all jobs.
60+
- `SAUCE_REGION` - The Sauce Labs region. Valid values are `us-west-1` (default) or `eu-central-1`.
61+
- `SAUCE_SCREEN_RESOLUTION` - The desktop browser screen resolution (not applicable to mobile). The format is `1920x1080`.
62+
3563
## Development
3664

3765
To use the local version of the plugin, you can link the package:

src/driver.ts

+36-7
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,56 @@ export type Size = {
88
height: number;
99
};
1010

11+
export type Region = 'us-west-1' | 'eu-central-1' | 'staging';
12+
13+
const hostByRegion = new Map<Region, string>([
14+
['us-west-1', 'ondemand.us-west-1.saucelabs.com'],
15+
['eu-central-1', 'ondemand.eu-central-1.saucelabs.com'],
16+
['staging', 'ondemand.staging.saucelabs.net'],
17+
]);
18+
1119
export class SauceDriver {
1220
private readonly username: string;
1321
private readonly accessKey: string;
1422
private readonly tunnelName: string;
1523
private sessions = new Map<string, Client>();
16-
17-
constructor(username: string, accessKey: string, tunnelName: string) {
24+
private readonly build: string;
25+
private readonly tags?: string[];
26+
private readonly region: Region;
27+
private readonly jobName?: string;
28+
29+
constructor(
30+
username: string,
31+
accessKey: string,
32+
region: Region,
33+
tunnelName: string,
34+
jobName?: string,
35+
build?: string,
36+
tags?: string[],
37+
) {
1838
this.username = username;
1939
this.accessKey = accessKey;
40+
this.region = region;
2041
this.tunnelName = tunnelName;
42+
this.jobName = jobName;
43+
this.build = build ?? Math.random().toString(36).substring(2, 10);
44+
this.tags = tags;
2145
}
2246

2347
createCapabilities(
2448
browserName: string,
2549
browserVersion: string,
2650
platformName: string,
51+
screenResolution?: string,
2752
): WebDriver.Capabilities {
2853
const sauceOpts = {
29-
name: 'testcafe sauce provider job', // TODO make this configurable
30-
build: 'TCPRVDR', // TODO make this configurable
54+
name:
55+
this.jobName ??
56+
`TestCafe via ${browserName}@${browserVersion} on ${platformName}`,
57+
build: this.build,
58+
tags: this.tags,
3159
tunnelIdentifier: this.tunnelName,
60+
screenResolution: screenResolution,
3261
idleTimeout: 3600, // 1 hour
3362
enableTestReport: true,
3463
};
@@ -59,17 +88,19 @@ export class SauceDriver {
5988
browserName: string,
6089
browserVersion: string,
6190
platformName: string,
91+
screenResolution?: string,
6292
) {
6393
const webDriver = await wd.newSession({
6494
protocol: 'https',
65-
hostname: `ondemand.us-west-1.saucelabs.com`, // TODO multi region support
95+
hostname: hostByRegion.get(this.region),
6696
port: 443,
6797
user: this.username,
6898
key: this.accessKey,
6999
capabilities: this.createCapabilities(
70100
browserName,
71101
browserVersion,
72102
platformName,
103+
screenResolution,
73104
),
74105
logLevel: 'error',
75106
connectionRetryTimeout: 9 * 60 * 1000, // 9 minutes
@@ -82,8 +113,6 @@ export class SauceDriver {
82113

83114
this.sessions.set(browserId, webDriver);
84115

85-
// TODO do we need a keep-alive?
86-
87116
await webDriver.navigateTo(url);
88117

89118
return {

src/errors.ts

+9
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,12 @@ export class WindowSizeRangeError extends Error {
3333
this.name = 'WindowSizeRangeError';
3434
}
3535
}
36+
37+
export class InvalidRegionError extends Error {
38+
constructor() {
39+
super(
40+
'Invalid region. The region must be one of the following: us-west-1, eu-central-1.',
41+
);
42+
this.name = 'InvalidRegionError';
43+
}
44+
}

src/index.ts

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { SauceDriver } from './driver';
2-
import { AuthError, TunnelNameError, WindowSizeRangeError } from './errors';
2+
import {
3+
AuthError,
4+
InvalidRegionError,
5+
TunnelNameError,
6+
WindowSizeRangeError,
7+
} from './errors';
38
import { getPlatforms } from './api';
49
import { rcompareOses, rcompareVersions } from './sort';
510
import { isDevice } from './device';
@@ -40,15 +45,34 @@ module.exports = {
4045
const username = process.env.SAUCE_USERNAME;
4146
const accessKey = process.env.SAUCE_ACCESS_KEY;
4247
const tunnelName = process.env.SAUCE_TUNNEL_NAME;
48+
const build = process.env.SAUCE_BUILD;
49+
const tags = (process.env.SAUCE_TAGS || '').split(',');
50+
const region = process.env.SAUCE_REGION || 'us-west-1';
51+
const jobName = process.env.SAUCE_JOB_NAME;
4352

4453
if (!username || !accessKey) {
4554
throw new AuthError();
4655
}
4756
if (!tunnelName) {
4857
throw new TunnelNameError();
4958
}
59+
if (
60+
region !== 'us-west-1' &&
61+
region !== 'eu-central-1' &&
62+
region !== 'staging'
63+
) {
64+
throw new InvalidRegionError();
65+
}
5066

51-
sauceDriver = new SauceDriver(username, accessKey, tunnelName);
67+
sauceDriver = new SauceDriver(
68+
username,
69+
accessKey,
70+
region,
71+
tunnelName,
72+
jobName,
73+
build,
74+
tags,
75+
);
5276

5377
const resp = await getPlatforms({ username, accessKey });
5478
const browserMap = new Map<Browser, Map<Version, Set<Os>>>();
@@ -145,6 +169,7 @@ module.exports = {
145169
bName,
146170
bVersion,
147171
os,
172+
process.env.SAUCE_SCREEN_RESOLUTION,
148173
);
149174
console.log('Browser started.');
150175

0 commit comments

Comments
 (0)