Best JavaScript code snippet using playwright-internal
crPage.js
Source: crPage.js
...366 outputFile367 };368 await this._crPage._browserContext._ensureVideosPath(); // Note: it is important to start video recorder before sending Page.startScreencast,369 // and it is equally important to send Page.startScreencast before sending Runtime.runIfWaitingForDebugger.370 await this._createVideoRecorder(screencastId, screencastOptions);371 this._crPage.pageOrError().then(p => {372 if (p instanceof Error) this._stopVideoRecording().catch(() => {});373 });374 }375 let lifecycleEventsEnabled;376 if (!this._isMainFrame()) this._addRendererListeners();377 this._addBrowserListeners();378 const promises = [this._client.send('Page.enable'), this._client.send('Page.getFrameTree').then(({379 frameTree380 }) => {381 if (this._isMainFrame()) {382 this._handleFrameTree(frameTree);383 this._addRendererListeners();384 }385 const localFrames = this._isMainFrame() ? this._page.frames() : [this._page._frameManager.frame(this._targetId)];386 for (const frame of localFrames) {387 // Note: frames might be removed before we send these.388 this._client._sendMayFail('Page.createIsolatedWorld', {389 frameId: frame._id,390 grantUniveralAccess: true,391 worldName: UTILITY_WORLD_NAME392 });393 for (const binding of this._crPage._browserContext._pageBindings.values()) frame.evaluateExpression(binding.source, false, undefined).catch(e => {});394 for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources) frame.evaluateExpression(source, false, undefined, 'main').catch(e => {});395 }396 const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':';397 if (isInitialEmptyPage) {398 // Ignore lifecycle events for the initial empty page. It is never the final page399 // hence we are going to get more lifecycle updates after the actual navigation has400 // started (even if the target url is about:blank).401 lifecycleEventsEnabled.catch(e => {}).then(() => {402 this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));403 });404 } else {405 this._firstNonInitialNavigationCommittedFulfill();406 this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));407 }408 }), this._client.send('Log.enable', {}), lifecycleEventsEnabled = this._client.send('Page.setLifecycleEventsEnabled', {409 enabled: true410 }), this._client.send('Runtime.enable', {}), this._client.send('Page.addScriptToEvaluateOnNewDocument', {411 source: '',412 worldName: UTILITY_WORLD_NAME413 }), this._networkManager.initialize(), this._client.send('Target.setAutoAttach', {414 autoAttach: true,415 waitForDebuggerOnStart: true,416 flatten: true417 })];418 if (this._isMainFrame()) promises.push(this._client.send('Emulation.setFocusEmulationEnabled', {419 enabled: true420 }));421 const options = this._crPage._browserContext._options;422 if (options.bypassCSP) promises.push(this._client.send('Page.setBypassCSP', {423 enabled: true424 }));425 if (options.ignoreHTTPSErrors) promises.push(this._client.send('Security.setIgnoreCertificateErrors', {426 ignore: true427 }));428 if (this._isMainFrame()) promises.push(this._updateViewport());429 if (options.hasTouch) promises.push(this._client.send('Emulation.setTouchEmulationEnabled', {430 enabled: true431 }));432 if (options.javaScriptEnabled === false) promises.push(this._client.send('Emulation.setScriptExecutionDisabled', {433 value: true434 }));435 if (options.userAgent || options.locale) promises.push(this._client.send('Emulation.setUserAgentOverride', {436 userAgent: options.userAgent || '',437 acceptLanguage: options.locale438 }));439 if (options.locale) promises.push(emulateLocale(this._client, options.locale));440 if (options.timezoneId) promises.push(emulateTimezone(this._client, options.timezoneId));441 promises.push(this._updateGeolocation(true));442 promises.push(this._updateExtraHTTPHeaders(true));443 promises.push(this._updateRequestInterception());444 promises.push(this._updateOffline(true));445 promises.push(this._updateHttpCredentials(true));446 promises.push(this._updateEmulateMedia(true));447 for (const binding of this._crPage._page.allBindings()) promises.push(this._initBinding(binding));448 for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources) promises.push(this._evaluateOnNewDocument(source, 'main'));449 for (const source of this._crPage._page._evaluateOnNewDocumentSources) promises.push(this._evaluateOnNewDocument(source, 'main'));450 if (screencastOptions) promises.push(this._startVideoRecording(screencastOptions));451 promises.push(this._client.send('Runtime.runIfWaitingForDebugger'));452 promises.push(this._firstNonInitialNavigationCommittedPromise);453 await Promise.all(promises);454 }455 dispose() {456 _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);457 this._networkManager.dispose();458 this._crPage._sessions.delete(this._targetId);459 }460 async _navigate(frame, url, referrer) {461 const response = await this._client.send('Page.navigate', {462 url,463 referrer,464 frameId: frame._id465 });466 if (response.errorText) throw new Error(`${response.errorText} at ${url}`);467 return {468 newDocumentId: response.loaderId469 };470 }471 _onLifecycleEvent(event) {472 if (this._eventBelongsToStaleFrame(event.frameId)) return;473 if (event.name === 'load') this._page._frameManager.frameLifecycleEvent(event.frameId, 'load');else if (event.name === 'DOMContentLoaded') this._page._frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded');474 }475 _onFrameStoppedLoading(frameId) {476 if (this._eventBelongsToStaleFrame(frameId)) return;477 this._page._frameManager.frameStoppedLoading(frameId);478 }479 _handleFrameTree(frameTree) {480 this._onFrameAttached(frameTree.frame.id, frameTree.frame.parentId || null);481 this._onFrameNavigated(frameTree.frame, true);482 if (!frameTree.childFrames) return;483 for (const child of frameTree.childFrames) this._handleFrameTree(child);484 }485 _eventBelongsToStaleFrame(frameId) {486 const frame = this._page._frameManager.frame(frameId); // Subtree may be already gone because some ancestor navigation destroyed the oopif.487 if (!frame) return true; // When frame goes remote, parent process may still send some events488 // related to the local frame before it sends frameDetached.489 // In this case, we already have a new session for this frame, so events490 // in the old session should be ignored.491 const session = this._crPage._sessionForFrame(frame);492 return session && session !== this && !session._swappedIn;493 }494 _onFrameAttached(frameId, parentFrameId) {495 const frameSession = this._crPage._sessions.get(frameId);496 if (frameSession && frameId !== this._targetId) {497 // This is a remote -> local frame transition.498 frameSession._swappedIn = true;499 const frame = this._page._frameManager.frame(frameId); // Frame or even a whole subtree may be already gone, because some ancestor did navigate.500 if (frame) this._page._frameManager.removeChildFramesRecursively(frame);501 return;502 }503 if (parentFrameId && !this._page._frameManager.frame(parentFrameId)) {504 // Parent frame may be gone already because some ancestor frame navigated and505 // destroyed the whole subtree of some oopif, while oopif's process is still sending us events.506 // Be careful to not confuse this with "main frame navigated cross-process" scenario507 // where parentFrameId is null.508 return;509 }510 this._page._frameManager.frameAttached(frameId, parentFrameId);511 }512 _onFrameNavigated(framePayload, initial) {513 if (this._eventBelongsToStaleFrame(framePayload.id)) return;514 this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url + (framePayload.urlFragment || ''), framePayload.name || '', framePayload.loaderId, initial);515 if (!initial) this._firstNonInitialNavigationCommittedFulfill();516 }517 _onFrameRequestedNavigation(payload) {518 if (this._eventBelongsToStaleFrame(payload.frameId)) return;519 if (payload.disposition === 'currentTab') this._page._frameManager.frameRequestedNavigation(payload.frameId);520 }521 _onFrameNavigatedWithinDocument(frameId, url) {522 if (this._eventBelongsToStaleFrame(frameId)) return;523 this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);524 }525 _onFrameDetached(frameId, reason) {526 if (this._crPage._sessions.has(frameId)) {527 // This is a local -> remote frame transtion, where528 // Page.frameDetached arrives after Target.attachedToTarget.529 // We've already handled the new target and frame reattach - nothing to do here.530 return;531 }532 if (reason === 'swap') {533 // This is a local -> remote frame transtion, where534 // Page.frameDetached arrives before Target.attachedToTarget.535 // We should keep the frame in the tree, and it will be used for the new target.536 const frame = this._page._frameManager.frame(frameId);537 if (frame) this._page._frameManager.removeChildFramesRecursively(frame);538 return;539 } // Just a regular frame detach.540 this._page._frameManager.frameDetached(frameId);541 }542 _onExecutionContextCreated(contextPayload) {543 const frame = contextPayload.auxData ? this._page._frameManager.frame(contextPayload.auxData.frameId) : null;544 if (!frame || this._eventBelongsToStaleFrame(frame._id)) return;545 const delegate = new _crExecutionContext.CRExecutionContext(this._client, contextPayload);546 let worldName = null;547 if (contextPayload.auxData && !!contextPayload.auxData.isDefault) worldName = 'main';else if (contextPayload.name === UTILITY_WORLD_NAME) worldName = 'utility';548 const context = new dom.FrameExecutionContext(delegate, frame, worldName);549 context[contextDelegateSymbol] = delegate;550 if (worldName) frame._contextCreated(worldName, context);551 this._contextIdToContext.set(contextPayload.id, context);552 }553 _onExecutionContextDestroyed(executionContextId) {554 const context = this._contextIdToContext.get(executionContextId);555 if (!context) return;556 this._contextIdToContext.delete(executionContextId);557 context.frame._contextDestroyed(context);558 }559 _onExecutionContextsCleared() {560 for (const contextId of Array.from(this._contextIdToContext.keys())) this._onExecutionContextDestroyed(contextId);561 }562 _onAttachedToTarget(event) {563 const session = _crConnection.CRConnection.fromSession(this._client).session(event.sessionId);564 if (event.targetInfo.type === 'iframe') {565 // Frame id equals target id.566 const targetId = event.targetInfo.targetId;567 const frame = this._page._frameManager.frame(targetId);568 if (!frame) return; // Subtree may be already gone due to renderer/browser race.569 this._page._frameManager.removeChildFramesRecursively(frame);570 const frameSession = new FrameSession(this._crPage, session, targetId, this);571 this._crPage._sessions.set(targetId, frameSession);572 frameSession._initialize(false).catch(e => e);573 return;574 }575 if (event.targetInfo.type !== 'worker') {576 // Ideally, detaching should resume any target, but there is a bug in the backend.577 session._sendMayFail('Runtime.runIfWaitingForDebugger').then(() => {578 this._client._sendMayFail('Target.detachFromTarget', {579 sessionId: event.sessionId580 });581 });582 return;583 }584 const url = event.targetInfo.url;585 const worker = new _page.Worker(this._page, url);586 this._page._addWorker(event.sessionId, worker);587 session.once('Runtime.executionContextCreated', async event => {588 worker._createExecutionContext(new _crExecutionContext.CRExecutionContext(session, event.context));589 }); // This might fail if the target is closed before we initialize.590 session._sendMayFail('Runtime.enable');591 session._sendMayFail('Network.enable');592 session._sendMayFail('Runtime.runIfWaitingForDebugger');593 session.on('Runtime.consoleAPICalled', event => {594 const args = event.args.map(o => worker._existingExecutionContext.createHandle(o));595 this._page._addConsoleMessage(event.type, args, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));596 });597 session.on('Runtime.exceptionThrown', exception => this._page.emit(_page.Page.Events.PageError, (0, _crProtocolHelper.exceptionToError)(exception.exceptionDetails))); // TODO: attribute workers to the right frame.598 this._networkManager.instrumentNetworkEvents(session, this._page._frameManager.frame(this._targetId));599 }600 _onDetachedFromTarget(event) {601 // This might be a worker...602 this._page._removeWorker(event.sessionId); // ... or an oopif.603 const childFrameSession = this._crPage._sessions.get(event.targetId);604 if (!childFrameSession) return; // Usually, we get frameAttached in this session first and mark child as swappedIn.605 if (childFrameSession._swappedIn) {606 childFrameSession.dispose();607 return;608 } // However, sometimes we get detachedFromTarget before frameAttached.609 // In this case we don't know wheter this is a remote frame detach,610 // or just a remote -> local transition. In the latter case, frameAttached611 // is already inflight, so let's make a safe roundtrip to ensure it arrives.612 this._client.send('Page.enable').catch(e => null).then(() => {613 // Child was not swapped in - that means frameAttached did not happen and614 // this is remote detach rather than remote -> local swap.615 if (!childFrameSession._swappedIn) this._page._frameManager.frameDetached(event.targetId);616 childFrameSession.dispose();617 });618 }619 _onWindowOpen(event) {620 this._crPage._nextWindowOpenPopupFeatures.push(event.windowFeatures);621 }622 async _onConsoleAPI(event) {623 if (event.executionContextId === 0) {624 // DevTools protocol stores the last 1000 console messages. These625 // messages are always reported even for removed execution contexts. In626 // this case, they are marked with executionContextId = 0 and are627 // reported upon enabling Runtime agent.628 //629 // Ignore these messages since:630 // - there's no execution context we can use to operate with message631 // arguments632 // - these messages are reported before Playwright clients can subscribe633 // to the 'console'634 // page event.635 //636 // @see https://github.com/GoogleChrome/puppeteer/issues/3865637 return;638 }639 const context = this._contextIdToContext.get(event.executionContextId);640 if (!context) return;641 const values = event.args.map(arg => context.createHandle(arg));642 this._page._addConsoleMessage(event.type, values, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));643 }644 async _initBinding(binding) {645 await Promise.all([this._client.send('Runtime.addBinding', {646 name: binding.name647 }), this._client.send('Page.addScriptToEvaluateOnNewDocument', {648 source: binding.source649 })]);650 }651 async _onBindingCalled(event) {652 const pageOrError = await this._crPage.pageOrError();653 if (!(pageOrError instanceof Error)) {654 const context = this._contextIdToContext.get(event.executionContextId);655 if (context) await this._page._onBindingCalled(event.payload, context);656 }657 }658 _onDialog(event) {659 if (!this._page._frameManager.frame(this._targetId)) return; // Our frame/subtree may be gone already.660 this._page.emit(_page.Page.Events.Dialog, new dialog.Dialog(this._page, event.type, event.message, async (accept, promptText) => {661 await this._client.send('Page.handleJavaScriptDialog', {662 accept,663 promptText664 });665 }, event.defaultPrompt));666 }667 _handleException(exceptionDetails) {668 this._page.firePageError((0, _crProtocolHelper.exceptionToError)(exceptionDetails));669 }670 async _onTargetCrashed() {671 this._client._markAsCrashed();672 this._page._didCrash();673 }674 _onLogEntryAdded(event) {675 const {676 level,677 text,678 args,679 source,680 url,681 lineNumber682 } = event.entry;683 if (args) args.map(arg => (0, _crProtocolHelper.releaseObject)(this._client, arg.objectId));684 if (source !== 'worker') {685 const location = {686 url: url || '',687 lineNumber: lineNumber || 0,688 columnNumber: 0689 };690 this._page._addConsoleMessage(level, [], location, text);691 }692 }693 async _onFileChooserOpened(event) {694 const frame = this._page._frameManager.frame(event.frameId);695 if (!frame) return;696 let handle;697 try {698 const utilityContext = await frame._utilityContext();699 handle = await this._adoptBackendNodeId(event.backendNodeId, utilityContext);700 } catch (e) {701 // During async processing, frame/context may go away. We should not throw.702 return;703 }704 await this._page._onFileChooserOpened(handle);705 }706 _willBeginDownload() {707 const originPage = this._crPage._initializedPage;708 if (!originPage) {709 // Resume the page creation with an error. The page will automatically close right710 // after the download begins.711 this._firstNonInitialNavigationCommittedReject(new Error('Starting new page download'));712 }713 }714 _onScreencastFrame(payload) {715 this._page.throttleScreencastFrameAck(() => {716 this._client.send('Page.screencastFrameAck', {717 sessionId: payload.sessionId718 }).catch(() => {});719 });720 const buffer = Buffer.from(payload.data, 'base64');721 this._page.emit(_page.Page.Events.ScreencastFrame, {722 buffer,723 timestamp: payload.metadata.timestamp,724 width: payload.metadata.deviceWidth,725 height: payload.metadata.deviceHeight726 });727 }728 async _createVideoRecorder(screencastId, options) {729 (0, _utils.assert)(!this._screencastId);730 const ffmpegPath = _registry.registry.findExecutable('ffmpeg').executablePathOrDie(this._page._browserContext._browser.options.sdkLanguage);731 this._videoRecorder = await _videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);732 this._screencastId = screencastId;733 }734 async _startVideoRecording(options) {735 const screencastId = this._screencastId;736 (0, _utils.assert)(screencastId);737 this._page.once(_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {}));738 const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));739 await this._startScreencast(this._videoRecorder, {740 format: 'jpeg',741 quality: 90,742 maxWidth: options.width,...
video-recorder-test.js
Source: video-recorder-test.js
1const { expect } = require('chai');2const { noop } = require('lodash');3const TestRun = require('../../lib/test-run/index');4const VideoRecorder = require('../../lib/video-recorder/recorder');5const Videos = require('../../lib/video-recorder/videos');6const TestRunVideoRecorder = require('../../lib/video-recorder/test-run-video-recorder');7const AsyncEmitter = require('../../lib/utils/async-event-emitter');8const WarningLog = require('../../lib/notifications/warning-log');9const COMMAND_TYPE = require('../../lib/test-run/commands/type');10const renderTemplate = require('../../lib/utils/render-template');11const VIDEOS_BASE_PATH = '__videos__';12class VideoRecorderProcessMock {13 constructor () {14 }15 init () {16 }17 startCapturing () {18 }19 finishCapturing () {20 }21}22class TestRunVideoRecorderMock extends TestRunVideoRecorder {23 constructor (testRunInfo, recordingOptions, warningLog, testLog) {24 super(testRunInfo, recordingOptions, warningLog);25 this.log = testLog;26 }27 _generateTempNames () {28 const result = super._generateTempNames();29 this.log.push('generate-names');30 return result;31 }32 _createVideoRecorderProcess () {33 return new VideoRecorderProcessMock();34 }35}36class VideoRecorderMock extends VideoRecorder {37 constructor (basePath, ffmpegPath, connection, customOptions) {38 super(basePath, ffmpegPath, connection, customOptions);39 this.log = [];40 this.warningLog = {41 addWarning: (message, ...args) => {42 const msg = renderTemplate(message, ...args);43 this.log.push(msg);44 }45 };46 }47 _createTestRunVideoRecorder (testRunInfo, recordingOptions) {48 return new TestRunVideoRecorderMock(testRunInfo, recordingOptions, this.warningLog, this.log);49 }50 _onBrowserJobStart () {51 this.log.push('job-start');52 return super._onBrowserJobStart()53 .then(() => {54 this.log.push('temp-dir-initialized');55 });56 }57 _onTestRunCreate (options) {58 this.log.push('test-created');59 return super._onTestRunCreate(options);60 }61 _getTargetVideoPath (testRunRecorder) {62 return `path-${testRunRecorder.testRun.id}`;63 }64 _saveFiles () {65 }66}67class VideosMock extends Videos {68 constructor (browserJobs, options, warningLog, timeStamp) {69 super(browserJobs, options, warningLog, timeStamp);70 }71 _createVideoRecorder (browserJob, videoPath, options, videoEncodingOptions, warningLog) {72 return new VideoRecorderMock(browserJob, videoPath, options, videoEncodingOptions, warningLog);73 }74}75function createTestRunMock (warningLog) {76 const testRun = Object.create(TestRun.prototype);77 Object.assign(testRun, {78 test: { name: 'Test', id: 'test-id' },79 debugLog: { command: noop },80 _enqueueCommand: noop,81 browserManipulationQueue: [],82 warningLog: warningLog,83 opts: { videoPath: 'path' },84 browserConnection: {85 id: 'connectionId',86 provider: {87 hasCustomActionForBrowser: () => {88 return {89 hasGetVideoFrameData: true90 };91 }92 },93 }94 });95 return {96 testRun,97 index: 098 };99}100describe('Video Recorder', () => {101 it('Should not start video recording for legacy tests', () => {102 const browserJobMock = new AsyncEmitter();103 const videoRecorder = new VideoRecorder(browserJobMock, VIDEOS_BASE_PATH, {}, {});104 const testRunCreateEventDataMock = {105 testRun: {},106 legacy: true,107 index: 1,108 test: {},109 quarantine: null110 };111 return browserJobMock112 .emit('start')113 .then(() => browserJobMock.emit('test-run-created', testRunCreateEventDataMock))114 .then(() => {115 expect(videoRecorder.testRunVideoRecorders).to.be.empty;116 });117 });118 it('Should correctly format the warning message about no suitable path pattern placeholders', () => {119 const browserJobMock = new AsyncEmitter();120 const warningLog = new WarningLog();121 const videoRecorder = new VideoRecorder(browserJobMock, VIDEOS_BASE_PATH, {}, {}, warningLog);122 videoRecorder._addProblematicPlaceholdersWarning(['${TEST_INDEX}']);123 expect(warningLog.messages).eql([124 'The "${TEST_INDEX}" path pattern placeholder cannot be applied to the recorded video.' +125 '\n\n' +126 'The placeholder was replaced with an empty string.'127 ]);128 warningLog.messages = [];129 videoRecorder._addProblematicPlaceholdersWarning(['${TEST_INDEX}', '${FIXTURE}']);130 expect(warningLog.messages).eql([131 'The "${TEST_INDEX}", "${FIXTURE}" path pattern placeholders cannot be applied to the recorded video.' +132 '\n\n' +133 'The placeholders were replaced with an empty string.'134 ]);135 });136 it('Should wait for Temp directory is initialized', () => {137 const browserJobMock = new AsyncEmitter();138 const warningLog = new WarningLog();139 const videoRecorder = new VideoRecorderMock(browserJobMock, VIDEOS_BASE_PATH, {}, {}, warningLog);140 browserJobMock.emit('start');141 const testRunCreatePromise = browserJobMock.emit('test-run-create', createTestRunMock());142 browserJobMock.emit('done');143 return testRunCreatePromise.then(() => {144 expect(videoRecorder.log).eql([145 'job-start',146 'test-created',147 'temp-dir-initialized',148 'generate-names'149 ]);150 });151 });152 it('Should emit a warning on resize action', () => {153 const browserJobMock = new AsyncEmitter();154 const videoRecorder = new VideoRecorderMock(browserJobMock, VIDEOS_BASE_PATH, {}, {});155 const testRunMock = createTestRunMock(videoRecorder.warningLog);156 return browserJobMock.emit('start')157 .then(() => browserJobMock.emit('test-run-create', testRunMock))158 .then(() => browserJobMock.emit('test-run-before-done', testRunMock))159 .then(() => {160 return testRunMock.testRun.executeCommand({ type: COMMAND_TYPE.resizeWindow });161 })162 .then(() => {163 expect(videoRecorder.log.includes('The browser window was resized during the "Test" test while TestCafe recorded a video. TestCafe cannot adjust the video resolution during recording. As a result, the video content may appear broken. Do not resize the browser window when TestCafe records a video.')).to.be.true;164 });165 });166 it('Should build correct video info object', () => {167 const browserJobMock = new AsyncEmitter();168 const videos1 = new VideosMock([browserJobMock], { videoPath: VIDEOS_BASE_PATH, videoOptions: { singleFile: true } });169 const videos2 = new VideosMock([browserJobMock], { videoPath: VIDEOS_BASE_PATH, videoOptions: { singleFile: false } });170 const testRunMock1 = createTestRunMock();171 const testRunMock2 = createTestRunMock();172 const testRunMock3 = createTestRunMock();173 const testRunMock4 = createTestRunMock();174 const test1 = { name: 'Test1', id: 'test-1' };175 const test2 = { name: 'Test2', id: 'test-2' };176 Object.assign(testRunMock1.testRun, { session: { id: 'test-run-1' }, test: test1 });177 Object.assign(testRunMock2.testRun, { session: { id: 'test-run-2' }, test: test1 });178 Object.assign(testRunMock3.testRun, { session: { id: 'test-run-3' }, test: test2 });179 Object.assign(testRunMock4.testRun, { session: { id: 'test-run-4' }, test: test2 });180 testRunMock1.index = 0;181 testRunMock2.index = 1;182 testRunMock3.index = 2;183 testRunMock4.index = 3;184 const expectedLog1 = {185 testVideoInfos: {186 'test-1': {187 recordings: [{188 testRunId: 'test-run-1',189 videoPath: 'path-test-run-1',190 singleFile: true191 }, {192 testRunId: 'test-run-2',193 videoPath: 'path-test-run-2',194 singleFile: true195 }]196 },197 'test-2': {198 recordings: [{199 testRunId: 'test-run-3',200 videoPath: 'path-test-run-3',201 singleFile: true202 }, {203 testRunId: 'test-run-4',204 videoPath: 'path-test-run-4',205 singleFile: true206 }]207 }208 }209 };210 const expectedLog2 = {211 testVideoInfos: {212 'test-1': {213 recordings: [{214 testRunId: 'test-run-1',215 videoPath: 'path-test-run-1',216 singleFile: false217 }, {218 testRunId: 'test-run-2',219 videoPath: 'path-test-run-2',220 singleFile: false221 }]222 },223 'test-2': {224 recordings: [{225 testRunId: 'test-run-3',226 videoPath: 'path-test-run-3',227 singleFile: false228 }, {229 testRunId: 'test-run-4',230 videoPath: 'path-test-run-4',231 singleFile: false232 }]233 }234 }235 };236 return browserJobMock.emit('start')237 .then(() => browserJobMock.emit('test-run-create', testRunMock1))238 .then(() => browserJobMock.emit('test-run-before-done', testRunMock1))239 .then(() => browserJobMock.emit('test-run-create', testRunMock2))240 .then(() => browserJobMock.emit('test-run-before-done', testRunMock2))241 .then(() => browserJobMock.emit('test-run-create', testRunMock3))242 .then(() => browserJobMock.emit('test-run-before-done', testRunMock3))243 .then(() => browserJobMock.emit('test-run-create', testRunMock4))244 .then(() => browserJobMock.emit('test-run-before-done', testRunMock4))245 .then(() => {246 expect(videos1).eql(expectedLog1);247 expect(videos2).eql(expectedLog2);248 });249 });...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const recorder = await page._createVideoRecorder();7 await recorder.stopAndSave('video.mp4');8 await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const context = await browser.newContext();14 const page = await context.newPage();15 const recorder = await page._createVideoRecorder();16 await recorder.stopAndSave('video.mp4');17 await browser.close();18})();19const { chromium } = require('playwright');20(async () => {21 const browser = await chromium.launch();22 const context = await browser.newContext();23 const page = await context.newPage();24 const recorder = await page._createVideoRecorder();25 await recorder.stopAndSave('video.mp4');26 await browser.close();27})();28const { chromium } = require('playwright');29(async () => {30 const browser = await chromium.launch();31 const context = await browser.newContext();32 const page = await context.newPage();33 const recorder = await page._createVideoRecorder();34 await recorder.stopAndSave('video.mp4');35 await browser.close();36})();37const { chromium } = require('playwright');38(async () => {39 const browser = await chromium.launch();40 const context = await browser.newContext();41 const page = await context.newPage();42 const recorder = await page._createVideoRecorder();43 await recorder.stopAndSave('video.mp4');44 await browser.close();45})();
Using AI Code Generation
1const playwright = require('playwright');2const path = require('path');3(async () => {4 const browser = await playwright.chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const video = await page._createVideoRecorder(path.join(__dirname, 'video', 'video.mp4'));8 await video.stop();9 await browser.close();10})();
Using AI Code Generation
1const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');2const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');3const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');4const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');5const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');6const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');7const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');8const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');9const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');10const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');11const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');12const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');13const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');14const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');15const { _createVideoRecorder } = require('playwright/lib/server/video/recorder');16const {
Using AI Code Generation
1const video = await page._createVideoRecorder("video.mp4");2await video.start();3await video.stop();4const video = await page._createVideoRecorder("video.mp4");5await video.start();6await video.stop();7const video = await page._createVideoRecorder("video.mp4");8await video.start();9await video.stop();10const video = await page._createVideoRecorder("video.mp4");11await video.start();12await video.stop();13const video = await page._createVideoRecorder("video.mp4");14await video.start();15await video.stop();16const video = await page._createVideoRecorder("video.mp4");17await video.start();18await video.stop();19const video = await page._createVideoRecorder("video.mp4");20await video.start();21await video.stop();22const video = await page._createVideoRecorder("video.mp4");23await video.start();24await video.stop();25const video = await page._createVideoRecorder("video.mp4");26await video.start();27await video.stop();28const video = await page._createVideoRecorder("video.mp4");29await video.start();
Using AI Code Generation
1const { _createVideoRecorder } = require('@playwright/test/lib/video');2async function main() {3 const videoRecorder = await _createVideoRecorder();4 await videoRecorder.start({ name: 'test', outputDir: '.' });5 await videoRecorder.stop();6}7main();8 at Process.ChildProcess._handle.onexit (internal/child_process.js:269:19)9 at onErrorNT (internal/child_process.js:465:16)10 at processTicksAndRejections (internal/process/task_queues.js:81:21)11Version 89.0.4389.90 (Official Build) (64-bit)
Using AI Code Generation
1const videoRecorder = await this._createVideoRecorder();2await videoRecorder.start();3await videoRecorder.stop();4const videoRecorder = await this._createVideoRecorder();5await videoRecorder.start();6await videoRecorder.stop();7const videoRecorder = await this._createVideoRecorder();8await videoRecorder.start();9await videoRecorder.stop();10const videoRecorder = await this._createVideoRecorder();11await videoRecorder.start();12await videoRecorder.stop();13const videoRecorder = await this._createVideoRecorder();14await videoRecorder.start();15await videoRecorder.stop();16const videoRecorder = await this._createVideoRecorder();17await videoRecorder.start();18await videoRecorder.stop();19const videoRecorder = await this._createVideoRecorder();20await videoRecorder.start();21await videoRecorder.stop();22const videoRecorder = await this._createVideoRecorder();23await videoRecorder.start();24await videoRecorder.stop();25const videoRecorder = await this._createVideoRecorder();26await videoRecorder.start();27await videoRecorder.stop();28const videoRecorder = await this._createVideoRecorder();29await videoRecorder.start();30await videoRecorder.stop();31const videoRecorder = await this._createVideoRecorder();32await videoRecorder.start();33await videoRecorder.stop();34const videoRecorder = await this._createVideoRecorder();35await videoRecorder.start();36await videoRecorder.stop();
Using AI Code Generation
1const { _createVideoRecorder } = require('playwright/lib/server/recorder/recorderApp');2const videoRecorder = _createVideoRecorder();3await videoRecorder.startVideoRecording('test-video');4await videoRecorder.stopVideoRecording();5await videoRecorder.close();6await videoRecorder.saveVideo('test-video.mp4');7const { _createVideoRecorder } = require('playwright/lib/server/recorder/recorderApp');8const videoRecorder = _createVideoRecorder();9await videoRecorder.startVideoRecording('test-video', {10 size: {11 }12});13await videoRecorder.stopVideoRecording();14await videoRecorder.close();15await videoRecorder.saveVideo('test-video.mp4');16Option Description fps Frames per second (default 30) size Object with width and height (default { width: 1280, height: 720 }) bitrate Video bitrate in bits per second (default 4Mbps) crf Constant rate factor (default 17)17const { _createVideoRecorder } = require('playwright/lib/server/recorder/recorderApp');18const videoRecorder = _createVideoRecorder();19await videoRecorder.startVideoRecording('test-video');20await videoRecorder.stopVideoRecording();21await videoRecorder.close();22await videoRecorder.saveVideo('test-video.mp4');
Using AI Code Generation
1const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });2await video.stop();3const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });4await video.stop();5const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });6await video.stop();7const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });8await video.stop();9const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });10await video.stop();11const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });12await video.stop();13const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });14await video.stop();15const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });16await video.stop();17const video = await page._createVideoRecorder({ dir: '/tmp/videos/' });18await video.stop();
Using AI Code Generation
1const playwright = require("playwright");2const { _createVideoRecorder } = require("playwright/lib/utils/video");3(async () => {4 const browser = await playwright.chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const recorder = _createVideoRecorder(page, {8 });9 await recorder.start();10 await page.screenshot({ path: "google.png" });11 await page.screenshot({ path: "bing.png" });12 await recorder.stop();13 await browser.close();14})();15const playwright = require("playwright");16const { _createVideoRecorder } = require("playwright/lib/utils/video");17(async () => {18 const browser = await playwright.chromium.launch();19await videoRecorder.stopVideoRecording();20await videoRecorder.close();21await videoRecorder.saveVideo('test-video.mp4');22const { _createVideoRecorder } = require('playwright/lib/server/recorder/recorderApp');23const videoRecorder = _createVideoRecorder();24await videoRecorder.startVideoRecording('test-video', {25 size: {26 }27});28await videoRecorder.stopVideoRecording();29await videoRecorder.close();30await videoRecorder.saveVideo('test-video.mp4');31Option Description fps Frames per second (default 30) size Object with width and height (default { width: 1280, height: 720 }) bitrate Video bitrate in bits per second (default 4Mbps) crf Constant rate factor (default 17)
Using AI Code Generation
1const playwright = require("playwright");2const { _createVideoRecorder } = require("playwright/lib/utils/video");3(async () => {4 const browser = await playwright.chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const recorder = _createVideoRecorder(page, {8 });9 await recorder.start();10 await page.screenshot({ path: "google.png" });11 await page.screenshot({ path: "bing.png" });12 await recorder.stop();13 await browser.close();14})();15const playwright = require("playwright");16const { _createVideoRecorder } = require("playwright/lib/utils/video");17(async () => {18 const browser = await playwright.chromium.launch();19const { _createVideoRecorder } = require('playwright/lib/server/recorder/recorderApp');20const videoRecorder = _createVideoRecorder();21await videoRecorder.startVideoRecording('test-video');22await videoRecorder.stopVideoRecording();23await videoRecorder.close();24await videoRecorder.saveVideo('test-video.mp4');
Using AI Code Generation
1const playwright = require("playwright");2const { _createVideoRecorder } = require("playwright/lib/utils/video");3(async () => {4 const browser = await playwright.chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 const recorder = _createVideoRecorder(page, {8 });9 await recorder.start();10 await page.screenshot({ path: "google.png" });11 await page.screenshot({ path: "bing.png" });12 await recorder.stop();13 await browser.close();14})();15const playwright = require("playwright");16const { _createVideoRecorder } = require("playwright/lib/utils/video");17(async () => {18 const browser = await playwright.chromium.launch();
Jest + Playwright - Test callbacks of event-based DOM library
firefox browser does not start in playwright
Is it possible to get the selector from a locator object in playwright?
How to run a list of test suites in a single file concurrently in jest?
Running Playwright in Azure Function
firefox browser does not start in playwright
This question is quite close to a "need more focus" question. But let's try to give it some focus:
Does Playwright has access to the cPicker object on the page? Does it has access to the window object?
Yes, you can access both cPicker and the window object inside an evaluate call.
Should I trigger the events from the HTML file itself, and in the callbacks, print in the DOM the result, in some dummy-element, and then infer from that dummy element text that the callbacks fired?
Exactly, or you can assign values to a javascript variable:
const cPicker = new ColorPicker({
onClickOutside(e){
},
onInput(color){
window['color'] = color;
},
onChange(color){
window['result'] = color;
}
})
And then
it('Should call all callbacks with correct arguments', async() => {
await page.goto(`http://localhost:5000/tests/visual/basic.html`, {waitUntil:'load'})
// Wait until the next frame
await page.evaluate(() => new Promise(requestAnimationFrame))
// Act
// Assert
const result = await page.evaluate(() => window['color']);
// Check the value
})
Check out the latest blogs from LambdaTest on this topic:
Native apps are developed specifically for one platform. Hence they are fast and deliver superior performance. They can be downloaded from various app stores and are not accessible through browsers.
One of the essential parts when performing automated UI testing, whether using Selenium or another framework, is identifying the correct web elements the tests will interact with. However, if the web elements are not located correctly, you might get NoSuchElementException in Selenium. This would cause a false negative result because we won’t get to the actual functionality check. Instead, our test will fail simply because it failed to interact with the correct element.
Smartphones have changed the way humans interact with technology. Be it travel, fitness, lifestyle, video games, or even services, it’s all just a few touches away (quite literally so). We only need to look at the growing throngs of smartphone or tablet users vs. desktop users to grasp this reality.
As part of one of my consulting efforts, I worked with a mid-sized company that was looking to move toward a more agile manner of developing software. As with any shift in work style, there is some bewilderment and, for some, considerable anxiety. People are being challenged to leave their comfort zones and embrace a continuously changing, dynamic working environment. And, dare I say it, testing may be the most ‘disturbed’ of the software roles in agile development.
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!