@cappa/core
Version:
Core Playwright screenshot functionality for Cappa
218 lines (214 loc) • 6.92 kB
JavaScript
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let node_fs = require("node:fs");
node_fs = __toESM(node_fs);
let node_path = require("node:path");
node_path = __toESM(node_path);
let playwright_core = require("playwright-core");
playwright_core = __toESM(playwright_core);
//#region src/config.ts
/**
* Type helper to make it easier to use vite.config.ts accepts a direct UserConfig object, or a function that returns it. The function receives a ConfigEnv object.
*/
function defineConfig(options) {
return options;
}
//#endregion
//#region src/screenshot.ts
var ScreenshotTool = class {
browserType;
headless;
viewport;
outputDir;
fullPage;
browser = null;
context = null;
page = null;
constructor(options) {
this.browserType = options.browserType || "chromium";
this.headless = options.headless !== false;
this.viewport = options.viewport || {
width: 1920,
height: 1080
};
this.outputDir = options.outputDir || "./screenshots";
this.fullPage = options.fullPage !== false;
}
async init() {
if (!node_fs.default.existsSync(this.outputDir)) node_fs.default.mkdirSync(this.outputDir, { recursive: true });
const browserClass = {
chromium: playwright_core.chromium,
firefox: playwright_core.firefox,
webkit: playwright_core.webkit
}[this.browserType];
if (!browserClass) throw new Error(`Unsupported browser type: ${this.browserType}`);
this.browser = await browserClass.launch({ headless: this.headless });
const defaultUserAgent = (await this.browser.newContext()).newPage().then((page) => page.evaluate(() => navigator.userAgent));
this.context = await this.browser.newContext({
reducedMotion: "reduce",
deviceScaleFactor: 1,
userAgent: `${await defaultUserAgent} CappaStorybook`
});
this.page = await this.context?.newPage();
this.page?.setViewportSize(this.viewport);
}
async close() {
if (this.browser) await this.browser.close();
}
async goTo(page, url) {
if (!this.context) throw new Error("Browser not initialized");
await page.goto(url, { waitUntil: "domcontentloaded" });
}
getFilePath(filename) {
return node_path.default.join(this.outputDir, filename);
}
async takeScreenshot(page, filename, options = {}) {
if (!this.browser) throw new Error("Browser not initialized");
try {
if (options.waitForSelector) {
console.log(`Waiting for selector: ${options.waitForSelector}`);
await page.waitForSelector(options.waitForSelector, { timeout: 1e4 });
}
const waitTime = options.waitForTimeout !== void 0 ? options.waitForTimeout : 0;
if (waitTime > 0) {
console.log(`Waiting for ${waitTime}ms for dynamic content`);
await page.waitForTimeout(waitTime);
}
const filepath = this.getFilePath(filename);
const screenshotOptions = {
path: filepath,
fullPage: options.fullPage !== void 0 ? options.fullPage : this.fullPage,
type: "png",
timeout: 6e4,
mask: options.mask,
omitBackground: options.omitBackground,
scale: "css"
};
await page.screenshot(screenshotOptions);
console.log(`Screenshot saved: ${filepath}`);
return filepath;
} catch (error) {
console.error(`Error taking screenshot of ${page.url()}:`, error.message);
throw error;
}
}
async takeElementScreenshot(page, selector, options = {}) {
if (!this.browser) throw new Error("Browser not initialized");
try {
await page.waitForSelector(selector, { timeout: 1e4 });
const element = await page.$(selector);
if (!element) throw new Error(`Element not found: ${selector}`);
const filename = options.filename || `${selector.replace(/[^a-zA-Z0-9]/g, "_")}.png`;
const filepath = this.getFilePath(filename);
const elementScreenshotOptions = {
path: filepath,
type: "png"
};
await element.screenshot(elementScreenshotOptions);
console.log(`Element screenshot saved: ${filepath}`);
return filepath;
} catch (error) {
console.error(`Error taking element screenshot of ${page.url()}:`, error.message);
throw error;
} finally {
await page.close();
}
}
async batchScreenshots(urls, options = {}) {
const results = [];
for (const url of urls) try {
const page = this.page;
if (!page) throw new Error("Page not initialized");
await this.goTo(page, url);
const filepath = await this.takeScreenshot(page, url, options);
results.push({
url,
success: true,
filepath
});
} catch (error) {
results.push({
url,
success: false,
error: error.message,
filepath: ""
});
}
return results;
}
async takeResponsiveScreenshots(url, viewports = [
{
width: 1920,
height: 1080,
name: "desktop"
},
{
width: 768,
height: 1024,
name: "tablet"
},
{
width: 375,
height: 667,
name: "mobile"
}
], options = {}) {
if (!this.context) throw new Error("Browser not initialized");
const results = [];
for (const viewport of viewports) try {
const page = await this.context?.newPage();
await page.setViewportSize(viewport);
await page.goto(url, { waitUntil: "domcontentloaded" });
await page.waitForTimeout(2e3);
const filename = `${viewport.name}.png`;
const filepath = this.getFilePath(filename);
const responsiveScreenshotOptions = {
path: filepath,
fullPage: options.fullPage !== void 0 ? options.fullPage : this.fullPage,
type: "png"
};
await page.screenshot(responsiveScreenshotOptions);
await page.close();
console.log(`Responsive screenshot saved: ${filepath}`);
results.push({
viewport: viewport.name,
success: true,
filepath
});
} catch (error) {
console.error(`Error taking responsive screenshot for ${viewport.name}:`, error.message);
results.push({
viewport: viewport.name,
success: false,
error: error.message,
filepath: ""
});
}
return results;
}
};
var screenshot_default = ScreenshotTool;
//#endregion
exports.ScreenshotTool = screenshot_default;
exports.defineConfig = defineConfig;
//# sourceMappingURL=index.js.map