mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-22 10:08:42 -06:00
chore: add testing infra to apps/web (#4563)
Co-authored-by: Dhruwang <dhruwangjariwala18@gmail.com> Co-authored-by: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com>
This commit is contained in:
88
apps/web/modules/auth/lib/totp.test.ts
Normal file
88
apps/web/modules/auth/lib/totp.test.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { Authenticator } from "@otplib/core";
|
||||
import type { AuthenticatorOptions } from "@otplib/core/authenticator";
|
||||
import { createDigest, createRandomBytes } from "@otplib/plugin-crypto";
|
||||
import { keyDecoder, keyEncoder } from "@otplib/plugin-thirty-two";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { totpAuthenticatorCheck } from "./totp";
|
||||
|
||||
vi.mock("@otplib/core");
|
||||
vi.mock("@otplib/plugin-crypto");
|
||||
vi.mock("@otplib/plugin-thirty-two");
|
||||
|
||||
describe("totpAuthenticatorCheck", () => {
|
||||
const token = "123456";
|
||||
const secret = "JBSWY3DPEHPK3PXP";
|
||||
const opts: Partial<AuthenticatorOptions> = { window: [1, 0] };
|
||||
|
||||
it("should check a TOTP token with a base32-encoded secret", () => {
|
||||
const checkMock = vi.fn().mockReturnValue(true);
|
||||
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
|
||||
check: checkMock,
|
||||
}));
|
||||
|
||||
const result = totpAuthenticatorCheck(token, secret, opts);
|
||||
|
||||
expect(Authenticator).toHaveBeenCalledWith({
|
||||
createDigest,
|
||||
createRandomBytes,
|
||||
keyDecoder,
|
||||
keyEncoder,
|
||||
window: [1, 0],
|
||||
});
|
||||
expect(checkMock).toHaveBeenCalledWith(token, secret);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should use default window if none is provided", () => {
|
||||
const checkMock = vi.fn().mockReturnValue(true);
|
||||
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
|
||||
check: checkMock,
|
||||
}));
|
||||
|
||||
const result = totpAuthenticatorCheck(token, secret);
|
||||
|
||||
expect(Authenticator).toHaveBeenCalledWith({
|
||||
createDigest,
|
||||
createRandomBytes,
|
||||
keyDecoder,
|
||||
keyEncoder,
|
||||
window: [1, 0],
|
||||
});
|
||||
expect(checkMock).toHaveBeenCalledWith(token, secret);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should throw an error for invalid token format", () => {
|
||||
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
|
||||
check: () => {
|
||||
throw new Error("Invalid token format");
|
||||
},
|
||||
}));
|
||||
|
||||
expect(() => {
|
||||
totpAuthenticatorCheck("invalidToken", secret);
|
||||
}).toThrow("Invalid token format");
|
||||
});
|
||||
|
||||
it("should throw an error for invalid secret format", () => {
|
||||
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
|
||||
check: () => {
|
||||
throw new Error("Invalid secret format");
|
||||
},
|
||||
}));
|
||||
|
||||
expect(() => {
|
||||
totpAuthenticatorCheck(token, "invalidSecret");
|
||||
}).toThrow("Invalid secret format");
|
||||
});
|
||||
|
||||
it("should return false if token verification fails", () => {
|
||||
const checkMock = vi.fn().mockReturnValue(false);
|
||||
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
|
||||
check: checkMock,
|
||||
}));
|
||||
|
||||
const result = totpAuthenticatorCheck(token, secret);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Authenticator, TOTP } from "@otplib/core";
|
||||
import { Authenticator } from "@otplib/core";
|
||||
import type { AuthenticatorOptions } from "@otplib/core/authenticator";
|
||||
import type { TOTPOptions } from "@otplib/core/totp";
|
||||
import { createDigest, createRandomBytes } from "@otplib/plugin-crypto";
|
||||
import { keyDecoder, keyEncoder } from "@otplib/plugin-thirty-two";
|
||||
|
||||
@@ -28,21 +27,3 @@ export const totpAuthenticatorCheck = (
|
||||
});
|
||||
return authenticator.check(token, secret);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks the validity of a TOTP token using a raw secret.
|
||||
*
|
||||
* @param token - The token.
|
||||
* @param secret - The raw hex-encoded shared secret.
|
||||
* @param opts - The TOTPOptions object.
|
||||
* @param opts.window - The amount of past and future tokens considered valid. Either a single value or array of `[past, future]`. Default: `[1, 0]`
|
||||
*/
|
||||
export const totpRawCheck = (token: string, secret: string, opts: Partial<TOTPOptions> = {}) => {
|
||||
const { window = [1, 0], ...rest } = opts;
|
||||
const authenticator = new TOTP({
|
||||
createDigest,
|
||||
window,
|
||||
...rest,
|
||||
});
|
||||
return authenticator.check(token, secret);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"build": "next build",
|
||||
"build:dev": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "next lint",
|
||||
"test": "dotenv -e ../../.env -- vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/azure": "1.0.10",
|
||||
@@ -91,6 +92,7 @@
|
||||
"next-auth": "4.24.11",
|
||||
"next-intl": "3.26.1",
|
||||
"next-safe-action": "7.10.2",
|
||||
"nodemailer": "6.9.16",
|
||||
"optional": "0.1.4",
|
||||
"otplib": "12.0.1",
|
||||
"papaparse": "5.4.1",
|
||||
@@ -127,6 +129,8 @@
|
||||
"@types/nodemailer": "6.4.17",
|
||||
"@types/papaparse": "5.3.15",
|
||||
"@types/qrcode": "1.5.5",
|
||||
"nodemailer": "6.9.16"
|
||||
"vite": "6.0.3",
|
||||
"vitest": "2.1.8",
|
||||
"vitest-mock-extended": "2.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
10
apps/web/vite.config.mts
Normal file
10
apps/web/vite.config.mts
Normal file
@@ -0,0 +1,10 @@
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
exclude: ["playwright/**", "node_modules/**"],
|
||||
setupFiles: ["../../packages/lib/vitestSetup.ts"],
|
||||
},
|
||||
plugins: [tsconfigPaths()],
|
||||
});
|
||||
17
pnpm-lock.yaml
generated
17
pnpm-lock.yaml
generated
@@ -583,6 +583,9 @@ importers:
|
||||
next-safe-action:
|
||||
specifier: 7.10.2
|
||||
version: 7.10.2(next@15.1.0(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(zod@3.24.1)
|
||||
nodemailer:
|
||||
specifier: 6.9.16
|
||||
version: 6.9.16
|
||||
optional:
|
||||
specifier: 0.1.4
|
||||
version: 0.1.4
|
||||
@@ -686,9 +689,15 @@ importers:
|
||||
'@types/qrcode':
|
||||
specifier: 1.5.5
|
||||
version: 1.5.5
|
||||
nodemailer:
|
||||
specifier: 6.9.16
|
||||
version: 6.9.16
|
||||
vite:
|
||||
specifier: 6.0.3
|
||||
version: 6.0.3(@types/node@22.10.2)(jiti@2.4.1)(lightningcss@1.27.0)(terser@5.37.0)(tsx@4.19.2)(yaml@2.6.1)
|
||||
vitest:
|
||||
specifier: 2.1.8
|
||||
version: 2.1.8(@types/node@22.10.2)(jsdom@25.0.1)(lightningcss@1.27.0)(terser@5.37.0)
|
||||
vitest-mock-extended:
|
||||
specifier: 2.0.2
|
||||
version: 2.0.2(typescript@5.7.2)(vitest@2.1.8(@types/node@22.10.2)(jsdom@25.0.1)(lightningcss@1.27.0)(terser@5.37.0))
|
||||
|
||||
packages/api:
|
||||
devDependencies:
|
||||
@@ -28503,7 +28512,7 @@ snapshots:
|
||||
'@vitest/spy': 2.1.8
|
||||
'@vitest/utils': 2.1.8
|
||||
chai: 5.1.2
|
||||
debug: 4.3.7
|
||||
debug: 4.4.0
|
||||
expect-type: 1.1.0
|
||||
magic-string: 0.30.14
|
||||
pathe: 1.1.2
|
||||
|
||||
Reference in New Issue
Block a user