browsertime 23.5.0 → 24.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -2
- package/bin/browsertime.js +3 -2
- package/lib/android/gnirehtet.js +2 -2
- package/lib/android/index.js +2 -2
- package/lib/android/root.js +2 -2
- package/lib/chrome/chromeDevtoolsProtocol.js +4 -4
- package/lib/chrome/har.js +2 -2
- package/lib/chrome/networkManager.js +2 -2
- package/lib/chrome/parseCpuTrace.js +2 -2
- package/lib/chrome/traceCategoriesParser.js +2 -2
- package/lib/chrome/webdriver/builder.js +1 -2
- package/lib/chrome/webdriver/chromium.js +2 -2
- package/lib/chrome/webdriver/setupChromiumOptions.js +2 -2
- package/lib/chrome/webdriver/traceUtilities.js +2 -2
- package/lib/connectivity/humble.js +2 -2
- package/lib/connectivity/index.js +2 -2
- package/lib/core/engine/collector.js +2 -2
- package/lib/core/engine/command/addText.js +2 -2
- package/lib/core/engine/command/android.js +2 -2
- package/lib/core/engine/command/bidi.js +2 -2
- package/lib/core/engine/command/cache.js +2 -2
- package/lib/core/engine/command/chromeDevToolsProtocol.js +2 -2
- package/lib/core/engine/command/chromeTrace.js +2 -2
- package/lib/core/engine/command/click.js +2 -2
- package/lib/core/engine/command/debug.js +2 -2
- package/lib/core/engine/command/geckoProfiler.js +2 -2
- package/lib/core/engine/command/javaScript.js +2 -2
- package/lib/core/engine/command/measure.js +2 -2
- package/lib/core/engine/command/mouse/clickAndHold.js +2 -2
- package/lib/core/engine/command/mouse/contextClick.js +2 -2
- package/lib/core/engine/command/mouse/doubleClick.js +2 -2
- package/lib/core/engine/command/mouse/mouseMove.js +2 -2
- package/lib/core/engine/command/mouse/singleClick.js +2 -2
- package/lib/core/engine/command/navigation.js +2 -2
- package/lib/core/engine/command/screenshot.js +2 -2
- package/lib/core/engine/command/scroll.js +2 -2
- package/lib/core/engine/command/select.js +2 -2
- package/lib/core/engine/command/set.js +2 -2
- package/lib/core/engine/command/stopWatch.js +2 -2
- package/lib/core/engine/command/switch.js +2 -2
- package/lib/core/engine/command/wait.js +2 -2
- package/lib/core/engine/index.js +8 -14
- package/lib/core/engine/iteration.js +2 -2
- package/lib/core/seleniumRunner.js +8 -12
- package/lib/core/webdriver/index.js +1 -1
- package/lib/edge/webdriver/builder.js +3 -4
- package/lib/firefox/firefoxBidi.js +2 -2
- package/lib/firefox/geckoProfiler.js +2 -2
- package/lib/firefox/memoryReport.js +2 -2
- package/lib/firefox/networkManager.js +2 -2
- package/lib/firefox/perfStats.js +2 -2
- package/lib/firefox/webdriver/builder.js +3 -5
- package/lib/firefox/webdriver/firefox.js +2 -2
- package/lib/screenshot/index.js +7 -9
- package/lib/screenshot/loadCustomJimp.js +17 -0
- package/lib/support/browserScript.js +4 -5
- package/lib/support/cli.js +15 -5
- package/lib/support/dns.js +2 -2
- package/lib/support/engineUtils.js +4 -5
- package/lib/support/fileUtil.js +20 -3
- package/lib/support/getPort.js +25 -0
- package/lib/support/getViewPort.js +2 -2
- package/lib/support/har/index.js +5 -6
- package/lib/support/images/index.js +8 -17
- package/lib/support/logging.js +14 -39
- package/lib/support/pathToFolder.js +3 -3
- package/lib/support/preURL.js +2 -2
- package/lib/support/statistics.js +2 -2
- package/lib/support/stop.js +2 -2
- package/lib/support/storageManager.js +5 -5
- package/lib/support/util.js +73 -3
- package/lib/support/xvfb.js +55 -26
- package/lib/video/postprocessing/finetune/addTextToVideo.js +2 -2
- package/lib/video/postprocessing/finetune/convertFps.js +2 -2
- package/lib/video/postprocessing/finetune/index.js +2 -2
- package/lib/video/postprocessing/finetune/removeOrange.js +2 -2
- package/lib/video/postprocessing/visualmetrics/getVideoMetrics.js +2 -2
- package/lib/video/postprocessing/visualmetrics/visualMetrics.js +2 -2
- package/lib/video/screenRecording/android/recorder.js +2 -2
- package/lib/video/screenRecording/desktop/convert.js +2 -2
- package/lib/video/screenRecording/desktop/desktopRecorder.js +2 -2
- package/lib/video/screenRecording/desktop/ffmpegRecorder.js +2 -2
- package/lib/video/screenRecording/desktop/osx/getScreen.js +2 -2
- package/lib/video/screenRecording/firefox/firefoxWindowRecorder.js +2 -2
- package/lib/video/screenRecording/ios/convertToMp4.js +2 -2
- package/lib/video/screenRecording/ios/iosRecorder.js +2 -2
- package/lib/video/screenRecording/iosSimulator/convertToMp4.js +2 -2
- package/lib/video/screenRecording/iosSimulator/recorder.js +2 -2
- package/lib/video/screenRecording/setOrangeBackground.js +2 -2
- package/package.json +8 -13
- package/types/support/engineUtils.d.ts.map +1 -1
- package/types/support/fileUtil.d.ts +1 -0
- package/types/support/fileUtil.d.ts.map +1 -1
- package/types/support/util.d.ts +3 -0
- package/types/support/util.d.ts.map +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Builder } from 'selenium-webdriver';
|
|
2
|
-
import isEmpty from 'lodash.isempty';
|
|
3
2
|
import { configureBuilder as configureBuilderChrome } from '../../chrome/webdriver/builder.js';
|
|
4
3
|
import { configureBuilder as configureBuilderEdge } from '../../edge/webdriver/builder.js';
|
|
5
4
|
import { configureBuilder as configureBuilderFirefox } from '../../firefox/webdriver/builder.js';
|
|
6
5
|
import { configureBuilder as configureBuilderSafari } from '../../safari/webdriver/builder.js';
|
|
6
|
+
import { isEmpty } from '../../support/util.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Create a new WebDriver instance based on the specified options.
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Options, ServiceBuilder } from 'selenium-webdriver/edge.js';
|
|
2
|
-
import
|
|
2
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
3
3
|
import get from 'lodash.get';
|
|
4
|
-
import pick from 'lodash.pick';
|
|
5
|
-
import isEmpty from 'lodash.isempty';
|
|
6
4
|
import { logging } from 'selenium-webdriver';
|
|
7
5
|
import { setupChromiumOptions } from '../../chrome/webdriver/setupChromiumOptions.js';
|
|
8
|
-
const log =
|
|
6
|
+
const log = getLogger('browsertime.edge');
|
|
9
7
|
const { pac, manual } = 'selenium-webdriver/proxy.js';
|
|
8
|
+
import { pick, isEmpty } from '../../support/util.js';
|
|
10
9
|
|
|
11
10
|
export async function configureBuilder(builder, baseDir, options) {
|
|
12
11
|
const edgeConfig = options.edge || {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Bidi } from '../core/engine/command/bidi.js';
|
|
2
|
-
import
|
|
2
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
3
3
|
import { toArray } from '../support/util.js';
|
|
4
|
-
const log =
|
|
4
|
+
const log = getLogger('browsertime.firefox.bidi');
|
|
5
5
|
|
|
6
6
|
export class FirefoxBidi {
|
|
7
7
|
constructor(bidi, browsingContextId, driver, options) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import get from 'lodash.get';
|
|
3
|
-
import
|
|
3
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
4
4
|
import { geckoProfilerDefaults } from './settings/geckoProfilerDefaults.js';
|
|
5
5
|
import { isAndroidConfigured, Android } from '../android/index.js';
|
|
6
6
|
import { pathToFolder } from '../support/pathToFolder.js';
|
|
7
7
|
import { BrowserError } from '../support/errors.js';
|
|
8
8
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
9
|
-
const log =
|
|
9
|
+
const log = getLogger('browsertime.firefox');
|
|
10
10
|
|
|
11
11
|
// Return power usage in Wh for a single counter.
|
|
12
12
|
function computeCounterPowerSum(counter) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import
|
|
2
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
3
3
|
import { pathToFolder } from '../support/pathToFolder.js';
|
|
4
4
|
import { BrowserError } from '../support/errors.js';
|
|
5
5
|
import { isAndroidConfigured, Android } from '../android/index.js';
|
|
6
6
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
7
|
-
const log =
|
|
7
|
+
const log = getLogger('browsertime.firefox');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Timeout a promise after ms. Use promise.race to compete
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
2
2
|
import get from 'lodash.get';
|
|
3
|
-
const log =
|
|
3
|
+
const log = getLogger('browsertime.chrome.network');
|
|
4
4
|
|
|
5
5
|
export class NetworkManager {
|
|
6
6
|
constructor(bidi, browsingContextIds, options) {
|
package/lib/firefox/perfStats.js
CHANGED
|
@@ -4,17 +4,15 @@ import {
|
|
|
4
4
|
Options,
|
|
5
5
|
Channel
|
|
6
6
|
} from 'selenium-webdriver/firefox.js';
|
|
7
|
-
import
|
|
7
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
8
8
|
import { pac, manual } from 'selenium-webdriver/proxy.js';
|
|
9
|
-
import pick from 'lodash.pick';
|
|
10
|
-
import isEmpty from 'lodash.isempty';
|
|
11
9
|
import get from 'lodash.get';
|
|
12
10
|
import { defaultFirefoxPreferences } from '../settings/firefoxPreferences.js';
|
|
13
11
|
import { disableSafeBrowsingPreferences } from '../settings/disableSafeBrowsingPreferences.js';
|
|
14
12
|
import { disableTrackingProtectionPreferences } from '../settings/disableTrackingProtectionPreferences.js';
|
|
15
|
-
import { toArray } from '../../support/util.js';
|
|
13
|
+
import { toArray, pick, isEmpty } from '../../support/util.js';
|
|
16
14
|
import { Android, isAndroidConfigured } from '../../android/index.js';
|
|
17
|
-
const log =
|
|
15
|
+
const log = getLogger('browsertime.firefox');
|
|
18
16
|
|
|
19
17
|
export async function configureBuilder(builder, baseDir, options) {
|
|
20
18
|
// Here we configure everything that we need to start Firefox
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { rename as _rename } from 'node:fs';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import
|
|
4
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
5
5
|
import get from 'lodash.get';
|
|
6
6
|
import usbPowerProfiler from 'usb-power-profiling/usb-power-profiling.js';
|
|
7
7
|
import { adapters } from 'ff-test-bidi-har-export';
|
|
@@ -16,7 +16,7 @@ import { MemoryReport } from '../memoryReport.js';
|
|
|
16
16
|
import { PerfStats } from '../perfStats.js';
|
|
17
17
|
import { NetworkManager } from '../networkManager.js';
|
|
18
18
|
|
|
19
|
-
const log =
|
|
19
|
+
const log = getLogger('browsertime.firefox');
|
|
20
20
|
const rename = promisify(_rename);
|
|
21
21
|
export class Firefox {
|
|
22
22
|
constructor(storageManager, options) {
|
package/lib/screenshot/index.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import merge from 'lodash.merge';
|
|
3
|
-
import
|
|
3
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
4
4
|
import { screenshotDefaults } from './defaults.js';
|
|
5
5
|
import {
|
|
6
6
|
savePngWithoutResize,
|
|
7
7
|
savePng,
|
|
8
8
|
saveJpg
|
|
9
9
|
} from '../support/images/index.js';
|
|
10
|
+
import { loadCustomJimp } from './loadCustomJimp.js';
|
|
11
|
+
|
|
10
12
|
const SCREENSHOT_DIR = 'screenshots';
|
|
11
|
-
const log =
|
|
13
|
+
const log = getLogger('browsertime.screenshot');
|
|
14
|
+
|
|
12
15
|
export class ScreenshotManager {
|
|
13
16
|
constructor(storageManager, options) {
|
|
14
17
|
this.storageManager = storageManager;
|
|
@@ -18,17 +21,12 @@ export class ScreenshotManager {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
async save(name, data, url, index) {
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
jimp = await import('jimp');
|
|
24
|
-
} catch {
|
|
25
|
-
jimp = undefined;
|
|
26
|
-
}
|
|
24
|
+
const jimp = await loadCustomJimp();
|
|
27
25
|
|
|
28
26
|
if (!jimp) {
|
|
29
27
|
if (this.config.type === 'jpg') {
|
|
30
28
|
log.info(
|
|
31
|
-
'Missing
|
|
29
|
+
'Missing jimp dependency so you can only save images as png at viewport size'
|
|
32
30
|
);
|
|
33
31
|
}
|
|
34
32
|
const pathAndName = await savePngWithoutResize(
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export async function loadCustomJimp() {
|
|
2
|
+
try {
|
|
3
|
+
const { default: configure } = await import('@jimp/custom');
|
|
4
|
+
const { default: pluginPng } = await import('@jimp/png');
|
|
5
|
+
const { default: pluginJpeg } = await import('@jimp/jpeg');
|
|
6
|
+
const { default: pluginScale } = await import('@jimp/plugin-scale');
|
|
7
|
+
// The scale plugin use resize
|
|
8
|
+
const { default: pluginResize } = await import('@jimp/plugin-resize');
|
|
9
|
+
const jimp = configure({
|
|
10
|
+
types: [pluginPng, pluginJpeg],
|
|
11
|
+
plugins: [pluginResize, pluginScale]
|
|
12
|
+
});
|
|
13
|
+
return jimp;
|
|
14
|
+
} catch {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -3,7 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import
|
|
6
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
7
7
|
import { onlyFiles, onlyWithExtension, onlyDirectories } from './filters.js';
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
9
9
|
const readdir = promisify(fs.readdir);
|
|
@@ -11,7 +11,7 @@ const readFile = promisify(fs.readFile);
|
|
|
11
11
|
const stat = promisify(fs.stat);
|
|
12
12
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
13
|
const rootFolder = path.resolve(__dirname, '..', '..', 'browserscripts');
|
|
14
|
-
const log =
|
|
14
|
+
const log = getLogger('browsertime');
|
|
15
15
|
|
|
16
16
|
function toFullPath(filename, root) {
|
|
17
17
|
return path.join(root, filename);
|
|
@@ -93,9 +93,8 @@ function generateScriptObject(name, path, contents) {
|
|
|
93
93
|
// Use this as a signal to fall back to an old-style script, but don't
|
|
94
94
|
// perform any action
|
|
95
95
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
96
|
+
log.verbose(name + ' is an old-style script object.');
|
|
97
|
+
|
|
99
98
|
return {
|
|
100
99
|
name: name,
|
|
101
100
|
content: contents,
|
package/lib/support/cli.js
CHANGED
|
@@ -2,10 +2,8 @@ import { format } from 'node:util';
|
|
|
2
2
|
import { readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import yargs from 'yargs';
|
|
4
4
|
import { hideBin } from 'yargs/helpers';
|
|
5
|
-
import { findUpSync } from 'find-up';
|
|
6
5
|
import get from 'lodash.get';
|
|
7
6
|
import set from 'lodash.set';
|
|
8
|
-
import hasbin from 'hasbin';
|
|
9
7
|
import {
|
|
10
8
|
framerate,
|
|
11
9
|
crf,
|
|
@@ -15,6 +13,8 @@ import {
|
|
|
15
13
|
} from '../video/defaults.js';
|
|
16
14
|
import { screenshotDefaults } from '../screenshot/defaults.js';
|
|
17
15
|
import { geckoProfilerDefaults } from '../firefox/settings/geckoProfilerDefaults.js';
|
|
16
|
+
import { findUpSync } from './fileUtil.js';
|
|
17
|
+
import { execaSync } from 'execa';
|
|
18
18
|
|
|
19
19
|
const configPath = findUpSync(['.browsertime.json']);
|
|
20
20
|
|
|
@@ -33,6 +33,16 @@ try {
|
|
|
33
33
|
throw error;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
function hasbin(bin) {
|
|
37
|
+
try {
|
|
38
|
+
const cmd = process.platform === 'win32' ? 'where' : 'which';
|
|
39
|
+
execaSync(cmd, bin);
|
|
40
|
+
return true;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
function validateInput(argv) {
|
|
37
47
|
// Check NodeJS major version
|
|
38
48
|
const fullVersion = process.versions.node;
|
|
@@ -70,7 +80,7 @@ function validateInput(argv) {
|
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
if ((argv.video || argv.visualMetrics) && !hasbin
|
|
83
|
+
if ((argv.video || argv.visualMetrics) && !hasbin(['ffmpeg'])) {
|
|
74
84
|
return 'You need to have ffmpeg in your path to be able to record a video.';
|
|
75
85
|
}
|
|
76
86
|
|
|
@@ -90,11 +100,11 @@ function validateInput(argv) {
|
|
|
90
100
|
return 'There is no benefit running debug mode inside a Docker container.';
|
|
91
101
|
}
|
|
92
102
|
|
|
93
|
-
if (argv.tcpdump && !hasbin
|
|
103
|
+
if (argv.tcpdump && !hasbin(['tcpdump'])) {
|
|
94
104
|
return 'You need to have tcpdump in your path to be able to record a tcpdump.';
|
|
95
105
|
}
|
|
96
106
|
|
|
97
|
-
if (argv.gnirehtet && !hasbin
|
|
107
|
+
if (argv.gnirehtet && !hasbin(['gnirehtet'])) {
|
|
98
108
|
return 'You need to have gnirehtet in your path to be able to use it. If you run on a Mac you can install it using Homebrew: brew install gnirehtet';
|
|
99
109
|
}
|
|
100
110
|
|
package/lib/support/dns.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execa } from 'execa';
|
|
2
|
-
import
|
|
2
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
3
3
|
import { isAndroidConfigured } from '../android/index.js';
|
|
4
|
-
const log =
|
|
4
|
+
const log = getLogger('browsertime.dns');
|
|
5
5
|
|
|
6
6
|
export async function flushDNS(options) {
|
|
7
7
|
if (isAndroidConfigured(options)) {
|
|
@@ -6,10 +6,9 @@ import {
|
|
|
6
6
|
readFile as _readFile
|
|
7
7
|
} from 'node:fs';
|
|
8
8
|
import { pathToFileURL } from 'node:url';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
const log = intel.getLogger('browsertime');
|
|
9
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
10
|
+
import { toArray, localTime } from '../support/util.js';
|
|
11
|
+
const log = getLogger('browsertime');
|
|
13
12
|
const writeFile = promisify(_writeFile);
|
|
14
13
|
const readFile = promisify(_readFile);
|
|
15
14
|
const unlink = promisify(_unlink);
|
|
@@ -104,5 +103,5 @@ export async function loadScript(script, options, throwError) {
|
|
|
104
103
|
return script;
|
|
105
104
|
}
|
|
106
105
|
export function timestamp() {
|
|
107
|
-
return
|
|
106
|
+
return localTime();
|
|
108
107
|
}
|
package/lib/support/fileUtil.js
CHANGED
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
rename as _rename,
|
|
10
10
|
readFile as _readFile,
|
|
11
11
|
copyFileSync as _copyFileSync,
|
|
12
|
-
unlinkSync as _unlinkSync
|
|
12
|
+
unlinkSync as _unlinkSync,
|
|
13
|
+
existsSync
|
|
13
14
|
} from 'node:fs';
|
|
14
|
-
import
|
|
15
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
15
16
|
import { onlyFiles, onlyWithExtension } from './filters.js';
|
|
16
17
|
const readdir = promisify(_readdir);
|
|
17
18
|
const lstat = promisify(_lstat);
|
|
@@ -20,7 +21,7 @@ const rmdir = promisify(_rmdir);
|
|
|
20
21
|
const copyFile2 = promisify(_copyFile);
|
|
21
22
|
const rename2 = promisify(_rename);
|
|
22
23
|
const readFile2 = promisify(_readFile);
|
|
23
|
-
const log =
|
|
24
|
+
const log = getLogger('browsertime');
|
|
24
25
|
|
|
25
26
|
export async function rename(old, newName) {
|
|
26
27
|
return rename2(old, newName);
|
|
@@ -83,3 +84,19 @@ export async function findFiles(dir, filter) {
|
|
|
83
84
|
});
|
|
84
85
|
return filePaths;
|
|
85
86
|
}
|
|
87
|
+
|
|
88
|
+
export function findUpSync(filenames, startDir = process.cwd()) {
|
|
89
|
+
let currentDir = startDir;
|
|
90
|
+
|
|
91
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
92
|
+
for (const filename of filenames) {
|
|
93
|
+
const filePath = path.resolve(currentDir, filename);
|
|
94
|
+
if (existsSync(filePath)) {
|
|
95
|
+
return filePath;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
currentDir = path.dirname(currentDir);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createServer } from 'node:net';
|
|
2
|
+
|
|
3
|
+
export async function getAvailablePort(portRange, host = '127.0.0.1') {
|
|
4
|
+
const startPort = portRange[0];
|
|
5
|
+
const endPort = portRange[1];
|
|
6
|
+
|
|
7
|
+
for (let port = startPort; port <= endPort; port++) {
|
|
8
|
+
if (await isPortAvailable(port, host)) {
|
|
9
|
+
return port;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
throw new Error(`No available ports found in range ${startPort}-${endPort}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isPortAvailable(port, host) {
|
|
17
|
+
return new Promise(resolve => {
|
|
18
|
+
const server = createServer();
|
|
19
|
+
server.unref();
|
|
20
|
+
server.on('error', () => resolve(false));
|
|
21
|
+
server.listen(port, host, () => {
|
|
22
|
+
server.close(() => resolve(true));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import get from 'lodash.get';
|
|
2
|
-
import
|
|
2
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
3
3
|
import { isAndroidConfigured } from '../android/index.js';
|
|
4
|
-
const log =
|
|
4
|
+
const log = getLogger('browsertime');
|
|
5
5
|
|
|
6
6
|
// Most use screen size as of 2018
|
|
7
7
|
// https://www.w3schools.com/browsers/browsers_display.asp
|
package/lib/support/har/index.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import merge from 'lodash.merge';
|
|
3
|
-
import pick from 'lodash.pick';
|
|
4
|
-
import isEmpty from 'lodash.isempty';
|
|
5
3
|
import get from 'lodash.get';
|
|
6
|
-
import dayjs from 'dayjs';
|
|
7
4
|
import { pathToFolder } from '../pathToFolder.js';
|
|
8
|
-
import
|
|
9
|
-
|
|
5
|
+
import { localTime } from '../util.js';
|
|
6
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
7
|
+
const log = getLogger('browsertime');
|
|
10
8
|
const require = createRequire(import.meta.url);
|
|
11
9
|
const version = require('../../../package.json').version;
|
|
10
|
+
import { pick, isEmpty } from '../../support/util.js';
|
|
12
11
|
|
|
13
12
|
function generateUniquePageId(baseId, existingIdMap) {
|
|
14
13
|
let newId = baseId;
|
|
@@ -288,7 +287,7 @@ export function getEmptyHAR(url, browser) {
|
|
|
288
287
|
},
|
|
289
288
|
pages: [
|
|
290
289
|
{
|
|
291
|
-
startedDateTime:
|
|
290
|
+
startedDateTime: localTime(),
|
|
292
291
|
id: 'failing_page',
|
|
293
292
|
title: url,
|
|
294
293
|
pageTimings: {},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { pathToFolder } from '../pathToFolder.js';
|
|
3
|
-
|
|
3
|
+
import { loadCustomJimp } from '../../screenshot/loadCustomJimp.js';
|
|
4
4
|
export async function savePngWithoutResize(
|
|
5
5
|
name,
|
|
6
6
|
data,
|
|
@@ -24,18 +24,13 @@ export async function savePng(
|
|
|
24
24
|
dir,
|
|
25
25
|
options
|
|
26
26
|
) {
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
jimp = await import('jimp');
|
|
30
|
-
} catch {
|
|
31
|
-
jimp = undefined;
|
|
32
|
-
}
|
|
27
|
+
const jimp = await loadCustomJimp();
|
|
33
28
|
|
|
34
29
|
if (jimp) {
|
|
35
|
-
const image = await jimp.
|
|
30
|
+
const image = await jimp.read(data);
|
|
36
31
|
const buffer = await image
|
|
37
32
|
.deflateLevel(config.png.compressionLevel)
|
|
38
|
-
.scaleToFit(config.maxSize, config.maxSize, jimp.
|
|
33
|
+
.scaleToFit(config.maxSize, config.maxSize, jimp.RESIZE_HERMITE)
|
|
39
34
|
.getBufferAsync('image/png');
|
|
40
35
|
|
|
41
36
|
return storageManager.writeData(
|
|
@@ -54,18 +49,14 @@ export async function saveJpg(
|
|
|
54
49
|
dir,
|
|
55
50
|
options
|
|
56
51
|
) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
jimp = await import('jimp');
|
|
60
|
-
} catch {
|
|
61
|
-
jimp = undefined;
|
|
62
|
-
}
|
|
52
|
+
const jimp = await loadCustomJimp();
|
|
53
|
+
|
|
63
54
|
if (jimp) {
|
|
64
|
-
const image = await jimp.
|
|
55
|
+
const image = await jimp.read(data);
|
|
65
56
|
// https://github.com/sitespeedio/sitespeed.io/issues/3922
|
|
66
57
|
const buffer = await image
|
|
67
58
|
.quality(config.jpg.quality)
|
|
68
|
-
.scaleToFit(config.maxSize, config.maxSize, jimp.
|
|
59
|
+
.scaleToFit(config.maxSize, config.maxSize, jimp.RESIZE_HERMITE)
|
|
69
60
|
.getBufferAsync('image/jpeg');
|
|
70
61
|
return storageManager.writeData(
|
|
71
62
|
`${name}.jpg`,
|
package/lib/support/logging.js
CHANGED
|
@@ -1,41 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// configure.js
|
|
2
|
+
import { configureLog } from '@sitespeed.io/log';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
case 3: {
|
|
18
|
-
level = TRACE;
|
|
19
|
-
break;
|
|
20
|
-
}
|
|
21
|
-
default: {
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (options.silent) {
|
|
27
|
-
level = NONE;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (level === INFO) {
|
|
31
|
-
basicConfig({
|
|
32
|
-
format: '[%(date)s] %(levelname)s: %(message)s',
|
|
33
|
-
level: level
|
|
34
|
-
});
|
|
35
|
-
} else {
|
|
36
|
-
basicConfig({
|
|
37
|
-
format: '[%(date)s] %(levelname)s: [%(name)s] %(message)s',
|
|
38
|
-
level: level
|
|
39
|
-
});
|
|
40
|
-
}
|
|
4
|
+
/**
|
|
5
|
+
* Adapted from old intel-based configure logic.
|
|
6
|
+
*
|
|
7
|
+
* @param {Object} options
|
|
8
|
+
* @param {number} [options.verbose=0] - 0: Info, 1: Debug, 2: Verbose, 3: Trace
|
|
9
|
+
* @param {boolean} [options.silent=false] - If true, disables logging
|
|
10
|
+
*/
|
|
11
|
+
export function configure(options = {}) {
|
|
12
|
+
configureLog({
|
|
13
|
+
verbose: options.verbose ?? 0,
|
|
14
|
+
silent: options.silent ?? false
|
|
15
|
+
});
|
|
41
16
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parse } from 'node:url';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
const log =
|
|
3
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
4
|
+
import { isEmpty } from './util.js';
|
|
5
|
+
const log = getLogger('browsertime');
|
|
6
6
|
|
|
7
7
|
function toSafeKey(key) {
|
|
8
8
|
// U+2013 : EN DASH – as used on https://en.wikipedia.org/wiki/2019–20_coronavirus_pandemic
|
package/lib/support/preURL.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
const log =
|
|
1
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
2
|
+
const log = getLogger('browsertime');
|
|
3
3
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
4
4
|
|
|
5
5
|
export async function preURL(browser, options) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import get from 'lodash.get';
|
|
2
2
|
import set from 'lodash.set';
|
|
3
3
|
import { Stats } from 'fast-stats';
|
|
4
|
-
import
|
|
5
|
-
const log =
|
|
4
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
5
|
+
const log = getLogger('browsertime');
|
|
6
6
|
|
|
7
7
|
function validateType(value, type, message) {
|
|
8
8
|
if (typeof value !== type) {
|
package/lib/support/stop.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execa } from 'execa';
|
|
2
|
-
import
|
|
3
|
-
const log =
|
|
2
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
3
|
+
const log = getLogger('browsertime');
|
|
4
4
|
|
|
5
5
|
export async function stop(processName) {
|
|
6
6
|
const scriptArguments = ['-9', processName];
|
|
@@ -11,19 +11,19 @@ import {
|
|
|
11
11
|
createReadStream,
|
|
12
12
|
createWriteStream
|
|
13
13
|
} from 'node:fs';
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
|
|
14
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
15
|
+
import { localTime, isEmpty } from './util.js';
|
|
16
|
+
|
|
17
17
|
const gunzip = promisify(_gunzip);
|
|
18
18
|
const writeFile = promisify(_writeFile);
|
|
19
19
|
const readFile = promisify(_readFile);
|
|
20
20
|
const gzip = promisify(_gzip);
|
|
21
21
|
const unlink = promisify(_unlink);
|
|
22
22
|
const mkdir = promisify(_mkdir);
|
|
23
|
-
const log =
|
|
23
|
+
const log = getLogger('browsertime');
|
|
24
24
|
|
|
25
25
|
const defaultDir = 'browsertime-results';
|
|
26
|
-
let timestamp =
|
|
26
|
+
let timestamp = localTime().replaceAll(':', '');
|
|
27
27
|
|
|
28
28
|
function pathNameFromUrl(url) {
|
|
29
29
|
const parsedUrl = parse(url),
|