From a2aaa55b89a582afa64df051df0b8decbe4f4943 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 26 Feb 2025 15:09:01 -0600 Subject: [PATCH] Add tests to captcha modules --- packages/captcha/assets.test.ts | 9 +++++++++ packages/captcha/canvas.test.ts | 22 ++++++++++++++++++++++ packages/captcha/captcha.test.ts | 12 ++++++++++++ packages/captcha/geometry.test.ts | 8 ++++++++ packages/captcha/geometry.ts | 9 +++++++-- 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 packages/captcha/assets.test.ts create mode 100644 packages/captcha/canvas.test.ts create mode 100644 packages/captcha/captcha.test.ts create mode 100644 packages/captcha/geometry.test.ts diff --git a/packages/captcha/assets.test.ts b/packages/captcha/assets.test.ts new file mode 100644 index 00000000..c86eb203 --- /dev/null +++ b/packages/captcha/assets.test.ts @@ -0,0 +1,9 @@ +import { assert } from '@std/assert'; + +import { getCaptchaImages } from './assets.ts'; + +Deno.test('getCaptchaImages', async () => { + // If this function runs at all, it most likely worked. + const { bgImages } = await getCaptchaImages(); + assert(bgImages.length); +}); diff --git a/packages/captcha/canvas.test.ts b/packages/captcha/canvas.test.ts new file mode 100644 index 00000000..6e066a1d --- /dev/null +++ b/packages/captcha/canvas.test.ts @@ -0,0 +1,22 @@ +import { createCanvas } from '@gfx/canvas-wasm'; +import { assertNotEquals } from '@std/assert'; +import { encodeHex } from '@std/encoding/hex'; + +import { addNoise } from './canvas.ts'; + +// This is almost impossible to truly test, +// but we can at least check that the image on the canvas changes. +Deno.test('addNoise', async () => { + const canvas = createCanvas(100, 100); + const ctx = canvas.getContext('2d'); + + const dataBefore = ctx.getImageData(0, 0, canvas.width, canvas.height); + const hashBefore = await crypto.subtle.digest('SHA-256', dataBefore.data); + + addNoise(ctx, canvas.width, canvas.height); + + const dataAfter = ctx.getImageData(0, 0, canvas.width, canvas.height); + const hashAfter = await crypto.subtle.digest('SHA-256', dataAfter.data); + + assertNotEquals(encodeHex(hashBefore), encodeHex(hashAfter)); +}); diff --git a/packages/captcha/captcha.test.ts b/packages/captcha/captcha.test.ts new file mode 100644 index 00000000..285adae7 --- /dev/null +++ b/packages/captcha/captcha.test.ts @@ -0,0 +1,12 @@ +import { getCaptchaImages } from './assets.ts'; +import { generateCaptcha, verifyCaptchaSolution } from './captcha.ts'; + +Deno.test('generateCaptcha', async () => { + const images = await getCaptchaImages(); + generateCaptcha(images, { w: 370, h: 400 }, { w: 65, h: 65 }); +}); + +Deno.test('verifyCaptchaSolution', () => { + verifyCaptchaSolution({ w: 65, h: 65 }, { x: 0, y: 0 }, { x: 0, y: 0 }); + verifyCaptchaSolution({ w: 65, h: 65 }, { x: 0, y: 0 }, { x: 10, y: 10 }); +}); diff --git a/packages/captcha/geometry.test.ts b/packages/captcha/geometry.test.ts new file mode 100644 index 00000000..057ebf3d --- /dev/null +++ b/packages/captcha/geometry.test.ts @@ -0,0 +1,8 @@ +import { assertEquals } from '@std/assert'; + +import { areIntersecting } from './geometry.ts'; + +Deno.test('areIntersecting', () => { + assertEquals(areIntersecting({ x: 0, y: 0, w: 10, h: 10 }, { x: 5, y: 5, w: 10, h: 10 }), true); + assertEquals(areIntersecting({ x: 0, y: 0, w: 10, h: 10 }, { x: 15, y: 15, w: 10, h: 10 }), false); +}); diff --git a/packages/captcha/geometry.ts b/packages/captcha/geometry.ts index b1993e0b..40e5f2fd 100644 --- a/packages/captcha/geometry.ts +++ b/packages/captcha/geometry.ts @@ -8,15 +8,20 @@ export interface Dimensions { h: number; } -export type Rectangle = Point & Dimensions; +type Rectangle = Point & Dimensions; +/** Check if the two rectangles intersect by at least `threshold` percent. */ export function areIntersecting(rect1: Rectangle, rect2: Rectangle, threshold = 0.5): boolean { const r1cx = rect1.x + rect1.w / 2; const r2cx = rect2.x + rect2.w / 2; + const r1cy = rect1.y + rect1.h / 2; const r2cy = rect2.y + rect2.h / 2; + const dist = Math.sqrt((r2cx - r1cx) ** 2 + (r2cy - r1cy) ** 2); + const e1 = Math.sqrt(rect1.h ** 2 + rect1.w ** 2) / 2; const e2 = Math.sqrt(rect2.h ** 2 + rect2.w ** 2) / 2; - return dist < (e1 + e2) * threshold; + + return dist <= (e1 + e2) * threshold; }