Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@web/test-runner-core

Package Overview
Dependencies
Maintainers
6
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@web/test-runner-core - npm Package Compare versions

Comparing version 0.6.17 to 0.6.18

6

CHANGELOG.md
# @web/test-runner-core
## 0.6.18
### Patch Changes
- 736d101: improve scheduling logic and error handling
## 0.6.17

@@ -4,0 +10,0 @@

@@ -34,2 +34,8 @@ import { CoverageMapData } from 'istanbul-lib-coverage';

/**
* Returns whether this session is currently active. If it is active, stopSession
* can be called.
* @param session
*/
isActive(session: TestSession): boolean;
/**
* Stops a single test session. There is no mandatory action to be taken here.

@@ -36,0 +42,0 @@ * Implementations can use this for example to recycle inactive tabs instead of

4

dist/config/TestRunnerCoreConfig.d.ts

@@ -39,6 +39,6 @@ import { BrowserLauncher } from '../browser-launcher/BrowserLauncher.js';

browserStartTimeout?: number;
sessionStartTimeout?: number;
sessionFinishTimeout?: number;
testsStartTimeout?: number;
testsFinishTimeout?: number;
staticLogging?: boolean;
}
//# sourceMappingURL=TestRunnerCoreConfig.d.ts.map

@@ -17,3 +17,3 @@ "use strict";

var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);

@@ -23,3 +23,3 @@ return result;

Object.defineProperty(exports, "__esModule", { value: true });
exports.constants = void 0;
exports.EventEmitter = exports.SESSION_STATUS = exports.TestSessionManager = exports.TestRunner = exports.constants = void 0;
const constants = __importStar(require("./browser-launcher/constants"));

@@ -26,0 +26,0 @@ exports.constants = constants;

@@ -126,3 +126,2 @@ "use strict";

try {
this.scheduler.runScheduled(this.testRun);
const finishedAll = Array.from(this.sessions.all()).every(s => s.status === TestSessionStatus_1.SESSION_STATUS.FINISHED);

@@ -129,0 +128,0 @@ if (finishedAll) {

@@ -9,13 +9,24 @@ import { TestRunnerCoreConfig } from '../config/TestRunnerCoreConfig';

constructor(config: TestRunnerCoreConfig, sessions: TestSessionManager);
/**
* Schedules a session for execution. Execution is batched, the session
* will be queued until there is a browser page available.
*/
schedule(testRun: number, sessionsToSchedule: Iterable<TestSession>): void;
stop(): void;
private addTimeoutId;
private clearTimeouts;
schedule(testRun: number, sessionsToSchedule: Iterable<TestSession>): void;
runScheduled(testRun: number): void;
/** Runs the next batch of scheduled sessions, if any. */
private runNextScheduled;
private startSession;
private setSessionFailed;
private setSessionStartedTimeout;
private setSessionFinishedTimeout;
stopSession(session: TestSession, errors?: TestResultError[]): Promise<void>;
private waitForTestsStarted;
private waitForTestsFinished;
/**
* Returns whether the session has gone stale. Sessions are immutable, this takes in a
* snapshot of a session and returns whether the session has since changed test run or status.
* This can be used to decide whether perform side effects like logging or changing status.
*/
private isStale;
private addTimeoutId;
private clearTimeouts;
}
//# sourceMappingURL=TestScheduler.d.ts.map

@@ -11,13 +11,32 @@ "use strict";

this.timeoutIdsPerSession = new Map();
sessions.on('session-status-updated', session => {
sessions.on('session-status-updated', async (session) => {
if (session.status === TestSessionStatus_1.SESSION_STATUS.TEST_STARTED) {
this.waitForTestsFinished(session.testRun, session.id);
return;
}
if (session.status === TestSessionStatus_1.SESSION_STATUS.TEST_FINISHED) {
this.stopSession(session);
// the session finished executing tests, close the browser page
await this.stopSession(session);
return;
}
const timeoutIds = this.timeoutIdsPerSession.get(session.id);
if (timeoutIds && session.status === TestSessionStatus_1.SESSION_STATUS.FINISHED) {
this.clearTimeouts(timeoutIds);
if (session.status === TestSessionStatus_1.SESSION_STATUS.FINISHED) {
// the session is full finished, clear any related timeouts
const timeoutIds = this.timeoutIdsPerSession.get(session.id);
if (timeoutIds) {
this.clearTimeouts(timeoutIds);
}
this.runNextScheduled();
}
});
}
/**
* Schedules a session for execution. Execution is batched, the session
* will be queued until there is a browser page available.
*/
schedule(testRun, sessionsToSchedule) {
for (const session of sessionsToSchedule) {
this.sessions.updateStatus(Object.assign(Object.assign({}, session), { testRun, request404s: [] }), TestSessionStatus_1.SESSION_STATUS.SCHEDULED);
}
this.runNextScheduled();
}
stop() {

@@ -28,40 +47,22 @@ for (const ids of this.timeoutIdsPerSession.values()) {

}
addTimeoutId(sessionId, id) {
let timeoutIds = this.timeoutIdsPerSession.get(sessionId);
if (!timeoutIds) {
timeoutIds = [];
this.timeoutIdsPerSession.set(sessionId, timeoutIds);
}
timeoutIds.push(id);
}
clearTimeouts(timeoutIds) {
for (const id of timeoutIds) {
clearTimeout(id);
}
}
schedule(testRun, sessionsToSchedule) {
for (const session of sessionsToSchedule) {
this.sessions.updateStatus(Object.assign(Object.assign({}, session), { request404s: [] }), TestSessionStatus_1.SESSION_STATUS.SCHEDULED);
}
this.runScheduled(testRun);
}
runScheduled(testRun) {
const scheduledIt = this.sessions.forStatus(TestSessionStatus_1.SESSION_STATUS.SCHEDULED);
/** Runs the next batch of scheduled sessions, if any. */
runNextScheduled() {
const runningCount = Array.from(this.sessions.forStatus(TestSessionStatus_1.SESSION_STATUS.INITIALIZING, TestSessionStatus_1.SESSION_STATUS.TEST_STARTED, TestSessionStatus_1.SESSION_STATUS.TEST_FINISHED)).length;
const count = this.config.concurrency - runningCount;
for (let i = 0; i < count; i += 1) {
const { done, value } = scheduledIt.next();
if (done || !value) {
break;
}
this.startSession(testRun, value);
if (count === 0) {
return;
}
const scheduled = Array.from(this.sessions.forStatus(TestSessionStatus_1.SESSION_STATUS.SCHEDULED)).slice(0, count);
for (const session of scheduled) {
this.startSession(session);
}
}
async startSession(testRun, session) {
this.sessions.update(Object.assign(Object.assign({}, session), { testRun, status: TestSessionStatus_1.SESSION_STATUS.INITIALIZING }));
let browserStartResponded = false;
async startSession(session) {
const updatedSession = Object.assign(Object.assign({}, session), { status: TestSessionStatus_1.SESSION_STATUS.INITIALIZING });
this.sessions.update(updatedSession);
let browserStarted = false;
// browser should be started within the specified milliseconds
const timeoutId = setTimeout(() => {
if (!browserStartResponded) {
this.setSessionFailed(this.sessions.get(session.id), {
if (!browserStarted && !this.isStale(updatedSession)) {
this.setSessionFailed(this.sessions.get(updatedSession.id), {
message: `The browser was unable to open the test page after ${this.config.browserStartTimeout}ms.`,

@@ -71,13 +72,20 @@ });

}, this.config.browserStartTimeout);
this.addTimeoutId(session.id, timeoutId);
this.addTimeoutId(updatedSession.id, timeoutId);
try {
await session.browserLauncher.startSession(session, createSessionUrl_1.createSessionUrl(this.config, session, false));
await updatedSession.browserLauncher.startSession(updatedSession, createSessionUrl_1.createSessionUrl(this.config, updatedSession, false));
// when the browser started, wait for session to ping back on time
this.setSessionStartedTimeout(testRun, session.id);
this.waitForTestsStarted(updatedSession.testRun, updatedSession.id);
}
catch (error) {
this.setSessionFailed(session, error);
if (this.isStale(updatedSession)) {
// something else has changed the test session, such as a the browser timeout
// or a re-run in watch mode. in that was we just log the error
this.config.logger.error(error);
}
else {
this.setSessionFailed(updatedSession, { message: error.message, stack: error.stack });
}
}
finally {
browserStartResponded = true;
browserStarted = true;
}

@@ -88,3 +96,29 @@ }

}
setSessionStartedTimeout(testRun, sessionId) {
async stopSession(session, errors = []) {
var _a;
if (this.isStale(session)) {
return;
}
const sessionErrors = [...errors];
const updatedSession = Object.assign({}, session);
try {
if (session.browserLauncher.isActive(session)) {
const { testCoverage, browserLogs } = await session.browserLauncher.stopSession(session);
updatedSession.testCoverage = testCoverage;
updatedSession.logs = browserLogs;
}
}
catch (error) {
sessionErrors.push(error);
}
finally {
if (sessionErrors.length > 0) {
// merge with existing erors
updatedSession.errors = [...((_a = updatedSession.errors) !== null && _a !== void 0 ? _a : []), ...sessionErrors];
updatedSession.passed = false;
}
this.sessions.updateStatus(updatedSession, TestSessionStatus_1.SESSION_STATUS.FINISHED);
}
}
waitForTestsStarted(testRun, sessionId) {
const timeoutId = setTimeout(() => {

@@ -98,15 +132,11 @@ const session = this.sessions.get(sessionId);

this.setSessionFailed(session, {
message: `Browser tests did not start after ${this.config.sessionStartTimeout}ms. Check the browser logs or open the browser in debug mode for more information.`,
message: `Browser tests did not start after ${this.config.testsStartTimeout}ms. ` +
'Check the browser logs or open the browser in debug mode for more information.',
});
return;
}
if ([TestSessionStatus_1.SESSION_STATUS.TEST_FINISHED, TestSessionStatus_1.SESSION_STATUS.FINISHED].includes(session.status)) {
// The session finished by now
return;
}
this.setSessionFinishedTimeout(testRun, session.id);
}, this.config.sessionStartTimeout);
}, this.config.testsStartTimeout);
this.addTimeoutId(sessionId, timeoutId);
}
setSessionFinishedTimeout(testRun, sessionId) {
waitForTestsFinished(testRun, sessionId) {
const timeoutId = setTimeout(() => {

@@ -118,23 +148,37 @@ const session = this.sessions.get(sessionId);

}
if (session.status !== TestSessionStatus_1.SESSION_STATUS.FINISHED) {
if (session.status !== TestSessionStatus_1.SESSION_STATUS.TEST_FINISHED) {
this.setSessionFailed(session, {
message: `Browser tests did not finish within ${this.config.sessionStartTimeout}ms. Check the browser logs or open the browser in debug mode for more information.`,
message: `Browser tests did not finish within ${this.config.testsFinishTimeout}ms. ` +
'Check the browser logs or open the browser in debug mode for more information.',
});
}
}, this.config.sessionFinishTimeout);
}, this.config.testsFinishTimeout);
this.addTimeoutId(sessionId, timeoutId);
}
async stopSession(session, errors = []) {
var _a;
const { testCoverage, browserLogs: logs } = await session.browserLauncher.stopSession(session);
const updatedSession = Object.assign(Object.assign({}, session), { testCoverage, logs });
if (errors.length > 0) {
// merge with existing erors
updatedSession.errors = [...((_a = updatedSession.errors) !== null && _a !== void 0 ? _a : []), ...errors];
updatedSession.passed = false;
/**
* Returns whether the session has gone stale. Sessions are immutable, this takes in a
* snapshot of a session and returns whether the session has since changed test run or status.
* This can be used to decide whether perform side effects like logging or changing status.
*/
isStale(session) {
const currentSession = this.sessions.get(session.id);
return (!currentSession ||
currentSession.testRun !== session.testRun ||
currentSession.status !== session.status);
}
addTimeoutId(sessionId, id) {
let timeoutIds = this.timeoutIdsPerSession.get(sessionId);
if (!timeoutIds) {
timeoutIds = [];
this.timeoutIdsPerSession.set(sessionId, timeoutIds);
}
this.sessions.updateStatus(updatedSession, TestSessionStatus_1.SESSION_STATUS.FINISHED);
timeoutIds.push(id);
}
clearTimeouts(timeoutIds) {
for (const id of timeoutIds) {
clearTimeout(id);
}
}
}
exports.TestScheduler = TestScheduler;
//# sourceMappingURL=TestScheduler.js.map
{
"name": "@web/test-runner-core",
"version": "0.6.17",
"version": "0.6.18",
"publishConfig": {

@@ -43,4 +43,6 @@ "access": "public"

"@types/istanbul-lib-coverage": "^2.0.2",
"@types/uuid": "^8.0.0"
"@types/uuid": "^8.0.0",
"sinon": "^9.0.2",
"sinon-chai": "^3.5.0"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc