playwright-cucumber-ts-steps
Version:
A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.
111 lines (110 loc) • 4.26 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomWorld = void 0;
const cucumber_1 = require("@cucumber/cucumber");
const test_1 = require("@playwright/test");
const dotenv = __importStar(require("dotenv"));
const playwright_1 = require("playwright");
dotenv.config();
const isHeadless = process.env.HEADLESS !== "false";
const slowMo = process.env.SLOWMO ? Number(process.env.SLOWMO) : 0;
class CustomWorld extends cucumber_1.World {
constructor(options) {
super(options);
this.data = {};
this.logs = [];
this.config = {
enableScreenshots: true,
enableVisualTest: false,
artifactDir: "test-artifacts",
};
this.log = (message) => {
this.logs.push(message);
console.log(`[LOG] ${message}`);
};
this.fakeTimersActive = false;
}
async init(testInfo) {
const info = testInfo ?? this.parameters?.testInfo;
const isMobile = info?.pickle.tags.some((tag) => tag.name === "@mobile");
const device = isMobile ? test_1.devices["Pixel 5"] : undefined;
this.browser = await playwright_1.chromium.launch({ headless: isHeadless, slowMo });
this.context = await this.browser.newContext({
...(device || {}),
recordVideo: { dir: `${this.config.artifactDir}/videos` },
});
// Important: Initialize clock mocking *before* navigating or interacting with the page
// if you intend to use page.clock. This typically involves addInitScript.
// However, the context.clock API does not usually require an init script for its methods.
// If you explicitly loaded a mocking library, you'd do it here.
// For just context.clock methods, they should be available.
this.page = await this.context.newPage();
this.testName = info?.pickle.name;
this.log(`🧪 Initialized context${isMobile ? " (mobile)" : ""}`);
}
/**
* Returns the current interaction scope: either the main page or active frame.
*/
getScope() {
return this.frame ?? this.page;
}
/**
* Returns a Locator scoped to the current iframe or page.
*/
getLocator(selector) {
return this.getScope().locator(selector);
}
exitIframe() {
this.frame = undefined;
this.log("⬅️ Exited iframe, scope is now main page");
}
async cleanup(testInfo) {
try {
await this.page?.close();
}
catch (err) {
this.log(`⚠️ Error closing page: ${err.message}`);
}
try {
await this.context?.close();
}
catch (err) {
this.log(`⚠️ Error closing context: ${err.message}`);
}
}
}
exports.CustomWorld = CustomWorld;
(0, cucumber_1.setWorldConstructor)(CustomWorld);