@memlab/api 1.0.1 → 1.0.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/dist/API.d.ts +80 -18
- package/dist/API.d.ts.map +1 -1
- package/dist/API.js +85 -15
- package/dist/__tests__/API/E2EDetachedDOMAnalysis.test.js +5 -6
- package/dist/__tests__/API/E2EDuplicateObjectAnalysis.test.js +5 -6
- package/dist/__tests__/API/E2EFindLeaks.example.d.ts +11 -0
- package/dist/__tests__/API/E2EFindLeaks.example.d.ts.map +1 -0
- package/dist/__tests__/API/E2EFindLeaks.example.js +50 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.d.ts +11 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.d.ts.map +1 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.js +51 -0
- package/dist/__tests__/API/E2EResultReader.test.d.ts +11 -0
- package/dist/__tests__/API/E2EResultReader.test.d.ts.map +1 -0
- package/dist/__tests__/API/E2EResultReader.test.js +72 -0
- package/dist/__tests__/API/E2ERunSingleSnapshot.example.js +11 -12
- package/dist/__tests__/API/E2EShapeUnboundGrowthAnalysis.test.js +4 -15
- package/dist/__tests__/API/E2EStringAnalysis.test.js +19 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/result-reader/BaseResultReader.d.ts +49 -0
- package/dist/result-reader/BaseResultReader.d.ts.map +1 -0
- package/dist/result-reader/BaseResultReader.js +72 -0
- package/dist/result-reader/BrowserInteractionResultReader.d.ts +46 -0
- package/dist/result-reader/BrowserInteractionResultReader.d.ts.map +1 -0
- package/dist/result-reader/BrowserInteractionResultReader.js +77 -0
- package/package.json +1 -1
package/dist/API.d.ts
CHANGED
|
@@ -7,34 +7,96 @@
|
|
|
7
7
|
* @emails oncall+ws_labs
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
|
-
import type { Page } from 'puppeteer';
|
|
11
10
|
import type { ParsedArgs } from 'minimist';
|
|
12
|
-
import type { AnyFunction,
|
|
11
|
+
import type { AnyFunction, AnyValue, ISerializedInfo, IScenario } from '@memlab/core';
|
|
13
12
|
import { MemLabConfig } from '@memlab/core';
|
|
14
13
|
import { TestPlanner } from '@memlab/e2e';
|
|
15
14
|
import { BaseAnalysis } from '@memlab/heap-analysis';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
declare type RunOptions = {
|
|
15
|
+
import BrowserInteractionResultReader from './result-reader/BrowserInteractionResultReader';
|
|
16
|
+
/**
|
|
17
|
+
* Options for configuring browser interaction run
|
|
18
|
+
*/
|
|
19
|
+
export declare type RunOptions = {
|
|
20
|
+
/** test scenario definition */
|
|
23
21
|
scenario?: IScenario;
|
|
22
|
+
/** cookies file */
|
|
24
23
|
cookiesFile?: string;
|
|
24
|
+
/** function to be evaluated in browser context after the web page initial load */
|
|
25
25
|
evalInBrowserAfterInitLoad?: AnyFunction;
|
|
26
|
+
/**
|
|
27
|
+
* if true, take heap snapshot for each interaction step,
|
|
28
|
+
* by default this is false, which means memlab will decide
|
|
29
|
+
* which steps it will take heap snapshots
|
|
30
|
+
*/
|
|
26
31
|
snapshotForEachStep?: boolean;
|
|
27
32
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
/**
|
|
34
|
+
* @ignore
|
|
35
|
+
* Options for memlab inter-package API calls
|
|
36
|
+
*/
|
|
37
|
+
export declare type APIOptions = {
|
|
38
|
+
testPlanner?: TestPlanner;
|
|
39
|
+
cache?: boolean;
|
|
40
|
+
config?: MemLabConfig;
|
|
41
|
+
evalInBrowserAfterInitLoad?: AnyFunction;
|
|
32
42
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
/**
|
|
44
|
+
* This API warms up web server, runs E2E interaction, and takes heap snapshots.
|
|
45
|
+
* This is equivalent to run `memlab warmup-and-snapshot` in CLI.
|
|
46
|
+
* This is also equivalent to call {@link warmup} and {@link takeSnapshots}.
|
|
47
|
+
*
|
|
48
|
+
* @param options configure browser interaction run
|
|
49
|
+
* @returns browser interaction results
|
|
50
|
+
*/
|
|
51
|
+
export declare function warmupAndTakeSnapshots(options?: RunOptions): Promise<BrowserInteractionResultReader>;
|
|
52
|
+
/**
|
|
53
|
+
* This API runs browser interaction and find memory leaks triggered in browser
|
|
54
|
+
* This is equivalent to run `memlab run` in CLI.
|
|
55
|
+
* This is also equivalent to call {@link warmup}, {@link takeSnapshots},
|
|
56
|
+
* and {@link findLeaks}.
|
|
57
|
+
*
|
|
58
|
+
* @param options configure browser interaction run
|
|
59
|
+
* @returns an array of leak traces detected and clustered from the
|
|
60
|
+
* browser interaction
|
|
61
|
+
*/
|
|
62
|
+
export declare function run(options?: RunOptions): Promise<ISerializedInfo[]>;
|
|
63
|
+
/**
|
|
64
|
+
* This API runs E2E interaction and takes heap snapshots.
|
|
65
|
+
* This is equivalent to run `memlab snapshot` in CLI.
|
|
66
|
+
*
|
|
67
|
+
* @param options configure browser interaction run
|
|
68
|
+
* @returns browser interaction results
|
|
69
|
+
*/
|
|
70
|
+
export declare function takeSnapshots(options?: RunOptions): Promise<BrowserInteractionResultReader>;
|
|
71
|
+
/**
|
|
72
|
+
* This API finds memory leaks by analyzing heap snapshot(s)
|
|
73
|
+
* This is equivalent to `memlab find-leaks` in CLI.
|
|
74
|
+
*
|
|
75
|
+
* @param runResult return value of a browser interaction run
|
|
76
|
+
* @returns an array of leak traces detected and clustered from the
|
|
77
|
+
* browser interaction
|
|
78
|
+
*/
|
|
79
|
+
export declare function findLeaks(runResult: BrowserInteractionResultReader): Promise<ISerializedInfo[]>;
|
|
80
|
+
/**
|
|
81
|
+
* This API analyzes heap snapshot(s) with a specified heap analysis.
|
|
82
|
+
* This is equivalent to `memlab analyze` in CLI.
|
|
83
|
+
*
|
|
84
|
+
* @param runResult return value of a browser interaction run
|
|
85
|
+
* @param heapAnalyzer instance of a heap analysis
|
|
86
|
+
* @param args other CLI arguments that needs to be passed to the heap analysis
|
|
87
|
+
* @returns
|
|
88
|
+
*/
|
|
89
|
+
export declare function analyze(runResult: BrowserInteractionResultReader, heapAnalyzer: BaseAnalysis, args?: ParsedArgs): Promise<AnyValue>;
|
|
90
|
+
/**
|
|
91
|
+
* @ignore
|
|
92
|
+
* This warms up web server by sending web requests to the web sever.
|
|
93
|
+
* This is equivalent to run `memlab warmup` in CLI.
|
|
94
|
+
*
|
|
95
|
+
* @param options configure browser interaction run
|
|
96
|
+
*/
|
|
36
97
|
export declare function warmup(options?: APIOptions): Promise<void>;
|
|
37
|
-
|
|
98
|
+
/**
|
|
99
|
+
* @ignore
|
|
100
|
+
*/
|
|
38
101
|
export declare function testInBrowser(options?: APIOptions): Promise<void>;
|
|
39
|
-
export {};
|
|
40
102
|
//# sourceMappingURL=API.d.ts.map
|
package/dist/API.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"API.d.ts","sourceRoot":"","sources":["../src/API.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"API.d.ts","sourceRoot":"","sources":["../src/API.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,eAAe,EACf,SAAS,EAGV,MAAM,cAAc,CAAC;AAEtB,OAAO,EAML,YAAY,EAEb,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,WAAW,EAGZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AAEnD,OAAO,8BAA8B,MAAM,gDAAgD,CAAC;AAE5F;;GAEG;AACH,oBAAY,UAAU,GAAG;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,0BAA0B,CAAC,EAAE,WAAW,CAAC;IACzC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,oBAAY,UAAU,GAAG;IAGvB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,0BAA0B,CAAC,EAAE,WAAW,CAAC;CAC1C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,8BAA8B,CAAC,CAUzC;AAED;;;;;;;;;GASG;AACH,wBAAsB,GAAG,CACvB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAW5B;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,8BAA8B,CAAC,CASzC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,8BAA8B,GACxC,OAAO,CAAC,eAAe,EAAE,CAAC,CAK5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,8BAA8B,EACzC,YAAY,EAAE,YAAY,EAC1B,IAAI,GAAE,UAAoB,GACzB,OAAO,CAAC,QAAQ,CAAC,CAInB;AAED;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCpE;AAsDD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD3E"}
|
package/dist/API.js
CHANGED
|
@@ -21,13 +21,43 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.testInBrowser = exports.
|
|
24
|
+
exports.testInBrowser = exports.warmup = exports.analyze = exports.findLeaks = exports.takeSnapshots = exports.run = exports.warmupAndTakeSnapshots = void 0;
|
|
25
25
|
const core_1 = require("@memlab/core");
|
|
26
26
|
const e2e_1 = require("@memlab/e2e");
|
|
27
27
|
const APIUtils_1 = __importDefault(require("./lib/APIUtils"));
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const BrowserInteractionResultReader_1 = __importDefault(require("./result-reader/BrowserInteractionResultReader"));
|
|
29
|
+
/**
|
|
30
|
+
* This API warms up web server, runs E2E interaction, and takes heap snapshots.
|
|
31
|
+
* This is equivalent to run `memlab warmup-and-snapshot` in CLI.
|
|
32
|
+
* This is also equivalent to call {@link warmup} and {@link takeSnapshots}.
|
|
33
|
+
*
|
|
34
|
+
* @param options configure browser interaction run
|
|
35
|
+
* @returns browser interaction results
|
|
36
|
+
*/
|
|
37
|
+
function warmupAndTakeSnapshots(options = {}) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
40
|
+
setConfigByRunOptions(config, options);
|
|
41
|
+
config.externalCookiesFile = options.cookiesFile;
|
|
42
|
+
config.scenario = options.scenario;
|
|
43
|
+
const testPlanner = new e2e_1.TestPlanner({ config });
|
|
44
|
+
const { evalInBrowserAfterInitLoad } = options;
|
|
45
|
+
yield warmup({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
46
|
+
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
47
|
+
return BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
48
|
+
});
|
|
30
49
|
}
|
|
50
|
+
exports.warmupAndTakeSnapshots = warmupAndTakeSnapshots;
|
|
51
|
+
/**
|
|
52
|
+
* This API runs browser interaction and find memory leaks triggered in browser
|
|
53
|
+
* This is equivalent to run `memlab run` in CLI.
|
|
54
|
+
* This is also equivalent to call {@link warmup}, {@link takeSnapshots},
|
|
55
|
+
* and {@link findLeaks}.
|
|
56
|
+
*
|
|
57
|
+
* @param options configure browser interaction run
|
|
58
|
+
* @returns an array of leak traces detected and clustered from the
|
|
59
|
+
* browser interaction
|
|
60
|
+
*/
|
|
31
61
|
function run(options = {}) {
|
|
32
62
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
63
|
const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
@@ -38,14 +68,18 @@ function run(options = {}) {
|
|
|
38
68
|
const { evalInBrowserAfterInitLoad } = options;
|
|
39
69
|
yield warmup({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
40
70
|
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
tabsOrder: core_1.utils.loadTabsOrder(),
|
|
44
|
-
metaInfo: core_1.utils.loadRunMetaInfo(),
|
|
45
|
-
};
|
|
71
|
+
const runResult = BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
72
|
+
return yield findLeaks(runResult);
|
|
46
73
|
});
|
|
47
74
|
}
|
|
48
75
|
exports.run = run;
|
|
76
|
+
/**
|
|
77
|
+
* This API runs E2E interaction and takes heap snapshots.
|
|
78
|
+
* This is equivalent to run `memlab snapshot` in CLI.
|
|
79
|
+
*
|
|
80
|
+
* @param options configure browser interaction run
|
|
81
|
+
* @returns browser interaction results
|
|
82
|
+
*/
|
|
49
83
|
function takeSnapshots(options = {}) {
|
|
50
84
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
85
|
const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
@@ -55,20 +89,51 @@ function takeSnapshots(options = {}) {
|
|
|
55
89
|
const testPlanner = new e2e_1.TestPlanner();
|
|
56
90
|
const { evalInBrowserAfterInitLoad } = options;
|
|
57
91
|
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
58
|
-
return
|
|
59
|
-
config,
|
|
60
|
-
tabsOrder: core_1.utils.loadTabsOrder(),
|
|
61
|
-
metaInfo: core_1.utils.loadRunMetaInfo(),
|
|
62
|
-
};
|
|
92
|
+
return BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
63
93
|
});
|
|
64
94
|
}
|
|
65
95
|
exports.takeSnapshots = takeSnapshots;
|
|
96
|
+
/**
|
|
97
|
+
* This API finds memory leaks by analyzing heap snapshot(s)
|
|
98
|
+
* This is equivalent to `memlab find-leaks` in CLI.
|
|
99
|
+
*
|
|
100
|
+
* @param runResult return value of a browser interaction run
|
|
101
|
+
* @returns an array of leak traces detected and clustered from the
|
|
102
|
+
* browser interaction
|
|
103
|
+
*/
|
|
104
|
+
function findLeaks(runResult) {
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
const workDir = runResult.getRootDirectory();
|
|
107
|
+
core_1.fileManager.initDirs(core_1.config, { workDir });
|
|
108
|
+
core_1.config.chaseWeakMapEdge = false;
|
|
109
|
+
return yield core_1.analysis.checkLeak();
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
exports.findLeaks = findLeaks;
|
|
113
|
+
/**
|
|
114
|
+
* This API analyzes heap snapshot(s) with a specified heap analysis.
|
|
115
|
+
* This is equivalent to `memlab analyze` in CLI.
|
|
116
|
+
*
|
|
117
|
+
* @param runResult return value of a browser interaction run
|
|
118
|
+
* @param heapAnalyzer instance of a heap analysis
|
|
119
|
+
* @param args other CLI arguments that needs to be passed to the heap analysis
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
66
122
|
function analyze(runResult, heapAnalyzer, args = { _: [] }) {
|
|
67
123
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
-
|
|
124
|
+
const workDir = runResult.getRootDirectory();
|
|
125
|
+
core_1.fileManager.initDirs(core_1.config, { workDir });
|
|
126
|
+
return yield heapAnalyzer.run({ args });
|
|
69
127
|
});
|
|
70
128
|
}
|
|
71
129
|
exports.analyze = analyze;
|
|
130
|
+
/**
|
|
131
|
+
* @ignore
|
|
132
|
+
* This warms up web server by sending web requests to the web sever.
|
|
133
|
+
* This is equivalent to run `memlab warmup` in CLI.
|
|
134
|
+
*
|
|
135
|
+
* @param options configure browser interaction run
|
|
136
|
+
*/
|
|
72
137
|
function warmup(options = {}) {
|
|
73
138
|
var _a, _b;
|
|
74
139
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -109,6 +174,9 @@ function warmup(options = {}) {
|
|
|
109
174
|
});
|
|
110
175
|
}
|
|
111
176
|
exports.warmup = warmup;
|
|
177
|
+
function setConfigByRunOptions(config, options) {
|
|
178
|
+
config.isFullRun = !!options.snapshotForEachStep;
|
|
179
|
+
}
|
|
112
180
|
function setupPage(page, options = {}) {
|
|
113
181
|
var _a, _b, _c;
|
|
114
182
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -130,7 +198,6 @@ function setupPage(page, options = {}) {
|
|
|
130
198
|
}));
|
|
131
199
|
});
|
|
132
200
|
}
|
|
133
|
-
exports.setupPage = setupPage;
|
|
134
201
|
function autoDismissDialog(page, options = {}) {
|
|
135
202
|
var _a;
|
|
136
203
|
const config = (_a = options.config) !== null && _a !== void 0 ? _a : core_1.config;
|
|
@@ -153,6 +220,9 @@ function initBrowserInfoInConfig(browser, options = {}) {
|
|
|
153
220
|
}
|
|
154
221
|
});
|
|
155
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* @ignore
|
|
225
|
+
*/
|
|
156
226
|
function testInBrowser(options = {}) {
|
|
157
227
|
var _a, _b;
|
|
158
228
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -17,12 +17,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
21
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
-
const path_1 = __importDefault(require("path"));
|
|
26
22
|
const index_1 = require("../../index");
|
|
27
23
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
28
24
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -34,14 +30,17 @@ function inject() {
|
|
|
34
30
|
};
|
|
35
31
|
}
|
|
36
32
|
test('Detached DOM analysis works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
37
|
-
const result = yield (0, index_1.
|
|
33
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
34
|
+
scenario: E2ETestSettings_1.scenario,
|
|
35
|
+
evalInBrowserAfterInitLoad: inject,
|
|
36
|
+
});
|
|
38
37
|
// test analysis from auto loading
|
|
39
38
|
let analysis = new index_1.DetachedDOMElementAnalysis();
|
|
40
39
|
yield analysis.run();
|
|
41
40
|
let domElems = analysis.getDetachedElements();
|
|
42
41
|
expect(domElems.some(node => node.name === 'Detached HTMLTableElement')).toBe(true);
|
|
43
42
|
// test analysis from file
|
|
44
|
-
const snapshotFile =
|
|
43
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
45
44
|
analysis = new index_1.DetachedDOMElementAnalysis();
|
|
46
45
|
yield analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
47
46
|
domElems = analysis.getDetachedElements();
|
|
@@ -17,11 +17,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
const path_1 = __importDefault(require("path"));
|
|
25
21
|
const index_1 = require("../../index");
|
|
26
22
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
27
23
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -39,14 +35,17 @@ function inject() {
|
|
|
39
35
|
};
|
|
40
36
|
}
|
|
41
37
|
test('Duplicate object analysis works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
-
const result = yield (0, index_1.
|
|
38
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
39
|
+
scenario: E2ETestSettings_1.scenario,
|
|
40
|
+
evalInBrowserAfterInitLoad: inject,
|
|
41
|
+
});
|
|
43
42
|
// test analysis from auto loading
|
|
44
43
|
let analysis = new index_1.ObjectShallowAnalysis();
|
|
45
44
|
yield analysis.run();
|
|
46
45
|
let dupcatedObjectInfo = analysis.getTopDuplicatedObjectInCount();
|
|
47
46
|
expect(dupcatedObjectInfo[0].n).toBe(12345);
|
|
48
47
|
// test analysis from file
|
|
49
|
-
const snapshotFile =
|
|
48
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
50
49
|
analysis = new index_1.ObjectShallowAnalysis();
|
|
51
50
|
yield analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
52
51
|
dupcatedObjectInfo = analysis.getTopDuplicatedObjectInCount();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=E2EFindLeaks.example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"E2EFindLeaks.example.d.ts","sourceRoot":"","sources":["../../../src/__tests__/API/E2EFindLeaks.example.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
22
|
+
const core_1 = require("@memlab/core");
|
|
23
|
+
const index_1 = require("../../index");
|
|
24
|
+
const scenario = {
|
|
25
|
+
app: () => 'test-spa',
|
|
26
|
+
url: () => '',
|
|
27
|
+
action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
|
|
28
|
+
};
|
|
29
|
+
function inject() {
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
window.injectHookForLink4 = () => {
|
|
32
|
+
const arr = [];
|
|
33
|
+
for (let i = 0; i < 23; ++i) {
|
|
34
|
+
arr.push(document.createElement('div'));
|
|
35
|
+
}
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
window.__injectedValue = arr;
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
window._path_1 = { x: { y: document.createElement('div') } };
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
window._path_2 = new Set([document.createElement('div')]);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function test() {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
const leaks = yield (0, index_1.run)({ scenario, evalInBrowserAfterInitLoad: inject });
|
|
47
|
+
core_1.info.lowLevel(`${leaks.length}`);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
test();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=E2EFindMemoryLeaks.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"E2EFindMemoryLeaks.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/API/E2EFindMemoryLeaks.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
22
|
+
const index_1 = require("../../index");
|
|
23
|
+
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
24
|
+
beforeEach(E2ETestSettings_1.testSetup);
|
|
25
|
+
function injectDetachedDOMElements() {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
window.injectHookForLink4 = () => {
|
|
28
|
+
const arr = [];
|
|
29
|
+
for (let i = 0; i < 23; ++i) {
|
|
30
|
+
arr.push(document.createElement('div'));
|
|
31
|
+
}
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
window.__injectedValue = arr;
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
window._path_1 = { x: { y: document.createElement('div') } };
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
window._path_2 = new Set([document.createElement('div')]);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
test('leak detector can find detached DOM elements', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
const leaks = yield (0, index_1.run)({
|
|
42
|
+
scenario: E2ETestSettings_1.scenario,
|
|
43
|
+
evalInBrowserAfterInitLoad: injectDetachedDOMElements,
|
|
44
|
+
});
|
|
45
|
+
// detected all different leak trace cluster
|
|
46
|
+
expect(leaks.length).toBe(3);
|
|
47
|
+
// expect all traces are found
|
|
48
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('__injectedValue')));
|
|
49
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('_path_1')));
|
|
50
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('_path_2')));
|
|
51
|
+
}), E2ETestSettings_1.testTimeout);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=E2EResultReader.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"E2EResultReader.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/API/E2EResultReader.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
+
const fs_1 = __importDefault(require("fs"));
|
|
26
|
+
const BrowserInteractionResultReader_1 = __importDefault(require("../../result-reader/BrowserInteractionResultReader"));
|
|
27
|
+
const index_1 = require("../../index");
|
|
28
|
+
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
29
|
+
beforeEach(E2ETestSettings_1.testSetup);
|
|
30
|
+
function inject() {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
window.injectHookForLink4 = () => {
|
|
33
|
+
const arr = [];
|
|
34
|
+
for (let i = 0; i < 10000; ++i) {
|
|
35
|
+
arr.push('duplicated string value' + (i % 1));
|
|
36
|
+
}
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
window.__injectedValue = arr;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function checkResultReader(result) {
|
|
42
|
+
const workDir = result.getRootDirectory();
|
|
43
|
+
expect(fs_1.default.existsSync(workDir)).toBe(true);
|
|
44
|
+
const snapshotDir = result.getSnapshotFileDir();
|
|
45
|
+
expect(fs_1.default.existsSync(snapshotDir)).toBe(true);
|
|
46
|
+
const snapshotFiles = result.getSnapshotFiles();
|
|
47
|
+
expect(snapshotFiles.length > 0).toBe(true);
|
|
48
|
+
const steps = result.getInteractionSteps();
|
|
49
|
+
expect(steps.length > 0).toBe(true);
|
|
50
|
+
expect(steps[0].name).toBe('page-load');
|
|
51
|
+
const runMeta = result.getRunMetaInfo();
|
|
52
|
+
expect(runMeta.app).toBe('test-spa');
|
|
53
|
+
result.cleanup();
|
|
54
|
+
expect(fs_1.default.existsSync(workDir)).toBe(false);
|
|
55
|
+
expect(() => result.getRootDirectory()).toThrowError();
|
|
56
|
+
expect(() => result.getSnapshotFileDir()).toThrowError();
|
|
57
|
+
expect(() => result.getSnapshotFiles()).toThrowError();
|
|
58
|
+
}
|
|
59
|
+
test('result data/file reader is working as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
61
|
+
scenario: E2ETestSettings_1.scenario,
|
|
62
|
+
evalInBrowserAfterInitLoad: inject,
|
|
63
|
+
});
|
|
64
|
+
checkResultReader(result);
|
|
65
|
+
}), E2ETestSettings_1.testTimeout);
|
|
66
|
+
test('ResultReader.from is working as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
68
|
+
scenario: E2ETestSettings_1.scenario,
|
|
69
|
+
evalInBrowserAfterInitLoad: inject,
|
|
70
|
+
});
|
|
71
|
+
checkResultReader(BrowserInteractionResultReader_1.default.from(result.getRootDirectory()));
|
|
72
|
+
}), E2ETestSettings_1.testTimeout);
|
|
@@ -17,22 +17,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
const path_1 = __importDefault(require("path"));
|
|
25
21
|
const index_1 = require("../../index");
|
|
26
22
|
const scenario = {
|
|
27
23
|
app: () => 'test-spa',
|
|
28
24
|
url: () => '',
|
|
29
25
|
action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
|
|
30
26
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
function test() {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
30
|
+
scenario,
|
|
31
|
+
});
|
|
32
|
+
const analysis = new index_1.StringAnalysis();
|
|
33
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
34
|
+
analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
test();
|
|
@@ -17,12 +17,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
21
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
-
const path_1 = __importDefault(require("path"));
|
|
26
22
|
const index_1 = require("../../index");
|
|
27
23
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
28
24
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -44,7 +40,7 @@ function inject() {
|
|
|
44
40
|
test('Shape unbound analysis works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
41
|
const repeatScenario = Object.assign({ repeat: () => 2 }, E2ETestSettings_1.scenario);
|
|
46
42
|
// test analysis from auto loading
|
|
47
|
-
const result = yield (0, index_1.
|
|
43
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
48
44
|
scenario: repeatScenario,
|
|
49
45
|
evalInBrowserAfterInitLoad: inject,
|
|
50
46
|
snapshotForEachStep: true,
|
|
@@ -54,19 +50,12 @@ test('Shape unbound analysis works as expected', () => __awaiter(void 0, void 0,
|
|
|
54
50
|
let shapeSummary = yield analysis.run();
|
|
55
51
|
expect(shapeSummary.reduce((acc, summary) => acc || summary.shape.includes('LeakObject'), false)).toBe(true);
|
|
56
52
|
// test analysis from file
|
|
57
|
-
const snapshotDir =
|
|
53
|
+
const snapshotDir = result.getSnapshotFileDir();
|
|
58
54
|
analysis = new index_1.ShapeUnboundGrowthAnalysis();
|
|
59
55
|
shapeSummary = yield analysis.analyzeSnapshotsInDirectory(snapshotDir);
|
|
60
56
|
expect(shapeSummary.some((summary) => summary.shape.includes('LeakObject'))).toBe(true);
|
|
61
57
|
// expect incorrect use of heap analysis to throw
|
|
62
|
-
const snapshotFile =
|
|
58
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
63
59
|
analysis = new index_1.ShapeUnboundGrowthAnalysis();
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
yield analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
67
|
-
}
|
|
68
|
-
catch (ex) {
|
|
69
|
-
isThrow = true;
|
|
70
|
-
}
|
|
71
|
-
expect(isThrow).toBe(true);
|
|
60
|
+
expect(() => __awaiter(void 0, void 0, void 0, function* () { return yield analysis.analyzeSnapshotFromFile(snapshotFile); })).rejects.toThrowError();
|
|
72
61
|
}), E2ETestSettings_1.testTimeout);
|
|
@@ -17,12 +17,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
-
};
|
|
23
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
21
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
25
|
-
const path_1 = __importDefault(require("path"));
|
|
26
22
|
const index_1 = require("../../index");
|
|
27
23
|
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
28
24
|
beforeEach(E2ETestSettings_1.testSetup);
|
|
@@ -38,7 +34,10 @@ function inject() {
|
|
|
38
34
|
};
|
|
39
35
|
}
|
|
40
36
|
test('String analysis works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
-
const result = yield (0, index_1.
|
|
37
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
38
|
+
scenario: E2ETestSettings_1.scenario,
|
|
39
|
+
evalInBrowserAfterInitLoad: inject,
|
|
40
|
+
});
|
|
42
41
|
// test analysis from auto loading
|
|
43
42
|
let analysis = new index_1.StringAnalysis();
|
|
44
43
|
yield analysis.run();
|
|
@@ -46,21 +45,26 @@ test('String analysis works as expected', () => __awaiter(void 0, void 0, void 0
|
|
|
46
45
|
expect(dupStrings[0].n).toBe(10000);
|
|
47
46
|
expect(dupStrings[0].str).toBe('duplicated string value0');
|
|
48
47
|
// test analysis from file
|
|
49
|
-
const snapshotFile =
|
|
48
|
+
const snapshotFile = result.getSnapshotFiles().pop();
|
|
50
49
|
analysis = new index_1.StringAnalysis();
|
|
51
50
|
yield analysis.analyzeSnapshotFromFile(snapshotFile);
|
|
52
51
|
dupStrings = analysis.getTopDuplicatedStringsInCount();
|
|
53
52
|
expect(dupStrings[0].n).toBe(10000);
|
|
54
53
|
expect(dupStrings[0].str).toBe('duplicated string value0');
|
|
55
54
|
// expect incorrect use of heap analysis to throw
|
|
56
|
-
const snapshotDir = result.
|
|
55
|
+
const snapshotDir = result.getSnapshotFileDir();
|
|
57
56
|
analysis = new index_1.StringAnalysis();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
57
|
+
expect(() => __awaiter(void 0, void 0, void 0, function* () { return yield analysis.analyzeSnapshotsInDirectory(snapshotDir); })).rejects.toThrowError();
|
|
58
|
+
}), E2ETestSettings_1.testTimeout);
|
|
59
|
+
test('analyze function works as expected', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
const result = yield (0, index_1.warmupAndTakeSnapshots)({
|
|
61
|
+
scenario: E2ETestSettings_1.scenario,
|
|
62
|
+
evalInBrowserAfterInitLoad: inject,
|
|
63
|
+
});
|
|
64
|
+
// test analysis from auto loading
|
|
65
|
+
const analysis = new index_1.StringAnalysis();
|
|
66
|
+
yield (0, index_1.analyze)(result, analysis);
|
|
67
|
+
const dupStrings = analysis.getTopDuplicatedStringsInCount();
|
|
68
|
+
expect(dupStrings[0].n).toBe(10000);
|
|
69
|
+
expect(dupStrings[0].str).toBe('duplicated string value0');
|
|
66
70
|
}), E2ETestSettings_1.testTimeout);
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AACpC,OAAO,EAAC,OAAO,IAAI,8BAA8B,EAAC,MAAM,gDAAgD,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -22,9 +22,14 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
22
22
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
23
23
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.config = void 0;
|
|
29
|
+
exports.BrowserInteractionResultReader = exports.config = void 0;
|
|
27
30
|
__exportStar(require("./API"), exports);
|
|
28
31
|
__exportStar(require("@memlab/heap-analysis"), exports);
|
|
29
32
|
var core_1 = require("@memlab/core");
|
|
30
33
|
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return core_1.config; } });
|
|
34
|
+
var BrowserInteractionResultReader_1 = require("./result-reader/BrowserInteractionResultReader");
|
|
35
|
+
Object.defineProperty(exports, "BrowserInteractionResultReader", { enumerable: true, get: function () { return __importDefault(BrowserInteractionResultReader_1).default; } });
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
import { FileManager } from '@memlab/core';
|
|
11
|
+
/**
|
|
12
|
+
* A utility entity to read all generated files from
|
|
13
|
+
* the directory holding the data and results from
|
|
14
|
+
* a memlab run
|
|
15
|
+
*/
|
|
16
|
+
export default class BaseResultReader {
|
|
17
|
+
/** @ignore */
|
|
18
|
+
protected workDir: string;
|
|
19
|
+
/** @ignore */
|
|
20
|
+
protected fileManager: FileManager;
|
|
21
|
+
/** @ignore */
|
|
22
|
+
private isValid;
|
|
23
|
+
/**
|
|
24
|
+
* build a result reader
|
|
25
|
+
* @param workDir absolute path of the directory where the data
|
|
26
|
+
* and generated files of the memlab run were stored
|
|
27
|
+
*/
|
|
28
|
+
protected constructor(workDir?: string);
|
|
29
|
+
/** @ignore */
|
|
30
|
+
protected check(): void;
|
|
31
|
+
/**
|
|
32
|
+
* build a result reader
|
|
33
|
+
* @param workDir absolute path of the directory where the data
|
|
34
|
+
* and generated files of the memlab run were stored
|
|
35
|
+
* @returns the ResultReader instance
|
|
36
|
+
*/
|
|
37
|
+
static from(workDir?: string): BaseResultReader;
|
|
38
|
+
/**
|
|
39
|
+
* get the directory where the data and generated files of
|
|
40
|
+
* the memlab run were stored
|
|
41
|
+
* @returns absolute path of the directory
|
|
42
|
+
*/
|
|
43
|
+
getRootDirectory(): string;
|
|
44
|
+
/**
|
|
45
|
+
* clean up data/files generated from the memlab run
|
|
46
|
+
*/
|
|
47
|
+
cleanup(): void;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=BaseResultReader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseResultReader.d.ts","sourceRoot":"","sources":["../../src/result-reader/BaseResultReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,WAAW,EAAC,MAAM,cAAc,CAAC;AAGhD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,cAAc;IACd,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,cAAc;IACd,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IACnC,cAAc;IACd,OAAO,CAAC,OAAO,CAAU;IAEzB;;;;OAIG;IACH,SAAS,aAAa,OAAO,SAAK;IASlC,cAAc;IACd,SAAS,CAAC,KAAK,IAAI,IAAI;IAOvB;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,SAAK,GAAG,gBAAgB;IAI3C;;;;OAIG;IACI,gBAAgB,IAAI,MAAM;IAKjC;;OAEG;IACI,OAAO,IAAI,IAAI;CAOvB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const core_1 = require("@memlab/core");
|
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
+
/**
|
|
18
|
+
* A utility entity to read all generated files from
|
|
19
|
+
* the directory holding the data and results from
|
|
20
|
+
* a memlab run
|
|
21
|
+
*/
|
|
22
|
+
class BaseResultReader {
|
|
23
|
+
/**
|
|
24
|
+
* build a result reader
|
|
25
|
+
* @param workDir absolute path of the directory where the data
|
|
26
|
+
* and generated files of the memlab run were stored
|
|
27
|
+
*/
|
|
28
|
+
constructor(workDir = '') {
|
|
29
|
+
this.fileManager = new core_1.FileManager();
|
|
30
|
+
if (workDir === '') {
|
|
31
|
+
workDir = this.fileManager.getWorkDir();
|
|
32
|
+
}
|
|
33
|
+
this.workDir = workDir;
|
|
34
|
+
this.check();
|
|
35
|
+
}
|
|
36
|
+
/** @ignore */
|
|
37
|
+
check() {
|
|
38
|
+
this.isValid = fs_extra_1.default.existsSync(this.workDir);
|
|
39
|
+
if (!this.isValid) {
|
|
40
|
+
core_1.utils.haltOrThrow(`invalid/removed data directory: ${this.workDir}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* build a result reader
|
|
45
|
+
* @param workDir absolute path of the directory where the data
|
|
46
|
+
* and generated files of the memlab run were stored
|
|
47
|
+
* @returns the ResultReader instance
|
|
48
|
+
*/
|
|
49
|
+
static from(workDir = '') {
|
|
50
|
+
return new BaseResultReader(workDir);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* get the directory where the data and generated files of
|
|
54
|
+
* the memlab run were stored
|
|
55
|
+
* @returns absolute path of the directory
|
|
56
|
+
*/
|
|
57
|
+
getRootDirectory() {
|
|
58
|
+
this.check();
|
|
59
|
+
return this.workDir;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* clean up data/files generated from the memlab run
|
|
63
|
+
*/
|
|
64
|
+
cleanup() {
|
|
65
|
+
if (!this.isValid) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
fs_extra_1.default.removeSync(this.workDir);
|
|
69
|
+
this.isValid = false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.default = BaseResultReader;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @emails oncall+ws_labs
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
import type { E2EStepInfo, RunMetaInfo } from '@memlab/core';
|
|
11
|
+
import BaseResultReader from './BaseResultReader';
|
|
12
|
+
/**
|
|
13
|
+
* A utility entity to read all generated files from
|
|
14
|
+
* the directory holding the data and results from the
|
|
15
|
+
* last browser interaction run
|
|
16
|
+
*/
|
|
17
|
+
export default class BrowserInteractionResultReader extends BaseResultReader {
|
|
18
|
+
/**
|
|
19
|
+
* build a result reader
|
|
20
|
+
* @param workDir absolute path of the directory where the data
|
|
21
|
+
* and generated files of the browser interaction run were stored
|
|
22
|
+
* @returns the ResultReader instance
|
|
23
|
+
*/
|
|
24
|
+
static from(workDir?: string): BrowserInteractionResultReader;
|
|
25
|
+
/**
|
|
26
|
+
* get all snapshot files
|
|
27
|
+
* @returns an array of snapshot file's absolute path
|
|
28
|
+
*/
|
|
29
|
+
getSnapshotFiles(): string[];
|
|
30
|
+
/**
|
|
31
|
+
* get the directory holding all snapshot files
|
|
32
|
+
* @returns the absolute path of the directory
|
|
33
|
+
*/
|
|
34
|
+
getSnapshotFileDir(): string;
|
|
35
|
+
/**
|
|
36
|
+
* browser interaction step sequence
|
|
37
|
+
* @returns an array of browser interaction step info
|
|
38
|
+
*/
|
|
39
|
+
getInteractionSteps(): E2EStepInfo[];
|
|
40
|
+
/**
|
|
41
|
+
* general meta data of the browser interaction run
|
|
42
|
+
* @returns meta data about the entire browser interaction
|
|
43
|
+
*/
|
|
44
|
+
getRunMetaInfo(): RunMetaInfo;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=BrowserInteractionResultReader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserInteractionResultReader.d.ts","sourceRoot":"","sources":["../../src/result-reader/BrowserInteractionResultReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AAK3D,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,8BAA+B,SAAQ,gBAAgB;IAC1E;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,SAAK,GAAG,8BAA8B;IAIzD;;;OAGG;IACI,gBAAgB,IAAI,MAAM,EAAE;IASnC;;;OAGG;IACI,kBAAkB,IAAI,MAAM;IAKnC;;;OAGG;IACI,mBAAmB,IAAI,WAAW,EAAE;IAQ3C;;;OAGG;IACI,cAAc,IAAI,WAAW;CAOrC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* @emails oncall+ws_labs
|
|
9
|
+
* @format
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const core_1 = require("@memlab/core");
|
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const BaseResultReader_1 = __importDefault(require("./BaseResultReader"));
|
|
19
|
+
/**
|
|
20
|
+
* A utility entity to read all generated files from
|
|
21
|
+
* the directory holding the data and results from the
|
|
22
|
+
* last browser interaction run
|
|
23
|
+
*/
|
|
24
|
+
class BrowserInteractionResultReader extends BaseResultReader_1.default {
|
|
25
|
+
/**
|
|
26
|
+
* build a result reader
|
|
27
|
+
* @param workDir absolute path of the directory where the data
|
|
28
|
+
* and generated files of the browser interaction run were stored
|
|
29
|
+
* @returns the ResultReader instance
|
|
30
|
+
*/
|
|
31
|
+
static from(workDir = '') {
|
|
32
|
+
return new BrowserInteractionResultReader(workDir);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* get all snapshot files
|
|
36
|
+
* @returns an array of snapshot file's absolute path
|
|
37
|
+
*/
|
|
38
|
+
getSnapshotFiles() {
|
|
39
|
+
this.check();
|
|
40
|
+
const dataDir = this.fileManager.getCurDataDir({ workDir: this.workDir });
|
|
41
|
+
return fs_extra_1.default
|
|
42
|
+
.readdirSync(dataDir)
|
|
43
|
+
.filter(file => file.endsWith('heapsnapshot'))
|
|
44
|
+
.map(file => path_1.default.join(dataDir, file));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* get the directory holding all snapshot files
|
|
48
|
+
* @returns the absolute path of the directory
|
|
49
|
+
*/
|
|
50
|
+
getSnapshotFileDir() {
|
|
51
|
+
this.check();
|
|
52
|
+
return this.fileManager.getCurDataDir({ workDir: this.workDir });
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* browser interaction step sequence
|
|
56
|
+
* @returns an array of browser interaction step info
|
|
57
|
+
*/
|
|
58
|
+
getInteractionSteps() {
|
|
59
|
+
this.check();
|
|
60
|
+
const metaFile = this.fileManager.getSnapshotSequenceMetaFile({
|
|
61
|
+
workDir: this.workDir,
|
|
62
|
+
});
|
|
63
|
+
return core_1.utils.loadTabsOrder(metaFile);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* general meta data of the browser interaction run
|
|
67
|
+
* @returns meta data about the entire browser interaction
|
|
68
|
+
*/
|
|
69
|
+
getRunMetaInfo() {
|
|
70
|
+
this.check();
|
|
71
|
+
const metaFile = this.fileManager.getRunMetaFile({
|
|
72
|
+
workDir: this.workDir,
|
|
73
|
+
});
|
|
74
|
+
return core_1.utils.loadRunMetaInfo(metaFile);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.default = BrowserInteractionResultReader;
|