Best JavaScript code snippet using playwright-internal
workerRunner.js
Source:workerRunner.js
1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.WorkerRunner = void 0;6var _fs = _interopRequireDefault(require("fs"));7var _path = _interopRequireDefault(require("path"));8var _rimraf = _interopRequireDefault(require("rimraf"));9var _util = _interopRequireDefault(require("util"));10var _events = require("events");11var _util2 = require("./util");12var _globals = require("./globals");13var _loader = require("./loader");14var _test = require("./test");15var _fixtures = require("./fixtures");16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }17/**18 * Copyright Microsoft Corporation. All rights reserved.19 *20 * Licensed under the Apache License, Version 2.0 (the "License");21 * you may not use this file except in compliance with the License.22 * You may obtain a copy of the License at23 *24 * http://www.apache.org/licenses/LICENSE-2.025 *26 * Unless required by applicable law or agreed to in writing, software27 * distributed under the License is distributed on an "AS IS" BASIS,28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.29 * See the License for the specific language governing permissions and30 * limitations under the License.31 */32const removeFolderAsync = _util.default.promisify(_rimraf.default);33class WorkerRunner extends _events.EventEmitter {34 constructor(params) {35 super();36 this._params = void 0;37 this._loader = void 0;38 this._project = void 0;39 this._workerInfo = void 0;40 this._projectNamePathSegment = '';41 this._uniqueProjectNamePathSegment = '';42 this._fixtureRunner = void 0;43 this._failedTestId = void 0;44 this._fatalError = void 0;45 this._entries = new Map();46 this._isStopped = false;47 this._runFinished = Promise.resolve();48 this._currentDeadlineRunner = void 0;49 this._currentTest = null;50 this._params = params;51 this._fixtureRunner = new _fixtures.FixtureRunner();52 }53 stop() {54 if (!this._isStopped) {55 var _this$_currentDeadlin;56 this._isStopped = true; // Interrupt current action.57 (_this$_currentDeadlin = this._currentDeadlineRunner) === null || _this$_currentDeadlin === void 0 ? void 0 : _this$_currentDeadlin.setDeadline(0); // TODO: mark test as 'interrupted' instead.58 if (this._currentTest && this._currentTest.testInfo.status === 'passed') this._currentTest.testInfo.status = 'skipped';59 }60 return this._runFinished;61 }62 async cleanup() {63 // We have to load the project to get the right deadline below.64 await this._loadIfNeeded(); // TODO: separate timeout for teardown?65 const result = await (0, _util2.raceAgainstDeadline)((async () => {66 await this._fixtureRunner.teardownScope('test');67 await this._fixtureRunner.teardownScope('worker');68 })(), this._deadline());69 if (result.timedOut) throw new Error(`Timeout of ${this._project.config.timeout}ms exceeded while shutting down environment`);70 }71 unhandledError(error) {72 if (this._currentTest && this._currentTest.type === 'test') {73 if (!this._currentTest.testInfo.error) {74 this._currentTest.testInfo.status = 'failed';75 this._currentTest.testInfo.error = (0, _util2.serializeError)(error);76 }77 } else {78 // No current test - fatal error.79 if (!this._fatalError) this._fatalError = (0, _util2.serializeError)(error);80 }81 this.stop();82 }83 _deadline() {84 return this._project.config.timeout ? (0, _util2.monotonicTime)() + this._project.config.timeout : undefined;85 }86 async _loadIfNeeded() {87 if (this._loader) return;88 this._loader = await _loader.Loader.deserialize(this._params.loader);89 this._project = this._loader.projects()[this._params.projectIndex];90 this._projectNamePathSegment = (0, _util2.sanitizeForFilePath)(this._project.config.name);91 const sameName = this._loader.projects().filter(project => project.config.name === this._project.config.name);92 if (sameName.length > 1) this._uniqueProjectNamePathSegment = this._project.config.name + (sameName.indexOf(this._project) + 1);else this._uniqueProjectNamePathSegment = this._project.config.name;93 this._uniqueProjectNamePathSegment = (0, _util2.sanitizeForFilePath)(this._uniqueProjectNamePathSegment);94 this._workerInfo = {95 workerIndex: this._params.workerIndex,96 project: this._project.config,97 config: this._loader.fullConfig()98 };99 }100 async run(runPayload) {101 let runFinishedCalback = () => {};102 this._runFinished = new Promise(f => runFinishedCalback = f);103 try {104 this._entries = new Map(runPayload.entries.map(e => [e.testId, e]));105 await this._loadIfNeeded();106 const fileSuite = await this._loader.loadTestFile(runPayload.file);107 let anyPool;108 const suite = this._project.cloneFileSuite(fileSuite, this._params.repeatEachIndex, test => {109 if (!this._entries.has(test._id)) return false;110 anyPool = test._pool;111 return true;112 });113 if (suite && anyPool) {114 this._fixtureRunner.setPool(anyPool);115 await this._runSuite(suite, []);116 }117 } catch (e) {118 // In theory, we should run above code without any errors.119 // However, in the case we screwed up, or loadTestFile failed in the worker120 // but not in the runner, let's do a fatal error.121 this.unhandledError(e);122 } finally {123 this._reportDone();124 runFinishedCalback();125 }126 }127 async _runSuite(suite, annotations) {128 // When stopped, do not run a suite. But if we have started running the suite with hooks,129 // always finish the hooks.130 if (this._isStopped) return;131 annotations = annotations.concat(suite._annotations);132 for (const beforeAllModifier of suite._modifiers) {133 if (!this._fixtureRunner.dependsOnWorkerFixturesOnly(beforeAllModifier.fn, beforeAllModifier.location)) continue; // TODO: separate timeout for beforeAll modifiers?134 const result = await (0, _util2.raceAgainstDeadline)(this._fixtureRunner.resolveParametersAndRunHookOrTest(beforeAllModifier.fn, this._workerInfo, undefined), this._deadline());135 if (result.timedOut) {136 this._fatalError = (0, _util2.serializeError)(new Error(`Timeout of ${this._project.config.timeout}ms exceeded while running ${beforeAllModifier.type} modifier`));137 this.stop();138 }139 if (!!result.result) annotations.push({140 type: beforeAllModifier.type,141 description: beforeAllModifier.description142 });143 }144 for (const hook of suite._allHooks) {145 var _this$_entries$get;146 if (hook._type !== 'beforeAll') continue;147 const firstTest = suite.allTests()[0];148 await this._runTestOrAllHook(hook, annotations, ((_this$_entries$get = this._entries.get(firstTest._id)) === null || _this$_entries$get === void 0 ? void 0 : _this$_entries$get.retry) || 0);149 }150 for (const entry of suite._entries) {151 if (entry instanceof _test.Suite) {152 await this._runSuite(entry, annotations);153 } else {154 const runEntry = this._entries.get(entry._id);155 if (runEntry && !this._isStopped) await this._runTestOrAllHook(entry, annotations, runEntry.retry);156 }157 }158 for (const hook of suite._allHooks) {159 if (hook._type !== 'afterAll') continue;160 await this._runTestOrAllHook(hook, annotations, 0);161 }162 }163 async _runTestOrAllHook(test, annotations, retry) {164 const reportEvents = test._type === 'test';165 const startTime = (0, _util2.monotonicTime)();166 const startWallTime = Date.now();167 let deadlineRunner;168 const testId = test._id;169 const baseOutputDir = (() => {170 const relativeTestFilePath = _path.default.relative(this._project.config.testDir, test._requireFile.replace(/\.(spec|test)\.(js|ts|mjs)$/, ''));171 const sanitizedRelativePath = relativeTestFilePath.replace(process.platform === 'win32' ? new RegExp('\\\\', 'g') : new RegExp('/', 'g'), '-');172 let testOutputDir = sanitizedRelativePath + '-' + (0, _util2.sanitizeForFilePath)(test.title);173 if (this._uniqueProjectNamePathSegment) testOutputDir += '-' + this._uniqueProjectNamePathSegment;174 if (retry) testOutputDir += '-retry' + retry;175 if (this._params.repeatEachIndex) testOutputDir += '-repeat' + this._params.repeatEachIndex;176 return _path.default.join(this._project.config.outputDir, testOutputDir);177 })();178 let testFinishedCallback = () => {};179 let lastStepId = 0;180 const testInfo = {181 workerIndex: this._params.workerIndex,182 project: this._project.config,183 config: this._loader.fullConfig(),184 title: test.title,185 file: test.location.file,186 line: test.location.line,187 column: test.location.column,188 fn: test.fn,189 repeatEachIndex: this._params.repeatEachIndex,190 retry,191 expectedStatus: test.expectedStatus,192 annotations: [],193 attachments: [],194 duration: 0,195 status: 'passed',196 stdout: [],197 stderr: [],198 timeout: this._project.config.timeout,199 snapshotSuffix: '',200 outputDir: baseOutputDir,201 outputPath: (...pathSegments) => {202 _fs.default.mkdirSync(baseOutputDir, {203 recursive: true204 });205 return _path.default.join(baseOutputDir, ...pathSegments);206 },207 snapshotPath: snapshotName => {208 let suffix = '';209 if (this._projectNamePathSegment) suffix += '-' + this._projectNamePathSegment;210 if (testInfo.snapshotSuffix) suffix += '-' + testInfo.snapshotSuffix;211 const ext = _path.default.extname(snapshotName);212 if (ext) snapshotName = (0, _util2.sanitizeForFilePath)(snapshotName.substring(0, snapshotName.length - ext.length)) + suffix + ext;else snapshotName = (0, _util2.sanitizeForFilePath)(snapshotName) + suffix;213 return _path.default.join(test._requireFile + '-snapshots', snapshotName);214 },215 skip: (...args) => modifier(testInfo, 'skip', args),216 fixme: (...args) => modifier(testInfo, 'fixme', args),217 fail: (...args) => modifier(testInfo, 'fail', args),218 slow: (...args) => modifier(testInfo, 'slow', args),219 setTimeout: timeout => {220 testInfo.timeout = timeout;221 if (deadlineRunner) deadlineRunner.setDeadline(deadline());222 },223 _testFinished: new Promise(f => testFinishedCallback = f),224 _addStep: (category, title) => {225 const stepId = `${category}@${title}@${++lastStepId}`;226 const payload = {227 testId,228 stepId,229 category,230 title,231 wallTime: Date.now()232 };233 if (reportEvents) this.emit('stepBegin', payload);234 let callbackHandled = false;235 return error => {236 if (callbackHandled) return;237 callbackHandled = true;238 if (error instanceof Error) error = (0, _util2.serializeError)(error);239 const payload = {240 testId,241 stepId,242 wallTime: Date.now(),243 error244 };245 if (reportEvents) this.emit('stepEnd', payload);246 };247 }248 }; // Inherit test.setTimeout() from parent suites.249 for (let suite = test.parent; suite; suite = suite.parent) {250 if (suite._timeout !== undefined) {251 testInfo.setTimeout(suite._timeout);252 break;253 }254 } // Process annotations defined on parent suites.255 for (const annotation of annotations) {256 testInfo.annotations.push(annotation);257 switch (annotation.type) {258 case 'fixme':259 case 'skip':260 testInfo.expectedStatus = 'skipped';261 break;262 case 'fail':263 if (testInfo.expectedStatus !== 'skipped') testInfo.expectedStatus = 'failed';264 break;265 case 'slow':266 testInfo.setTimeout(testInfo.timeout * 3);267 break;268 }269 }270 this._currentTest = {271 testInfo,272 testId,273 type: test._type274 };275 (0, _globals.setCurrentTestInfo)(testInfo);276 const deadline = () => {277 return testInfo.timeout ? startTime + testInfo.timeout : undefined;278 };279 if (reportEvents) this.emit('testBegin', buildTestBeginPayload(testId, testInfo, startWallTime));280 if (testInfo.expectedStatus === 'skipped') {281 testInfo.status = 'skipped';282 if (reportEvents) this.emit('testEnd', buildTestEndPayload(testId, testInfo));283 return;284 } // Update the fixture pool - it may differ between tests, but only in test-scoped fixtures.285 this._fixtureRunner.setPool(test._pool);286 this._currentDeadlineRunner = deadlineRunner = new _util2.DeadlineRunner(this._runTestWithBeforeHooks(test, testInfo), deadline());287 const result = await deadlineRunner.result; // Do not overwrite test failure upon hook timeout.288 if (result.timedOut && testInfo.status === 'passed') testInfo.status = 'timedOut';289 testFinishedCallback();290 if (!result.timedOut) {291 this._currentDeadlineRunner = deadlineRunner = new _util2.DeadlineRunner(this._runAfterHooks(test, testInfo), deadline());292 deadlineRunner.setDeadline(deadline());293 const hooksResult = await deadlineRunner.result; // Do not overwrite test failure upon hook timeout.294 if (hooksResult.timedOut && testInfo.status === 'passed') testInfo.status = 'timedOut';295 } else {296 // A timed-out test gets a full additional timeout to run after hooks.297 const newDeadline = this._deadline();298 this._currentDeadlineRunner = deadlineRunner = new _util2.DeadlineRunner(this._runAfterHooks(test, testInfo), newDeadline);299 await deadlineRunner.result;300 }301 this._currentDeadlineRunner = undefined;302 testInfo.duration = (0, _util2.monotonicTime)() - startTime;303 if (reportEvents) this.emit('testEnd', buildTestEndPayload(testId, testInfo));304 const isFailure = testInfo.status === 'timedOut' || testInfo.status === 'failed' && testInfo.expectedStatus !== 'failed';305 const preserveOutput = this._loader.fullConfig().preserveOutput === 'always' || this._loader.fullConfig().preserveOutput === 'failures-only' && isFailure;306 if (!preserveOutput) await removeFolderAsync(testInfo.outputDir).catch(e => {});307 this._currentTest = null;308 (0, _globals.setCurrentTestInfo)(null);309 if (testInfo.status !== 'passed' && testInfo.status !== 'skipped') {310 if (test._type === 'test') this._failedTestId = testId;else this._fatalError = testInfo.error;311 this.stop();312 }313 }314 async _runBeforeHooks(test, testInfo) {315 try {316 const beforeEachModifiers = [];317 for (let s = test.parent; s; s = s.parent) {318 const modifiers = s._modifiers.filter(modifier => !this._fixtureRunner.dependsOnWorkerFixturesOnly(modifier.fn, modifier.location));319 beforeEachModifiers.push(...modifiers.reverse());320 }321 beforeEachModifiers.reverse();322 for (const modifier of beforeEachModifiers) {323 const result = await this._fixtureRunner.resolveParametersAndRunHookOrTest(modifier.fn, this._workerInfo, testInfo);324 testInfo[modifier.type](!!result, modifier.description);325 }326 await this._runHooks(test.parent, 'beforeEach', testInfo);327 } catch (error) {328 if (error instanceof SkipError) {329 if (testInfo.status === 'passed') testInfo.status = 'skipped';330 } else {331 testInfo.status = 'failed';332 testInfo.error = (0, _util2.serializeError)(error);333 } // Continue running afterEach hooks even after the failure.334 }335 }336 async _runTestWithBeforeHooks(test, testInfo) {337 const completeStep = testInfo._addStep('hook', 'Before Hooks');338 if (test._type === 'test') await this._runBeforeHooks(test, testInfo); // Do not run the test when beforeEach hook fails.339 if (testInfo.status === 'failed' || testInfo.status === 'skipped') {340 completeStep === null || completeStep === void 0 ? void 0 : completeStep(testInfo.error);341 return;342 }343 try {344 await this._fixtureRunner.resolveParametersAndRunHookOrTest(test.fn, this._workerInfo, testInfo, completeStep);345 } catch (error) {346 if (error instanceof SkipError) {347 if (testInfo.status === 'passed') testInfo.status = 'skipped';348 } else {349 // We might fail after the timeout, e.g. due to fixture teardown.350 // Do not overwrite the timeout status.351 if (testInfo.status === 'passed') testInfo.status = 'failed'; // Keep the error even in the case of timeout, if there was no error before.352 if (!('error' in testInfo)) testInfo.error = (0, _util2.serializeError)(error);353 }354 } finally {355 completeStep === null || completeStep === void 0 ? void 0 : completeStep(testInfo.error);356 }357 }358 async _runAfterHooks(test, testInfo) {359 var _completeStep;360 let completeStep;361 let teardownError;362 try {363 completeStep = testInfo._addStep('hook', 'After Hooks');364 if (test._type === 'test') await this._runHooks(test.parent, 'afterEach', testInfo);365 } catch (error) {366 if (!(error instanceof SkipError)) {367 if (testInfo.status === 'passed') testInfo.status = 'failed'; // Do not overwrite test failure error.368 if (!('error' in testInfo)) testInfo.error = (0, _util2.serializeError)(error); // Continue running even after the failure.369 }370 }371 try {372 await this._fixtureRunner.teardownScope('test');373 } catch (error) {374 if (testInfo.status === 'passed') testInfo.status = 'failed'; // Do not overwrite test failure error.375 if (!('error' in testInfo)) {376 testInfo.error = (0, _util2.serializeError)(error);377 teardownError = testInfo.error;378 }379 }380 (_completeStep = completeStep) === null || _completeStep === void 0 ? void 0 : _completeStep(teardownError);381 }382 async _runHooks(suite, type, testInfo) {383 const all = [];384 for (let s = suite; s; s = s.parent) {385 const funcs = s._eachHooks.filter(e => e.type === type).map(e => e.fn);386 all.push(...funcs.reverse());387 }388 if (type === 'beforeEach') all.reverse();389 let error;390 for (const hook of all) {391 try {392 await this._fixtureRunner.resolveParametersAndRunHookOrTest(hook, this._workerInfo, testInfo);393 } catch (e) {394 // Always run all the hooks, and capture the first error.395 error = error || e;396 }397 }398 if (error) throw error;399 }400 _reportDone() {401 const donePayload = {402 failedTestId: this._failedTestId,403 fatalError: this._fatalError404 };405 this.emit('done', donePayload);406 }407}408exports.WorkerRunner = WorkerRunner;409function buildTestBeginPayload(testId, testInfo, startWallTime) {410 return {411 testId,412 workerIndex: testInfo.workerIndex,413 startWallTime414 };415}416function buildTestEndPayload(testId, testInfo) {417 return {418 testId,419 duration: testInfo.duration,420 status: testInfo.status,421 error: testInfo.error,422 expectedStatus: testInfo.expectedStatus,423 annotations: testInfo.annotations,424 timeout: testInfo.timeout,425 attachments: testInfo.attachments.map(a => {426 var _a$body;427 return {428 name: a.name,429 contentType: a.contentType,430 path: a.path,431 body: (_a$body = a.body) === null || _a$body === void 0 ? void 0 : _a$body.toString('base64')432 };433 })434 };435}436function modifier(testInfo, type, modifierArgs) {437 if (typeof modifierArgs[1] === 'function') {438 throw new Error(['It looks like you are calling test.skip() inside the test and pass a callback.', 'Pass a condition instead and optional description instead:', `test('my test', async ({ page, isMobile }) => {`, ` test.skip(isMobile, 'This test is not applicable on mobile');`, `});`].join('\n'));439 }440 if (modifierArgs.length >= 1 && !modifierArgs[0]) return;441 const description = modifierArgs[1];442 testInfo.annotations.push({443 type,444 description445 });446 if (type === 'slow') {447 testInfo.setTimeout(testInfo.timeout * 3);448 } else if (type === 'skip' || type === 'fixme') {449 testInfo.expectedStatus = 'skipped';450 throw new SkipError('Test is skipped: ' + (description || ''));451 } else if (type === 'fail') {452 if (testInfo.expectedStatus !== 'skipped') testInfo.expectedStatus = 'failed';453 }454}...
globals.js
Source:globals.js
...21 * See the License for the specific language governing permissions and22 * limitations under the License.23 */24let currentTestInfoValue = null;25function setCurrentTestInfo(testInfo) {26 currentTestInfoValue = testInfo;27}28function currentTestInfo() {29 return currentTestInfoValue;30}31let currentFileSuite;32function setCurrentlyLoadingFileSuite(suite) {33 currentFileSuite = suite;34}35function currentlyLoadingFileSuite() {36 return currentFileSuite;...
Using AI Code Generation
1const { setCurrentTestInfo } = require('@playwright/test');2const test = require('@playwright/test').test;3test('test', async ({ page }) => {4 await setCurrentTestInfo({5 });6});7### `setCurrentTestInfo(options)`
Using AI Code Generation
1const playwright = require('playwright');2const { setCurrentTestInfo } = require('@playwright/test');3const test = require('@playwright/test').test;4test('simple test', async ({ page }) => {5 setCurrentTestInfo({6 });7});8test('simple test', async ({ page }) => {9 setCurrentTestInfo({10 });11});12test('simple test', async ({ page }) => {13 setCurrentTestInfo({14 });15});16const { test, expect } = require('@playwright/test');17test('simple test', async ({ page }) => {18 const title = page.locator('.navbar__inner .navbar__title');19 await expect(title).toHaveText('Playwright');20});21test('simple test', async ({ page }) => {22 const title = page.locator('.navbar__inner .navbar__title');23 await expect(title).toHaveText('Playwright');24});25test('simple test', async ({ page }) => {26 const title = page.locator('.navbar__inner .navbar__title');27 await expect(title).toHaveText('Playwright');28});29const { test, expect } = require('@playwright/test');30test('simple test', async ({ page }) => {31 const title = page.locator('.navbar__inner .navbar__title');32 await expect(title).toHaveText('Playwright');33});34test('simple test', async ({ page }) => {35 const title = page.locator('.navbar__inner .navbar__title');36 await expect(title).toHaveText('Playwright');37});38test('simple test', async ({
Using AI Code Generation
1const { setCurrentTestInfo } = require('@playwright/test');2const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };3setCurrentTestInfo(testInfo);4const { setCurrentTestInfo } = require('@playwright/test');5const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };6setCurrentTestInfo(testInfo);7const { setCurrentTestInfo } = require('@playwright/test');8const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };9setCurrentTestInfo(testInfo);10const { setCurrentTestInfo } = require('@playwright/test');11const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };12setCurrentTestInfo(testInfo);13const { setCurrentTestInfo } = require('@playwright/test');14const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };15setCurrentTestInfo(testInfo);16const { setCurrentTestInfo } = require('@playwright/test');17const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };18setCurrentTestInfo(testInfo);19const { setCurrentTestInfo } = require('@playwright/test');20const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };21setCurrentTestInfo(testInfo);22const { setCurrentTestInfo } = require('@playwright/test');23const testInfo = { title: 'My test', file: 'test.js', line: 10, column: 2 };24setCurrentTestInfo(testInfo);
Using AI Code Generation
1const { testInfo } = require("@playwright/test");2testInfo().setCurrentTestInfo({3});4const { testInfo } = require("playwright-test-info");5testInfo().setCurrentTestInfo({6});7### testInfo()8### testInfo().setCurrentTestInfo(testInfo)9MIT © [Sergey Kuznetsov](
Using AI Code Generation
1const { setCurrentTestInfo } = require('@playwright/test');2const { TestInfo } = require('@playwright/test');3module.exports = {4}5const { setCurrentTestInfo, TestInfo } = require('./test');6const test = require('@playwright/test');7test.describe('My Test', () => {8 test('My Test Case', async ({ page }) => {9 const testInfo = new TestInfo();10 testInfo.attachments.push({11 });12 setCurrentTestInfo(testInfo);13 });14});
Using AI Code Generation
1const { test, expect } = require('@playwright/test');2const { BASE_URL } = require('../config');3const { LoginPage } = require('../pages/login.page');4const { HomePage } = require('../pages/home.page');5const { ProfilePage } = require('../pages/profile.page');6const { NewArticlePage } = require('../pages/new-article.page');7const { ArticlePage } = require('../pages/article.page');8test.describe('New article', () => {9 let loginPage;10 let homePage;11 let profilePage;12 let newArticlePage;13 let articlePage;14 test.beforeEach(async ({ page }) => {15 loginPage = new LoginPage(page);16 homePage = new HomePage(page);17 profilePage = new ProfilePage(page);18 newArticlePage = new NewArticlePage(page);19 articlePage = new ArticlePage(page);20 await loginPage.goto();21 await loginPage.login();22 await homePage.goto();23 await homePage.clickNewArticleLink();24 });25 test('should be able to publish new article', async ({ page }) => {26 const articleData = {27 };28 await newArticlePage.fillForm(articleData);29 await newArticlePage.clickPublishButton();30 await articlePage.waitForLoad();31 const articleTitle = await articlePage.getArticleTitle();32 expect(articleTitle).toBe(articleData.title);33 const articleAbout = await articlePage.getArticleAbout();34 expect(articleAbout).toBe(articleData.about);35 const articleBody = await articlePage.getArticleBody();36 expect(articleBody).toBe(articleData.body);37 const articleTags = await articlePage.getArticleTags();38 expect(articleTags).toEqual(articleData.tags);39 });40 test('should be able to save draft', async ({ page }) => {41 const articleData = {42 };43 await newArticlePage.fillForm(articleData
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!!