2023-02-12 05:41:04 +03:00
|
|
|
const fs = require('fs');
|
|
|
|
const BrowserStack = require('browserstack');
|
|
|
|
const https = require('https');
|
|
|
|
|
|
|
|
let portraitJobId = null;
|
|
|
|
let landscapeJobId = null;
|
|
|
|
let finished = false;
|
|
|
|
|
|
|
|
const testBrowsersPortrait = [
|
|
|
|
{
|
|
|
|
os: 'OS X',
|
|
|
|
os_version: 'Ventura',
|
|
|
|
browser: 'chrome',
|
|
|
|
device: null,
|
|
|
|
browser_version: '71.0',
|
|
|
|
real_mobile: null,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
os: 'OS X',
|
|
|
|
os_version: 'Ventura',
|
|
|
|
browser: 'safari',
|
|
|
|
device: null,
|
|
|
|
browser_version: '16.0',
|
|
|
|
real_mobile: null,
|
|
|
|
},
|
2023-02-13 01:50:26 +03:00
|
|
|
{
|
|
|
|
os: 'OS X',
|
|
|
|
os_version: 'Ventura',
|
|
|
|
browser: 'firefox',
|
|
|
|
device: null,
|
|
|
|
browser_version: '89.0',
|
|
|
|
real_mobile: null,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
os: 'Windows',
|
|
|
|
os_version: '11',
|
|
|
|
browser: 'firefox',
|
|
|
|
device: null,
|
|
|
|
browser_version: '89.0',
|
|
|
|
real_mobile: null,
|
|
|
|
},
|
2023-02-12 05:41:04 +03:00
|
|
|
{
|
|
|
|
os: 'Windows',
|
|
|
|
os_version: '11',
|
|
|
|
browser: 'chrome',
|
|
|
|
device: null,
|
|
|
|
browser_version: '71.0',
|
|
|
|
real_mobile: null,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
os: 'ios',
|
|
|
|
os_version: '16',
|
|
|
|
browser: 'Mobile Safari',
|
|
|
|
device: 'iPhone 14 Pro',
|
|
|
|
browser_version: null,
|
|
|
|
real_mobile: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
os: 'ios',
|
|
|
|
os_version: '16',
|
|
|
|
browser: 'Mobile Safari',
|
|
|
|
device: 'iPad Pro 11 2022',
|
|
|
|
browser_version: null,
|
|
|
|
real_mobile: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
os: 'android',
|
|
|
|
os_version: '13.0',
|
|
|
|
browser: 'Android Browser',
|
|
|
|
device: 'Google Pixel 7 Pro',
|
|
|
|
browser_version: null,
|
|
|
|
real_mobile: true,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const testBrowsersLandscape = [
|
2023-02-13 01:50:26 +03:00
|
|
|
{
|
|
|
|
os: 'android',
|
|
|
|
os_version: '10.0',
|
|
|
|
browser: 'Android Browser',
|
|
|
|
device: 'Samsung Galaxy S20 Ultra',
|
|
|
|
browser_version: null,
|
|
|
|
real_mobile: true,
|
|
|
|
},
|
2023-02-12 05:41:04 +03:00
|
|
|
{
|
|
|
|
os: 'ios',
|
|
|
|
os_version: '16',
|
|
|
|
browser: 'Mobile Safari',
|
|
|
|
device: 'iPad Pro 11 2022',
|
|
|
|
browser_version: null,
|
|
|
|
real_mobile: true,
|
|
|
|
},
|
|
|
|
// {
|
|
|
|
// os: 'ios',
|
|
|
|
// os_version: '16',
|
|
|
|
// browser: 'Mobile Safari',
|
2023-02-13 01:50:26 +03:00
|
|
|
// device: 'iPhone 14',
|
2023-02-12 05:41:04 +03:00
|
|
|
// browser_version: null,
|
|
|
|
// real_mobile: true,
|
|
|
|
// },
|
|
|
|
];
|
|
|
|
|
|
|
|
const USERNAME = process.env.BROWSERSTACK_USERNAME;
|
|
|
|
const PASSWORD = process.env.BROWSERSTACK_PASSWORD;
|
|
|
|
const URL = process.env.TEST_URL;
|
|
|
|
const FILE_SUFFIX = process.env.FILE_SUFFIX;
|
|
|
|
|
|
|
|
if (!URL) {
|
|
|
|
console.error('Missing URL');
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!USERNAME || !PASSWORD) {
|
|
|
|
console.error('Missing BrowserStack credentials');
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!FILE_SUFFIX) {
|
|
|
|
console.error('Missing file suffix');
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const { exit } = require('process');
|
|
|
|
var browserStackCredentials = {
|
|
|
|
username: USERNAME,
|
|
|
|
password: PASSWORD,
|
|
|
|
};
|
|
|
|
|
|
|
|
let screenshotClient = BrowserStack.createScreenshotClient(
|
|
|
|
browserStackCredentials
|
|
|
|
);
|
|
|
|
|
|
|
|
function start() {
|
|
|
|
console.log(
|
|
|
|
`creating screenshots for ${URL} using ${
|
|
|
|
[...testBrowsersPortrait, ...testBrowsersLandscape].length
|
|
|
|
} browsers...`
|
|
|
|
);
|
|
|
|
|
|
|
|
const portraitOptions = {
|
|
|
|
url: URL,
|
|
|
|
orientation: 'portrait',
|
|
|
|
mac_res: '1920x1080',
|
|
|
|
win_res: '1280x1024',
|
|
|
|
browsers: testBrowsersPortrait,
|
|
|
|
wait_time: 20,
|
|
|
|
local: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
const landscapeOptions = {
|
|
|
|
url: URL,
|
|
|
|
orientation: 'landscape',
|
|
|
|
mac_res: '1920x1080',
|
|
|
|
win_res: '1280x1024',
|
|
|
|
browsers: testBrowsersLandscape,
|
|
|
|
wait_time: 20,
|
|
|
|
local: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
screenshotClient.generateScreenshots(
|
|
|
|
portraitOptions,
|
|
|
|
function (error, response) {
|
|
|
|
if (error) {
|
|
|
|
console.error(error);
|
|
|
|
exit(0);
|
|
|
|
} else {
|
|
|
|
const { job_id } = response;
|
|
|
|
portraitJobId = job_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
screenshotClient.generateScreenshots(
|
|
|
|
landscapeOptions,
|
|
|
|
function (error, response) {
|
|
|
|
if (error) {
|
|
|
|
console.error(error);
|
|
|
|
exit(0);
|
|
|
|
} else {
|
|
|
|
const { job_id } = response;
|
|
|
|
landscapeJobId = job_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
setTimeout(check, 30000);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function checkJob(jobId) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
screenshotClient.getJob(jobId, function (error, job) {
|
|
|
|
if (error) {
|
|
|
|
return reject(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
return resolve(job);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function check() {
|
|
|
|
if (finished) {
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!portraitJobId || !landscapeJobId) {
|
|
|
|
setTimeout(check, 5000);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const portraitStatus = await checkJob(portraitJobId);
|
|
|
|
const landscapeStatus = await checkJob(landscapeJobId);
|
|
|
|
|
|
|
|
const { screenshots: portraitScreenshots } = portraitStatus;
|
|
|
|
const { screenshots: landscapeScreenshots } = landscapeStatus;
|
|
|
|
const screenshots = [...portraitScreenshots, ...landscapeScreenshots];
|
|
|
|
|
|
|
|
const completed = screenshots.filter((s) => s.state === 'done');
|
|
|
|
console.log(`completed ${completed.length} of ${screenshots.length}...`);
|
|
|
|
console.log(screenshots.filter((s) => s.state !== 'done'));
|
|
|
|
|
|
|
|
if (completed.length === screenshots.length) {
|
|
|
|
complete(screenshots);
|
|
|
|
}
|
|
|
|
|
|
|
|
const timedOut = screenshots.filter((s) => s.state === 'timed-out');
|
|
|
|
if (timedOut.length > 0) {
|
|
|
|
console.log('timed out');
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(check, 5000);
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
function complete(screenshots) {
|
|
|
|
console.log('downloading screenshots...');
|
|
|
|
var saveCounter = 0;
|
|
|
|
for (const screenshot of screenshots) {
|
|
|
|
const { os, os_version, browser, device, orientation, image_url } =
|
|
|
|
screenshot;
|
|
|
|
const name = `${os} ${os_version} ${browser} ${device || 'desktop'} ${
|
|
|
|
orientation || 'default'
|
|
|
|
} ${FILE_SUFFIX}`;
|
|
|
|
|
|
|
|
const filename = name.replace(/ /g, '-').toLowerCase();
|
|
|
|
|
|
|
|
const file = fs.createWriteStream(`./screenshots/${filename}.png`);
|
|
|
|
https
|
|
|
|
.get(image_url, function (response) {
|
|
|
|
response.pipe(file);
|
|
|
|
|
|
|
|
file.on('finish', () => {
|
|
|
|
file.close();
|
|
|
|
saveCounter++;
|
|
|
|
if (saveCounter === screenshots.length) {
|
|
|
|
finished = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.on('error', function (err) {
|
|
|
|
console.error(err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|