From 61997e62703e079d73a8b8fb84cf4c85ac393a24 Mon Sep 17 00:00:00 2001 From: Rushabh Shroff Date: Tue, 19 Dec 2023 17:46:36 +0530 Subject: [PATCH] fix: url path based screenshot download --- package-lock.json | 60 ++++++++++++++++++++++++++++++++++++++++++++--- package.json | 7 +++--- src/generate.js | 29 ++++++++++++++++------- 3 files changed, 82 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24839fa..c54d7e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@percy/report", - "version": "0.0.3", + "version": "0.0.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@percy/report", - "version": "0.0.3", + "version": "0.0.6", "license": "MIT", "dependencies": { "@percy/cli": "^1.16.0", @@ -16,7 +16,8 @@ "commander": "^9.4.0", "date-fns": "^2.29.3", "dotenv": "^16.0.3", - "ejs": "^3.1.8" + "ejs": "^3.1.8", + "p-queue": "^8.0.1" }, "bin": { "percy-report": "bin/cli.js" @@ -25,6 +26,9 @@ "@percy/selenium-webdriver": "^1.0.2", "chai": "^4.3.7", "mocha": "^10.2.0" + }, + "engines": { + "node": ">=14" } }, "node_modules/@babel/code-frame": { @@ -956,6 +960,11 @@ "node": ">=0.8.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -1800,6 +1809,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -3150,6 +3185,11 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, + "eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, "extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -3764,6 +3804,20 @@ "aggregate-error": "^3.0.0" } }, + "p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "requires": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + } + }, + "p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==" + }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", diff --git a/package.json b/package.json index bc6ab7e..ae6007a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@percy/report", "description": "Package to generate a build report and project summary report for Percy, BrowserStack's visual testing platform", - "version": "0.0.5", + "version": "0.0.6", "main": "src/index.js", "license": "MIT", "author": "BrowserStack Pvt Ltd", @@ -44,11 +44,12 @@ "commander": "^9.4.0", "date-fns": "^2.29.3", "dotenv": "^16.0.3", - "ejs": "^3.1.8" + "ejs": "^3.1.8", + "p-queue": "^8.0.1" }, "devDependencies": { "@percy/selenium-webdriver": "^1.0.2", "chai": "^4.3.7", "mocha": "^10.2.0" } -} \ No newline at end of file +} diff --git a/src/generate.js b/src/generate.js index 6bdeb5d..a36f294 100644 --- a/src/generate.js +++ b/src/generate.js @@ -9,6 +9,7 @@ const defaultConfig = { downloadPath: './Reports', diffThreshold: 1 } +let downloadQueue; module.exports.Generate = async function (config) { let { buildId, percyToken, apiUrl, downloadImages, downloadPath, diffThreshold } = Object.assign({}, defaultConfig, config) let axios = new Axios({ @@ -28,6 +29,11 @@ module.exports.Generate = async function (config) { throw res.data } }) + if(!downloadQueue){ + await import('p-queue').then(({default:PQueue})=>{ + downloadQueue = new PQueue({concurrency:1,intervalCap:5,interval:5000}) + }) + } const isApp = buildDetails['data']['attributes']['type'] == 'app' while (buildDetails.data && buildDetails.data.attributes.state !== 'finished') { console.log("Waiting for build to complete on Percy...") @@ -101,10 +107,12 @@ module.exports.Generate = async function (config) { } } if (downloadImages) { + + ['base', 'head', 'diff'].forEach((val) => { if (images[val]) { images[val].file = downloadImage({ - name: String(snapshot?.['attributes'].name).replace('/', '-'), + name: String(snapshot?.['attributes'].name), compTag, width: images[val].width, type: val, @@ -167,18 +175,23 @@ function downloadImage(options) { if (!fs.existsSync(`${baseDir}/${type}`)) { fs.mkdirSync(`${baseDir}/${type}`, { recursive: true }) } - let path = `${baseDir}/${type}/${name}-${compTag}-${width}.png` + let composedName = `${name}-${compTag}-${width}.png`.replace(/[\\\/]/g,'_') + let path = `${baseDir}/${type}/${composedName}` try { - new Axios({ responseType: 'arraybuffer', url: url }).get(url).then((file) => { + downloadQueue.add(()=>new Axios({ responseType: 'arraybuffer', url: url }).get(url).then((file) => { console.log("Download Complete:" + path) fs.writeFileSync(path, file.data) }).catch((err) => { console.error("Failed to Download: " + path) - console.error(err) - }) - return `file:./${type}/${name}-${compTag}-${width}.png`; - } catch { - + if(err.code == 'ECONNRESET'){ + console.log('Retrying '+ path) + }else{ + console.error(`Failed ${path}, error: ${err.code}`) + } + })) + return `file:./${type}/${composedName}`; + } catch(err) { + } }