Files
calendar/packages/lib/crypto.test.ts
T
sean-brydonGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
19563aa697 feat: Self hosted onboarding (#22102)
* intro work

* update wixard form to have content callback to remove preset navigation

* more fixes to deployment

* fix calling static service

* fix save license key text

* ensure default steps work as expected

* fix conditional for rendering step

* skip step

* add on next step for free license

* refactor wizard form to use nuqs

* fix styles

* merge base param with step config

* fix next stepo text

* use deployment Signature token

* decrypt signature token

* fix: resolve type errors and test failures from wizard form refactor

- Fix signatureToken field name to signatureTokenEncrypted in deployment repository
- Add missing getSignatureToken method to verifyApiKey test mock
- Fix WizardForm import from default to named export in test file
- Add missing nextStep prop to Steps component in WizardForm

Resolves TypeScript type check errors and unit test failures without changing functionality.

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: add missing getDeploymentSignatureToken mock in LicenseKeyService test

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: add nuqs library mock for WizardForm test

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: add missing nav prop to AdminAppsList component with eslint disable

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* Apply suggestions from code review

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* Update apps/web/modules/auth/setup-view.tsx

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* fix license schema changes

* revret schema generation

* fix eslint errors

* remove required nav type + add use client

* fix types

* Update packages/ui/components/form/wizard/useWizardState.ts

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* fix controller issue

* add checks for deployment key being null - add more tests

* fix tests

* add deployment key tests

* fix: resolve crypto mock to handle empty encryption keys gracefully

- Updated symmetricDecrypt mock to return null instead of throwing 'Invalid key' error when encryption key is empty
- All getDeploymentKey tests now pass including the previously failing 'should return null when decryption fails due to missing encryption key' test
- Fixes mocking issues in PR 22102 self-hosted onboarding wizard form refactor

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix label

* add i18n to error

* use enum for steps

* add as const

* fix test env issues

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-07-09 09:26:01 +01:00

92 lines
3.2 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { symmetricEncrypt, symmetricDecrypt } from "./crypto";
describe("crypto", () => {
const testKey = "12345678901234567890123456789012"; // 32 bytes key
const testText = "Hello, World!";
describe("symmetricEncrypt", () => {
it("should encrypt text with a valid key", () => {
const encrypted = symmetricEncrypt(testText, testKey);
// Verify the format is "iv:ciphertext"
expect(encrypted).toContain(":");
const [iv, ciphertext] = encrypted.split(":");
// IV should be 32 characters (16 bytes in hex)
expect(iv).toHaveLength(32);
// Ciphertext should exist
expect(ciphertext).toBeDefined();
expect(ciphertext.length).toBeGreaterThan(0);
});
it("should produce different ciphertexts for the same input due to random IV", () => {
const encrypted1 = symmetricEncrypt(testText, testKey);
const encrypted2 = symmetricEncrypt(testText, testKey);
expect(encrypted1).not.toBe(encrypted2);
});
it("should throw error if key is not 32 bytes", () => {
const shortKey = "short";
expect(() => symmetricEncrypt(testText, shortKey)).toThrow();
});
});
describe("symmetricDecrypt", () => {
it("should correctly decrypt encrypted text", () => {
const encrypted = symmetricEncrypt(testText, testKey);
const decrypted = symmetricDecrypt(encrypted, testKey);
expect(decrypted).toBe(testText);
});
it("should throw error for malformed encrypted text", () => {
// Test with invalid IV:ciphertext format
expect(() => symmetricDecrypt("invalid", testKey)).toThrow();
expect(() => symmetricDecrypt("invalid:data", testKey)).toThrow();
expect(() => symmetricDecrypt(":", testKey)).toThrow();
});
it("should throw error if wrong key is used", () => {
const encrypted = symmetricEncrypt(testText, testKey);
const wrongKey = "12345678901234567890123456789013"; // Different 32 bytes key
expect(() => symmetricDecrypt(encrypted, wrongKey)).toThrow();
});
it("should handle empty string encryption/decryption", () => {
const emptyText = "";
const encrypted = symmetricEncrypt(emptyText, testKey);
const decrypted = symmetricDecrypt(encrypted, testKey);
expect(decrypted).toBe(emptyText);
});
it("should handle long text encryption/decryption", () => {
const longText = "a".repeat(1000);
const encrypted = symmetricEncrypt(longText, testKey);
const decrypted = symmetricDecrypt(encrypted, testKey);
expect(decrypted).toBe(longText);
});
it("should handle special characters", () => {
const specialChars = "!@#$%^&*()_+-=[]{}|;:'\",.<>?/\\`~";
const encrypted = symmetricEncrypt(specialChars, testKey);
const decrypted = symmetricDecrypt(encrypted, testKey);
expect(decrypted).toBe(specialChars);
});
it("should handle unicode characters", () => {
const unicodeText = "Hello, 世界! 👋 🌍";
const encrypted = symmetricEncrypt(unicodeText, testKey);
const decrypted = symmetricDecrypt(encrypted, testKey);
expect(decrypted).toBe(unicodeText);
});
});
});