Skip to content

Commit f7d352d

Browse files
committed
test thunk behavior
1 parent 99c2881 commit f7d352d

File tree

2 files changed

+204
-2
lines changed

2 files changed

+204
-2
lines changed

packages/compass-collection/src/modules/collection-tab.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export type CollectionState = {
9696
fakerSchemaGeneration: MockDataGeneratorState;
9797
};
9898

99-
enum CollectionActions {
99+
export enum CollectionActions {
100100
CollectionMetadataFetched = 'compass-collection/CollectionMetadataFetched',
101101
SchemaAnalysisStarted = 'compass-collection/SchemaAnalysisStarted',
102102
SchemaAnalysisFinished = 'compass-collection/SchemaAnalysisFinished',
@@ -587,7 +587,7 @@ export const generateFakerMappings = (
587587
fakerSchema: response,
588588
requestId: requestId,
589589
});
590-
} catch {
590+
} catch (e) {
591591
logger.log.error(
592592
mongoLogId(1_001_000_312),
593593
'Collection',

packages/compass-collection/src/stores/collection-tab.spec.ts

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ import { createNoopLogger } from '@mongodb-js/compass-logging/provider';
1313
import { ReadOnlyPreferenceAccess } from 'compass-preferences-model/provider';
1414
import { ExperimentTestName } from '@mongodb-js/compass-telemetry/provider';
1515
import { type CollectionMetadata } from 'mongodb-collection-model';
16+
import {
17+
SCHEMA_ANALYSIS_STATE_COMPLETE,
18+
SCHEMA_ANALYSIS_STATE_INITIAL,
19+
} from '../schema-analysis-types';
20+
import {
21+
MOCK_DATA_GENERATOR_STATE_GENERATING,
22+
MOCK_DATA_GENERATOR_STATE_IDLE,
23+
} from '../mock-data-generator-types';
24+
import { CollectionActions } from '../modules/collection-tab';
25+
import { type MockDataSchemaResponse } from '@mongodb-js/compass-generative-ai';
1626

1727
const defaultMetadata = {
1828
namespace: 'test.foo',
@@ -62,8 +72,10 @@ describe('Collection Tab Content store', function () {
6272
const analyzeCollectionSchemaStub = sandbox
6373
.stub(collectionTabModule, 'analyzeCollectionSchema')
6474
.returns(async () => {});
75+
6576
const dataService = {} as any;
6677
const atlasAiService = {} as any;
78+
6779
let store: ReturnType<typeof activatePlugin>['store'];
6880
let deactivate: ReturnType<typeof activatePlugin>['deactivate'];
6981

@@ -274,4 +286,194 @@ describe('Collection Tab Content store', function () {
274286
expect(analyzeCollectionSchemaStub).to.not.have.been.called;
275287
});
276288
});
289+
290+
describe('generateFakerMappings thunk', function () {
291+
it('can complete successfully', async function () {
292+
const dispatch = sandbox.spy();
293+
const getState = sandbox.stub().returns({
294+
schemaAnalysis: {
295+
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
296+
processedSchema: {
297+
collectionName: 'foo',
298+
databaseName: 'test',
299+
schema: {
300+
name: {
301+
type: 'String',
302+
sampleValues: ['John', 'Jane', 'Bob'],
303+
probability: 1.0,
304+
},
305+
age: {
306+
type: 'Number',
307+
sampleValues: [25, 30, 35],
308+
probability: 0.9,
309+
},
310+
isActive: {
311+
type: 'Boolean',
312+
sampleValues: [true, false],
313+
probability: 0.8,
314+
},
315+
},
316+
},
317+
},
318+
fakerSchemaGeneration: { status: MOCK_DATA_GENERATOR_STATE_IDLE },
319+
});
320+
const logger = {
321+
log: { error: sandbox.spy() },
322+
debug: sandbox.spy(),
323+
};
324+
325+
const mockDataSchemaResponse: MockDataSchemaResponse = {
326+
content: {
327+
fields: [
328+
{
329+
fieldPath: 'name',
330+
probability: 1.0,
331+
mongoType: 'string',
332+
fakerMethod: 'person.firstName',
333+
fakerArgs: [],
334+
isArray: false,
335+
},
336+
{
337+
fieldPath: 'age',
338+
probability: 1.0,
339+
mongoType: 'number',
340+
fakerMethod: 'number.int',
341+
fakerArgs: [],
342+
isArray: false,
343+
},
344+
{
345+
fieldPath: 'isActive',
346+
probability: 1.0,
347+
mongoType: 'boolean',
348+
fakerMethod: 'datatype.boolean',
349+
fakerArgs: [],
350+
isArray: false,
351+
},
352+
],
353+
},
354+
};
355+
const atlasAiService = {
356+
getMockDataSchema: sandbox
357+
.stub()
358+
.returns(Promise.resolve(mockDataSchemaResponse)),
359+
};
360+
361+
// Act
362+
const thunk = collectionTabModule.generateFakerMappings(
363+
mockAtlasConnectionInfo.current
364+
);
365+
await thunk(dispatch, getState, { logger, atlasAiService } as any);
366+
367+
// Assert
368+
expect(dispatch).to.have.been.calledTwice;
369+
370+
const calls = dispatch.getCalls();
371+
const startedCall = calls[0];
372+
const completedCall = calls[1];
373+
374+
expect(startedCall).to.be.calledWith({
375+
type: CollectionActions.FakerMappingGenerationStarted,
376+
requestId: Sinon.match.string,
377+
});
378+
379+
expect(completedCall).to.be.calledWith({
380+
type: CollectionActions.FakerMappingGenerationCompleted,
381+
fakerSchema: mockDataSchemaResponse,
382+
requestId: Sinon.match.string,
383+
});
384+
});
385+
386+
it('can dispatch a failure', async function () {
387+
const dispatch = sandbox.spy();
388+
const getState = sandbox.stub().returns({
389+
schemaAnalysis: {
390+
status: SCHEMA_ANALYSIS_STATE_COMPLETE,
391+
processedSchema: undefined,
392+
},
393+
fakerSchemaGeneration: { status: MOCK_DATA_GENERATOR_STATE_IDLE },
394+
});
395+
const logger = {
396+
log: { error: sandbox.spy() },
397+
debug: sandbox.spy(),
398+
};
399+
400+
const atlasAiService = {
401+
getMockDataSchema: sandbox.stub().returns(Promise.resolve({})),
402+
};
403+
404+
// Act
405+
const thunk = collectionTabModule.generateFakerMappings(
406+
mockAtlasConnectionInfo.current
407+
);
408+
await thunk(dispatch, getState, { logger, atlasAiService } as any);
409+
410+
// Assert
411+
expect(dispatch).to.have.been.calledTwice;
412+
413+
const calls = dispatch.getCalls();
414+
const startedCall = calls[0];
415+
const completedCall = calls[1];
416+
417+
expect(startedCall).to.be.calledWith({
418+
type: CollectionActions.FakerMappingGenerationStarted,
419+
requestId: Sinon.match.string,
420+
});
421+
422+
expect(completedCall).to.be.calledWith({
423+
type: CollectionActions.FakerMappingGenerationFailed,
424+
error: Sinon.match.string,
425+
requestId: Sinon.match.string,
426+
});
427+
});
428+
429+
it('should not initiate if schemaAnalysis is incomplete', async function () {
430+
// Arrange
431+
const dispatch = sandbox.spy();
432+
const getState = sandbox.stub().returns({
433+
schemaAnalysis: { status: SCHEMA_ANALYSIS_STATE_INITIAL },
434+
fakerSchemaGeneration: { status: MOCK_DATA_GENERATOR_STATE_IDLE },
435+
});
436+
const logger = {
437+
log: { error: sandbox.spy() },
438+
debug: sandbox.spy(),
439+
};
440+
const atlasAiService = {};
441+
442+
// Act
443+
const thunk = collectionTabModule.generateFakerMappings(
444+
mockAtlasConnectionInfo.current
445+
);
446+
await thunk(dispatch, getState, { logger, atlasAiService } as any);
447+
448+
// Assert
449+
expect(dispatch).to.not.have.been.called;
450+
expect(logger.log.error).to.have.been.calledOnce;
451+
});
452+
453+
it('should not initiate if fakerSchemaGeneration is in progress', async function () {
454+
// Arrange
455+
const dispatch = sandbox.spy();
456+
const getState = sandbox.stub().returns({
457+
schemaAnalysis: { status: SCHEMA_ANALYSIS_STATE_COMPLETE },
458+
fakerSchemaGeneration: { status: MOCK_DATA_GENERATOR_STATE_GENERATING },
459+
});
460+
const logger = {
461+
log: { error: sandbox.spy() },
462+
debug: sandbox.spy(),
463+
};
464+
const atlasAiService = {
465+
getMockDataSchema: sandbox.stub().returns(Promise.resolve({})),
466+
};
467+
468+
// Act
469+
const thunk = collectionTabModule.generateFakerMappings(
470+
mockAtlasConnectionInfo.current
471+
);
472+
await thunk(dispatch, getState, { logger, atlasAiService } as any);
473+
474+
// Assert
475+
expect(dispatch).to.not.have.been.called;
476+
expect(logger.debug).to.have.been.calledOnce;
477+
});
478+
});
277479
});

0 commit comments

Comments
 (0)