Common Testing Scenarios
Practical examples of common testing scenarios using factories and utilities
Table of Contents
- Introduction
- User & Organization Management
- Permission & Access Control
- Graph Operations
- WorkOS Webhook Processing
- Transitive Permissions
- RLS Policy Testing
- Cleanup & Data Isolation
- Error Conditions
- Performance Testing
Introduction
This guide provides complete, working examples of common testing scenarios. Each scenario includes:
- Setup - Creating necessary test data
- Action - Performing the operation being tested
- Verification - Asserting expected outcomes
- Cleanup - Removing test data
Copy these examples and adapt them to your needs.
User & Organization Management
Scenario 1: Creating a User with Organization
Use Case: Test user creation with organization membership
import { describe, expect } from 'vitest';
import test from '../test';
import { generateTestId } from '@/test-utils-integration/utils/graph-fixtures';
import { createUserWithOrgSetup } from '../setup/factories/database-fixtures';
import { queryUserAccessCache, refreshUserAccessCache } from '../setup/utilities';
describe('User Creation', () => {
test('creates user with organization membership', async ({ asSystem }) => {
await asSystem(async (client) => {
// Setup: Generate unique IDs
const userId = generateTestId('user');
const orgId = generateTestId('org');
// Action: Create user with org
const { user, org } = await createUserWithOrgSetup(client, {
userId,
orgId,
userData: {
email: 'john.doe@example.com',
first_name: 'John',
last_name: 'Doe',
role: 'developer'
},
orgData: {
name: 'Acme Corporation',
domains: ['acme.com'],
plan: 'enterprise'
}
});
// Verify: User created correctly
expect(user.id).toBe(userId);
expect(user.nodeId).toBeTruthy();
expect(user.data.email).toBe('john.doe@example.com');
// Verify: Organization created correctly
expect(org.id).toBe(orgId);
expect(org.nodeId).toBeTruthy();
expect(org.data.name).toBe('Acme Corporation');
// Verify: User has access to organization
await refreshUserAccessCache(client, userId);
const access = await queryUserAccessCache(client, userId, org.nodeId);
expect(access.length).toBeGreaterThan(0);
});
});
});
Scenario 2: Creating User with Team
Use Case: Test organizational hierarchy with teams
test('creates user with organization and team', async ({ asSystem }) => {
await asSystem(async (client) => {
// Action: Create complete hierarchy
const { user, org, team } = await createUserWithOrgSetup(client, {
includeTeam: true,
teamName: 'Engineering Team',
userData: {
email: 'engineer@example.com',
role: 'engineer'
}
});
// Verify: All entities created
expect(user).toBeDefined();
expect(org).toBeDefined();
expect(team).toBeDefined();
// Verify: Team linked to organization
expect(team!.data.org_id).toBe(org.id);
expect(team!.data.name).toBe('Engineering Team');
// Verify: User has access through hierarchy
await refreshUserAccessCache(client, user.id);
const orgAccess = await queryUserAccessCache(client, user.id, org.nodeId);
const teamAccess = await queryUserAccessCache(client, user.id, team!.nodeId);
expect(orgAccess.length).toBeGreaterThan(0);
expect(teamAccess.length).toBeGreaterThan(0);
});
});
Scenario 3: Multiple Users in Same Organization
Use Case: Test multi-user organization membership
test('creates multiple users in same organization', async ({ asSystem }) => {
await asSystem(async (client) => {
const orgId = generateTestId('org');
// Create first user with org
const { user: user1, org } = await createUserWithOrgSetup(client, {
orgId,
userData: { email: 'user1@example.com', role: 'admin' }
});
// Create second user in same org
const { user: user2 } = await createUserWithOrgSetup(client, {
orgId, // Same org
userData: { email: 'user2@example.com', role: 'member' }
});
// Verify: Both users in same organization
await refreshUserAccessCache(client, user1.id);
await refreshUserAccessCache(client, user2.id);
const user1Access = await queryUserAccessCache(client, user1.id, org.nodeId);
const user2Access = await queryUserAccessCache(client, user2.id, org.nodeId);
expect(user1Access.length).toBeGreaterThan(0);
expect(user2Access.length).toBeGreaterThan(0);
});
});
Permission & Access Control
Scenario 4: Granting Read Permission
Use Case: Test basic permission grant
import { createResourceWithPermission } from '../setup/factories/database-fixtures';
import { checkUserHasAccess } from '../setup/utilities';
test('grants read permission to user', async ({ asSystem, asUser }) => {
let userId: string;
let orgId: string;
let resourceId: string;
// Setup: Create user and resource
await asSystem(async (client) => {
const { user } = await createUserWithOrgSetup(client);
userId = user.id;
orgId = 'org_id'; // Get from user setup
const { resourceNodeId } = await createResourceWithPermission(client, {
userNodeId: user.nodeId,
resourceType: 'test.document',
permissionLevel: 'read',
resourceData: {
title: 'Public Document',
status: 'published'
}
});
resourceId = resourceNodeId;
await refreshUserAccessCache(client, userId);
});
// Verify: User can access resource
await asUser(userId, orgId, async (client) => {
const hasAccess = await checkUserHasAccess(client, resourceId);
expect(hasAccess).toBe(true);
});
});
Scenario 5: Permission Levels (Read, Write, Admin)
Use Case: Test different permission levels
test('verifies permission hierarchy', async ({ asSystem }) => {
await asSystem(async (client) => {
const { user } = await createUserWithOrgSetup(client);
// Create resources with different permissions
const { resourceNodeId: readResource } = await createResourceWithPermission(
client,
{
userNodeId: user.nodeId,
permissionLevel: 'read',
resourceData: { name: 'Read Only' }
}
);
const { resourceNodeId: writeResource } = await createResourceWithPermission(
client,
{
userNodeId: user.nodeId,
permissionLevel: 'write',
resourceData: { name: 'Editable' }
}
);
const { resourceNodeId: adminResource } = await createResourceWithPermission(
client,
{
userNodeId: user.nodeId,
permissionLevel: 'admin',
resourceData: { name: 'Full Control' }
}
);
await refreshUserAccessCache(client, user.id);
// Verify: Read permission
const readAccess = await queryUserAccessCache(client, user.id, readResource);
expect(readAccess[0]?.min_permission).toBe('auth.read');
// Verify: Write permission
const writeAccess = await queryUserAccessCache(client, user.id, writeResource);
expect(writeAccess[0]?.min_permission).toMatch(/auth\.read\.write/);
// Verify: Admin permission
const adminAccess = await queryUserAccessCache(client, user.id, adminResource);
expect(adminAccess[0]?.min_permission).toBe('auth.read.write.admin');
});
});
Scenario 6: Revoking Permissions
Use Case: Test permission removal
import { deleteEdge } from '../setup/utilities';
test('revokes user permission', async ({ asSystem, asUser }) => {
let userId: string;
let orgId: string;
let resourceId: string;
let permissionId: string;
// Setup: Grant permission
await asSystem(async (client) => {
const { user, org } = await createUserWithOrgSetup(client);
userId = user.id;
orgId = org.id;
const result = await createResourceWithPermission(client, {
userNodeId: user.nodeId,
permissionLevel: 'write'
});
resourceId = result.resourceNodeId;
permissionId = result.permissionId;
await refreshUserAccessCache(client, userId);
});
// Verify: Initially has access
await asUser(userId, orgId, async (client) => {
const hasAccess = await checkUserHasAccess(client, resourceId);
expect(hasAccess).toBe(true);
});
// Action: Revoke permission
await asSystem(async (client) => {
await deleteEdge(client, permissionId);
await refreshUserAccessCache(client, userId);
});
// Verify: No longer has access
await asUser(userId, orgId, async (client) => {
const hasAccess = await checkUserHasAccess(client, resourceId);
expect(hasAccess).toBe(false);
});
});
Graph Operations
Scenario 7: Creating Node Relationships
Use Case: Test graph edge creation
import { createConnectedNodes } from '../setup/factories/database-fixtures';
import { getEdgesBetweenNodes } from '../setup/utilities';
test('creates connected nodes', async ({ asSystem }) => {
await asSystem(async (client) => {
// Action: Create person → company relationship
const { source: person, target: company, edge } = await createConnectedNodes(
client,
{
sourceType: 'test.person',
targetType: 'test.company',
edgeType: 'test.works_at',
sourceData: {
name: 'Alice Johnson',
title: 'Senior Engineer',
skills: ['TypeScript', 'React', 'Node.js']
},
targetData: {
name: 'Acme Corp',
industry: 'Software',
size: 'enterprise'
},
edgeData: {
start_date: '2024-01-01',
employment_type: 'full-time'
}
}
);
// Verify: Nodes created
expect(person.nodeId).toBeTruthy();
expect(company.nodeId).toBeTruthy();
// Verify: Edge exists
const edges = await getEdgesBetweenNodes(
client,
person.nodeId,
company.nodeId,
'test.works_at'
);
expect(edges).toHaveLength(1);
expect(edges[0].data.employment_type).toBe('full-time');
});
});
Scenario 8: Graph Traversal
Use Case: Test multi-hop relationships
test('traverses multi-level graph', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create: Person → Company → Project chain
const { source: person, target: company } = await createConnectedNodes(client, {
sourceType: 'test.person',
targetType: 'test.company',
edgeType: 'test.works_at',
sourceData: { name: 'Alice' },
targetData: { name: 'Acme Corp' }
});
const { target: project } = await createConnectedNodes(client, {
sourceType: 'test.company',
targetType: 'test.project',
edgeType: 'test.owns',
sourceData: { id: company.id },
targetData: { name: 'Project X', status: 'active' }
});
// Verify: All relationships exist
const companyEdges = await getEdgesBetweenNodes(
client,
person.nodeId,
company.nodeId
);
expect(companyEdges).toHaveLength(1);
const projectEdges = await getEdgesBetweenNodes(
client,
company.nodeId,
project.nodeId
);
expect(projectEdges).toHaveLength(1);
});
});
Scenario 9: Querying Nodes by Type
Use Case: Find all nodes of a specific type
import { getNodesByType } from '../setup/utilities';
test('queries nodes by type', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create multiple resources
const workspace = await setupTestWorkspace(client, {
resourceCount: 5,
resourceType: 'test.document'
});
// Query all documents
const documents = await getNodesByType(client, 'test.document');
// Verify: All documents found
expect(documents.length).toBeGreaterThanOrEqual(5);
// Verify: Each has correct type
documents.forEach(doc => {
expect(doc.node_type_id).toBe('test.document');
});
});
});
WorkOS Webhook Processing
Scenario 10: User Created Webhook
Use Case: Test user.created webhook processing
import { createUserEvent } from '../setup/factories/workos-events';
import { getNodesByType } from '../setup/utilities';
test('processes user.created webhook', async ({ asSystem }) => {
const userId = 'user_workos_123';
// Action: Create webhook event
const event = createUserEvent('user.created', userId, {
email: 'john.doe@example.com',
firstName: 'John',
lastName: 'Doe',
emailVerified: true,
metadata: { source: 'sso' }
});
// Process webhook (your handler)
await handleWorkOSWebhook(event);
// Verify: User created in database
await asSystem(async (client) => {
const users = await getNodesByType(client, 'platform.user');
const user = users.find(u => u.external_id === userId);
expect(user).toBeDefined();
expect(user.data.email).toBe('john.doe@example.com');
expect(user.data.first_name).toBe('John');
expect(user.data.last_name).toBe('Doe');
expect(user.data.email_verified).toBe(true);
});
});
Scenario 11: Organization Created Webhook
Use Case: Test organization.created webhook
import { createOrgEvent } from '../setup/factories/workos-events';
test('processes organization.created webhook', async ({ asSystem }) => {
const orgId = 'org_workos_456';
// Action: Create webhook event
const event = createOrgEvent('organization.created', orgId, {
name: 'Acme Corporation',
domains: [
{ domain: 'acme.com', state: 'verified' },
{ domain: 'acmecorp.com', state: 'verified' }
],
allowProfilesOutsideOrganization: false,
metadata: { tier: 'enterprise' }
});
await handleWorkOSWebhook(event);
// Verify: Organization created
await asSystem(async (client) => {
const orgs = await getNodesByType(client, 'platform.organization');
const org = orgs.find(o => o.external_id === orgId);
expect(org).toBeDefined();
expect(org.data.name).toBe('Acme Corporation');
expect(org.data.domains).toHaveLength(2);
expect(org.data.allow_profiles_outside_organization).toBe(false);
});
});
Scenario 12: Complete User Onboarding Flow
Use Case: Test complete webhook sequence
import {
createUserEvent,
createOrgEvent,
createMembershipEvent
} from '../setup/factories/workos-events';
test('processes complete user onboarding', async ({ asSystem }) => {
const userId = 'user_789';
const orgId = 'org_789';
const membershipId = 'membership_789';
// Step 1: Organization created
const orgEvent = createOrgEvent('organization.created', orgId, {
name: 'Tech Startup Inc',
domains: [{ domain: 'techstartup.com' }]
});
await handleWorkOSWebhook(orgEvent);
// Step 2: User created
const userEvent = createUserEvent('user.created', userId, {
email: 'founder@techstartup.com',
firstName: 'Jane',
lastName: 'Founder'
});
await handleWorkOSWebhook(userEvent);
// Step 3: Membership created
const membershipEvent = createMembershipEvent(
'organization_membership.created',
membershipId,
userId,
orgId,
{
role: { slug: 'admin' },
status: 'active'
}
);
await handleWorkOSWebhook(membershipEvent);
// Verify: Complete state
await asSystem(async (client) => {
// Verify user
const users = await getNodesByType(client, 'platform.user');
const user = users.find(u => u.external_id === userId);
expect(user).toBeDefined();
// Verify org
const orgs = await getNodesByType(client, 'platform.organization');
const org = orgs.find(o => o.external_id === orgId);
expect(org).toBeDefined();
// Verify membership edge
const edges = await getEdgesBetweenNodes(
client,
user.id,
org.id,
'auth.read.member'
);
expect(edges).toHaveLength(1);
// Verify user access
await refreshUserAccessCache(client, userId);
const access = await queryUserAccessCache(client, userId, org.id);
expect(access.length).toBeGreaterThan(0);
});
});
Transitive Permissions
Scenario 13: Inherited Organization Permissions
Use Case: Test permission inheritance through organization
test('inherits permissions through organization', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create user → org → resource hierarchy
const { user, org } = await createUserWithOrgSetup(client);
// Grant permission to organization (not user directly)
const { resourceNodeId } = await createResourceWithPermission(client, {
userNodeId: org.nodeId, // Grant to org, not user
resourceType: 'test.company_resource',
permissionLevel: 'read',
resourceData: { shared_with: 'all_org_members' }
});
// Refresh cache to pick up transitive permissions
await refreshUserAccessCache(client, user.id);
// Verify: User has access through org membership
const access = await queryUserAccessCache(client, user.id, resourceNodeId);
expect(access.length).toBeGreaterThan(0);
// Verify: Permission is transitive (depth > 0)
expect(access[0].depth).toBeGreaterThan(0);
expect(access[0].min_permission).toBe('auth.read');
});
});
Scenario 14: Team-Based Permissions
Use Case: Test permission inheritance through team
test('inherits permissions through team', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create user → team → org hierarchy
const { user, org, team } = await createUserWithOrgSetup(client, {
includeTeam: true,
teamName: 'Engineering'
});
// Grant permission to team
const { resourceNodeId } = await createResourceWithPermission(client, {
userNodeId: team!.nodeId,
resourceType: 'test.team_project',
permissionLevel: 'write',
resourceData: { team_name: 'Engineering' }
});
await refreshUserAccessCache(client, user.id);
// Verify: User has access through team membership
const access = await queryUserAccessCache(client, user.id, resourceNodeId);
expect(access.length).toBeGreaterThan(0);
expect(access[0].min_permission).toMatch(/auth\.read\.write/);
});
});
Scenario 15: Multi-Level Permission Chain
Use Case: Test deep permission hierarchies
test('follows multi-level permission chain', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create: User → Team → Org → Department → Project
const { user, org, team } = await createUserWithOrgSetup(client, {
includeTeam: true
});
// Create department node
const department = await createNodeWithType(client, 'test.department', {
name: 'Engineering Department',
org_id: org.id
});
// Link org → department
await createConnectedNodes(client, {
sourceType: 'platform.organization',
targetType: 'test.department',
edgeType: 'auth.read.member',
sourceData: { id: org.id },
targetData: { id: department.id }
});
// Create project owned by department
const { resourceNodeId: projectId } = await createResourceWithPermission(client, {
userNodeId: department.nodeId,
resourceType: 'test.project',
permissionLevel: 'admin'
});
await refreshUserAccessCache(client, user.id);
// Verify: User has access through entire chain
const access = await queryUserAccessCache(client, user.id, projectId);
expect(access.length).toBeGreaterThan(0);
expect(access[0].depth).toBeGreaterThan(1); // Multi-hop
});
});
RLS Policy Testing
Scenario 16: Row-Level Security Enforcement
Use Case: Test RLS policies prevent unauthorized access
test('enforces RLS policies', async ({ asSystem, asUser }) => {
let user1Id: string, user1NodeId: string;
let user2Id: string, user2NodeId: string;
let privateResourceId: string;
// Setup: Create two users and a private resource
await asSystem(async (client) => {
const { user: user1 } = await createUserWithOrgSetup(client);
const { user: user2 } = await createUserWithOrgSetup(client);
user1Id = user1.id;
user1NodeId = user1.nodeId;
user2Id = user2.id;
user2NodeId = user2.nodeId;
// Create private resource for user1
const { resourceNodeId } = await createResourceWithPermission(client, {
userNodeId: user1NodeId,
resourceType: 'test.private_document',
permissionLevel: 'admin',
resourceData: { classification: 'confidential' }
});
privateResourceId = resourceNodeId;
await refreshUserAccessCache(client, user1Id);
await refreshUserAccessCache(client, user2Id);
});
// Test: User1 can access
await asUser(user1Id, 'org1', async (client) => {
const hasAccess = await checkUserHasAccess(client, privateResourceId);
expect(hasAccess).toBe(true);
});
// Test: User2 cannot access
await asUser(user2Id, 'org2', async (client) => {
const hasAccess = await checkUserHasAccess(client, privateResourceId);
expect(hasAccess).toBe(false);
});
});
Scenario 17: Cross-Organization Isolation
Use Case: Ensure organizations cannot see each other's data
test('isolates data between organizations', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create two separate organizations
const { user: user1, org: org1 } = await createUserWithOrgSetup(client, {
orgData: { name: 'Company A' }
});
const { user: user2, org: org2 } = await createUserWithOrgSetup(client, {
orgData: { name: 'Company B' }
});
// Create org-specific resources
const { resourceNodeId: org1Resource } = await createResourceWithPermission(
client,
{
userNodeId: org1.nodeId,
resourceData: { owner: 'Company A' }
}
);
const { resourceNodeId: org2Resource } = await createResourceWithPermission(
client,
{
userNodeId: org2.nodeId,
resourceData: { owner: 'Company B' }
}
);
await refreshUserAccessCache(client, user1.id);
await refreshUserAccessCache(client, user2.id);
// Verify: User1 can only see org1 resources
const user1Access = await queryUserAccessCache(client, user1.id);
const user1CanSeeOrg2 = user1Access.some(a => a.node_id === org2Resource);
expect(user1CanSeeOrg2).toBe(false);
// Verify: User2 can only see org2 resources
const user2Access = await queryUserAccessCache(client, user2.id);
const user2CanSeeOrg1 = user2Access.some(a => a.node_id === org1Resource);
expect(user2CanSeeOrg1).toBe(false);
});
});
Cleanup & Data Isolation
Scenario 18: Cleanup After Test
Use Case: Proper test cleanup to prevent data leakage
import { cleanupTestData } from '../setup/utilities';
test('cleans up test data properly', async ({ asSystem }) => {
await asSystem(async (client) => {
try {
// Create test data
const workspace = await setupTestWorkspace(client, {
resourceCount: 10,
resourceType: 'test.temp_resource'
});
// Run test operations...
expect(workspace.resources).toHaveLength(10);
} finally {
// Always cleanup, even if test fails
const result = await cleanupTestData(client, {
nodeTypes: [
'platform.user',
'platform.organization',
'test.temp_resource'
],
edgeTypes: ['auth.read', 'auth.read.member'],
externalIdPattern: 'test_%'
});
console.log(`Cleaned up: ${result.nodes} nodes, ${result.edges} edges`);
}
});
});
Scenario 19: Pattern-Based Cleanup
Use Case: Clean up by external ID pattern
import { cleanupByExternalIdPattern } from '../setup/utilities';
test('cleans up by pattern', async ({ asSystem }) => {
await asSystem(async (client) => {
const testPrefix = `test_${Date.now()}`;
try {
// Create nodes with specific prefix
await createUserWithOrgSetup(client, {
userId: `${testPrefix}_user1`,
orgId: `${testPrefix}_org1`
});
await createUserWithOrgSetup(client, {
userId: `${testPrefix}_user2`,
orgId: `${testPrefix}_org2`
});
// Test operations...
} finally {
// Clean up all nodes matching pattern
const deleted = await cleanupByExternalIdPattern(
client,
`${testPrefix}_%`
);
expect(deleted).toBeGreaterThan(0);
}
});
});
Error Conditions
Scenario 20: Testing Access Denial
Use Case: Verify operations fail without proper permissions
test('denies access without permission', async ({ asSystem, asUser }) => {
let userId: string;
let orgId: string;
let resourceId: string;
// Setup: Create user and resource (no permission)
await asSystem(async (client) => {
const { user, org } = await createUserWithOrgSetup(client);
userId = user.id;
orgId = org.id;
// Create resource WITHOUT granting permission to user
const resource = await createNodeWithType(client, 'test.protected', {
classification: 'top-secret'
});
resourceId = resource.nodeId;
await refreshUserAccessCache(client, userId);
});
// Verify: User cannot access
await asUser(userId, orgId, async (client) => {
const hasAccess = await checkUserHasAccess(client, resourceId);
expect(hasAccess).toBe(false);
// Attempting to read should fail
await expect(
client.query('SELECT * FROM graph.nodes WHERE id = $1', [resourceId])
).rejects.toThrow(); // RLS should block
});
});
Performance Testing
Scenario 21: Bulk Resource Creation
Use Case: Test performance with many resources
import { setupTestWorkspace } from '../setup/factories/database-fixtures';
test('handles bulk resource creation', async ({ asSystem }) => {
const startTime = Date.now();
await asSystem(async (client) => {
// Create workspace with 100 resources
const workspace = await setupTestWorkspace(client, {
resourceCount: 100,
resourceType: 'test.bulk_resource',
resourcePermission: 'read'
});
expect(workspace.resources).toHaveLength(100);
// Verify cache updated
await refreshUserAccessCache(client, workspace.user.id);
const access = await queryUserAccessCache(client, workspace.user.id);
// Should have access to all resources
expect(access.length).toBeGreaterThanOrEqual(100);
// Cleanup
await cleanupTestData(client, {
nodeTypes: ['test.bulk_resource', 'platform.user', 'platform.organization'],
externalIdPattern: 'test_%'
});
});
const duration = Date.now() - startTime;
console.log(`Bulk creation took ${duration}ms`);
// Should complete in reasonable time
expect(duration).toBeLessThan(30000); // 30 seconds
});
Scenario 22: Cache Performance
Use Case: Test access cache query performance
test('queries cache efficiently with many permissions', async ({ asSystem }) => {
await asSystem(async (client) => {
// Create user with many permissions
const workspace = await setupTestWorkspace(client, {
resourceCount: 50,
resourcePermission: 'admin'
});
await refreshUserAccessCache(client, workspace.user.id);
// Measure query performance
const startTime = Date.now();
const access = await queryUserAccessCache(client, workspace.user.id);
const duration = Date.now() - startTime;
expect(access.length).toBeGreaterThanOrEqual(50);
expect(duration).toBeLessThan(1000); // Should be fast
console.log(`Cache query returned ${access.length} records in ${duration}ms`);
});
});
Scenario 23: Concurrent Operations
Use Case: Test handling of concurrent permission grants
test('handles concurrent permission grants', async ({ asSystem }) => {
await asSystem(async (client) => {
const { user } = await createUserWithOrgSetup(client);
// Create multiple resources concurrently
const promises = Array.from({ length: 20 }, (_, i) =>
createResourceWithPermission(client, {
userNodeId: user.nodeId,
resourceType: 'test.concurrent',
permissionLevel: 'read',
resourceData: { index: i }
})
);
const startTime = Date.now();
const results = await Promise.all(promises);
const duration = Date.now() - startTime;
expect(results).toHaveLength(20);
console.log(`Concurrent creation took ${duration}ms`);
// Verify all permissions granted
await refreshUserAccessCache(client, user.id);
const access = await queryUserAccessCache(client, user.id);
expect(access.length).toBeGreaterThanOrEqual(20);
});
});
Summary
This guide has covered 23 common testing scenarios:
User & Organization Management (3 scenarios)
- Creating users with organizations
- Team hierarchies
- Multi-user organizations
Permission & Access Control (3 scenarios)
- Granting permissions
- Permission levels
- Revoking permissions
Graph Operations (3 scenarios)
- Node relationships
- Graph traversal
- Querying by type
WorkOS Webhook Processing (3 scenarios)
- User webhooks
- Organization webhooks
- Complete onboarding flows
Transitive Permissions (3 scenarios)
- Organization inheritance
- Team-based permissions
- Multi-level chains
RLS Policy Testing (2 scenarios)
- Row-level security
- Cross-organization isolation
Cleanup & Data Isolation (2 scenarios)
- Proper cleanup
- Pattern-based cleanup
Error Conditions (1 scenario)
- Access denial
Performance Testing (3 scenarios)
- Bulk operations
- Cache performance
- Concurrent operations
Next Steps
- Adapt these scenarios to your specific use cases
- Combine patterns to create complex test scenarios
- Use as templates for new tests
- Reference when migrating existing tests
Related Documentation
- Integration Test Guide - Complete testing guide
- Factories and Utilities Reference - Full API reference
- Migration Guide - Migrate existing tests
Questions? Check the Troubleshooting Guide or use /reportbug