@memlab/api 1.0.0 → 1.0.3
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/README.md +5 -9
- package/dist/API.d.ts +139 -18
- package/dist/API.js +146 -17
- 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.js +50 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.d.ts +11 -0
- package/dist/__tests__/API/E2EFindMemoryLeaks.test.js +72 -0
- package/dist/__tests__/API/E2EResultReader.test.d.ts +11 -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 +8 -17
- package/dist/__tests__/API/E2EStringAnalysis.test.js +19 -15
- package/dist/__tests__/packages/heap-analysis.test.d.ts +11 -0
- package/dist/__tests__/packages/heap-analysis.test.js +82 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +11 -2
- package/dist/result-reader/BaseResultReader.d.ts +70 -0
- package/dist/result-reader/BaseResultReader.js +96 -0
- package/dist/result-reader/BrowserInteractionResultReader.d.ts +105 -0
- package/dist/result-reader/BrowserInteractionResultReader.js +136 -0
- package/package.json +15 -6
- package/dist/API.d.ts.map +0 -1
- package/dist/__tests__/API/E2EBasicAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2EDetachedDOMAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2EDuplicateObjectAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2ERunMultipleSnapshots.example.d.ts.map +0 -1
- package/dist/__tests__/API/E2ERunSingleSnapshot.example.d.ts.map +0 -1
- package/dist/__tests__/API/E2EShapeUnboundGrowthAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/E2EStringAnalysis.test.d.ts.map +0 -1
- package/dist/__tests__/API/lib/E2ETestSettings.d.ts.map +0 -1
- package/dist/__tests__/heap/E2EHeapParser.test.d.ts.map +0 -1
- package/dist/__tests__/heap/lib/HeapParserTestUtils.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/APIUtils.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
## memlab API
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This is the memlab API library. Add this dependency to your project
|
|
4
|
+
if you want to integrate memlab with your continuous testing system.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
const api = require('@memlab/api');
|
|
9
|
-
|
|
10
|
-
// TODO: DEMONSTRATE API
|
|
11
|
-
```
|
|
6
|
+
## Full documentation
|
|
7
|
+
https://facebookincubator.github.io/memlab
|
package/dist/API.d.ts
CHANGED
|
@@ -7,34 +7,155 @@
|
|
|
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, 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, all fields are optional
|
|
18
|
+
*/
|
|
19
|
+
export declare type RunOptions = {
|
|
20
|
+
/** test scenario definition */
|
|
23
21
|
scenario?: IScenario;
|
|
22
|
+
/** the absolute path of 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
|
+
* Options for memlab inter-package API calls
|
|
35
|
+
* @internal
|
|
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 warm up and call {@link takeSnapshots}.
|
|
47
|
+
*
|
|
48
|
+
* @param options configure browser interaction run
|
|
49
|
+
* @returns browser interaction results
|
|
50
|
+
* * **Examples**:
|
|
51
|
+
* ```javascript
|
|
52
|
+
* const {warmupAndTakeSnapshots} = require('@memlab/api');
|
|
53
|
+
*
|
|
54
|
+
* (async function () {
|
|
55
|
+
* const scenario = {
|
|
56
|
+
* url: () => 'https://www.facebook.com',
|
|
57
|
+
* };
|
|
58
|
+
* const result = await warmupAndTakeSnapshots({scenario});
|
|
59
|
+
* })();
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function warmupAndTakeSnapshots(options?: RunOptions): Promise<BrowserInteractionResultReader>;
|
|
63
|
+
/**
|
|
64
|
+
* This API runs browser interaction and find memory leaks triggered in browser
|
|
65
|
+
* This is equivalent to run `memlab run` in CLI.
|
|
66
|
+
* This is also equivalent to warm up, and call {@link takeSnapshots}
|
|
67
|
+
* and {@link findLeaks}.
|
|
68
|
+
*
|
|
69
|
+
* @param runOptions configure browser interaction run
|
|
70
|
+
* @returns leak traces detected and clustered from the browser interaction
|
|
71
|
+
* * **Examples**:
|
|
72
|
+
* ```javascript
|
|
73
|
+
* const {run} = require('@memlab/api');
|
|
74
|
+
*
|
|
75
|
+
* (async function () {
|
|
76
|
+
* const scenario = {
|
|
77
|
+
* url: () => 'https://www.facebook.com',
|
|
78
|
+
* };
|
|
79
|
+
* const leaks = await run({scenario});
|
|
80
|
+
* })();
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function run(runOptions?: RunOptions): Promise<ISerializedInfo[]>;
|
|
84
|
+
/**
|
|
85
|
+
* This API runs E2E interaction and takes heap snapshots.
|
|
86
|
+
* This is equivalent to run `memlab snapshot` in CLI.
|
|
87
|
+
*
|
|
88
|
+
* @param options configure browser interaction run
|
|
89
|
+
* @returns browser interaction results
|
|
90
|
+
* * **Examples**:
|
|
91
|
+
* ```javascript
|
|
92
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
93
|
+
*
|
|
94
|
+
* (async function () {
|
|
95
|
+
* const scenario = {
|
|
96
|
+
* url: () => 'https://www.facebook.com',
|
|
97
|
+
* };
|
|
98
|
+
* const result = await takeSnapshots({scenario});
|
|
99
|
+
* })();
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function takeSnapshots(options?: RunOptions): Promise<BrowserInteractionResultReader>;
|
|
103
|
+
/**
|
|
104
|
+
* This API finds memory leaks by analyzing heap snapshot(s)
|
|
105
|
+
* This is equivalent to `memlab find-leaks` in CLI.
|
|
106
|
+
*
|
|
107
|
+
* @param runResult return value of a browser interaction run
|
|
108
|
+
* @returns leak traces detected and clustered from the browser interaction
|
|
109
|
+
* * **Examples**:
|
|
110
|
+
* ```javascript
|
|
111
|
+
* const {findLeaks, takeSnapshots} = require('@memlab/api');
|
|
112
|
+
*
|
|
113
|
+
* (async function () {
|
|
114
|
+
* const scenario = {
|
|
115
|
+
* url: () => 'https://www.facebook.com',
|
|
116
|
+
* };
|
|
117
|
+
* const result = await takeSnapshots({scenario});
|
|
118
|
+
* const leaks = findLeaks(result);
|
|
119
|
+
* })();
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export declare function findLeaks(runResult: BrowserInteractionResultReader): Promise<ISerializedInfo[]>;
|
|
123
|
+
/**
|
|
124
|
+
* This API analyzes heap snapshot(s) with a specified heap analysis.
|
|
125
|
+
* This is equivalent to `memlab analyze` in CLI.
|
|
126
|
+
*
|
|
127
|
+
* @param runResult return value of a browser interaction run
|
|
128
|
+
* @param heapAnalyzer instance of a heap analysis
|
|
129
|
+
* @param args other CLI arguments that needs to be passed to the heap analysis
|
|
130
|
+
* @returns each analysis may have a different return type, please check out
|
|
131
|
+
* the type definition or the documentation for the `process` method of the
|
|
132
|
+
* analysis class you are using for `heapAnalyzer`.
|
|
133
|
+
* * **Examples**:
|
|
134
|
+
* ```javascript
|
|
135
|
+
* const {takeSnapshots, StringAnalysis} = require('@memlab/api');
|
|
136
|
+
*
|
|
137
|
+
* (async function () {
|
|
138
|
+
* const scenario = {
|
|
139
|
+
* url: () => 'https://www.facebook.com',
|
|
140
|
+
* };
|
|
141
|
+
* const result = await takeSnapshots({scenario});
|
|
142
|
+
* const analysis = new StringAnalysis();
|
|
143
|
+
* await analyze(result, analysis);
|
|
144
|
+
* })();
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export declare function analyze(runResult: BrowserInteractionResultReader, heapAnalyzer: BaseAnalysis, args?: ParsedArgs): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* This warms up web server by sending web requests to the web sever.
|
|
150
|
+
* This is equivalent to run `memlab warmup` in CLI.
|
|
151
|
+
* @internal
|
|
152
|
+
*
|
|
153
|
+
* @param options configure browser interaction run
|
|
154
|
+
*/
|
|
36
155
|
export declare function warmup(options?: APIOptions): Promise<void>;
|
|
37
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Browser interaction API used by MemLab API and MemLab CLI
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
38
160
|
export declare function testInBrowser(options?: APIOptions): Promise<void>;
|
|
39
|
-
export {};
|
|
40
161
|
//# sourceMappingURL=API.d.ts.map
|
package/dist/API.js
CHANGED
|
@@ -21,14 +21,31 @@ 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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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 warm up and call {@link takeSnapshots}.
|
|
33
|
+
*
|
|
34
|
+
* @param options configure browser interaction run
|
|
35
|
+
* @returns browser interaction results
|
|
36
|
+
* * **Examples**:
|
|
37
|
+
* ```javascript
|
|
38
|
+
* const {warmupAndTakeSnapshots} = require('@memlab/api');
|
|
39
|
+
*
|
|
40
|
+
* (async function () {
|
|
41
|
+
* const scenario = {
|
|
42
|
+
* url: () => 'https://www.facebook.com',
|
|
43
|
+
* };
|
|
44
|
+
* const result = await warmupAndTakeSnapshots({scenario});
|
|
45
|
+
* })();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
function warmupAndTakeSnapshots(options = {}) {
|
|
32
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
50
|
const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
34
51
|
setConfigByRunOptions(config, options);
|
|
@@ -38,14 +55,63 @@ function run(options = {}) {
|
|
|
38
55
|
const { evalInBrowserAfterInitLoad } = options;
|
|
39
56
|
yield warmup({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
40
57
|
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
return BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
exports.warmupAndTakeSnapshots = warmupAndTakeSnapshots;
|
|
62
|
+
/**
|
|
63
|
+
* This API runs browser interaction and find memory leaks triggered in browser
|
|
64
|
+
* This is equivalent to run `memlab run` in CLI.
|
|
65
|
+
* This is also equivalent to warm up, and call {@link takeSnapshots}
|
|
66
|
+
* and {@link findLeaks}.
|
|
67
|
+
*
|
|
68
|
+
* @param runOptions configure browser interaction run
|
|
69
|
+
* @returns leak traces detected and clustered from the browser interaction
|
|
70
|
+
* * **Examples**:
|
|
71
|
+
* ```javascript
|
|
72
|
+
* const {run} = require('@memlab/api');
|
|
73
|
+
*
|
|
74
|
+
* (async function () {
|
|
75
|
+
* const scenario = {
|
|
76
|
+
* url: () => 'https://www.facebook.com',
|
|
77
|
+
* };
|
|
78
|
+
* const leaks = await run({scenario});
|
|
79
|
+
* })();
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
function run(runOptions = {}) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
85
|
+
setConfigByRunOptions(config, runOptions);
|
|
86
|
+
config.externalCookiesFile = runOptions.cookiesFile;
|
|
87
|
+
config.scenario = runOptions.scenario;
|
|
88
|
+
const testPlanner = new e2e_1.TestPlanner({ config });
|
|
89
|
+
const { evalInBrowserAfterInitLoad } = runOptions;
|
|
90
|
+
yield warmup({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
91
|
+
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
92
|
+
const runResult = BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
93
|
+
return yield findLeaks(runResult);
|
|
46
94
|
});
|
|
47
95
|
}
|
|
48
96
|
exports.run = run;
|
|
97
|
+
/**
|
|
98
|
+
* This API runs E2E interaction and takes heap snapshots.
|
|
99
|
+
* This is equivalent to run `memlab snapshot` in CLI.
|
|
100
|
+
*
|
|
101
|
+
* @param options configure browser interaction run
|
|
102
|
+
* @returns browser interaction results
|
|
103
|
+
* * **Examples**:
|
|
104
|
+
* ```javascript
|
|
105
|
+
* const {takeSnapshots} = require('@memlab/api');
|
|
106
|
+
*
|
|
107
|
+
* (async function () {
|
|
108
|
+
* const scenario = {
|
|
109
|
+
* url: () => 'https://www.facebook.com',
|
|
110
|
+
* };
|
|
111
|
+
* const result = await takeSnapshots({scenario});
|
|
112
|
+
* })();
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
49
115
|
function takeSnapshots(options = {}) {
|
|
50
116
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
117
|
const config = core_1.MemLabConfig.resetConfigWithTranscientDir();
|
|
@@ -55,20 +121,77 @@ function takeSnapshots(options = {}) {
|
|
|
55
121
|
const testPlanner = new e2e_1.TestPlanner();
|
|
56
122
|
const { evalInBrowserAfterInitLoad } = options;
|
|
57
123
|
yield testInBrowser({ testPlanner, config, evalInBrowserAfterInitLoad });
|
|
58
|
-
return
|
|
59
|
-
config,
|
|
60
|
-
tabsOrder: core_1.utils.loadTabsOrder(),
|
|
61
|
-
metaInfo: core_1.utils.loadRunMetaInfo(),
|
|
62
|
-
};
|
|
124
|
+
return BrowserInteractionResultReader_1.default.from(config.workDir);
|
|
63
125
|
});
|
|
64
126
|
}
|
|
65
127
|
exports.takeSnapshots = takeSnapshots;
|
|
128
|
+
/**
|
|
129
|
+
* This API finds memory leaks by analyzing heap snapshot(s)
|
|
130
|
+
* This is equivalent to `memlab find-leaks` in CLI.
|
|
131
|
+
*
|
|
132
|
+
* @param runResult return value of a browser interaction run
|
|
133
|
+
* @returns leak traces detected and clustered from the browser interaction
|
|
134
|
+
* * **Examples**:
|
|
135
|
+
* ```javascript
|
|
136
|
+
* const {findLeaks, takeSnapshots} = require('@memlab/api');
|
|
137
|
+
*
|
|
138
|
+
* (async function () {
|
|
139
|
+
* const scenario = {
|
|
140
|
+
* url: () => 'https://www.facebook.com',
|
|
141
|
+
* };
|
|
142
|
+
* const result = await takeSnapshots({scenario});
|
|
143
|
+
* const leaks = findLeaks(result);
|
|
144
|
+
* })();
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
function findLeaks(runResult) {
|
|
148
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
149
|
+
const workDir = runResult.getRootDirectory();
|
|
150
|
+
core_1.fileManager.initDirs(core_1.config, { workDir });
|
|
151
|
+
core_1.config.chaseWeakMapEdge = false;
|
|
152
|
+
return yield core_1.analysis.checkLeak();
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
exports.findLeaks = findLeaks;
|
|
156
|
+
/**
|
|
157
|
+
* This API analyzes heap snapshot(s) with a specified heap analysis.
|
|
158
|
+
* This is equivalent to `memlab analyze` in CLI.
|
|
159
|
+
*
|
|
160
|
+
* @param runResult return value of a browser interaction run
|
|
161
|
+
* @param heapAnalyzer instance of a heap analysis
|
|
162
|
+
* @param args other CLI arguments that needs to be passed to the heap analysis
|
|
163
|
+
* @returns each analysis may have a different return type, please check out
|
|
164
|
+
* the type definition or the documentation for the `process` method of the
|
|
165
|
+
* analysis class you are using for `heapAnalyzer`.
|
|
166
|
+
* * **Examples**:
|
|
167
|
+
* ```javascript
|
|
168
|
+
* const {takeSnapshots, StringAnalysis} = require('@memlab/api');
|
|
169
|
+
*
|
|
170
|
+
* (async function () {
|
|
171
|
+
* const scenario = {
|
|
172
|
+
* url: () => 'https://www.facebook.com',
|
|
173
|
+
* };
|
|
174
|
+
* const result = await takeSnapshots({scenario});
|
|
175
|
+
* const analysis = new StringAnalysis();
|
|
176
|
+
* await analyze(result, analysis);
|
|
177
|
+
* })();
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
66
180
|
function analyze(runResult, heapAnalyzer, args = { _: [] }) {
|
|
67
181
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
-
|
|
182
|
+
const workDir = runResult.getRootDirectory();
|
|
183
|
+
core_1.fileManager.initDirs(core_1.config, { workDir });
|
|
184
|
+
return yield heapAnalyzer.run({ args });
|
|
69
185
|
});
|
|
70
186
|
}
|
|
71
187
|
exports.analyze = analyze;
|
|
188
|
+
/**
|
|
189
|
+
* This warms up web server by sending web requests to the web sever.
|
|
190
|
+
* This is equivalent to run `memlab warmup` in CLI.
|
|
191
|
+
* @internal
|
|
192
|
+
*
|
|
193
|
+
* @param options configure browser interaction run
|
|
194
|
+
*/
|
|
72
195
|
function warmup(options = {}) {
|
|
73
196
|
var _a, _b;
|
|
74
197
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -109,6 +232,9 @@ function warmup(options = {}) {
|
|
|
109
232
|
});
|
|
110
233
|
}
|
|
111
234
|
exports.warmup = warmup;
|
|
235
|
+
function setConfigByRunOptions(config, options) {
|
|
236
|
+
config.isFullRun = !!options.snapshotForEachStep;
|
|
237
|
+
}
|
|
112
238
|
function setupPage(page, options = {}) {
|
|
113
239
|
var _a, _b, _c;
|
|
114
240
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -130,7 +256,6 @@ function setupPage(page, options = {}) {
|
|
|
130
256
|
}));
|
|
131
257
|
});
|
|
132
258
|
}
|
|
133
|
-
exports.setupPage = setupPage;
|
|
134
259
|
function autoDismissDialog(page, options = {}) {
|
|
135
260
|
var _a;
|
|
136
261
|
const config = (_a = options.config) !== null && _a !== void 0 ? _a : core_1.config;
|
|
@@ -153,6 +278,10 @@ function initBrowserInfoInConfig(browser, options = {}) {
|
|
|
153
278
|
}
|
|
154
279
|
});
|
|
155
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Browser interaction API used by MemLab API and MemLab CLI
|
|
283
|
+
* @internal
|
|
284
|
+
*/
|
|
156
285
|
function testInBrowser(options = {}) {
|
|
157
286
|
var _a, _b;
|
|
158
287
|
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,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,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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const index_1 = require("../../index");
|
|
22
|
+
const E2ETestSettings_1 = require("./lib/E2ETestSettings");
|
|
23
|
+
beforeEach(E2ETestSettings_1.testSetup);
|
|
24
|
+
function injectDetachedDOMElements() {
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
window.injectHookForLink4 = () => {
|
|
27
|
+
class TestObject {
|
|
28
|
+
}
|
|
29
|
+
const arr = [];
|
|
30
|
+
for (let i = 0; i < 23; ++i) {
|
|
31
|
+
arr.push(document.createElement('div'));
|
|
32
|
+
}
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
window.__injectedValue = arr;
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
window._path_1 = { x: { y: document.createElement('div') } };
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
window._path_2 = new Set([document.createElement('div')]);
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
window._randomObject = [new TestObject()];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
test('leak detector can find detached DOM elements', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
const leaks = yield (0, index_1.run)({
|
|
45
|
+
scenario: E2ETestSettings_1.scenario,
|
|
46
|
+
evalInBrowserAfterInitLoad: injectDetachedDOMElements,
|
|
47
|
+
});
|
|
48
|
+
// detected all different leak trace cluster
|
|
49
|
+
expect(leaks.length).toBe(3);
|
|
50
|
+
// expect all traces are found
|
|
51
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('__injectedValue')));
|
|
52
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('_path_1')));
|
|
53
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('_path_2')));
|
|
54
|
+
}), E2ETestSettings_1.testTimeout);
|
|
55
|
+
test('self-defined leak detector can find TestObject', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
+
const selfDefinedScenario = {
|
|
57
|
+
app: () => 'test-spa',
|
|
58
|
+
url: () => '',
|
|
59
|
+
action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
|
|
60
|
+
leakFilter: (node) => {
|
|
61
|
+
return node.name === 'TestObject' && node.type === 'object';
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
const leaks = yield (0, index_1.run)({
|
|
65
|
+
scenario: selfDefinedScenario,
|
|
66
|
+
evalInBrowserAfterInitLoad: injectDetachedDOMElements,
|
|
67
|
+
});
|
|
68
|
+
// detected all different leak trace cluster
|
|
69
|
+
expect(leaks.length).toBe(1);
|
|
70
|
+
// expect all traces are found
|
|
71
|
+
expect(leaks.some(leak => JSON.stringify(leak).includes('_randomObject')));
|
|
72
|
+
}), 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
|