diff --git a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx
index 1f98a73199d..8b737157663 100644
--- a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx
+++ b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx
@@ -13,26 +13,16 @@ import {
import type { PreferencesAccess } from 'compass-preferences-model';
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
import { PreferencesProvider } from 'compass-preferences-model/provider';
-import { ExperimentTestName } from '@mongodb-js/compass-telemetry/provider';
-import { CompassExperimentationProvider } from '@mongodb-js/compass-telemetry';
+
import type { ConnectionInfo } from '@mongodb-js/compass-connections/provider';
import CollectionHeaderActions from '../collection-header-actions';
describe('CollectionHeaderActions [Component]', function () {
let preferences: PreferencesAccess;
- let mockUseAssignment: sinon.SinonStub;
beforeEach(async function () {
preferences = await createSandboxFromDefaultPreferences();
- mockUseAssignment = sinon.stub();
- mockUseAssignment.returns({
- assignment: {
- assignmentData: {
- variant: 'mockDataGeneratorControl',
- },
- },
- });
});
afterEach(function () {
@@ -45,27 +35,19 @@ describe('CollectionHeaderActions [Component]', function () {
connectionInfo?: ConnectionInfo
) => {
return renderWithActiveConnection(
-
-
-
-
-
-
- ,
+
+
+
+
+ ,
connectionInfo
);
};
@@ -225,34 +207,15 @@ describe('CollectionHeaderActions [Component]', function () {
},
};
- it('should call useAssignment with correct parameters', async function () {
- await renderCollectionHeaderActions({
- namespace: 'test.collection',
- isReadonly: false,
- });
-
- expect(mockUseAssignment).to.have.been.calledWith(
- ExperimentTestName.mockDataGenerator,
- true // trackIsInSample - Experiment viewed analytics event
- );
- });
-
it('should call onOpenMockDataModal when CTA button is clicked', async function () {
const onOpenMockDataModal = sinon.stub();
- mockUseAssignment.returns({
- assignment: {
- assignmentData: {
- variant: 'mockDataGeneratorVariant',
- },
- },
- });
-
await renderCollectionHeaderActions(
{
namespace: 'test.collection',
isReadonly: false,
onOpenMockDataModal,
+ schemaAnalysisStatus: 'complete',
},
{},
atlasConnectionInfo
@@ -267,14 +230,6 @@ describe('CollectionHeaderActions [Component]', function () {
});
it('should disable button for deeply nested collections', async function () {
- mockUseAssignment.returns({
- assignment: {
- assignmentData: {
- variant: 'mockDataGeneratorVariant', // Treatment variant
- },
- },
- });
-
await renderCollectionHeaderActions(
{
namespace: 'test.collection',
diff --git a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx
index e8204823d5c..c078c220731 100644
--- a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx
+++ b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx
@@ -12,14 +12,10 @@ import React from 'react';
import { usePreferences } from 'compass-preferences-model/provider';
import toNS from 'mongodb-ns';
import { wrapField } from '@mongodb-js/mongodb-constants';
-import {
- useTelemetry,
- useAssignment,
- ExperimentTestName,
- ExperimentTestGroup,
-} from '@mongodb-js/compass-telemetry/provider';
+import { useTelemetry } from '@mongodb-js/compass-telemetry/provider';
import {
SCHEMA_ANALYSIS_STATE_ANALYZING,
+ SCHEMA_ANALYSIS_STATE_COMPLETE,
type SchemaAnalysisStatus,
} from '../../schema-analysis-types';
@@ -82,21 +78,13 @@ const CollectionHeaderActions: React.FunctionComponent<
usePreferences(['readOnly', 'enableShell']);
const track = useTelemetry();
- // Get experiment assignment for Mock Data Generator
- const mockDataGeneratorAssignment = useAssignment(
- ExperimentTestName.mockDataGenerator,
- true // trackIsInSample - this will fire the "Experiment Viewed" event
- );
-
const { database, collection } = toNS(namespace);
- // Check if user is in treatment group for Mock Data Generator experiment
- const isInMockDataTreatmentVariant =
- mockDataGeneratorAssignment?.assignment?.assignmentData?.variant ===
- ExperimentTestGroup.mockDataGeneratorVariant;
-
+ // Show Mock Data Generator button if schema analysis has been initiated (indicating user is in treatment variant)
+ // Schema analysis only runs for users in the treatment variant
const shouldShowMockDataButton =
- isInMockDataTreatmentVariant &&
+ (schemaAnalysisStatus === SCHEMA_ANALYSIS_STATE_ANALYZING ||
+ schemaAnalysisStatus === SCHEMA_ANALYSIS_STATE_COMPLETE) &&
atlasMetadata && // Only show in Atlas
!isReadonly && // Don't show for readonly collections (views)
!sourceName; // sourceName indicates it's a view
diff --git a/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx b/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx
index 82553cc22af..890bda8467e 100644
--- a/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx
+++ b/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx
@@ -17,8 +17,10 @@ import {
type WorkspacesService,
} from '@mongodb-js/compass-workspaces/provider';
import { MockDataGeneratorStep } from '../mock-data-generator-modal/types';
-import { SCHEMA_ANALYSIS_STATE_COMPLETE } from '../../schema-analysis-types';
-import { CompassExperimentationProvider } from '@mongodb-js/compass-telemetry';
+import {
+ SCHEMA_ANALYSIS_STATE_COMPLETE,
+ SCHEMA_ANALYSIS_STATE_INITIAL,
+} from '../../schema-analysis-types';
import type { ConnectionInfo } from '@mongodb-js/compass-connections/provider';
import Sinon from 'sinon';
@@ -26,7 +28,8 @@ import Sinon from 'sinon';
function renderCollectionHeader(
props: Partial> = {},
workspaceService: Partial = {},
- stateOverrides: any = {}
+ stateOverrides: Record = {},
+ connectionInfo?: ConnectionInfo
) {
const defaultState = {
mockDataGenerator: {
@@ -38,7 +41,7 @@ function renderCollectionHeader(
const mockStore = createStore(() => defaultState);
- return renderWithConnections(
+ return renderWithActiveConnection(
-
+ ,
+ connectionInfo
);
}
@@ -59,8 +63,8 @@ describe('CollectionHeader [Component]', function () {
afterEach(cleanup);
context('when the collection is not readonly', function () {
- beforeEach(function () {
- renderCollectionHeader();
+ beforeEach(async function () {
+ await renderCollectionHeader();
});
it('renders the correct root classname', function () {
@@ -89,8 +93,11 @@ describe('CollectionHeader [Component]', function () {
});
context('when the collection is readonly', function () {
- beforeEach(function () {
- renderCollectionHeader({ isReadonly: true, sourceName: 'orig.coll' });
+ beforeEach(async function () {
+ await renderCollectionHeader({
+ isReadonly: true,
+ sourceName: 'orig.coll',
+ });
});
afterEach(cleanup);
@@ -113,8 +120,8 @@ describe('CollectionHeader [Component]', function () {
});
context('when the collection is readonly but not a view', function () {
- beforeEach(function () {
- renderCollectionHeader({ isReadonly: true, sourceName: undefined });
+ beforeEach(async function () {
+ await renderCollectionHeader({ isReadonly: true, sourceName: undefined });
});
it('renders the readonly badge', function () {
@@ -127,8 +134,8 @@ describe('CollectionHeader [Component]', function () {
});
context('when the collection is a time-series collection', function () {
- beforeEach(function () {
- renderCollectionHeader({ isTimeSeries: true });
+ beforeEach(async function () {
+ await renderCollectionHeader({ isTimeSeries: true });
});
it('does not render the readonly badge', function () {
@@ -141,8 +148,8 @@ describe('CollectionHeader [Component]', function () {
});
context('when the collection is a clustered collection', function () {
- beforeEach(function () {
- renderCollectionHeader({ isClustered: true });
+ beforeEach(async function () {
+ await renderCollectionHeader({ isClustered: true });
});
it('does not render the readonly badge', function () {
@@ -159,8 +166,8 @@ describe('CollectionHeader [Component]', function () {
});
context('when the collection is a fle collection', function () {
- beforeEach(function () {
- renderCollectionHeader({ isFLE: true });
+ beforeEach(async function () {
+ await renderCollectionHeader({ isFLE: true });
});
it('renders the fle badge', function () {
@@ -169,8 +176,8 @@ describe('CollectionHeader [Component]', function () {
});
describe('insights', function () {
- it('should show an insight when $text is used in the pipeline source', function () {
- renderCollectionHeader({
+ it('should show an insight when $text is used in the pipeline source', async function () {
+ await renderCollectionHeader({
sourcePipeline: [{ $match: { $text: {} } }],
});
expect(screen.getByTestId('insight-badge-button')).to.exist;
@@ -179,8 +186,8 @@ describe('CollectionHeader [Component]', function () {
.exist;
});
- it('should show an insight when $regex is used in the pipeline source', function () {
- renderCollectionHeader({
+ it('should show an insight when $regex is used in the pipeline source', async function () {
+ await renderCollectionHeader({
sourcePipeline: [{ $match: { $regex: {} } }],
});
expect(screen.getByTestId('insight-badge-button')).to.exist;
@@ -189,8 +196,8 @@ describe('CollectionHeader [Component]', function () {
.exist;
});
- it('should show an insight when $lookup is used in the pipeline source', function () {
- renderCollectionHeader({
+ it('should show an insight when $lookup is used in the pipeline source', async function () {
+ await renderCollectionHeader({
sourcePipeline: [{ $lookup: {} }],
});
expect(screen.getByTestId('insight-badge-button')).to.exist;
@@ -209,7 +216,7 @@ describe('CollectionHeader [Component]', function () {
});
function assertBreadcrumbText(items: string[]) {
- const crumbs: any[] = [];
+ const crumbs: (string | null)[] = [];
screen.getByTestId('breadcrumbs').childNodes.forEach((item) => {
crumbs.push(item.textContent);
});
@@ -230,13 +237,13 @@ describe('CollectionHeader [Component]', function () {
}
context('renders correclty', function () {
- it('for a collection', function () {
- renderCollectionHeader({ namespace: 'db.coll1' });
+ it('for a collection', async function () {
+ await renderCollectionHeader({ namespace: 'db.coll1' });
assertBreadcrumbText(['db', 'coll1']);
});
- it('for a view', function () {
- renderCollectionHeader({
+ it('for a view', async function () {
+ await renderCollectionHeader({
namespace: 'db.coll1',
sourceName: 'db.coll2',
});
@@ -244,8 +251,8 @@ describe('CollectionHeader [Component]', function () {
assertBreadcrumbText(['db', 'coll2', 'coll1']);
});
- it('for a view when its being edited', function () {
- renderCollectionHeader({
+ it('for a view when its being edited', async function () {
+ await renderCollectionHeader({
namespace: 'db.coll3',
editViewName: 'db.coll1',
});
@@ -255,10 +262,10 @@ describe('CollectionHeader [Component]', function () {
});
context('calls onClick correclty', function () {
- it('for a collection', function () {
+ it('for a collection', async function () {
const openCollectionsWorkspaceStub = sandbox.stub();
const openCollectionWorkspaceStub = sandbox.stub();
- renderCollectionHeader(
+ await renderCollectionHeader(
{ namespace: 'db.coll1' },
{
openCollectionsWorkspace: openCollectionsWorkspaceStub,
@@ -279,9 +286,9 @@ describe('CollectionHeader [Component]', function () {
]);
});
- it('for a view, opens source collection', function () {
+ it('for a view, opens source collection', async function () {
const openCollectionWorkspaceStub = sandbox.stub();
- renderCollectionHeader(
+ await renderCollectionHeader(
{ namespace: 'db.coll1', sourceName: 'db.coll2' },
{
openCollectionWorkspace: openCollectionWorkspaceStub,
@@ -335,23 +342,6 @@ describe('CollectionHeader [Component]', function () {
});
describe('Mock Data Generator integration', function () {
- let mockUseAssignment: Sinon.SinonStub;
-
- beforeEach(function () {
- // Mock the useAssignment hook from compass-experimentation
- mockUseAssignment = Sinon.stub().returns({
- assignment: {
- assignmentData: {
- variant: 'mockDataGeneratorVariant',
- },
- },
- });
- });
-
- afterEach(function () {
- Sinon.restore();
- });
-
const atlasConnectionInfo: ConnectionInfo = {
id: 'test-atlas-connection',
connectionOptions: {
@@ -375,50 +365,8 @@ describe('CollectionHeader [Component]', function () {
},
};
- function renderCollectionHeaderWithExperimentation(
- props: Partial> = {},
- workspaceService: Partial = {},
- stateOverrides: any = {},
- connectionInfo?: ConnectionInfo
- ) {
- const defaultState = {
- mockDataGenerator: {
- isModalOpen: false,
- currentStep: MockDataGeneratorStep.SCHEMA_CONFIRMATION,
- },
- ...stateOverrides,
- };
-
- const mockStore = createStore(() => defaultState);
-
- return renderWithActiveConnection(
-
-
-
-
-
-
- ,
- connectionInfo
- );
- }
-
it('should show Mock Data Generator button when all conditions are met', async function () {
- await renderCollectionHeaderWithExperimentation(
+ await renderCollectionHeader(
{
isAtlas: true, // Atlas environment
isReadonly: false, // Not readonly
@@ -447,7 +395,7 @@ describe('CollectionHeader [Component]', function () {
});
it('should disable Mock Data Generator button when collection has no schema analysis data', async function () {
- await renderCollectionHeaderWithExperimentation(
+ await renderCollectionHeader(
{
isAtlas: true,
isReadonly: false,
@@ -474,7 +422,7 @@ describe('CollectionHeader [Component]', function () {
});
it('should disable Mock Data Generator button for collections with excessive nesting depth', async function () {
- await renderCollectionHeaderWithExperimentation(
+ await renderCollectionHeader(
{
isAtlas: true,
isReadonly: false,
@@ -503,7 +451,7 @@ describe('CollectionHeader [Component]', function () {
});
it('should not show Mock Data Generator button for readonly collections (views)', async function () {
- await renderCollectionHeaderWithExperimentation(
+ await renderCollectionHeader(
{
isAtlas: true,
isReadonly: true, // Readonly (view)
@@ -530,7 +478,7 @@ describe('CollectionHeader [Component]', function () {
});
it('should not show Mock Data Generator button in non-Atlas environments', async function () {
- await renderCollectionHeaderWithExperimentation(
+ await renderCollectionHeader(
{
isAtlas: false, // Not Atlas
isReadonly: false,
@@ -556,16 +504,8 @@ describe('CollectionHeader [Component]', function () {
).to.not.exist;
});
- it('should not show Mock Data Generator button when not in treatment variant', async function () {
- mockUseAssignment.returns({
- assignment: {
- assignmentData: {
- variant: 'control',
- },
- },
- });
-
- await renderCollectionHeaderWithExperimentation(
+ it('should not show Mock Data Generator button when schema analysis has not run', async function () {
+ await renderCollectionHeader(
{
isAtlas: true,
isReadonly: false,
@@ -574,13 +514,7 @@ describe('CollectionHeader [Component]', function () {
{},
{
schemaAnalysis: {
- status: SCHEMA_ANALYSIS_STATE_COMPLETE,
- processedSchema: {
- field1: { type: 'String', sample_values: ['value1'] },
- },
- schemaMetadata: {
- maxNestingDepth: 2,
- },
+ status: SCHEMA_ANALYSIS_STATE_INITIAL, // No schema analysis has run
},
},
atlasConnectionInfo
diff --git a/packages/compass-collection/src/modules/collection-tab.ts b/packages/compass-collection/src/modules/collection-tab.ts
index e1f3afa2eac..82e913d4865 100644
--- a/packages/compass-collection/src/modules/collection-tab.ts
+++ b/packages/compass-collection/src/modules/collection-tab.ts
@@ -39,8 +39,6 @@ import type { MockDataGeneratorState } from '../components/mock-data-generator-m
const DEFAULT_SAMPLE_SIZE = 100;
-const NO_DOCUMENTS_ERROR = 'No documents found in the collection to analyze.';
-
function isAction(
action: AnyAction,
type: A['type']
@@ -590,10 +588,17 @@ export const analyzeCollectionSchema = (): CollectionThunkAction<
return;
}
if (sampleDocuments.length === 0) {
- logger.debug(NO_DOCUMENTS_ERROR);
+ logger.debug(
+ 'Collection is empty, completing schema analysis with empty schema'
+ );
dispatch({
- type: CollectionActions.SchemaAnalysisFailed,
- error: new Error(NO_DOCUMENTS_ERROR),
+ type: CollectionActions.SchemaAnalysisFinished,
+ processedSchema: {},
+ sampleDocument: {},
+ schemaMetadata: {
+ maxNestingDepth: 0,
+ validationRules: null,
+ },
});
return;
}