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+ } from '@mongodb-js/testing-library-compass' ;
47import sinon from 'sinon' ;
58import {
69 WorkspacesServiceProvider ,
@@ -9,46 +12,83 @@ import {
912import type { PreferencesAccess } from 'compass-preferences-model' ;
1013import { createSandboxFromDefaultPreferences } from 'compass-preferences-model' ;
1114import { PreferencesProvider } from 'compass-preferences-model/provider' ;
15+ import {
16+ TelemetryProvider ,
17+ ExperimentTestName ,
18+ } from '@mongodb-js/compass-telemetry/provider' ;
19+ import { CompassExperimentationProvider } from '@mongodb-js/compass-telemetry' ;
20+ import type { ConnectionInfo } from '@mongodb-js/compass-connections/provider' ;
1221
1322import CollectionHeaderActions from '../collection-header-actions' ;
1423
1524describe ( 'CollectionHeaderActions [Component]' , function ( ) {
1625 let preferences : PreferencesAccess ;
26+ let mockUseAssignment : sinon . SinonStub ;
27+
1728 beforeEach ( async function ( ) {
1829 preferences = await createSandboxFromDefaultPreferences ( ) ;
30+ mockUseAssignment = sinon . stub ( ) ;
31+ mockUseAssignment . returns ( {
32+ assignment : {
33+ assignmentData : {
34+ variant : 'mockDataGeneratorControl' ,
35+ } ,
36+ } ,
37+ } ) ;
1938 } ) ;
39+
2040 afterEach ( function ( ) {
2141 sinon . restore ( ) ;
2242 } ) ;
2343
24- const renderCollectionHeaderActions = (
44+ const renderCollectionHeaderActions = async (
2545 props : Partial < ComponentProps < typeof CollectionHeaderActions > > = { } ,
26- workspaceService : Partial < WorkspacesService > = { }
46+ workspaceService : Partial < WorkspacesService > = { } ,
47+ connectionInfo ?: ConnectionInfo
2748 ) => {
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 >
49+ const defaultProps = {
50+ namespace : 'test.test' ,
51+ isReadonly : false ,
52+ onOpenMockDataModal : sinon . stub ( ) ,
53+ ...props ,
54+ } ;
55+
56+ const ui = (
57+ < TelemetryProvider options = { { sendTrack : sinon . stub ( ) } } >
58+ < CompassExperimentationProvider
59+ useAssignment = { mockUseAssignment }
60+ assignExperiment = { sinon . stub ( ) }
61+ >
62+ < WorkspacesServiceProvider
63+ value = { workspaceService as WorkspacesService }
64+ >
65+ < PreferencesProvider value = { preferences } >
66+ < CollectionHeaderActions { ...defaultProps } />
67+ </ PreferencesProvider >
68+ </ WorkspacesServiceProvider >
69+ </ CompassExperimentationProvider >
70+ </ TelemetryProvider >
3871 ) ;
72+
73+ if ( connectionInfo ) {
74+ // For tests that need Atlas metadata (Mock Data Generator button visibility, etc.)
75+ return await renderWithActiveConnection ( ui , connectionInfo ) ;
76+ } else {
77+ // For tests that only need basic component rendering (readonly checks, view buttons, etc.)
78+ const { render } = await import ( '@mongodb-js/testing-library-compass' ) ;
79+ return render ( ui ) ;
80+ }
3981 } ;
4082
4183 context ( 'when the collection is not readonly' , function ( ) {
42- beforeEach ( function ( ) {
43- renderCollectionHeaderActions ( {
84+ beforeEach ( async function ( ) {
85+ await renderCollectionHeaderActions ( {
4486 isReadonly : false ,
4587 namespace : 'db.coll2' ,
4688 sourceName : 'db.coll' ,
4789 } ) ;
4890 } ) ;
4991
50- afterEach ( cleanup ) ;
51-
5292 it ( 'does not render any buttons' , function ( ) {
5393 expect (
5494 screen . queryByTestId ( 'collection-header-actions-edit-button' )
@@ -63,7 +103,7 @@ describe('CollectionHeaderActions [Component]', function () {
63103 it ( 'does not render edit view buttons when in readonly mode' , async function ( ) {
64104 await preferences . savePreferences ( { readOnly : true } ) ;
65105
66- renderCollectionHeaderActions ( {
106+ await renderCollectionHeaderActions ( {
67107 isReadonly : true ,
68108 namespace : 'db.coll2' ,
69109 sourceName : 'db.someSource' ,
@@ -78,8 +118,8 @@ describe('CollectionHeaderActions [Component]', function () {
78118 ) . to . not . exist ;
79119 } ) ;
80120
81- it ( 'renders edit view buttons when not in readonly mode' , function ( ) {
82- renderCollectionHeaderActions ( {
121+ it ( 'renders edit view buttons when not in readonly mode' , async function ( ) {
122+ await renderCollectionHeaderActions ( {
83123 isReadonly : true ,
84124 namespace : 'db.coll2' ,
85125 sourceName : 'db.someSource' ,
@@ -94,9 +134,9 @@ describe('CollectionHeaderActions [Component]', function () {
94134
95135 context ( 'when the collection is a view' , function ( ) {
96136 let openEditViewWorkspaceStub : sinon . SinonStub ;
97- beforeEach ( function ( ) {
137+ beforeEach ( async function ( ) {
98138 openEditViewWorkspaceStub = sinon . stub ( ) ;
99- renderCollectionHeaderActions (
139+ await renderCollectionHeaderActions (
100140 {
101141 isReadonly : true ,
102142 namespace : 'db.coll2' ,
@@ -109,8 +149,6 @@ describe('CollectionHeaderActions [Component]', function () {
109149 ) ;
110150 } ) ;
111151
112- afterEach ( cleanup ) ;
113-
114152 it ( 'shows a button to edit the view pipeline' , function ( ) {
115153 expect (
116154 screen . getByTestId ( 'collection-header-actions-edit-button' )
@@ -135,9 +173,9 @@ describe('CollectionHeaderActions [Component]', function () {
135173
136174 context ( 'when the collection is editing a view' , function ( ) {
137175 let openCollectionWorkspaceStub : sinon . SinonStub ;
138- beforeEach ( function ( ) {
176+ beforeEach ( async function ( ) {
139177 openCollectionWorkspaceStub = sinon . stub ( ) ;
140- renderCollectionHeaderActions (
178+ await renderCollectionHeaderActions (
141179 {
142180 isReadonly : false ,
143181 namespace : 'db.coll2' ,
@@ -149,8 +187,6 @@ describe('CollectionHeaderActions [Component]', function () {
149187 ) ;
150188 } ) ;
151189
152- afterEach ( cleanup ) ;
153-
154190 it ( 'shows a button to return to the view' , function ( ) {
155191 expect (
156192 screen . getByTestId ( 'collection-header-actions-return-to-view-button' )
@@ -168,4 +204,182 @@ describe('CollectionHeaderActions [Component]', function () {
168204 ) ;
169205 } ) ;
170206 } ) ;
207+
208+ context ( 'Mock Data Generator Button' , function ( ) {
209+ const atlasConnectionInfo : ConnectionInfo = {
210+ id : 'test-atlas-connection' ,
211+ connectionOptions : {
212+ connectionString : 'mongodb://localhost:27017' ,
213+ } ,
214+ atlasMetadata : {
215+ orgId : 'test-org' ,
216+ projectId : 'test-project' ,
217+ clusterName : 'test-cluster' ,
218+ clusterUniqueId : 'test-cluster-unique-id' ,
219+ clusterType : 'REPLICASET' ,
220+ clusterState : 'IDLE' ,
221+ metricsId : 'test-metrics-id' ,
222+ metricsType : 'replicaSet' ,
223+ regionalBaseUrl : null ,
224+ instanceSize : 'M10' ,
225+ supports : {
226+ globalWrites : false ,
227+ rollingIndexes : true ,
228+ } ,
229+ } ,
230+ } ;
231+
232+ it ( 'should not show Mock Data Generator button when user is in control group' , async function ( ) {
233+ mockUseAssignment . returns ( {
234+ assignment : {
235+ assignmentData : {
236+ variant : 'mockDataGeneratorControl' ,
237+ } ,
238+ } ,
239+ } ) ;
240+
241+ await renderCollectionHeaderActions (
242+ {
243+ namespace : 'test.collection' ,
244+ isReadonly : false ,
245+ } ,
246+ { } ,
247+ atlasConnectionInfo
248+ ) ;
249+
250+ expect (
251+ screen . queryByTestId ( 'collection-header-generate-mock-data' )
252+ ) . to . not . exist ;
253+ } ) ;
254+
255+ it ( 'should not show Mock Data Generator button when not in Atlas' , async function ( ) {
256+ mockUseAssignment . returns ( {
257+ assignment : {
258+ assignmentData : {
259+ variant : 'treatment' ,
260+ } ,
261+ } ,
262+ } ) ;
263+
264+ await renderCollectionHeaderActions ( {
265+ namespace : 'test.collection' ,
266+ isReadonly : false ,
267+ // Don't pass atlasConnectionInfo, to simulate not being in Atlas
268+ } ) ;
269+
270+ expect (
271+ screen . queryByTestId ( 'collection-header-generate-mock-data' )
272+ ) . to . not . exist ;
273+ } ) ;
274+
275+ it ( 'should not show Mock Data Generator button for readonly collections' , async function ( ) {
276+ mockUseAssignment . returns ( {
277+ assignment : {
278+ assignmentData : {
279+ variant : 'treatment' ,
280+ } ,
281+ } ,
282+ } ) ;
283+
284+ await renderCollectionHeaderActions (
285+ {
286+ namespace : 'test.collection' ,
287+ isReadonly : true ,
288+ } ,
289+ { } ,
290+ atlasConnectionInfo
291+ ) ;
292+
293+ expect (
294+ screen . queryByTestId ( 'collection-header-generate-mock-data' )
295+ ) . to . not . exist ;
296+ } ) ;
297+
298+ it ( 'should not show Mock Data Generator button for views (sourceName present)' , async function ( ) {
299+ mockUseAssignment . returns ( {
300+ assignment : {
301+ assignmentData : {
302+ variant : 'treatment' ,
303+ } ,
304+ } ,
305+ } ) ;
306+
307+ await renderCollectionHeaderActions (
308+ {
309+ namespace : 'test.collection' ,
310+ isReadonly : false ,
311+ sourceName : 'source-collection' ,
312+ } ,
313+ { } ,
314+ atlasConnectionInfo
315+ ) ;
316+
317+ expect (
318+ screen . queryByTestId ( 'collection-header-generate-mock-data' )
319+ ) . to . not . exist ;
320+ } ) ;
321+
322+ it ( 'should show Mock Data Generator button when user is in treatment group and in Atlas' , async function ( ) {
323+ mockUseAssignment . returns ( {
324+ assignment : {
325+ assignmentData : {
326+ variant : 'mockDataGeneratorVariant' ,
327+ } ,
328+ } ,
329+ } ) ;
330+
331+ await renderCollectionHeaderActions (
332+ {
333+ namespace : 'test.collection' ,
334+ isReadonly : false ,
335+ } ,
336+ { } ,
337+ atlasConnectionInfo
338+ ) ;
339+
340+ expect (
341+ screen . getByTestId ( 'collection-header-generate-mock-data' )
342+ ) . to . exist ;
343+ expect ( screen . getByText ( 'Generate Mock Data' ) ) . to . exist ;
344+ } ) ;
345+
346+ it ( 'should call useAssignment with correct parameters' , async function ( ) {
347+ await renderCollectionHeaderActions ( {
348+ namespace : 'test.collection' ,
349+ isReadonly : false ,
350+ } ) ;
351+
352+ expect ( mockUseAssignment ) . to . have . been . calledWith (
353+ ExperimentTestName . mockDataGenerator ,
354+ true // trackIsInSample - Experiment viewed analytics event
355+ ) ;
356+ } ) ;
357+
358+ it ( 'should call onOpenMockDataModal when CTA button is clicked' , async function ( ) {
359+ const onOpenMockDataModal = sinon . stub ( ) ;
360+
361+ mockUseAssignment . returns ( {
362+ assignment : {
363+ assignmentData : {
364+ variant : 'mockDataGeneratorVariant' ,
365+ } ,
366+ } ,
367+ } ) ;
368+
369+ await renderCollectionHeaderActions (
370+ {
371+ namespace : 'test.collection' ,
372+ isReadonly : false ,
373+ onOpenMockDataModal,
374+ } ,
375+ { } ,
376+ atlasConnectionInfo
377+ ) ;
378+
379+ const button = screen . getByTestId ( 'collection-header-generate-mock-data' ) ;
380+ button . click ( ) ;
381+
382+ expect ( onOpenMockDataModal ) . to . have . been . calledOnce ;
383+ } ) ;
384+ } ) ;
171385} ) ;
0 commit comments