11import { expect } from 'chai' ;
22import React , { type ComponentProps } from 'react' ;
3- import { render , screen , cleanup } from '@mongodb-js/testing-library-compass' ;
3+ import {
4+ renderWithActiveConnection ,
5+ screen ,
6+ cleanup ,
7+ } from '@mongodb-js/testing-library-compass' ;
48import sinon from 'sinon' ;
59import {
610 WorkspacesServiceProvider ,
@@ -9,38 +13,62 @@ import {
913import type { PreferencesAccess } from 'compass-preferences-model' ;
1014import { createSandboxFromDefaultPreferences } from 'compass-preferences-model' ;
1115import { PreferencesProvider } from 'compass-preferences-model/provider' ;
16+ import { ExperimentTestName } from '@mongodb-js/compass-telemetry/provider' ;
17+ import { CompassExperimentationProvider } from '@mongodb-js/compass-telemetry' ;
18+ import type { ConnectionInfo } from '@mongodb-js/compass-connections/provider' ;
1219
1320import CollectionHeaderActions from '../collection-header-actions' ;
1421
1522describe ( 'CollectionHeaderActions [Component]' , function ( ) {
1623 let preferences : PreferencesAccess ;
24+ let mockUseAssignment : sinon . SinonStub ;
25+
1726 beforeEach ( async function ( ) {
1827 preferences = await createSandboxFromDefaultPreferences ( ) ;
28+ mockUseAssignment = sinon . stub ( ) ;
29+ mockUseAssignment . returns ( {
30+ assignment : {
31+ assignmentData : {
32+ variant : 'mockDataGeneratorControl' ,
33+ } ,
34+ } ,
35+ } ) ;
1936 } ) ;
37+
2038 afterEach ( function ( ) {
2139 sinon . restore ( ) ;
2240 } ) ;
2341
2442 const renderCollectionHeaderActions = (
2543 props : Partial < ComponentProps < typeof CollectionHeaderActions > > = { } ,
26- workspaceService : Partial < WorkspacesService > = { }
44+ workspaceService : Partial < WorkspacesService > = { } ,
45+ connectionInfo ?: ConnectionInfo
2746 ) => {
28- return render (
29- < WorkspacesServiceProvider value = { workspaceService as WorkspacesService } >
30- < PreferencesProvider value = { preferences } >
31- < CollectionHeaderActions
32- namespace = "test.test"
33- isReadonly = { false }
34- { ...props }
35- />
36- </ PreferencesProvider >
37- </ WorkspacesServiceProvider >
47+ return renderWithActiveConnection (
48+ < CompassExperimentationProvider
49+ useAssignment = { mockUseAssignment }
50+ assignExperiment = { sinon . stub ( ) }
51+ >
52+ < WorkspacesServiceProvider
53+ value = { workspaceService as WorkspacesService }
54+ >
55+ < PreferencesProvider value = { preferences } >
56+ < CollectionHeaderActions
57+ namespace = "test.test"
58+ isReadonly = { false }
59+ onOpenMockDataModal = { sinon . stub ( ) }
60+ { ...props }
61+ />
62+ </ PreferencesProvider >
63+ </ WorkspacesServiceProvider >
64+ </ CompassExperimentationProvider > ,
65+ connectionInfo
3866 ) ;
3967 } ;
4068
4169 context ( 'when the collection is not readonly' , function ( ) {
42- beforeEach ( function ( ) {
43- renderCollectionHeaderActions ( {
70+ beforeEach ( async function ( ) {
71+ await renderCollectionHeaderActions ( {
4472 isReadonly : false ,
4573 namespace : 'db.coll2' ,
4674 sourceName : 'db.coll' ,
@@ -63,7 +91,7 @@ describe('CollectionHeaderActions [Component]', function () {
6391 it ( 'does not render edit view buttons when in readonly mode' , async function ( ) {
6492 await preferences . savePreferences ( { readOnly : true } ) ;
6593
66- renderCollectionHeaderActions ( {
94+ await renderCollectionHeaderActions ( {
6795 isReadonly : true ,
6896 namespace : 'db.coll2' ,
6997 sourceName : 'db.someSource' ,
@@ -78,8 +106,8 @@ describe('CollectionHeaderActions [Component]', function () {
78106 ) . to . not . exist ;
79107 } ) ;
80108
81- it ( 'renders edit view buttons when not in readonly mode' , function ( ) {
82- renderCollectionHeaderActions ( {
109+ it ( 'renders edit view buttons when not in readonly mode' , async function ( ) {
110+ await renderCollectionHeaderActions ( {
83111 isReadonly : true ,
84112 namespace : 'db.coll2' ,
85113 sourceName : 'db.someSource' ,
@@ -94,9 +122,9 @@ describe('CollectionHeaderActions [Component]', function () {
94122
95123 context ( 'when the collection is a view' , function ( ) {
96124 let openEditViewWorkspaceStub : sinon . SinonStub ;
97- beforeEach ( function ( ) {
125+ beforeEach ( async function ( ) {
98126 openEditViewWorkspaceStub = sinon . stub ( ) ;
99- renderCollectionHeaderActions (
127+ await renderCollectionHeaderActions (
100128 {
101129 isReadonly : true ,
102130 namespace : 'db.coll2' ,
@@ -135,9 +163,9 @@ describe('CollectionHeaderActions [Component]', function () {
135163
136164 context ( 'when the collection is editing a view' , function ( ) {
137165 let openCollectionWorkspaceStub : sinon . SinonStub ;
138- beforeEach ( function ( ) {
166+ beforeEach ( async function ( ) {
139167 openCollectionWorkspaceStub = sinon . stub ( ) ;
140- renderCollectionHeaderActions (
168+ await renderCollectionHeaderActions (
141169 {
142170 isReadonly : false ,
143171 namespace : 'db.coll2' ,
@@ -168,4 +196,183 @@ describe('CollectionHeaderActions [Component]', function () {
168196 ) ;
169197 } ) ;
170198 } ) ;
199+
200+ context ( 'Mock Data Generator Button' , function ( ) {
201+ const atlasConnectionInfo : ConnectionInfo = {
202+ id : 'test-atlas-connection' ,
203+ connectionOptions : {
204+ connectionString : 'mongodb://localhost:27017' ,
205+ } ,
206+ atlasMetadata : {
207+ orgId : 'test-org' ,
208+ projectId : 'test-project' ,
209+ clusterName : 'test-cluster' ,
210+ clusterUniqueId : 'test-cluster-unique-id' ,
211+ clusterType : 'REPLICASET' ,
212+ clusterState : 'IDLE' ,
213+ metricsId : 'test-metrics-id' ,
214+ metricsType : 'replicaSet' ,
215+ regionalBaseUrl : null ,
216+ instanceSize : 'M10' ,
217+ supports : {
218+ globalWrites : false ,
219+ rollingIndexes : true ,
220+ } ,
221+ } ,
222+ } ;
223+
224+ it ( 'should not show Mock Data Generator button when user is in control group' , async function ( ) {
225+ mockUseAssignment . returns ( {
226+ assignment : {
227+ assignmentData : {
228+ variant : 'mockDataGeneratorControl' ,
229+ } ,
230+ } ,
231+ } ) ;
232+
233+ await renderCollectionHeaderActions (
234+ {
235+ namespace : 'test.collection' ,
236+ isReadonly : false ,
237+ } ,
238+ { } ,
239+ atlasConnectionInfo
240+ ) ;
241+
242+ expect (
243+ screen . queryByTestId ( 'collection-header-generate-mock-data-button' )
244+ ) . to . not . exist ;
245+ } ) ;
246+
247+ it ( 'should not show Mock Data Generator button when not in Atlas' , async function ( ) {
248+ mockUseAssignment . returns ( {
249+ assignment : {
250+ assignmentData : {
251+ variant : 'treatment' ,
252+ } ,
253+ } ,
254+ } ) ;
255+
256+ await renderCollectionHeaderActions ( {
257+ namespace : 'test.collection' ,
258+ isReadonly : false ,
259+ // Don't pass atlasConnectionInfo, to simulate not being in Atlas
260+ } ) ;
261+
262+ expect (
263+ screen . queryByTestId ( 'collection-header-generate-mock-data-button' )
264+ ) . to . not . exist ;
265+ } ) ;
266+
267+ it ( 'should not show Mock Data Generator button for readonly collections' , async function ( ) {
268+ mockUseAssignment . returns ( {
269+ assignment : {
270+ assignmentData : {
271+ variant : 'treatment' ,
272+ } ,
273+ } ,
274+ } ) ;
275+
276+ await renderCollectionHeaderActions (
277+ {
278+ namespace : 'test.collection' ,
279+ isReadonly : true ,
280+ } ,
281+ { } ,
282+ atlasConnectionInfo
283+ ) ;
284+
285+ expect (
286+ screen . queryByTestId ( 'collection-header-generate-mock-data-button' )
287+ ) . to . not . exist ;
288+ } ) ;
289+
290+ it ( 'should not show Mock Data Generator button for views (sourceName present)' , async function ( ) {
291+ mockUseAssignment . returns ( {
292+ assignment : {
293+ assignmentData : {
294+ variant : 'treatment' ,
295+ } ,
296+ } ,
297+ } ) ;
298+
299+ await renderCollectionHeaderActions (
300+ {
301+ namespace : 'test.collection' ,
302+ isReadonly : false ,
303+ sourceName : 'source-collection' ,
304+ } ,
305+ { } ,
306+ atlasConnectionInfo
307+ ) ;
308+
309+ expect (
310+ screen . queryByTestId ( 'collection-header-generate-mock-data-button' )
311+ ) . to . not . exist ;
312+ } ) ;
313+
314+ it ( 'should show Mock Data Generator button when user is in treatment group and in Atlas' , async function ( ) {
315+ mockUseAssignment . returns ( {
316+ assignment : {
317+ assignmentData : {
318+ variant : 'mockDataGeneratorVariant' ,
319+ } ,
320+ } ,
321+ } ) ;
322+
323+ await renderCollectionHeaderActions (
324+ {
325+ namespace : 'test.collection' ,
326+ isReadonly : false ,
327+ } ,
328+ { } ,
329+ atlasConnectionInfo
330+ ) ;
331+
332+ expect (
333+ screen . getByTestId ( 'collection-header-generate-mock-data-button' )
334+ ) . to . exist ;
335+ } ) ;
336+
337+ it ( 'should call useAssignment with correct parameters' , async function ( ) {
338+ await renderCollectionHeaderActions ( {
339+ namespace : 'test.collection' ,
340+ isReadonly : false ,
341+ } ) ;
342+
343+ expect ( mockUseAssignment ) . to . have . been . calledWith (
344+ ExperimentTestName . mockDataGenerator ,
345+ true // trackIsInSample - Experiment viewed analytics event
346+ ) ;
347+ } ) ;
348+
349+ it ( 'should call onOpenMockDataModal when CTA button is clicked' , async function ( ) {
350+ const onOpenMockDataModal = sinon . stub ( ) ;
351+
352+ mockUseAssignment . returns ( {
353+ assignment : {
354+ assignmentData : {
355+ variant : 'mockDataGeneratorVariant' ,
356+ } ,
357+ } ,
358+ } ) ;
359+
360+ await renderCollectionHeaderActions (
361+ {
362+ namespace : 'test.collection' ,
363+ isReadonly : false ,
364+ onOpenMockDataModal,
365+ } ,
366+ { } ,
367+ atlasConnectionInfo
368+ ) ;
369+
370+ const button = screen . getByTestId (
371+ 'collection-header-generate-mock-data-button'
372+ ) ;
373+ button . click ( ) ;
374+
375+ expect ( onOpenMockDataModal ) . to . have . been . calledOnce ;
376+ } ) ;
377+ } ) ;
171378} ) ;
0 commit comments