]> git.ardis.lu - envpass/commitdiff
Wrap HTML loading logic for mocking purposes and add tests for it
authorArdis Lu <ardisglu@gmail.com>
Wed, 22 Jul 2026 07:15:17 +0000 (00:15 -0700)
committerArdis Lu <ardisglu@gmail.com>
Wed, 22 Jul 2026 07:15:17 +0000 (00:15 -0700)
src/getPrf.js
test/getPrf.test.js

index 6663e1c152d5588d586c23a2704f0f39b8ae2eb4..3a66334ad54a6327bebfa773e91e023796ea684e 100644 (file)
@@ -7,11 +7,25 @@ import open from 'open';
 /** @import { Bytes32 } from '#src/utils.js'; */
 
 /**
- * Wrapper around browser operations (currently, only `open`). This wrapper object is required
- * to mock the methods for testing purposes.
+ * Load from disk the HTML to be served by the passkey bridge server.
+ * @returns {Promise<string>} The HTML file to serve.
+ */
+async function getHTML() {
+  return await readFile(new URL('./getPrf.html', import.meta.url), { encoding: 'utf8' });
+}
+
+/**
+ * Wrapper around browser operations. This wrapper object is required to mock the methods for
+ * testing purposes.
  */
 export const BROWSER = { open };
 
+/**
+ * Wrapper around server operations. This wrapper object is required to mock the methods for
+ * testing purposes.
+ */
+export const SERVER = { getHTML };
+
 /**
  * 2 minutes in milliseconds. After this duration, the http server will close and the flow
  * must be restarted.
@@ -58,7 +72,7 @@ export async function getPrf(options = {}) {
   const { promise: prfPromise, resolve: prfResolve } = /** @type {PromiseWithResolvers<Bytes32>}*/(Promise.withResolvers());
   const { promise: abortPromise, resolve: abortResolve } = /** @type {PromiseWithResolvers<null>}*/(Promise.withResolvers());
 
-  const html = await readFile(new URL('./getPrf.html', import.meta.url), { encoding: 'utf8' });
+  const html = await SERVER.getHTML();
 
   // Generate hashes of <style> and <script> contents for the CSP header
   const encoder = new TextEncoder();
index 656e615e1bac6afa7224a92569d9203bc98138ad..e5bdedfacedad86e0d5e7e36ac0a805f5800d0eb 100644 (file)
@@ -4,7 +4,7 @@ import { Readable } from 'node:stream';
 
 import { request } from 'undici';
 
-import { WINDOW_EXPIRATION_DURATION } from '#src/getPrf.js';
+import { SERVER, WINDOW_EXPIRATION_DURATION } from '#src/getPrf.js';
 import { setupPlaywright, setupServer } from '#test/setup.js';
 
 /**
@@ -55,6 +55,18 @@ function makePostRequest(url, options = {}) {
 }
 
 suite('getPrf.js (server)', () => {
+  test('validates <style> tag is present in HTML template', async (t) => {
+    const html = await SERVER.getHTML();
+    const modified = html.replaceAll('<style>', '');
+    t.mock.method(SERVER, 'getHTML', () => modified);
+    await rejects(setupServer(t), { message: 'Could not find <style> tag in getPrf.html file.' });
+  });
+  test('validates <script> tag is present in HTML template', async (t) => {
+    const html = await SERVER.getHTML();
+    const modified = html.replaceAll('<script type="module">', '');
+    t.mock.method(SERVER, 'getHTML', () => modified);
+    await rejects(setupServer(t), { message: 'Could not find <script> tag in getPrf.html file.' });
+  });
   test('valid GET works', async (t) => {
     const { url } = await setupServer(t);
     deepStrictEqual((await fetch(url)).status, 200);
This page took 0.068814 seconds and 4 git commands to generate.