browsertime 23.4.5 → 24.0.0-alpha.1
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 +32 -1
- 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 +14 -3
- 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 +15 -16
- 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 +19 -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/userTiming.js +10 -0
- 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 +19 -24
- package/types/core/engine/command/measure.d.ts.map +1 -1
- 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/storageManager.d.ts +0 -1
- package/types/support/storageManager.d.ts.map +1 -1
- package/types/support/userTiming.d.ts +1 -0
- package/types/support/userTiming.d.ts.map +1 -1
- package/types/support/util.d.ts +3 -0
- package/types/support/util.d.ts.map +1 -1
- package/types/video/defaults.d.ts.map +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getLogger } from '@sitespeed.io/log';
|
|
2
2
|
import merge from 'lodash.merge';
|
|
3
3
|
import get from 'lodash.get';
|
|
4
4
|
import { Condition } from 'selenium-webdriver';
|
|
@@ -9,7 +9,7 @@ import { getViewPort } from '../support/getViewPort.js';
|
|
|
9
9
|
import { defaultPageCompleteCheck } from './pageCompleteChecks/defaultPageCompleteCheck.js';
|
|
10
10
|
import { pageCompleteCheckByInactivity } from './pageCompleteChecks/pageCompleteCheckByInactivity.js';
|
|
11
11
|
import { spaInactivity as spaCheck } from './pageCompleteChecks/spaInactivity.js';
|
|
12
|
-
const log =
|
|
12
|
+
const log = getLogger('browsertime');
|
|
13
13
|
|
|
14
14
|
const defaults = {
|
|
15
15
|
timeouts: {
|
|
@@ -402,11 +402,8 @@ export class SeleniumRunner {
|
|
|
402
402
|
async runScript(script, name, arguments_) {
|
|
403
403
|
let scriptTimeout = this.options.timeouts.script;
|
|
404
404
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
} else if (log.isEnabledFor(log.VERBOSE)) {
|
|
408
|
-
log.verbose('Executing script %s', name);
|
|
409
|
-
}
|
|
405
|
+
log.verbose('Executing script %s', script);
|
|
406
|
+
log.verbose('Executing script %s', name);
|
|
410
407
|
|
|
411
408
|
try {
|
|
412
409
|
const result = await timeout(
|
|
@@ -463,11 +460,10 @@ export class SeleniumRunner {
|
|
|
463
460
|
* @throws {BrowserError}
|
|
464
461
|
*/
|
|
465
462
|
async runAsyncScript(script, name, arguments_) {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
463
|
+
log.verbose('Executing async script %s', script);
|
|
464
|
+
|
|
465
|
+
log.verbose('Executing async script %s', name);
|
|
466
|
+
|
|
471
467
|
return this.driver.executeAsyncScript(script, arguments_);
|
|
472
468
|
}
|
|
473
469
|
|
|
@@ -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
|
|
|
@@ -1255,6 +1265,10 @@ export function parseCommandLine() {
|
|
|
1255
1265
|
describe:
|
|
1256
1266
|
'All userTimings are captured by default this option takes a regex that will allow which userTimings to capture in the results.'
|
|
1257
1267
|
})
|
|
1268
|
+
.option('userTimingBlockList', {
|
|
1269
|
+
describe:
|
|
1270
|
+
'All userTimings are captured by default this option takes a regex that will block some usertimings in the results.'
|
|
1271
|
+
})
|
|
1258
1272
|
.option('headless', {
|
|
1259
1273
|
type: 'boolean',
|
|
1260
1274
|
default: false,
|
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),
|