Skip to content

Commit 8f9d83f

Browse files
committed
WIP
1 parent db7e9b8 commit 8f9d83f

File tree

6 files changed

+329
-32
lines changed

6 files changed

+329
-32
lines changed

packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx

Lines changed: 242 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { expect } from 'chai';
22
import 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';
47
import sinon from 'sinon';
58
import {
69
WorkspacesServiceProvider,
@@ -9,46 +12,83 @@ import {
912
import type { PreferencesAccess } from 'compass-preferences-model';
1013
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
1114
import { 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

1322
import CollectionHeaderActions from '../collection-header-actions';
1423

1524
describe('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

Comments
 (0)