/
reporter.ts
108 lines (90 loc) · 3.23 KB
/
reporter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import {BrowserMap} from "../browser-info";
import SauceLabsAPI, {Job} from 'saucelabs';
const REGION_MAPPING = {
'us': '', // default endpoint
'eu': 'eu-central-1.',
};
/**
* Get the Sauce Labs endpoint
* @param region
*/
function getSauceEndpoint(region) {
const shortRegion = REGION_MAPPING[region] ? region : 'us'
return `https://app.${REGION_MAPPING[shortRegion]}saucelabs.com/tests/`
}
/**
* Karma browser reported that updates corresponding Saucelabs jobs whenever a given
* browser finishes.
*/
export function SaucelabsReporter(logger, browserMap: BrowserMap) {
const log = logger.create('reporter.sauce');
let pendingUpdates: Promise<Job>[] = [];
this.adapters = [];
// This fires when a single test is executed and will update the run in sauce labs with an annotation
// of the test including the status of the test
this.onSpecComplete = function (browser, result) {
const browserId = browser.id;
const browserData = browserMap.get(browserId);
// Do nothing if the current browser has not been launched through the Saucelabs
// launcher.
if (!browserData) {
return;
}
const status = result.success ? '✅' : result.skipped ? '➖' : '❌';
browserData.results.push({
status: 'info',
message: `${status} ${result.fullName || result.description}`,
screenshot: null
})
if (!result.success && result.log.length > 0) {
browserData.results.push({
status: 'info',
message: `${result.log[0]}`,
screenshot: null
})
}
}
// This fires whenever any browser completes. This is when we want to report results
// to the Saucelabs API, so that people can create coverage banners for their project.
this.onBrowserComplete = function (browser) {
const result = browser.lastResult;
const browserId = browser.id;
if (result.disconnected) {
log.error('✖ Browser disconnected');
}
if (result.error) {
log.error('✖ Tests errored');
}
const browserData = browserMap.get(browserId);
// Do nothing if the current browser has not been launched through the Saucelabs
// launcher.
if (!browserData) {
return;
}
const {sessionId} = browserData;
const api = new SauceLabsAPI({
user: browserData.username,
key: browserData.accessKey,
region: browserData.region,
headless: browserData.headless
});
const hasPassed = !result.failed && !result.error && !result.disconnected;
// Update the job by reporting the test results. Also we need to store the promise here
// because in case "onExit" is being called, we want to wait for the API calls to finish.
pendingUpdates.push(api.updateJob(browserData.username, sessionId, {
id: sessionId,
passed: hasPassed,
'custom-data': result
}));
log.info(`Check out job at ${getSauceEndpoint(browserData.region)}${sessionId}`)
};
// Whenever this method is being called, we just need to wait for all API calls to finish,
// and then we can notify Karma about proceeding with the exit.
this.onExit = (doneFn: () => void) => Promise.all(pendingUpdates).then(
doneFn,
(error) => {
log.error('Could not report results to Saucelabs: %s', error)
doneFn()
}
);
}