mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-22 06:00:51 -06:00
Compare commits
1 Commits
fix/6957-c
...
groundwork
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b05a636914 |
183
apps/web/lib/testing/README.md
Normal file
183
apps/web/lib/testing/README.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# Testing Utilities
|
||||
|
||||
Centralized testing utilities to reduce boilerplate and ensure consistency across test files.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { FIXTURES, TEST_IDS } from "@/lib/testing/constants";
|
||||
import { setupTestEnvironment } from "@/lib/testing/setup";
|
||||
|
||||
// Setup standard test environment with cleanup
|
||||
setupTestEnvironment();
|
||||
|
||||
describe("MyModule", () => {
|
||||
test("should use standard test IDs", () => {
|
||||
// Use TEST_IDS instead of magic strings
|
||||
const result = processContact(TEST_IDS.contact);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
test("should use fixtures for test data", () => {
|
||||
// Use FIXTURES instead of defining data inline
|
||||
const result = validateEmail(FIXTURES.contact.email);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Available Utilities
|
||||
|
||||
### TEST_IDS
|
||||
|
||||
Standard identifiers to eliminate magic strings in tests.
|
||||
|
||||
**Available IDs:**
|
||||
|
||||
- `contact`, `contactAlt`
|
||||
- `user`
|
||||
- `environment`
|
||||
- `survey`
|
||||
- `organization`
|
||||
- `quota`
|
||||
- `attribute`
|
||||
- `response`
|
||||
- `team`
|
||||
- `project`
|
||||
- `segment`
|
||||
- `webhook`
|
||||
- `apiKey`
|
||||
- `membership`
|
||||
|
||||
**Before:**
|
||||
|
||||
```typescript
|
||||
const contactId = "contact-1";
|
||||
const envId = "env-123";
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```typescript
|
||||
import { TEST_IDS } from "@/lib/testing/constants";
|
||||
|
||||
// Use TEST_IDS.contact and TEST_IDS.environment
|
||||
```
|
||||
|
||||
### FIXTURES
|
||||
|
||||
Common test data structures to reduce duplication.
|
||||
|
||||
**Available fixtures:**
|
||||
|
||||
- `contact` - Basic contact object
|
||||
- `survey` - Survey object
|
||||
- `attributeKey` - Single attribute key
|
||||
- `attributeKeys` - Array of attribute keys
|
||||
- `responseData` - Sample response data
|
||||
- `environment` - Environment object
|
||||
- `organization` - Organization object
|
||||
- `project` - Project object
|
||||
|
||||
**Before:**
|
||||
|
||||
```typescript
|
||||
const mockContact = {
|
||||
id: "contact-1",
|
||||
email: "test@example.com",
|
||||
userId: "user-1",
|
||||
};
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```typescript
|
||||
import { FIXTURES } from "@/lib/testing/constants";
|
||||
|
||||
// Use FIXTURES.contact directly
|
||||
```
|
||||
|
||||
### setupTestEnvironment()
|
||||
|
||||
Standardized test cleanup to replace manual beforeEach/afterEach blocks.
|
||||
|
||||
**Before:**
|
||||
|
||||
```typescript
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```typescript
|
||||
import { setupTestEnvironment } from "@/lib/testing/setup";
|
||||
|
||||
setupTestEnvironment();
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Consistency:** All tests use the same IDs and cleanup patterns
|
||||
- **Maintainability:** Update IDs in one place instead of 200+ locations
|
||||
- **Readability:** Less boilerplate, more test logic
|
||||
- **Speed:** Write new tests faster with ready-to-use fixtures
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### For New Tests
|
||||
|
||||
Use these utilities immediately in all new test files.
|
||||
|
||||
### For Existing Tests
|
||||
|
||||
Migrate opportunistically when editing existing tests. No forced migration required.
|
||||
|
||||
### Example Migration
|
||||
|
||||
**Before (60 lines with boilerplate):**
|
||||
|
||||
```typescript
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
|
||||
const contactId = "contact-1";
|
||||
const environmentId = "env-1";
|
||||
|
||||
describe("getContact", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("fetches contact", async () => {
|
||||
const result = await getContact(contactId);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**After (45 lines, cleaner):**
|
||||
|
||||
```typescript
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { TEST_IDS } from "@/lib/testing/constants";
|
||||
import { setupTestEnvironment } from "@/lib/testing/setup";
|
||||
|
||||
setupTestEnvironment();
|
||||
|
||||
describe("getContact", () => {
|
||||
test("fetches contact", async () => {
|
||||
const result = await getContact(TEST_IDS.contact);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
120
apps/web/lib/testing/constants.ts
Normal file
120
apps/web/lib/testing/constants.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { TContactAttributeKey } from "@formbricks/types/contact-attribute-key";
|
||||
|
||||
/**
|
||||
* Standard test IDs to eliminate magic strings across test files.
|
||||
* Use these constants instead of hardcoded IDs like "contact-1", "env-123", etc.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { TEST_IDS } from "@/lib/testing/constants";
|
||||
*
|
||||
* test("should fetch contact", async () => {
|
||||
* const result = await getContact(TEST_IDS.contact);
|
||||
* expect(result).toBeDefined();
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export const TEST_IDS = {
|
||||
contact: "contact-123",
|
||||
contactAlt: "contact-456",
|
||||
user: "user-123",
|
||||
environment: "env-123",
|
||||
survey: "survey-123",
|
||||
organization: "org-123",
|
||||
quota: "quota-123",
|
||||
attribute: "attr-123",
|
||||
response: "response-123",
|
||||
team: "team-123",
|
||||
project: "project-123",
|
||||
segment: "segment-123",
|
||||
webhook: "webhook-123",
|
||||
apiKey: "api-key-123",
|
||||
membership: "membership-123",
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Common test fixtures to reduce duplicate test data definitions.
|
||||
* Extend these as needed for your specific test cases.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { FIXTURES } from "@/lib/testing/constants";
|
||||
*
|
||||
* test("should create contact", async () => {
|
||||
* vi.mocked(getContactAttributeKeys).mockResolvedValue(FIXTURES.attributeKeys);
|
||||
* const result = await createContact(FIXTURES.contact);
|
||||
* expect(result.email).toBe(FIXTURES.contact.email);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export const FIXTURES = {
|
||||
contact: {
|
||||
id: TEST_IDS.contact,
|
||||
email: "test@example.com",
|
||||
userId: TEST_IDS.user,
|
||||
},
|
||||
|
||||
survey: {
|
||||
id: TEST_IDS.survey,
|
||||
name: "Test Survey",
|
||||
environmentId: TEST_IDS.environment,
|
||||
},
|
||||
|
||||
attributeKey: {
|
||||
id: TEST_IDS.attribute,
|
||||
key: "email",
|
||||
name: "Email",
|
||||
environmentId: TEST_IDS.environment,
|
||||
createdAt: new Date("2024-01-01"),
|
||||
updatedAt: new Date("2024-01-02"),
|
||||
isUnique: false,
|
||||
description: null,
|
||||
type: "default" as const,
|
||||
},
|
||||
|
||||
attributeKeys: [
|
||||
{
|
||||
id: "key-1",
|
||||
key: "email",
|
||||
name: "Email",
|
||||
environmentId: TEST_IDS.environment,
|
||||
createdAt: new Date("2024-01-01"),
|
||||
updatedAt: new Date("2024-01-02"),
|
||||
isUnique: false,
|
||||
description: null,
|
||||
type: "default",
|
||||
},
|
||||
{
|
||||
id: "key-2",
|
||||
key: "name",
|
||||
name: "Name",
|
||||
environmentId: TEST_IDS.environment,
|
||||
createdAt: new Date("2024-01-01"),
|
||||
updatedAt: new Date("2024-01-02"),
|
||||
isUnique: false,
|
||||
description: null,
|
||||
type: "default",
|
||||
},
|
||||
] as TContactAttributeKey[],
|
||||
|
||||
responseData: {
|
||||
q1: "Open text answer",
|
||||
q2: "Option 1",
|
||||
},
|
||||
|
||||
environment: {
|
||||
id: TEST_IDS.environment,
|
||||
name: "Test Environment",
|
||||
type: "development" as const,
|
||||
},
|
||||
|
||||
organization: {
|
||||
id: TEST_IDS.organization,
|
||||
name: "Test Organization",
|
||||
},
|
||||
|
||||
project: {
|
||||
id: TEST_IDS.project,
|
||||
name: "Test Project",
|
||||
},
|
||||
} as const;
|
||||
31
apps/web/lib/testing/setup.ts
Normal file
31
apps/web/lib/testing/setup.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { afterEach, beforeEach, vi } from "vitest";
|
||||
|
||||
/**
|
||||
* Standard test environment setup with consistent cleanup patterns.
|
||||
* Call this function once at the top of your test file to ensure
|
||||
* mocks are properly cleaned up between tests.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { setupTestEnvironment } from "@/lib/testing/setup";
|
||||
*
|
||||
* setupTestEnvironment();
|
||||
*
|
||||
* describe("MyModule", () => {
|
||||
* test("should work correctly", () => {
|
||||
* // Your test code here
|
||||
* });
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Note: This replaces manual beforeEach/afterEach blocks in individual test files.
|
||||
*/
|
||||
export function setupTestEnvironment() {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
}
|
||||
@@ -184,6 +184,10 @@ export const testInputValidation = async (service: Function, ...args: any[]): Pr
|
||||
});
|
||||
};
|
||||
|
||||
// Export new testing utilities for easy access
|
||||
export { setupTestEnvironment } from "./lib/testing/setup";
|
||||
export { TEST_IDS, FIXTURES } from "./lib/testing/constants";
|
||||
|
||||
vi.mock("@/lib/constants", () => ({
|
||||
IS_FORMBRICKS_CLOUD: false,
|
||||
POSTHOG_API_KEY: "mock-posthog-api-key",
|
||||
|
||||
Reference in New Issue
Block a user