Skip to content

Commit 7fbb335

Browse files
committed
shorthand schema render logic in confirmation step
1 parent b4d1784 commit 7fbb335

File tree

6 files changed

+493
-26
lines changed

6 files changed

+493
-26
lines changed

packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.spec.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ describe('MockDataGeneratorModal', () => {
2020
async function renderModal({
2121
isOpen = true,
2222
currentStep = MockDataGeneratorStep.SCHEMA_CONFIRMATION,
23+
enableGenAISampleDocumentPassing = false,
2324
mockServices = createMockServices(),
2425
connectionInfo,
2526
}: {
2627
isOpen?: boolean;
28+
enableGenAISampleDocumentPassing?: boolean;
2729
currentStep?: MockDataGeneratorStep;
2830
mockServices?: any;
2931
connectionInfo?: ConnectionInfo;
@@ -63,7 +65,12 @@ describe('MockDataGeneratorModal', () => {
6365
<Provider store={store}>
6466
<MockDataGeneratorModal />
6567
</Provider>,
66-
connectionInfo
68+
connectionInfo,
69+
{
70+
preferences: {
71+
enableGenAISampleDocumentPassing,
72+
},
73+
}
6774
);
6875
}
6976

@@ -109,6 +116,34 @@ describe('MockDataGeneratorModal', () => {
109116
expect(screen.queryByTestId('generate-mock-data-modal')).to.not.exist;
110117
});
111118

119+
it('uses the appropriate copy when Generative AI sample document passing is enabled', async () => {
120+
await renderModal({ enableGenAISampleDocumentPassing: true });
121+
expect(screen.queryByText('Sample Documents Collected')).to.exist;
122+
expect(
123+
screen.queryByText(
124+
'A sample of document values from your collection will be sent to an LLM for processing.'
125+
)
126+
).to.exist;
127+
// fragment from { "name": "John" }
128+
expect(screen.queryByText('"John"')).to.exist;
129+
expect(screen.queryByText('"String"')).to.not.exist;
130+
});
131+
132+
it('uses the appropriate copy when Generative AI sample document passing is disabled', async () => {
133+
await renderModal();
134+
expect(screen.queryByText('Document Schema Identified')).to.exist;
135+
expect(
136+
screen.queryByText(
137+
'We have identified the following schema from your documents. This schema will be sent to an LLM for processing.'
138+
)
139+
).to.exist;
140+
// fragment from { "name": "String" }
141+
expect(screen.queryByText('"String"')).to.exist;
142+
expect(screen.queryByText('"John"')).to.not.exist;
143+
144+
screen.debug();
145+
});
146+
112147
it('closes the modal when the close button is clicked', async () => {
113148
await renderModal();
114149

packages/compass-collection/src/components/mock-data-generator-modal/raw-schema-confirmation-screen.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import {
99
BannerVariant,
1010
Code,
1111
Body,
12-
Subtitle,
1312
} from '@mongodb-js/compass-components';
1413

1514
import { usePreference } from 'compass-preferences-model/provider';
16-
import toUserFriendlyFieldInfo from './to-user-friendly-field-info';
15+
import toSimplifiedFieldInfo from './to-simplified-field-info';
1716
import type { CollectionState } from '../../modules/collection-tab';
1817
import type { SchemaAnalysisState } from '../../schema-analysis-types';
1918
import type { MockDataGeneratorState } from './types';
@@ -49,11 +48,12 @@ const errorBannerTextStyles = css({
4948
color: palette.red.dark2,
5049
});
5150

52-
// Note: Currently a placeholder. The final contents will be addressed by CLOUDP-333852
53-
const RawSchemaConfirmationScreen = (
54-
props: RawSchemaConfirmationScreenProps
55-
) => {
56-
let enableSampleDocumentPassing = usePreference(
51+
const RawSchemaConfirmationScreen = ({
52+
schemaAnalysis,
53+
namespace,
54+
fakerSchemaGenerationStatus,
55+
}: RawSchemaConfirmationScreenProps) => {
56+
const enableSampleDocumentPassing = usePreference(
5757
'enableGenAISampleDocumentPassing'
5858
);
5959

@@ -73,9 +73,9 @@ const RawSchemaConfirmationScreen = (
7373

7474
return (
7575
<div data-testid="raw-schema-confirmation">
76-
{props.schemaAnalysis.status === 'complete' ? (
76+
{schemaAnalysis.status === 'complete' ? (
7777
<>
78-
<Body className={namespaceStyles}>{props.namespace}</Body>
78+
<Body className={namespaceStyles}>{namespace}</Body>
7979
<Body
8080
as="h2"
8181
className={headingStyles}
@@ -87,14 +87,14 @@ const RawSchemaConfirmationScreen = (
8787
<Body className={descriptionStyles}>{descriptionText}</Body>
8888
<Code language="javascript" copyable={false} className={codeStyles}>
8989
{enableSampleDocumentPassing
90-
? JSON.stringify(props.schemaAnalysis.sampleDocument, null, 4)
90+
? JSON.stringify(schemaAnalysis.sampleDocument, null, 4)
9191
: JSON.stringify(
92-
toUserFriendlyFieldInfo(props.schemaAnalysis.processedSchema),
92+
toSimplifiedFieldInfo(schemaAnalysis.processedSchema),
9393
null,
9494
4
9595
)}
9696
</Code>
97-
{props.fakerSchemaGenerationStatus === 'error' && (
97+
{fakerSchemaGenerationStatus === 'error' && (
9898
<Banner
9999
variant={BannerVariant.Danger}
100100
className={errorBannerStyles}
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
import { expect } from 'chai';
2+
import toSimplifiedFieldInfo from './to-simplified-field-info';
3+
import type { UserFriendlyFieldInfoTree } from './to-simplified-field-info';
4+
5+
describe('toSimplifiedFieldInfo', function () {
6+
it('simple case with minimal nesting and no arrays', function () {
7+
const input = {
8+
'user.name': {
9+
type: 'String' as const,
10+
sample_values: ['John'],
11+
probability: 1.0,
12+
},
13+
'user.age': {
14+
type: 'Number' as const,
15+
sample_values: [25, 30],
16+
probability: 0.8,
17+
},
18+
'user.profile.bio': {
19+
type: 'String' as const,
20+
sample_values: ['Software engineer'],
21+
probability: 0.9,
22+
},
23+
'user.profile.isVerified': {
24+
type: 'Boolean' as const,
25+
sample_values: [true, false],
26+
probability: 0.7,
27+
},
28+
'metadata.createdAt': {
29+
type: 'Date' as const,
30+
sample_values: [new Date('2023-01-01')],
31+
probability: 1.0,
32+
},
33+
'metadata.objectId': {
34+
type: 'ObjectId' as const,
35+
sample_values: ['642d766b7300158b1f22e972'],
36+
probability: 1.0,
37+
},
38+
};
39+
40+
const result = toSimplifiedFieldInfo(input);
41+
42+
const expected: UserFriendlyFieldInfoTree = {
43+
user: {
44+
name: 'String',
45+
age: 'Number',
46+
profile: {
47+
bio: 'String',
48+
isVerified: 'Boolean',
49+
},
50+
},
51+
metadata: {
52+
createdAt: 'Date',
53+
objectId: 'ObjectId',
54+
},
55+
};
56+
57+
expect(result).to.deep.equal(expected);
58+
});
59+
60+
it('handles nested arrays of primitives', function () {
61+
const input = {
62+
'tags[]': {
63+
type: 'String' as const,
64+
sample_values: ['red', 'blue', 'green'],
65+
probability: 1.0,
66+
},
67+
'scores[]': {
68+
type: 'Number' as const,
69+
sample_values: [85, 92, 78],
70+
probability: 0.9,
71+
},
72+
'matrix[][]': {
73+
type: 'Number' as const,
74+
sample_values: [1, 2, 3, 4],
75+
probability: 1.0,
76+
},
77+
'flags[]': {
78+
type: 'Boolean' as const,
79+
sample_values: [true, false],
80+
probability: 0.8,
81+
},
82+
'timestamps[]': {
83+
type: 'Date' as const,
84+
sample_values: [new Date('2023-01-01'), new Date('2023-06-15')],
85+
probability: 0.7,
86+
},
87+
'ids[]': {
88+
type: 'ObjectId' as const,
89+
sample_values: ['642d766b7300158b1f22e972', '642d766b7300158b1f22e973'],
90+
probability: 1.0,
91+
},
92+
};
93+
94+
const result = toSimplifiedFieldInfo(input);
95+
96+
const expected: UserFriendlyFieldInfoTree = {
97+
'tags[]': 'String',
98+
'scores[]': 'Number',
99+
'matrix[][]': 'Number',
100+
'flags[]': 'Boolean',
101+
'timestamps[]': 'Date',
102+
'ids[]': 'ObjectId',
103+
};
104+
105+
expect(result).to.deep.equal(expected);
106+
});
107+
108+
it('handles nested arrays of documents', function () {
109+
const input = {
110+
'items[].id': {
111+
type: 'Number' as const,
112+
sample_values: [1, 2],
113+
probability: 1.0,
114+
},
115+
'items[].name': {
116+
type: 'String' as const,
117+
sample_values: ['Item A', 'Item B'],
118+
probability: 1.0,
119+
},
120+
'items[].metadata.createdBy': {
121+
type: 'String' as const,
122+
sample_values: ['admin', 'user'],
123+
probability: 0.9,
124+
},
125+
'items[].metadata.tags[]': {
126+
type: 'String' as const,
127+
sample_values: ['urgent', 'review', 'approved'],
128+
probability: 0.8,
129+
},
130+
'items[].price': {
131+
type: 'Decimal128' as const,
132+
sample_values: [19.99, 29.99],
133+
probability: 0.95,
134+
},
135+
'items[].binary': {
136+
type: 'Binary' as const,
137+
sample_values: ['dGVzdA=='],
138+
probability: 0.3,
139+
},
140+
};
141+
142+
const result = toSimplifiedFieldInfo(input);
143+
144+
const expected: UserFriendlyFieldInfoTree = {
145+
'items[]': {
146+
id: 'Number',
147+
name: 'String',
148+
metadata: {
149+
createdBy: 'String',
150+
'tags[]': 'String',
151+
},
152+
price: 'Decimal128',
153+
binary: 'Binary',
154+
},
155+
};
156+
157+
expect(result).to.deep.equal(expected);
158+
});
159+
160+
it('handles nested arrays of arrays', function () {
161+
// Input based on complex nested array structures
162+
const input = {
163+
'cube[][][]': {
164+
type: 'Number' as const,
165+
sample_values: [1, 2, 3, 4, 5, 6, 7, 8],
166+
probability: 1.0,
167+
},
168+
'matrix[][].x': {
169+
type: 'Number' as const,
170+
sample_values: [1, 3],
171+
probability: 1.0,
172+
},
173+
'matrix[][].y': {
174+
type: 'Number' as const,
175+
sample_values: [2, 4],
176+
probability: 1.0,
177+
},
178+
'teams[].members[]': {
179+
type: 'String' as const,
180+
sample_values: ['Alice', 'Bob', 'Charlie'],
181+
probability: 1.0,
182+
},
183+
'teams[].name': {
184+
type: 'String' as const,
185+
sample_values: ['Team A', 'Team B'],
186+
probability: 1.0,
187+
},
188+
'complex[][].data[]': {
189+
type: 'Long' as const,
190+
sample_values: [123456789, 987654321],
191+
probability: 0.9,
192+
},
193+
'complex[][].regex': {
194+
type: 'RegExp' as const,
195+
sample_values: ['pattern'],
196+
probability: 0.6,
197+
},
198+
'complex[][].code': {
199+
type: 'Code' as const,
200+
sample_values: ['function() {}'],
201+
probability: 0.4,
202+
},
203+
'nested[][].symbols[]': {
204+
type: 'Symbol' as const,
205+
sample_values: ['symbol1', 'symbol2'],
206+
probability: 0.5,
207+
},
208+
'timestamps[][].created': {
209+
type: 'Timestamp' as const,
210+
sample_values: [4294967297],
211+
probability: 0.8,
212+
},
213+
'keys[][].max': {
214+
type: 'MaxKey' as const,
215+
sample_values: ['MaxKey'],
216+
probability: 0.2,
217+
},
218+
'keys[][].min': {
219+
type: 'MinKey' as const,
220+
sample_values: ['MinKey'],
221+
probability: 0.2,
222+
},
223+
};
224+
225+
const result = toSimplifiedFieldInfo(input);
226+
227+
const expected: UserFriendlyFieldInfoTree = {
228+
'cube[][][]': 'Number',
229+
'matrix[][]': {
230+
x: 'Number',
231+
y: 'Number',
232+
},
233+
'teams[]': {
234+
'members[]': 'String',
235+
name: 'String',
236+
},
237+
'complex[][]': {
238+
'data[]': 'Long',
239+
regex: 'RegExp',
240+
code: 'Code',
241+
},
242+
'nested[][]': {
243+
'symbols[]': 'Symbol',
244+
},
245+
'timestamps[][]': {
246+
created: 'Timestamp',
247+
},
248+
'keys[][]': {
249+
max: 'MaxKey',
250+
min: 'MinKey',
251+
},
252+
};
253+
254+
expect(result).to.deep.equal(expected);
255+
});
256+
});

0 commit comments

Comments
 (0)