Skip to content

Commit 3441021

Browse files
authored
feat(compass-collection): Update Mock Data Generator Script Result Screen – CLOUDP-381909 (#7859)
* WIP * WIP
1 parent 00762dc commit 3441021

5 files changed

Lines changed: 64 additions & 39 deletions

File tree

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,25 @@ describe('MockDataGeneratorModal', () => {
596596
).to.not.equal('true');
597597
});
598598

599+
it('renders the title and description', async () => {
600+
await renderModal({
601+
currentStep: MockDataGeneratorSteps.SCRIPT_RESULT,
602+
fakerSchemaGeneration: createCompletedFakerSchema({
603+
name: {
604+
fakerMethod: 'person.firstName',
605+
fakerArgs: [],
606+
probability: 1.0,
607+
mongoType: 'String',
608+
},
609+
}),
610+
});
611+
612+
expect(screen.getByText('Generate Mock Data Script')).to.exist;
613+
expect(
614+
screen.getByText(/We've created the following script for your use\./)
615+
).to.exist;
616+
});
617+
599618
it('renders the main sections: Prerequisites, steps, and Resources', async () => {
600619
await renderModal({
601620
currentStep: MockDataGeneratorSteps.SCRIPT_RESULT,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ const MockDataGeneratorModal = ({
158158
}}
159159
data-testid="generate-mock-data-modal"
160160
>
161-
<ModalHeader title="Generate Mock Data" />
161+
<ModalHeader title="Generate Mock Data Script" />
162162
<ModalBody>
163163
{shouldShowNamespace && (
164164
<Body className={namespaceStyles}>{namespace}</Body>

packages/compass-collection/src/components/mock-data-generator-modal/script-generation-utils.spec.ts

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ describe('Script Generation', () => {
7272
email: faker.internet.email()
7373
};`;
7474
expect(result.script).to.contain(expectedReturnBlock);
75-
expect(result.script).to.contain('use("testdb")');
75+
expect(result.script).to.contain('const DB_NAME = "testdb"');
76+
expect(result.script).to.contain('const COLL_NAME = "users"');
77+
expect(result.script).to.contain('use(DB_NAME)');
7678
expect(result.script).to.contain('insertMany');
7779

7880
// Test that the generated document code is executable
@@ -382,13 +384,17 @@ describe('Script Generation', () => {
382384

383385
expect(result1.success).to.equal(true);
384386
if (result1.success) {
385-
expect(result1.script).to.contain('use("test\'db`with\\"quotes")');
386387
expect(result1.script).to.contain(
387-
'getCollection("coll\\nwith\\ttabs")'
388+
'const DB_NAME = "test\'db`with\\"quotes"'
388389
);
390+
expect(result1.script).to.contain(
391+
'const COLL_NAME = "coll\\nwith\\ttabs"'
392+
);
393+
expect(result1.script).to.contain('use(DB_NAME)');
394+
expect(result1.script).to.contain('getCollection(COLL_NAME)');
389395
// Should not contain unescaped special characters that could break JS
390-
expect(result1.script).not.to.contain("use('test'db");
391-
expect(result1.script).not.to.contain("getCollection('coll\nwith");
396+
expect(result1.script).not.to.contain("DB_NAME = 'test'db");
397+
expect(result1.script).not.to.contain("COLL_NAME = 'coll\nwith");
392398

393399
// Test that the generated document code is executable
394400
testDocumentCodeExecution(result1.script);
@@ -407,9 +413,11 @@ describe('Script Generation', () => {
407413
// eslint-disable-next-line @typescript-eslint/no-implied-eval
408414
expect(() => new Function(result2.script)).to.not.throw();
409415

410-
// Verify template literal characters are properly escaped in console.log
411-
expect(result2.script).to.contain('test\\`\\${}');
412-
expect(result2.script).to.contain('collection\\`\\${}');
416+
// Verify template literal characters are properly handled in constants via JSON.stringify
417+
expect(result2.script).to.contain('const DB_NAME = "test`${}"');
418+
expect(result2.script).to.contain('const COLL_NAME = "collection`${}"');
419+
expect(result2.script).to.contain('use(DB_NAME)');
420+
expect(result2.script).to.contain('getCollection(COLL_NAME)');
413421

414422
// Test that the generated document code is executable
415423
testDocumentCodeExecution(result2.script);
@@ -438,28 +446,23 @@ describe('Script Generation', () => {
438446
// eslint-disable-next-line @typescript-eslint/no-implied-eval
439447
expect(() => new Function(result.script)).to.not.throw();
440448

441-
// Verify malicious code is safely contained in string
442-
expect(result.script).to.contain(
443-
'use(\'test`; require("fs").rmSync("/"); //\')'
444-
);
445-
expect(result.script).to.contain('getCollection(\'my "collection"\')');
446-
447-
// Verify template literal injection is prevented (backticks are escaped)
449+
// Verify malicious code is safely contained in DB_NAME and COLL_NAME constants
450+
// Note: prettier may split long lines and uses single quotes when string contains double quotes
448451
expect(result.script).to.contain(
449-
'test\\`; require("fs").rmSync("/"); //'
452+
'\'test`; require("fs").rmSync("/"); //\''
450453
);
451-
452-
// Verify malicious code in name is safely contained in code comment
453454
expect(result.script).to.contain(
454-
'// Generated for database: test`; require("fs").rmSync("/"); //; collection: my "collection"'
455+
'const COLL_NAME = \'my "collection"\''
455456
);
457+
expect(result.script).to.contain('use(DB_NAME)');
458+
expect(result.script).to.contain('getCollection(COLL_NAME)');
456459

457460
// Test that the generated document code is executable
458461
testDocumentCodeExecution(result.script);
459462
}
460463
});
461464

462-
it('should sanitize newlines in database and collection names in comments', () => {
465+
it('should sanitize newlines in database and collection names in constants', () => {
463466
const schema = {
464467
field: {
465468
mongoType: 'String' as const,
@@ -477,10 +480,15 @@ describe('Script Generation', () => {
477480

478481
expect(result.success).to.equal(true);
479482
if (result.success) {
480-
// Verify newlines are replaced with spaces in comments to prevent syntax errors
483+
// Verify newlines are escaped in constants via JSON.stringify
484+
expect(result.script).to.contain(
485+
'const DB_NAME = "test\\nwith\\nnewlines"'
486+
);
481487
expect(result.script).to.contain(
482-
'// Generated for database: test with newlines; collection: coll with returns'
488+
'const COLL_NAME = "coll\\rwith\\r\\nreturns"'
483489
);
490+
expect(result.script).to.contain('use(DB_NAME)');
491+
expect(result.script).to.contain('getCollection(COLL_NAME)');
484492

485493
// Verify the script is still syntactically valid
486494
// eslint-disable-next-line @typescript-eslint/no-implied-eval

packages/compass-collection/src/components/mock-data-generator-modal/script-generation-utils.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,16 @@ export function generateScript(
6060

6161
// Generate unformatted script
6262
const unformattedScript = `// Mock Data Generator Script
63-
// Generated for database: ${options.databaseName.replace(
64-
/[\r\n]/g, // Prevent newlines in names that could break the comment
65-
' '
66-
)}; collection: ${options.collectionName.replace(/[\r\n]/g, ' ')}
6763
// Document count: ${options.documentCount}
6864
6965
const { faker } = require('@faker-js/faker');
7066
67+
// Database and collection configuration - edit these to target a different location
68+
const DB_NAME = ${JSON.stringify(options.databaseName)};
69+
const COLL_NAME = ${JSON.stringify(options.collectionName)};
70+
7171
// Connect to database
72-
use(${JSON.stringify(options.databaseName)});
72+
use(DB_NAME);
7373
7474
// Document generation function
7575
function generateDocument() {
@@ -80,10 +80,7 @@ const BATCH_SIZE = 1000; // Number of documents to insert per batch
8080
const TOTAL_DOCUMENTS = ${options.documentCount};
8181
const numBatches = Math.ceil(TOTAL_DOCUMENTS / BATCH_SIZE);
8282
83-
console.log(\`Starting mock data generation for ${options.databaseName.replace(
84-
/[\\`$]/g,
85-
'\\$&'
86-
)}.${options.collectionName.replace(/[\\`$]/g, '\\$&')}\`);
83+
console.log(\`Starting mock data generation for \${DB_NAME}.\${COLL_NAME}\`);
8784
console.log(\`Total documents to generate: \${TOTAL_DOCUMENTS} documents\`);
8885
console.log(\`Batch size: \${BATCH_SIZE} documents per batch\`);
8986
@@ -102,9 +99,7 @@ for (let batchStart = 0; batchStart < TOTAL_DOCUMENTS; batchStart += BATCH_SIZE)
10299
}
103100
104101
// Insert the batch
105-
db.getCollection(${JSON.stringify(
106-
options.collectionName
107-
)}).insertMany(batchDocuments);
102+
db.getCollection(COLL_NAME).insertMany(batchDocuments);
108103
109104
console.log(\`Batch inserted successfully.\`);
110105
}
@@ -114,10 +109,7 @@ const duration = ((endTime - startTime) / 1000).toFixed(2);
114109
115110
console.log(\`\\n=== Mock Data Generation Complete ===\`);
116111
console.log(\`Total time: \${duration} seconds\`);
117-
console.log(\`Collection: ${options.databaseName.replace(
118-
/[\\`$]/g,
119-
'\\$&'
120-
)}.${options.collectionName.replace(/[\\`$]/g, '\\$&')}\`);`;
112+
console.log(\`Collection: \${DB_NAME}.\${COLL_NAME}\`);`;
121113

122114
// Format the script using prettier
123115
const script = prettify(unformattedScript, 'javascript');

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ const ScriptScreen = ({
151151

152152
return (
153153
<section className={outerSectionStyles}>
154+
<Body>
155+
We&apos;ve created the following script for your use. The script can be
156+
edited to generate mock data for any collection you specify.
157+
</Body>
154158
{!scriptResult.success && (
155159
<Banner variant="danger">
156160
<strong>Script Generation Failed:</strong> {scriptResult.error}
@@ -193,6 +197,8 @@ const ScriptScreen = ({
193197
<Body className={sectionInstructionStyles}>
194198
In the directory that you created, create a file named{' '}
195199
<strong>mockdatascript.js</strong> (or any name you&apos;d like).
200+
Change the DB_NAME and COLL_NAME in the below script to any database
201+
or collection you&apos;d like to add mock data to.
196202
</Body>
197203
<Code
198204
copyButtonAppearance={scriptResult.success ? 'hover' : 'persist'}

0 commit comments

Comments
 (0)