@memlab/api 1.0.24 → 1.0.26

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.map CHANGED
@@ -1 +1 @@
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,eAAe,EACf,SAAS,EAGT,QAAQ,EACT,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;AAC5F,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,WAAW,CAAC;IACzC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB;;OAEG;IACH,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB;;OAEG;IACH,SAAS,EAAE,8BAA8B,CAAC;CAC3C,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,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;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,8BAA8B,CAAC,CAWzC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,GAAG,CAAC,UAAU,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAazE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,8BAA8B,CAAC,CAQzC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,gBAAgB,GAC1B,OAAO,CAAC,eAAe,EAAE,CAAC,CAK5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAM,GAC/B,OAAO,CAAC,eAAe,EAAE,CAAC,CAU5B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,YAAY,EAC1B,IAAI,GAAE,UAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCpE;AAmED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAsD3E"}
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,eAAe,EACf,SAAS,EAGT,QAAQ,EACT,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;AAC5F,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,WAAW,CAAC;IACzC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB;;OAEG;IACH,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB;;OAEG;IACH,SAAS,EAAE,8BAA8B,CAAC;CAC3C,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,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;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,8BAA8B,CAAC,CAWzC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,GAAG,CAAC,UAAU,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAazE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,8BAA8B,CAAC,CAQzC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,gBAAgB,GAC1B,OAAO,CAAC,eAAe,EAAE,CAAC,CAK5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAM,GAC/B,OAAO,CAAC,eAAe,EAAE,CAAC,CAU5B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,YAAY,EAC1B,IAAI,GAAE,UAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCpE;AA4DD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD3E"}
package/dist/API.js CHANGED
@@ -299,27 +299,20 @@ function setupPage(page, options = {}) {
299
299
  yield page.setCacheEnabled(cache);
300
300
  // automatically accept dialog
301
301
  page.on('dialog', (dialog) => __awaiter(this, void 0, void 0, function* () {
302
+ if (config.verbose) {
303
+ core_1.info.lowLevel(`Browser dialog: ${dialog.message()}`);
304
+ }
302
305
  yield dialog.accept();
303
306
  }));
304
307
  });
305
308
  }
306
- function autoDismissDialog(page, options = {}) {
307
- var _a;
308
- const config = (_a = options.config) !== null && _a !== void 0 ? _a : core_1.config;
309
- page.on('dialog', (dialog) => __awaiter(this, void 0, void 0, function* () {
310
- if (config.verbose) {
311
- core_1.info.lowLevel(`Browser dialog: ${dialog.message()}`);
312
- }
313
- yield dialog.dismiss();
314
- }));
315
- }
316
309
  function initBrowserInfoInConfig(browser, options = {}) {
317
310
  var _a;
318
311
  return __awaiter(this, void 0, void 0, function* () {
319
312
  const config = (_a = options.config) !== null && _a !== void 0 ? _a : core_1.config;
320
- core_1.browserInfo.setPuppeteerConfig(config.puppeteerConfig);
313
+ core_1.browserInfo.recordPuppeteerConfig(config.puppeteerConfig);
321
314
  const version = yield browser.version();
322
- core_1.browserInfo.setBrowserVersion(version);
315
+ core_1.browserInfo.recordBrowserVersion(version);
323
316
  if (config.verbose) {
324
317
  core_1.info.lowLevel(JSON.stringify(core_1.browserInfo, null, 2));
325
318
  }
@@ -355,7 +348,6 @@ function testInBrowser(options = {}) {
355
348
  const visitPlan = testPlanner.getVisitPlan();
356
349
  // setup page configuration
357
350
  config.setDevice(visitPlan.device);
358
- autoDismissDialog(page);
359
351
  yield initBrowserInfoInConfig(browser);
360
352
  core_1.browserInfo.monitorWebConsole(page);
361
353
  yield setupPage(page, options);
@@ -81,3 +81,57 @@ test('self-defined leak detector can find TestObject', () => __awaiter(void 0, v
81
81
  const reader = result.runResult;
82
82
  expect(path_1.default.resolve(reader.getRootDirectory())).toBe(path_1.default.resolve(workDir));
83
83
  }), E2ETestSettings_1.testTimeout);
84
+ function injectDetachedDOMElementsWithPrompt() {
85
+ // @ts-ignore
86
+ window.injectHookForLink4 = () => {
87
+ class TestObject {
88
+ }
89
+ const arr = [];
90
+ for (let i = 0; i < 23; ++i) {
91
+ arr.push(document.createElement('div'));
92
+ }
93
+ // @ts-ignore
94
+ window.__injectedValue = arr;
95
+ // @ts-ignore
96
+ window._path_1 = { x: { y: document.createElement('div') } };
97
+ // @ts-ignore
98
+ window._path_2 = new Set([document.createElement('div')]);
99
+ // @ts-ignore
100
+ window._randomObject = [new TestObject()];
101
+ // pop up dialogs
102
+ alert('alert test');
103
+ confirm('confirm test');
104
+ prompt('prompt test:', 'default');
105
+ };
106
+ }
107
+ test('test runner should work with pages having pop up dialog', () => __awaiter(void 0, void 0, void 0, function* () {
108
+ const selfDefinedScenario = {
109
+ app: () => 'test-spa',
110
+ url: () => '',
111
+ action: (page) => __awaiter(void 0, void 0, void 0, function* () {
112
+ yield page.evaluate(() => {
113
+ // pop up dialogs
114
+ alert('alert test');
115
+ confirm('confirm test');
116
+ prompt('prompt test:', 'default');
117
+ });
118
+ yield page.click('[data-testid="link-4"]');
119
+ }),
120
+ leakFilter: (node) => {
121
+ return node.name === 'TestObject' && node.type === 'object';
122
+ },
123
+ };
124
+ const workDir = path_1.default.join(os_1.default.tmpdir(), 'memlab-api-test', `${process.pid}`);
125
+ fs_extra_1.default.mkdirsSync(workDir);
126
+ const result = yield (0, index_1.run)({
127
+ scenario: selfDefinedScenario,
128
+ evalInBrowserAfterInitLoad: injectDetachedDOMElementsWithPrompt,
129
+ workDir,
130
+ });
131
+ // detected all different leak trace cluster
132
+ expect(result.leaks.length).toBe(1);
133
+ // expect all traces are found
134
+ expect(result.leaks.some(leak => JSON.stringify(leak).includes('_randomObject')));
135
+ const reader = result.runResult;
136
+ expect(path_1.default.resolve(reader.getRootDirectory())).toBe(path_1.default.resolve(workDir));
137
+ }), E2ETestSettings_1.testTimeout);
@@ -60,7 +60,7 @@ test('leak detector can find detached DOM elements', () => __awaiter(void 0, voi
60
60
  newSnapshotFiles.push(newFile);
61
61
  fs_extra_1.default.moveSync(file, newFile);
62
62
  });
63
- fs_extra_1.default.rmdirSync(result.getRootDirectory(), { recursive: true });
63
+ fs_extra_1.default.removeSync(result.getRootDirectory());
64
64
  // find memory leaks with the new snapshot files
65
65
  const leaks = yield (0, index_1.findLeaksBySnapshotFilePaths)(newSnapshotFiles[0], newSnapshotFiles[1], newSnapshotFiles[2]);
66
66
  // detected all different leak trace cluster
@@ -70,7 +70,7 @@ test('leak detector can find detached DOM elements', () => __awaiter(void 0, voi
70
70
  expect(leaks.some(leak => JSON.stringify(leak).includes('_path_1')));
71
71
  expect(leaks.some(leak => JSON.stringify(leak).includes('_path_2')));
72
72
  // finally clean up the temporary directory
73
- fs_extra_1.default.rmdirSync(tmpDir, { recursive: true });
73
+ fs_extra_1.default.removeSync(tmpDir);
74
74
  }), E2ETestSettings_1.testTimeout);
75
75
  test('takeSnapshot API allows to throw and catch exceptions from scenario', () => __awaiter(void 0, void 0, void 0, function* () {
76
76
  const scenarioThatThrows = Object.assign({}, E2ETestSettings_1.scenario);
@@ -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
+ * @format
8
+ * @oncall web_perf_infra
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=E2EFindTaggedMemoryLeaks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"E2EFindTaggedMemoryLeaks.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/API/E2EFindTaggedMemoryLeaks.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,82 @@
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
+ * @format
9
+ * @oncall web_perf_infra
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
+ const os_1 = __importDefault(require("os"));
25
+ const path_1 = __importDefault(require("path"));
26
+ const fs_extra_1 = __importDefault(require("fs-extra"));
27
+ const index_1 = require("../../index");
28
+ const E2ETestSettings_1 = require("./lib/E2ETestSettings");
29
+ beforeEach(E2ETestSettings_1.testSetup);
30
+ function tagObjectsAsLeaks() {
31
+ // this class definition must be defined within `tagObjectsAsLeaks`
32
+ // since this function will be serialized and executed in browser context
33
+ class MemLabTracker {
34
+ constructor() {
35
+ this.memlabIdentifier = 'MemLabObjectTracker';
36
+ this.tagToTrackedObjectsMap = new Map();
37
+ }
38
+ tag(target, useCaseId = 'MEMLAB_TAGGED') {
39
+ let trackedItems = this.tagToTrackedObjectsMap.get(useCaseId);
40
+ if (!trackedItems) {
41
+ trackedItems = {
42
+ useCaseId,
43
+ taggedObjects: new WeakSet(),
44
+ };
45
+ this.tagToTrackedObjectsMap.set(useCaseId, trackedItems);
46
+ }
47
+ trackedItems.taggedObjects.add(target);
48
+ }
49
+ }
50
+ // @ts-ignore
51
+ window.injectHookForLink4 = () => {
52
+ // @ts-ignore
53
+ const tracker = (window._memlabTrack = new MemLabTracker());
54
+ const leaks = [];
55
+ // @ts-ignore
56
+ window._taggedLeaks = leaks;
57
+ for (let i = 0; i < 11; ++i) {
58
+ leaks.push({ x: i });
59
+ }
60
+ leaks.forEach(item => {
61
+ tracker.tag(item);
62
+ });
63
+ };
64
+ }
65
+ test('tagged leak objects can be identified as leaks', () => __awaiter(void 0, void 0, void 0, function* () {
66
+ const selfDefinedScenario = {
67
+ app: () => 'test-spa',
68
+ url: () => '',
69
+ action: (page) => __awaiter(void 0, void 0, void 0, function* () { return yield page.click('[data-testid="link-4"]'); }),
70
+ };
71
+ const workDir = path_1.default.join(os_1.default.tmpdir(), 'memlab-api-test', `${process.pid}`);
72
+ fs_extra_1.default.mkdirsSync(workDir);
73
+ const result = yield (0, index_1.run)({
74
+ scenario: selfDefinedScenario,
75
+ evalInBrowserAfterInitLoad: tagObjectsAsLeaks,
76
+ workDir,
77
+ });
78
+ // tagged objects should be detected as leaks
79
+ expect(result.leaks.length).toBe(1);
80
+ // expect all traces are found
81
+ expect(result.leaks.some(leak => JSON.stringify(leak).includes('_taggedLeaks')));
82
+ }), E2ETestSettings_1.testTimeout);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memlab/api",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "license": "MIT",
5
5
  "description": "memlab API",
6
6
  "author": "Liang Gong <lgong@fb.com>",