Skip to content

Commit

Permalink
feat: add Readme, fix workflows
Browse files Browse the repository at this point in the history
  • Loading branch information
BobrImperator committed Sep 9, 2024
1 parent b7da8f6 commit d3e45b6
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: CI
on:
push:
branches:
- master
- main
pull_request: {}

jobs:
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/plan-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ on:
push:
branches:
- main
- master
pull_request_target: # This workflow has permissions on the repo, do NOT run code from PRs in this workflow. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
types:
- labeled
Expand All @@ -24,7 +23,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: 'master'
ref: 'main'
# This will only cause the `check-plan` job to have a "command" of `release`
# when the .release-plan.json file was changed on the last commit.
- id: check-release
Expand All @@ -51,7 +50,7 @@ jobs:
# github-changelog can discover what's changed since the last release
with:
fetch-depth: 0
ref: 'master'
ref: 'main'
- uses: actions/setup-node@v4
with:
node_version: 20
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# For every push to the master branch, this checks if the release-plan was
# For every push to the main branch, this checks if the release-plan was
# updated and if it was it will publish stable npm packages based on the
# release plan

Expand All @@ -8,7 +8,7 @@ on:
workflow_dispatch:
push:
branches:
- master
- main

concurrency:
group: publish-${{ github.head_ref || github.ref }}
Expand All @@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: 'master'
ref: 'main'
# This will only cause the `check-plan` job to have a result of `success`
# when the .release-plan.json file was changed on the last commit. This
# plus the fact that this action only runs on main will be enough of a guard
Expand Down
85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# memory-leak-detector

Memory Leak Detector is a tiny node server that exposes an HTTP API for making snapshots and queries against a Google Chrome instance, typically from tests.

It requires a path to the source code so it can scan codebase for `class`.

`pnpm memory-leak-detector ./app`

## Example app

An example app can be found [here](/tree/main/packages/test-app).

### Running it

- checkout the repo
- `pnpm install`
- `pnpm test:memory-leak-ember`

## Usage

Install the `memory-leak-detector` dependency

- `pnpm add -D memory-leak-detector`

Define a script that runs a `memory-leak-detector` node server and listen, run your tests as usual, finally wait for the process results.

```sh
pnpm memory-leak-detector ./app & pid=$!; pnpm test; wait $pid
```

The reason for waiting for that process' pid is that e.g. Qunit doesn't have a good way to dynamically create and run a test at the end of your test suite while we must have a way to fail the CI in case something's wrong.
For that reason `detectLeakingClasses` is meant to be used at the end only, because it always exits the process with either fail or success.

That also means that if you don't intend to use `detectLeakingClasses`, your script should not wait for the `memory-leak-detector` to exit i.e.

```sh
pnpm memory-leak-detector ./app & pnpm test
```

### Checking for memory leaks after test suite finishes

The following code checks for any known, dangling objects (Classes) that `memory-leak-detector` had found in the codebase.

```js
// tests/test-helper.js

// this checks whether there are any of `our` classes retained after all tests have passed.
globalThis.Testem?.afterTests(async (_config, _data, callback) => {
// Give some time for Garbage collector to kick in
await new Promise((resolve) => setTimeout(resolve, 5000));

await detectLeakingClasses("title", document.title);
callback();
});
```
This approach doesn't catch all memory-leaks as it will only detect the ones that have manipulated a window/document objects by e.g. storing references or not removed `addEventListener` calls.
### Asserting object count
The following code performs an assertion against current memory state of the browser while the test and an application is running.
```js
test("paginating back and forth", async function (assert) {
// Initial load and each page has 30 items
await visit("users");

await click("[data-test-pagination-next]");
await click("[data-test-pagination-next]");
await click("[data-test-pagination-previous]");

const assertions = {
UserListItemComponent: 30,
};

const results = await detectMemoryLeak(
"url",
document.location.href,
assertions,
); // { UserListItemComponent: 120 }

assert.deepEqual(results, assertions);
assert.strictEqual(currentURL(), "users");
});
```

0 comments on commit d3e45b6

Please sign in to comment.