UNPKG

@percy/agent

Version:

An agent process for integrating with Percy.

89 lines (88 loc) 3.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const bodyParser = require("body-parser"); const cors = require("cors"); const express = require("express"); const globby = require("globby"); const puppeteer = require("puppeteer"); const configuration_1 = require("../configuration/configuration"); const configuration_2 = require("../utils/configuration"); const logger_1 = require("../utils/logger"); const sdk_utils_1 = require("../utils/sdk-utils"); class StaticSnapshotService { constructor(configuration) { this.server = null; this.app = express(); this.configuration = configuration || configuration_1.DEFAULT_CONFIGURATION['static-snapshots']; this.app.use(cors()); this.app.use(bodyParser.urlencoded({ extended: true })); this.app.use(bodyParser.json({ limit: '50mb' })); this.app.use(this.configuration['base-url'], express.static(this.configuration.path)); } async start() { logger_1.default.info(`serving static site at ${this._buildLocalUrl()}`); this.server = await this.app.listen(this.configuration.port); } async snapshotAll() { logger_1.default.debug('taking snapshots of static site'); const browser = await puppeteer.launch({ args: ['--no-sandbox'], handleSIGINT: false, }); const percyAgentClientFilename = sdk_utils_1.agentJsFilename(); const page = await browser.newPage(); // Do not follow redirects to ensure we don't navigate to another page await page.setRequestInterception(true); page.on('request', (request) => { if (request.isNavigationRequest() && request.redirectChain().length) { logger_1.default.debug(`Skipping redirect: ${request.url()}`); request.abort(); } else { request.continue(); } }); const pageUrls = await this._buildPageUrls(); for (const url of pageUrls) { logger_1.default.debug(`visiting ${url}`); try { await page.goto(url, { waitUntil: 'networkidle2' }); } catch (error) { logger_1.default.error(`Failed to navigate to ${url}, skipping. Error: ${error}`); } try { await page.addScriptTag({ path: percyAgentClientFilename, }); await page.evaluate((url) => { const percyAgentClient = new PercyAgent(); const parsedURL = new URL(url); const snapshotName = parsedURL.pathname || url; return percyAgentClient.snapshot(snapshotName); }, url); } catch (error) { logger_1.default.error(`Failed to inject agent JS: ${error}`); } } await browser.close(); } async stop() { if (this.server) { await this.server.close(); } logger_1.default.info(`shutting down static site at ${this._buildLocalUrl()}`); } _buildLocalUrl() { return `http://localhost:${this.configuration.port}${this.configuration['base-url']}`; } async _buildPageUrls() { const globs = configuration_2.parseGlobs(this.configuration['snapshot-files']); const ignore = configuration_2.parseGlobs(this.configuration['ignore-files']); const paths = await globby(globs, { cwd: this.configuration.path, ignore }); const baseUrl = this._buildLocalUrl(); return paths.map((path) => baseUrl + path); } } exports.default = StaticSnapshotService;