@@ -20,6 +20,11 @@ import { createNoopTrack } from '@mongodb-js/compass-telemetry/provider';
2020import type { ConnectionInfoRef } from '@mongodb-js/compass-connections/provider' ;
2121import { type WorkspacesService } from '@mongodb-js/compass-workspaces/provider' ;
2222import Sinon from 'sinon' ;
23+ import {
24+ generateValidationRules ,
25+ stopRulesGeneration ,
26+ } from '../modules/rules-generation' ;
27+ import { waitFor } from '@mongodb-js/testing-library-compass' ;
2328
2429const topologyDescription = {
2530 type : 'Unknown' ,
@@ -39,14 +44,16 @@ const fakeDataService = {
3944 new Promise ( ( ) => {
4045 /* never resolves */
4146 } ) ,
47+ isCancelError : ( ) => false ,
48+ sample : ( ) => [ { prop1 : 'abc' } ] ,
4249} as any ;
4350
4451const fakeWorkspaces = {
4552 onTabReplace : ( ) => { } ,
4653 onTabClose : ( ) => { } ,
4754} as unknown as WorkspacesService ;
4855
49- const getMockedStore = async ( ) => {
56+ const getMockedStore = async ( analyzeSchema : any ) => {
5057 const globalAppRegistry = new AppRegistry ( ) ;
5158 const connectionInfoRef = {
5259 current : { } ,
@@ -63,11 +70,16 @@ const getMockedStore = async () => {
6370 track : createNoopTrack ( ) ,
6471 connectionInfoRef,
6572 } ,
66- createActivateHelpers ( )
73+ createActivateHelpers ( ) ,
74+ analyzeSchema
6775 ) ;
6876 return activateResult ;
6977} ;
7078
79+ const schemaAccessor = {
80+ getMongoDBJsonSchema : ( ) => ( { required : [ 'prop1' ] } ) ,
81+ } ;
82+
7183describe ( 'Schema Validation Store' , function ( ) {
7284 let store : Store < RootState , RootAction > ;
7385 let deactivate : null | ( ( ) => void ) = null ;
@@ -77,7 +89,8 @@ describe('Schema Validation Store', function () {
7789 sandbox = Sinon . createSandbox ( ) ;
7890 fakeWorkspaces . onTabClose = sandbox . stub ( ) ;
7991 fakeWorkspaces . onTabReplace = sandbox . stub ( ) ;
80- const activateResult = await getMockedStore ( ) ;
92+ const fakeAnalyzeSchema = sandbox . fake . resolves ( schemaAccessor ) ;
93+ const activateResult = await getMockedStore ( fakeAnalyzeSchema ) ;
8194 store = activateResult . store ;
8295 deactivate = activateResult . deactivate ;
8396 } ) ;
@@ -278,5 +291,121 @@ describe('Schema Validation Store', function () {
278291 store . dispatch ( validationLevelChanged ( validationLevel ) ) ;
279292 } ) ;
280293 } ) ;
294+
295+ context ( 'when the action is generateValidationRules' , function ( ) {
296+ it ( 'executes rules generation' , async function ( ) {
297+ store . dispatch ( generateValidationRules ( ) as any ) ;
298+
299+ await waitFor ( ( ) => {
300+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal ( true ) ;
301+ } ) ;
302+ await waitFor ( ( ) => {
303+ expect (
304+ JSON . parse ( store . getState ( ) . validation . validator )
305+ ) . to . deep . equal ( {
306+ $jsonSchema : {
307+ required : [ 'prop1' ] ,
308+ } ,
309+ } ) ;
310+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal ( false ) ;
311+ expect ( store . getState ( ) . rulesGeneration . error ) . to . be . undefined ;
312+ } ) ;
313+ } ) ;
314+
315+ it ( 'rules generation can be aborted' , async function ( ) {
316+ store . dispatch ( generateValidationRules ( ) as any ) ;
317+
318+ await waitFor ( ( ) => {
319+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal ( true ) ;
320+ } ) ;
321+
322+ store . dispatch ( stopRulesGeneration ( ) as any ) ;
323+ await waitFor ( ( ) => {
324+ expect ( store . getState ( ) . validation . validator ) . to . equal ( '' ) ;
325+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal ( false ) ;
326+ expect ( store . getState ( ) . rulesGeneration . error ) . to . be . undefined ;
327+ } ) ;
328+ } ) ;
329+
330+ context ( 'rules generation failure' , function ( ) {
331+ it ( 'handles general error' , async function ( ) {
332+ const fakeAnalyzeSchema = sandbox . fake . rejects (
333+ new Error ( 'Such a failure' )
334+ ) ;
335+ const activateResult = await getMockedStore ( fakeAnalyzeSchema ) ;
336+ store = activateResult . store ;
337+ deactivate = activateResult . deactivate ;
338+ store . dispatch ( generateValidationRules ( ) as any ) ;
339+
340+ await waitFor ( ( ) => {
341+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal (
342+ true
343+ ) ;
344+ } ) ;
345+
346+ await waitFor ( ( ) => {
347+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal (
348+ false
349+ ) ;
350+ expect ( store . getState ( ) . rulesGeneration . error ) . to . deep . equal ( {
351+ errorMessage : 'Such a failure' ,
352+ errorType : 'general' ,
353+ } ) ;
354+ } ) ;
355+ } ) ;
356+
357+ it ( 'handles complexity error' , async function ( ) {
358+ const fakeAnalyzeSchema = sandbox . fake . rejects (
359+ new Error ( 'Schema analysis aborted: Fields count above 1000' )
360+ ) ;
361+ const activateResult = await getMockedStore ( fakeAnalyzeSchema ) ;
362+ store = activateResult . store ;
363+ deactivate = activateResult . deactivate ;
364+ store . dispatch ( generateValidationRules ( ) as any ) ;
365+
366+ await waitFor ( ( ) => {
367+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal (
368+ true
369+ ) ;
370+ } ) ;
371+
372+ await waitFor ( ( ) => {
373+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal (
374+ false
375+ ) ;
376+ expect ( store . getState ( ) . rulesGeneration . error ) . to . deep . equal ( {
377+ errorMessage : 'Schema analysis aborted: Fields count above 1000' ,
378+ errorType : 'highComplexity' ,
379+ } ) ;
380+ } ) ;
381+ } ) ;
382+
383+ it ( 'handles timeout error' , async function ( ) {
384+ const timeoutError : any = new Error ( 'Too long, didnt execute' ) ;
385+ timeoutError . code = 50 ;
386+ const fakeAnalyzeSchema = sandbox . fake . rejects ( timeoutError ) ;
387+ const activateResult = await getMockedStore ( fakeAnalyzeSchema ) ;
388+ store = activateResult . store ;
389+ deactivate = activateResult . deactivate ;
390+ store . dispatch ( generateValidationRules ( ) as any ) ;
391+
392+ await waitFor ( ( ) => {
393+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal (
394+ true
395+ ) ;
396+ } ) ;
397+
398+ await waitFor ( ( ) => {
399+ expect ( store . getState ( ) . rulesGeneration . isInProgress ) . to . equal (
400+ false
401+ ) ;
402+ expect ( store . getState ( ) . rulesGeneration . error ) . to . deep . equal ( {
403+ errorMessage : 'Too long, didnt execute' ,
404+ errorType : 'timeout' ,
405+ } ) ;
406+ } ) ;
407+ } ) ;
408+ } ) ;
409+ } ) ;
281410 } ) ;
282411} ) ;
0 commit comments