diff --git a/packages/cli-repl/src/format-output.spec.ts b/packages/cli-repl/src/format-output.spec.ts index 7eacd90189..41d0959c58 100644 --- a/packages/cli-repl/src/format-output.spec.ts +++ b/packages/cli-repl/src/format-output.spec.ts @@ -140,6 +140,19 @@ for (const colors of [ false, true ]) { expect(output).to.equal( '\rError: Something went wrong.\nResult: { nInserted: 0 }'); }); + + it('provides violation info if present', () => { + const err = Object.assign(new Error('Something went wrong.'), { + violations: [{ ids: [1] }] + }); + const output = stripAnsiColors(format({ + value: err, + type: 'Error' + })); + + expect(output).to.equal( + '\rError: Something went wrong.\nViolations: [ { ids: [ 1 ] } ]'); + }); }); context('when the result is ShowDatabasesResult', () => { diff --git a/packages/cli-repl/src/format-output.ts b/packages/cli-repl/src/format-output.ts index 5b413d1d12..d9f8462483 100644 --- a/packages/cli-repl/src/format-output.ts +++ b/packages/cli-repl/src/format-output.ts @@ -199,6 +199,7 @@ function formatListCommands(output: Record, options: FormatOptions) return tableEntries.join('\n\n'); } +// eslint-disable-next-line complexity export function formatError(error: Error, options: FormatOptions): string { let result = ''; if (error.name) result += `\r${clr(error.name, 'mongosh:error', options)}: `; @@ -231,6 +232,10 @@ export function formatError(error: Error, options: FormatOptions): string { result += `\n${clr(i18n.__('cli-repl.cli-repl.additionalErrorResult'), 'mongosh:additional-error-info', options)}: `; result += inspect((error as any).result, options); } + if ((error as any).violations) { + result += `\n${clr(i18n.__('cli-repl.cli-repl.additionalErrorViolations'), 'mongosh:additional-error-info', options)}: `; + result += inspect((error as any).violations, options); + } return result; } diff --git a/packages/cli-repl/test/e2e.spec.ts b/packages/cli-repl/test/e2e.spec.ts index 7fc4e6f924..6d4eb70677 100644 --- a/packages/cli-repl/test/e2e.spec.ts +++ b/packages/cli-repl/test/e2e.spec.ts @@ -310,6 +310,45 @@ describe('e2e', function() { expect(shell.output).to.match( /multi update (only works with \$ operators|is not supported for replacement-style update)/); }); + context('when creating unique index', () => { + skipIfServerVersion(testServer, '< 5.3'); + + afterEach(async() => { + await shell.executeLine('db.apples.drop()'); + }); + + it('prints out violations for unique index creation', async() => { + await shell.executeLine(`db.apples.insertMany([ + { type: 'Delicious', quantity: 12 }, + { type: 'Macintosh', quantity: 13 }, + { type: 'Delicious', quantity: 13 }, + { type: 'Fuji', quantity: 15 }, + { type: 'Washington', quantity: 10 } + ]);`); + + await shell.executeLine('db.apples.createIndex({ type: 1 });'); + + await shell.executeLine(`db.runCommand({ + collMod: 'apples', + index: { + keyPattern: { type: 1 }, + prepareUnique: true + } + });`); + + const result = await shell.executeLine(`db.runCommand({ + collMod: 'apples', + index: { + keyPattern: { type: 1 }, + unique: true + } + });`); + + expect(result).to.match(/Violations\:/); + // Two duplicated ids + expect(result).to.match(/ids: \[\s+ObjectId.+?\s+?ObjectId.+?\s+\]/m); + }); + }); }); it('throws multiline input with a single line string', async() => { // this is an unterminated string constant and should throw, since it does diff --git a/packages/i18n/src/locales/en_US.ts b/packages/i18n/src/locales/en_US.ts index 5a6f4f6993..df98da0bb2 100644 --- a/packages/i18n/src/locales/en_US.ts +++ b/packages/i18n/src/locales/en_US.ts @@ -83,7 +83,8 @@ const translations: Catalog = { link: 'https://docs.mongodb.com/mongodb-shell/' }, additionalErrorInfo: 'Additional information', - additionalErrorResult: 'Result' + additionalErrorResult: 'Result', + additionalErrorViolations: 'Violations' }, 'uri-generator': { 'no-host-port': 'If a full URI is provided, you cannot also specify --host or --port',