integration tests
Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m51s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m51s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { DatabaseTestContext, DriverData } from '../DatabaseTestContext';
|
||||
|
||||
describe('Database Constraints - Concurrent Operations', () => {
|
||||
let context: DatabaseTestContext;
|
||||
|
||||
beforeEach(() => {
|
||||
context = DatabaseTestContext.create();
|
||||
});
|
||||
|
||||
it('should handle concurrent team creation attempts safely', async () => {
|
||||
// Given: Multiple drivers exist
|
||||
const drivers: DriverData[] = await Promise.all(
|
||||
Array(5).fill(null).map((_, i) => {
|
||||
const driver = {
|
||||
id: `driver-${i}`,
|
||||
iracingId: `iracing-${i}`,
|
||||
name: `Test Driver ${i}`,
|
||||
country: 'US',
|
||||
joinedAt: new Date(),
|
||||
};
|
||||
return context.driverRepository.create(driver);
|
||||
})
|
||||
);
|
||||
|
||||
// When: Multiple concurrent attempts to create teams with same name
|
||||
// We use a small delay to ensure they don't all get the same timestamp
|
||||
// if the implementation uses Date.now() for IDs
|
||||
const concurrentRequests = drivers.map(async (driver, i) => {
|
||||
await new Promise(resolve => setTimeout(resolve, i * 10));
|
||||
return context.createTeamUseCase.execute({
|
||||
name: 'Concurrent Team',
|
||||
tag: 'CT', // Same tag for all to trigger duplicate error
|
||||
description: 'Concurrent creation',
|
||||
ownerId: driver.id,
|
||||
leagues: [],
|
||||
});
|
||||
});
|
||||
|
||||
const results = await Promise.all(concurrentRequests);
|
||||
|
||||
// Then: Exactly one should succeed, others should fail
|
||||
const successes = results.filter(r => r.isOk());
|
||||
const failures = results.filter(r => r.isErr());
|
||||
|
||||
// Note: In-memory implementation is synchronous, so concurrent requests
|
||||
// actually run sequentially in this test environment.
|
||||
expect(successes.length).toBe(1);
|
||||
expect(failures.length).toBe(4);
|
||||
|
||||
// All failures should be duplicate errors
|
||||
failures.forEach(result => {
|
||||
if (result.isErr()) {
|
||||
expect(result.error.code).toBe('DUPLICATE_TEAM');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle concurrent join requests safely', async () => {
|
||||
// Given: A driver and team exist
|
||||
const driver: DriverData = {
|
||||
id: 'driver-123',
|
||||
iracingId: '12345',
|
||||
name: 'Test Driver',
|
||||
country: 'US',
|
||||
joinedAt: new Date(),
|
||||
};
|
||||
await context.driverRepository.create(driver);
|
||||
|
||||
const team = {
|
||||
id: 'team-123',
|
||||
name: 'Test Team',
|
||||
tag: 'TT',
|
||||
description: 'A test team',
|
||||
ownerId: 'other-driver',
|
||||
leagues: [],
|
||||
isRecruiting: false,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
await context.teamRepository.create(team);
|
||||
|
||||
// When: Multiple concurrent join attempts
|
||||
const concurrentJoins = Array(3).fill(null).map(() =>
|
||||
context.joinTeamUseCase.execute({
|
||||
teamId: team.id,
|
||||
driverId: driver.id,
|
||||
})
|
||||
);
|
||||
|
||||
const results = await Promise.all(concurrentJoins);
|
||||
|
||||
// Then: Exactly one should succeed
|
||||
const successes = results.filter(r => r.isOk());
|
||||
const failures = results.filter(r => r.isErr());
|
||||
|
||||
expect(successes.length).toBe(1);
|
||||
expect(failures.length).toBe(2);
|
||||
|
||||
// All failures should be already member errors
|
||||
failures.forEach(result => {
|
||||
if (result.isErr()) {
|
||||
expect(result.error.code).toBe('ALREADY_MEMBER');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user