Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ import {
ProcessAttachmentReturnType,
} from '../types';
import { AttachmentsStreamingPool } from './attachments-streaming-pool';
import {
runWithSdkLogContext,
runWithUserLogContext,
getSdkLogContextValue,
} from '../logger/logger.context';

// Mock types
interface TestState {
attachments: { completed: boolean };
}
Expand Down Expand Up @@ -83,7 +77,6 @@ describe(AttachmentsStreamingPool.name, () => {
stream: mockStream,
});

expect(pool).toBeDefined();
expect(pool['adapter']).toBe(mockAdapter);
expect(pool['attachments']).toEqual(mockAttachments);
expect(pool['batchSize']).toBe(10);
Expand Down Expand Up @@ -656,13 +649,13 @@ describe(AttachmentsStreamingPool.name, () => {
});

it('should process user stream callback correctly while maintaining context isolation', async () => {
let userCallbackContextId: string | undefined;
let userCallbackExecuted = false;

// Mock stream to capture context info
const mockStreamFn: ExternalSystemAttachmentStreamingFunction = jest
.fn()
.mockImplementation(async () => {
await Promise.resolve();
userCallbackExecuted = true;
// Record that the callback executed
return {
Expand Down
200 changes: 200 additions & 0 deletions src/common/event-type-translation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import { EventType, ExtractorEventType } from '../types/extraction';
import { LoaderEventType } from '../types/loading';
import {
translateExtractorEventType,
translateIncomingEventType,
translateLoaderEventType,
translateOutgoingEventType,
} from './event-type-translation';

describe(translateIncomingEventType.name, () => {
it.each([
[
EventType.ExtractionExternalSyncUnitsStart,
EventType.StartExtractingExternalSyncUnits,
],
[EventType.ExtractionMetadataStart, EventType.StartExtractingMetadata],
[EventType.ExtractionDataStart, EventType.StartExtractingData],
[EventType.ExtractionDataContinue, EventType.ContinueExtractingData],
[EventType.ExtractionDataDelete, EventType.StartDeletingExtractorState],
[
EventType.ExtractionAttachmentsStart,
EventType.StartExtractingAttachments,
],
[
EventType.ExtractionAttachmentsContinue,
EventType.ContinueExtractingAttachments,
],
[
EventType.ExtractionAttachmentsDelete,
EventType.StartDeletingExtractorAttachmentsState,
],
])('maps legacy extraction event %s to %s', (legacy, modern) => {
expect(translateIncomingEventType(legacy)).toBe(modern);
});

it.each([
[EventType.StartExtractingExternalSyncUnits],
[EventType.StartExtractingMetadata],
[EventType.StartExtractingData],
[EventType.ContinueExtractingData],
[EventType.StartDeletingExtractorState],
[EventType.StartExtractingAttachments],
[EventType.ContinueExtractingAttachments],
[EventType.StartDeletingExtractorAttachmentsState],
[EventType.StartLoadingData],
[EventType.ContinueLoadingData],
[EventType.StartLoadingAttachments],
[EventType.ContinueLoadingAttachments],
[EventType.StartDeletingLoaderState],
[EventType.StartDeletingLoaderAttachmentState],
[EventType.UnknownEventType],
])('is a no-op for already-modern event type %s', (eventType) => {
expect(translateIncomingEventType(eventType)).toBe(eventType);
});

it('warns and returns the input verbatim for an unrecognised event type', () => {
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});

const result = translateIncomingEventType('NONSENSE_EVENT' as EventType);

expect(result).toBe('NONSENSE_EVENT');
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('NONSENSE_EVENT')
);

warnSpy.mockRestore();
});
});

describe(translateExtractorEventType.name, () => {
it.each([
[
ExtractorEventType.ExtractionExternalSyncUnitsDone,
ExtractorEventType.ExternalSyncUnitExtractionDone,
],
[
ExtractorEventType.ExtractionExternalSyncUnitsError,
ExtractorEventType.ExternalSyncUnitExtractionError,
],
[
ExtractorEventType.ExtractionMetadataDone,
ExtractorEventType.MetadataExtractionDone,
],
[
ExtractorEventType.ExtractionMetadataError,
ExtractorEventType.MetadataExtractionError,
],
[
ExtractorEventType.ExtractionDataProgress,
ExtractorEventType.DataExtractionProgress,
],
[
ExtractorEventType.ExtractionDataDelay,
ExtractorEventType.DataExtractionDelayed,
],
[
ExtractorEventType.ExtractionDataDone,
ExtractorEventType.DataExtractionDone,
],
[
ExtractorEventType.ExtractionDataError,
ExtractorEventType.DataExtractionError,
],
[
ExtractorEventType.ExtractionDataDeleteDone,
ExtractorEventType.ExtractorStateDeletionDone,
],
[
ExtractorEventType.ExtractionDataDeleteError,
ExtractorEventType.ExtractorStateDeletionError,
],
[
ExtractorEventType.ExtractionAttachmentsProgress,
ExtractorEventType.AttachmentExtractionProgress,
],
[
ExtractorEventType.ExtractionAttachmentsDelay,
ExtractorEventType.AttachmentExtractionDelayed,
],
[
ExtractorEventType.ExtractionAttachmentsDone,
ExtractorEventType.AttachmentExtractionDone,
],
[
ExtractorEventType.ExtractionAttachmentsError,
ExtractorEventType.AttachmentExtractionError,
],
[
ExtractorEventType.ExtractionAttachmentsDeleteDone,
ExtractorEventType.ExtractorAttachmentsStateDeletionDone,
],
[
ExtractorEventType.ExtractionAttachmentsDeleteError,
ExtractorEventType.ExtractorAttachmentsStateDeletionError,
],
])('maps legacy extractor event %s to %s', (legacy, modern) => {
expect(translateExtractorEventType(legacy)).toBe(modern);
});

it.each([
[ExtractorEventType.DataExtractionDone],
[ExtractorEventType.DataExtractionProgress],
[ExtractorEventType.AttachmentExtractionDone],
[ExtractorEventType.MetadataExtractionDone],
[ExtractorEventType.UnknownEventType],
])('is a no-op for already-modern extractor event %s', (eventType) => {
expect(translateExtractorEventType(eventType)).toBe(eventType);
});
});

describe(translateLoaderEventType.name, () => {
it.each([
[LoaderEventType.DataLoadingDelay, LoaderEventType.DataLoadingDelayed],
[
LoaderEventType.AttachmentsLoadingProgress,
LoaderEventType.AttachmentLoadingProgress,
],
[
LoaderEventType.AttachmentsLoadingDelayed,
LoaderEventType.AttachmentLoadingDelayed,
],
[
LoaderEventType.AttachmentsLoadingDone,
LoaderEventType.AttachmentLoadingDone,
],
[
LoaderEventType.AttachmentsLoadingError,
LoaderEventType.AttachmentLoadingError,
],
])('maps legacy loader event %s to %s', (legacy, modern) => {
expect(translateLoaderEventType(legacy)).toBe(modern);
});

it.each([
[LoaderEventType.DataLoadingDone],
[LoaderEventType.DataLoadingProgress],
[LoaderEventType.AttachmentLoadingDone],
])('is a no-op for already-modern loader event %s', (eventType) => {
expect(translateLoaderEventType(eventType)).toBe(eventType);
});
});

describe(translateOutgoingEventType.name, () => {
it('routes extractor events through translateExtractorEventType', () => {
expect(
translateOutgoingEventType(ExtractorEventType.ExtractionDataDone)
).toBe(ExtractorEventType.DataExtractionDone);
});

it('routes loader events through translateLoaderEventType', () => {
expect(
translateOutgoingEventType(LoaderEventType.AttachmentsLoadingDone)
).toBe(LoaderEventType.AttachmentLoadingDone);
});

it('passes through unknown event types unchanged', () => {
const unknown = 'SOME_UNKNOWN_EVENT' as ExtractorEventType;
expect(translateOutgoingEventType(unknown)).toBe(unknown);
});
});
1 change: 0 additions & 1 deletion src/common/time-value-resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ describe('time-value-resolver', () => {
);
const after = new Date().toISOString();

expect(result).toBeDefined();
expect(result! >= before).toBe(true);
expect(result! <= after).toBe(true);
});
Expand Down
50 changes: 34 additions & 16 deletions src/multithreading/create-worker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import { createWorker } from './create-worker';

describe(createWorker.name, () => {
it('should create a Worker instance when valid parameters are provided', async () => {
// Arrange
const workerPath = __dirname + '../tests/dummy-worker.ts';
const event = createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionExternalSyncUnitsStart },
});

// Act
const worker = isMainThread
? await createWorker<object>({
event: createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionExternalSyncUnitsStart },
}),
event,
initialState: {},
workerPath,
})
: null;

// Assert
expect(worker).not.toBeNull();
expect(worker).toBeInstanceOf(Worker);

Expand All @@ -28,78 +32,92 @@ describe(createWorker.name, () => {
});

it('should throw error when not in main thread', async () => {
// Arrange
const originalIsMainThread = isMainThread;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(isMainThread as any) = false;
const workerPath = __dirname + '../tests/dummy-worker.ts';
const event = createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionExternalSyncUnitsStart },
});

// Act & Assert
await expect(
createWorker<object>({
event: createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionExternalSyncUnitsStart },
}),
event,
initialState: {},
workerPath,
})
).rejects.toThrow('Worker threads can not start more worker threads.');

// Restore original value
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(isMainThread as any) = originalIsMainThread;
});

it('[edge] should handle worker creation with minimal valid data', async () => {
// Arrange
const workerPath = __dirname + '../tests/dummy-worker.ts';
const event = createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionExternalSyncUnitsStart },
});

if (isMainThread) {
// Act
const worker = await createWorker<object>({
event: createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionExternalSyncUnitsStart },
}),
event,
initialState: {},
workerPath,
});

// Assert
expect(worker).toBeInstanceOf(Worker);
await worker.terminate();
}
});

it('[edge] should handle worker creation with complex initial state', async () => {
// Arrange
const workerPath = __dirname + '../tests/dummy-worker.ts';
const complexState = {
nested: {
data: [1, 2, 3],
config: { enabled: true },
},
};
const event = createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionDataStart },
});

if (isMainThread) {
// Act
const worker = await createWorker<typeof complexState>({
event: createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionDataStart },
}),
event,
initialState: complexState,
workerPath,
});

// Assert
expect(worker).toBeInstanceOf(Worker);
await worker.terminate();
}
});

it('[edge] should handle different event types', async () => {
// Arrange
const workerPath = __dirname + '../tests/dummy-worker.ts';
const event = createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionMetadataStart },
});

if (isMainThread) {
// Act
const worker = await createWorker<object>({
event: createMockEvent(mockServer.baseUrl, {
payload: { event_type: EventType.ExtractionMetadataStart },
}),
event,
initialState: {},
workerPath,
});

// Assert
expect(worker).toBeInstanceOf(Worker);
await worker.terminate();
}
Expand Down
Loading
Loading