@memlab/e2e 1.0.2 → 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/dist/plugins/DefaultScenarioSynthesizer.js +4 -1
- package/package.json +2 -1
- package/static/example/pages/examples/{unbound-object.jsx → oversized-object.jsx} +6 -3
- package/static/example/pages/index.js +1 -1
- package/static/example/scenarios/detached-dom.js +9 -7
- package/static/example/scenarios/oversized-leak-filter.js +9 -0
- package/static/example/scenarios/oversized-object-with-filter.js +23 -0
- package/static/example/scenarios/oversized-object.js +17 -0
- package/static/example/scenarios/unbound-object.js +0 -22
|
@@ -53,7 +53,10 @@ class DefaultScenarioSynthesizer extends BaseSynthesizer_1.default {
|
|
|
53
53
|
getPageLoadChecker() {
|
|
54
54
|
return (page) => __awaiter(this, void 0, void 0, function* () {
|
|
55
55
|
yield InteractionUtils_1.default.waitFor(500);
|
|
56
|
-
yield page.waitForNavigation({
|
|
56
|
+
yield page.waitForNavigation({
|
|
57
|
+
waitUntil: 'networkidle0',
|
|
58
|
+
timeout: this.config.waitForNetworkInDefaultScenario,
|
|
59
|
+
});
|
|
57
60
|
return true;
|
|
58
61
|
});
|
|
59
62
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memlab/e2e",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "memlab browser E2E interaction libraries",
|
|
6
6
|
"author": "Liang Gong <lgong@fb.com>",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build-pkg": "tsc",
|
|
51
|
+
"publish-patch": "npm version patch --force && npm publish",
|
|
51
52
|
"clean-pkg": "rm -rf ./dist && rm -rf ./node_modules && rm -f ./tsconfig.tsbuildinfo"
|
|
52
53
|
},
|
|
53
54
|
"bugs": {
|
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
import Link from 'next/link';
|
|
3
3
|
import React, {useEffect} from 'react';
|
|
4
4
|
|
|
5
|
-
export default function
|
|
5
|
+
export default function OversizedObject() {
|
|
6
6
|
const bigArray = Array(1024 * 1024 * 2).fill(0);
|
|
7
7
|
|
|
8
8
|
const eventHandler = () => {
|
|
9
|
-
|
|
9
|
+
// the eventHandler closure keeps a reference
|
|
10
|
+
// to the bigArray in the outter scope
|
|
11
|
+
console.log('Using hugeObject', bigArray);
|
|
10
12
|
};
|
|
11
13
|
|
|
12
14
|
useEffect(() => {
|
|
15
|
+
// eventHandler is never unregistered
|
|
13
16
|
window.addEventListener('custom-click', eventHandler);
|
|
14
17
|
}, []);
|
|
15
18
|
|
|
@@ -18,7 +21,7 @@ export default function UnboundObject() {
|
|
|
18
21
|
<div className="row">
|
|
19
22
|
<Link href="/">Go back</Link>
|
|
20
23
|
</div>
|
|
21
|
-
<br
|
|
24
|
+
<br/>
|
|
22
25
|
<div className="row">
|
|
23
26
|
Object<code>bigArray</code>is leaked. Please check <code>Memory</code>{' '}
|
|
24
27
|
tab in devtools
|
|
@@ -11,28 +11,30 @@ function url() {
|
|
|
11
11
|
* Specify how memlab should perform action that you want
|
|
12
12
|
* to test whether the action is causing memory leak.
|
|
13
13
|
*
|
|
14
|
-
* @param page - Puppeteer's
|
|
14
|
+
* @param page - Puppeteer's page object:
|
|
15
|
+
* https://pptr.dev/api/puppeteer.page/
|
|
15
16
|
*/
|
|
16
17
|
async function action(page) {
|
|
17
|
-
const
|
|
18
|
+
const elements = await page.$x(
|
|
18
19
|
"//button[contains(., 'Create detached DOMs')]"
|
|
19
20
|
);
|
|
21
|
+
const [button] = elements;
|
|
20
22
|
if (button) {
|
|
21
23
|
await button.click();
|
|
22
24
|
}
|
|
25
|
+
// clean up external references from memlab
|
|
26
|
+
await Promise.all(elements.map(e => e.dispose()));
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
26
30
|
* Specify how memlab should perform action that would
|
|
27
31
|
* reset the action you performed above.
|
|
28
32
|
*
|
|
29
|
-
* @param page - Puppeteer's
|
|
33
|
+
* @param page - Puppeteer's page object:
|
|
34
|
+
* https://pptr.dev/api/puppeteer.page/
|
|
30
35
|
*/
|
|
31
36
|
async function back(page) {
|
|
32
|
-
|
|
33
|
-
if (button) {
|
|
34
|
-
await button.click();
|
|
35
|
-
}
|
|
37
|
+
await page.click('a[href="/"]');
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
module.exports = { action, back, url };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* @nolint */
|
|
2
|
+
|
|
3
|
+
// leakFilter is called with each object (node) in browser
|
|
4
|
+
// allocated by `action` but not released after the `back` call
|
|
5
|
+
function leakFilter(node, _snapshot, _leakedNodeIds) {
|
|
6
|
+
return node.retainedSize > 1000 * 1000;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
module.exports = { leakFilter };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* @nolint */
|
|
2
|
+
|
|
3
|
+
function url() {
|
|
4
|
+
return 'http://localhost:3000/';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// action where you suspect the memory leak might be happening
|
|
8
|
+
async function action(page) {
|
|
9
|
+
await page.click('a[href="/examples/oversized-object"]');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// how to go back to the state before actionw
|
|
13
|
+
async function back(page) {
|
|
14
|
+
await page.click('a[href="/"]');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// leakFilter is called with each object (node) in browser
|
|
18
|
+
// allocated by `action` but not released after the `back` call
|
|
19
|
+
function leakFilter(node, _snapshot, _leakedNodeIds) {
|
|
20
|
+
return node.retainedSize > 1000 * 1000;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = { action, back, leakFilter, url };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* @nolint */
|
|
2
|
+
|
|
3
|
+
function url() {
|
|
4
|
+
return 'http://localhost:3000/';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// action where you suspect the memory leak might be happening
|
|
8
|
+
async function action(page) {
|
|
9
|
+
await page.click('a[href="/examples/oversized-object"]');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// how to go back to the state before actionw
|
|
13
|
+
async function back(page) {
|
|
14
|
+
await page.click('a[href="/"]');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { action, back, url };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// @nolint
|
|
2
|
-
|
|
3
|
-
// memlab/packages/e2e/static/example/scenario/unbound-object.js
|
|
4
|
-
function url() {
|
|
5
|
-
return "http://localhost:3000/";
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// action where you suspect the memory leak might be happening
|
|
9
|
-
async function action(page) {
|
|
10
|
-
await page.click('a[href="/examples/unbound-object"]');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// how to go back to the state before actionw
|
|
14
|
-
async function back(page) {
|
|
15
|
-
await page.click('a[href="/"]');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// function leakFilter(node, _snapshot, _leakedNodeIds) {
|
|
19
|
-
// return node.retainedSize > 1000 * 1000;
|
|
20
|
-
// };
|
|
21
|
-
|
|
22
|
-
module.exports = { action, back, url };
|