@@ -13,6 +13,16 @@ import { createNoopLogger } from '@mongodb-js/compass-logging/provider';
1313import { ReadOnlyPreferenceAccess } from 'compass-preferences-model/provider' ;
1414import { ExperimentTestName } from '@mongodb-js/compass-telemetry/provider' ;
1515import { 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 '../components/mock-data-generator-modal/types' ;
24+ import { CollectionActions } from '../modules/collection-tab' ;
25+ import { type MockDataSchemaResponse } from '@mongodb-js/compass-generative-ai' ;
1626
1727const defaultMetadata = {
1828 namespace : 'test.foo' ,
@@ -62,7 +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 ;
77+ const atlasAiService = { } as any ;
78+
6679 let store : ReturnType < typeof activatePlugin > [ 'store' ] ;
6780 let deactivate : ReturnType < typeof activatePlugin > [ 'deactivate' ] ;
6881
@@ -99,6 +112,7 @@ describe('Collection Tab Content store', function () {
99112 } ,
100113 {
101114 dataService,
115+ atlasAiService,
102116 localAppRegistry,
103117 collection : mockCollection as any ,
104118 workspaces : workspaces as any ,
@@ -272,4 +286,194 @@ describe('Collection Tab Content store', function () {
272286 expect ( analyzeCollectionSchemaStub ) . to . not . have . been . called ;
273287 } ) ;
274288 } ) ;
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+ namespace : 'some_db.some_collection' ,
295+ schemaAnalysis : {
296+ status : SCHEMA_ANALYSIS_STATE_COMPLETE ,
297+ processedSchema : {
298+ name : {
299+ type : 'String' ,
300+ probability : 1.0 ,
301+ sampleValues : [ 'John' , 'Jane' , 'Bob' ] ,
302+ } ,
303+ age : {
304+ type : 'Number' ,
305+ probability : 0.9 ,
306+ sampleValues : [ 25 , 30 ] ,
307+ } ,
308+ isActive : {
309+ type : 'Boolean' ,
310+ probability : 0.8 ,
311+ sampleValues : [ true , false ] ,
312+ } ,
313+ } ,
314+ schemaMetadata : {
315+ maxNestingDepth : 1 ,
316+ validationRules : null ,
317+ } ,
318+ } ,
319+ fakerSchemaGeneration : { status : MOCK_DATA_GENERATOR_STATE_IDLE } ,
320+ } ) ;
321+ const logger = {
322+ log : { error : sandbox . spy ( ) } ,
323+ debug : sandbox . spy ( ) ,
324+ } ;
325+
326+ const mockDataSchemaResponse : MockDataSchemaResponse = {
327+ content : {
328+ fields : [
329+ {
330+ fieldPath : 'name' ,
331+ probability : 1.0 ,
332+ mongoType : 'string' ,
333+ fakerMethod : 'person.firstName' ,
334+ fakerArgs : [ ] ,
335+ isArray : false ,
336+ } ,
337+ {
338+ fieldPath : 'age' ,
339+ probability : 1.0 ,
340+ mongoType : 'number' ,
341+ fakerMethod : 'number.int' ,
342+ fakerArgs : [ ] ,
343+ isArray : false ,
344+ } ,
345+ {
346+ fieldPath : 'isActive' ,
347+ probability : 1.0 ,
348+ mongoType : 'boolean' ,
349+ fakerMethod : 'datatype.boolean' ,
350+ fakerArgs : [ ] ,
351+ isArray : false ,
352+ } ,
353+ ] ,
354+ } ,
355+ } ;
356+ const atlasAiService = {
357+ getMockDataSchema : sandbox . stub ( ) . resolves ( mockDataSchemaResponse ) ,
358+ } ;
359+
360+ // Act
361+ const thunk = collectionTabModule . generateFakerMappings (
362+ mockAtlasConnectionInfo . current
363+ ) ;
364+ await thunk ( dispatch , getState , { logger, atlasAiService } as any ) ;
365+
366+ // Assert
367+ expect ( dispatch ) . to . have . been . calledTwice ;
368+
369+ const calls = dispatch . getCalls ( ) ;
370+ const startedCall = calls [ 0 ] ;
371+ const completedCall = calls [ 1 ] ;
372+
373+ expect ( startedCall ) . to . be . calledWith ( {
374+ type : CollectionActions . FakerMappingGenerationStarted ,
375+ requestId : Sinon . match . string ,
376+ } ) ;
377+
378+ expect ( completedCall ) . to . be . calledWith ( {
379+ type : CollectionActions . FakerMappingGenerationCompleted ,
380+ fakerSchema : mockDataSchemaResponse ,
381+ requestId : Sinon . match . string ,
382+ } ) ;
383+ } ) ;
384+
385+ it ( 'can dispatch a failure' , async function ( ) {
386+ const dispatch = sandbox . spy ( ) ;
387+ const getState = sandbox . stub ( ) . returns ( {
388+ namespace : 'some_db.some_collection' ,
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 ( ) . resolves ( { } ) ,
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+ } ) ;
275479} ) ;
0 commit comments