Skip to content

fix(tests): resolve resource leak in www/main_test.ts#3428

Merged
marvinhagemeister merged 14 commits into
freshframework:mainfrom
fry69:fix-test-resource-leak
Sep 15, 2025
Merged

fix(tests): resolve resource leak in www/main_test.ts#3428
marvinhagemeister merged 14 commits into
freshframework:mainfrom
fry69:fix-test-resource-leak

Conversation

@fry69

@fry69 fry69 commented Sep 14, 2025

Copy link
Copy Markdown
Contributor

The buildVite function returns a disposable object which was not being properly disposed of, leading to a resource leak warning in the test suite.

This change wraps the tests in www/main_test.ts in an async function and uses await using to ensure that the temporary directory created by buildVite is cleaned up after the tests complete.

google-labs-jules Bot and others added 2 commits September 14, 2025 11:31
The `buildVite` function returns a disposable object which was not being properly disposed of, leading to a resource leak warning in the test suite.

This change wraps the tests in `www/main_test.ts` in an async function and uses `await using` to ensure that the temporary directory created by `buildVite` is cleaned up after the tests complete.
Comment thread www/main_test.ts Outdated
import { buildVite } from "../packages/plugin-vite/tests/test_utils.ts";

const result = await buildVite(import.meta.dirname!);
async function runTests() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try Deno.test.beforeAll instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know if using more Deno 2.5.0 isms is the way, people are already complaining that the Fresh 2 does not work with Deno LTS (2.2.14), see here -> denoland/deno#30712

@marvinhagemeister marvinhagemeister Sep 15, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine imo for our own test suite. User's don't typically run our test suite.

marvinhagemeister and others added 7 commits September 15, 2025 12:46
Detect if a file is ESM based on file extension or finding ESM-only
statements. When we know that it's an ESM file we should keep
`require()` calls as is, because some libraries use it as a conditional
check like `npm:motion`.

Fixes freshframework#3429
Our validation didn't account for `_middleware` files exporting an Array
of middlewares.

Fixes freshframework#3400
Added a CSP and header middleware to simplify the HTTP Security Response
Header creation.

Fixes:
- freshframework#1705

Example:

```ts
// main.ts

export const app = new App<State>()
    .use(csp({
        reportTo: '/api/csp-reports',
    }))
    .use(headers({
        'Cross-Origin-Resource-Policy': 'same-site',
        'Cross-Origin-Embedder-Policy': 'require-corp',
        'Cross-Origin-Opener-Policy': 'same-origin',
        'Permissions-Policy':
            'geolocation=(), camera=(), microphone=(), payment=(), usb=(), bluetooth=(), magnetometer=(), gyroscope=(), accelerometer=()',
        'Referrer-Policy': 'strict-origin-when-cross-origin',
        'X-Content-Type-Options': 'nosniff',
        'X-Frame-Options': 'DENY',
        'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',
    }))
```

Endpoint example:
```ts
// routes/api/csp-handler.ts

import { Context } from 'fresh';
import { State } from '../../main.ts';

export const handler = {
    async POST(ctx: Context<State>) {
        try {
            const text = await ctx.req.text();
            const body = JSON.parse(text);

            const logEntry = {
                timestamp: new Date().toISOString(),
                report: body,
                userAgent: ctx.req.headers.get('user-agent') || 'unknown',
            };
            await Deno.writeFile('csp-reports.log', new TextEncoder().encode(JSON.stringify(logEntry) + '\n'), { append: true });

            return new Response(JSON.stringify({ status: "ok" }), { status: 200 });
        } catch (error) {
            console.error("Error handling CSP report:", error);
            return new Response(JSON.stringify({ status: "error", error: String(error) }), { status: 500 });
        }
    },
};

```

Implementing these headers improved the security report at [Security
Headers](securityheaders.com) from F to A and helps to prevent security
vulnerabilities like Cross-Site Scripting and Clickjacking.

**Before**
<img width="1200" height="308" alt="image"
src="https://github.com/user-attachments/assets/01adfff4-5bb4-4cc6-bd8f-5e74b471301b"
/>
**After**
<img width="1200" height="335" alt="image"
src="https://github.com/user-attachments/assets/c5a9b07e-babf-4797-b47d-4368de70cbc3"
/>

---------

Co-authored-by: Marvin Hagemeister <marvin@deno.com>
@fry69 fry69 force-pushed the fix-test-resource-leak branch from 7193255 to 5c84543 Compare September 15, 2025 11:11
@fry69 fry69 force-pushed the fix-test-resource-leak branch from 04a32ad to 513a10d Compare September 15, 2025 11:28
@fry69

fry69 commented Sep 15, 2025

Copy link
Copy Markdown
Contributor Author

Well, the test pass now, but I think the PR title is a bit hyperbole now with these in place:

Deno.test({
  name: "shows version selector",
  sanitizeOps: false,
  sanitizeResources: false,
}, async () => {

But since suppressing resource leak warnings in tests seem to be extremely common in this codebase, it is okay to do so?

$ git grep "sanitizeResources: false" | wc
      75     225    5193

@fry69

fry69 commented Sep 15, 2025

Copy link
Copy Markdown
Contributor Author

In other news: I think I may have tripped over this issue -> denoland/deno#30675

I'll leave this PR open for now as kind of an issue, if case others trip over this too.

Comment thread www/main_test.ts Outdated
await page.waitForSelector("#version");
sanitizeOps: false,
sanitizeResources: false,
}, async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's reduce indentation noise by moving the test function into the options object fn: async () => {.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@marvinhagemeister marvinhagemeister left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@marvinhagemeister marvinhagemeister merged commit 1506734 into freshframework:main Sep 15, 2025
7 checks passed
@fry69

fry69 commented Sep 15, 2025

Copy link
Copy Markdown
Contributor Author

Note to self: I should read more existing code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants