Skip to content

Commit 1765a50

Browse files
authored
fix: set a consistent key for output elements rather than using the array index MONGOSH-2021 (#2382)
* set a consistent key for output elements rather than using the array index * make key required * fix tests
1 parent 6b662ef commit 1765a50

File tree

5 files changed

+41
-12
lines changed

5 files changed

+41
-12
lines changed

packages/browser-repl/src/components/shell-output-line.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type ShellOutputEntryValue = any;
3535
type Glyph = 'ChevronRight' | 'XWithCircle' | 'ChevronLeft';
3636

3737
export interface ShellOutputEntry {
38+
key: number | string;
3839
format: 'input' | 'output' | 'error';
3940
type?: string | null;
4041
value: ShellOutputEntryValue;

packages/browser-repl/src/components/shell-output.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ export class ShellOutput extends Component<ShellOutputProps> {
1414
output: PropTypes.arrayOf(PropTypes.any).isRequired,
1515
};
1616

17-
renderLine = (entry: ShellOutputEntry, index: number): JSX.Element => {
17+
renderLine = (entry: ShellOutputEntry): JSX.Element => {
1818
return (
19-
<ShellOutputLine key={`shell-output-entry-${index}`} entry={entry} />
19+
<ShellOutputLine key={`shell-output-entry-${entry.key}`} entry={entry} />
2020
);
2121
};
2222

packages/browser-repl/src/components/shell.spec.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import _ from 'lodash';
12
import React, { useState, useEffect } from 'react';
23
import sinon from 'sinon';
34
import { render, screen, waitFor, configure } from '@testing-library/react';
@@ -37,6 +38,14 @@ function filterEvaluateCalls(calls: any) {
3738
});
3839
}
3940

41+
let lastKey = 0;
42+
43+
function stripKeys(output: ShellOutputEntry[]) {
44+
return output.map((entry) => {
45+
return _.omit(entry, ['key']);
46+
});
47+
}
48+
4049
describe('shell', function () {
4150
let fakeRuntime;
4251
let scrollIntoView;
@@ -79,7 +88,7 @@ describe('shell', function () {
7988

8089
it('takes output', function () {
8190
const output: ShellOutputEntry[] = [
82-
{ format: 'output', value: 'Welcome message goes here' },
91+
{ key: lastKey++, format: 'output', value: 'Welcome message goes here' },
8392
];
8493

8594
render(<ShellWrapper runtime={fakeRuntime} output={output} />);
@@ -105,7 +114,7 @@ describe('shell', function () {
105114
);
106115

107116
await waitFor(() => {
108-
expect(output).to.deep.equal([
117+
expect(stripKeys(output)).to.deep.equal([
109118
{
110119
format: 'input',
111120
value: 'my command',
@@ -262,7 +271,7 @@ describe('shell', function () {
262271
);
263272

264273
await waitFor(() => {
265-
expect(output).to.deep.equal([
274+
expect(stripKeys(output)).to.deep.equal([
266275
{
267276
format: 'input',
268277
value: ' ',
@@ -293,7 +302,7 @@ describe('shell', function () {
293302
);
294303

295304
await waitFor(() => {
296-
expect(output).to.deep.equal([
305+
expect(stripKeys(output)).to.deep.equal([
297306
{
298307
format: 'input',
299308
value: 'my command',
@@ -312,6 +321,7 @@ describe('shell', function () {
312321
let output: ShellOutputEntry[] = [];
313322
for (let i = 0; i < 1000; i++) {
314323
output.push({
324+
key: lastKey++,
315325
format: 'output',
316326
type: undefined,
317327
value: 'some result',
@@ -333,7 +343,7 @@ describe('shell', function () {
333343
);
334344

335345
await waitFor(() => {
336-
expect(output).to.deep.equal([
346+
expect(stripKeys(output)).to.deep.equal([
337347
{
338348
format: 'output',
339349
type: undefined,
@@ -405,14 +415,14 @@ describe('shell', function () {
405415
);
406416

407417
await waitFor(() => {
408-
expect(output[output.length - 1]).to.deep.equal({
418+
expect(stripKeys(output)[output.length - 1]).to.deep.equal({
409419
format: 'output',
410420
type: undefined,
411421
value: 'some result',
412422
});
413423
});
414424

415-
expect(output).to.deep.equal([
425+
expect(stripKeys(output)).to.deep.equal([
416426
// we typed "my command"
417427
{ format: 'input', value: 'my command' },
418428
// while evaluating it printed something
@@ -425,6 +435,7 @@ describe('shell', function () {
425435
it('clears the output when onClearCommand is called', async function () {
426436
let output: ShellOutputEntry[] = [
427437
{
438+
key: lastKey++,
428439
format: 'output',
429440
type: undefined,
430441
value: 'some result',

packages/browser-repl/src/components/shell.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ const capLengthStart = (elements: unknown[], maxLength: number) => {
184184
elements.splice(maxLength);
185185
};
186186

187+
let lastKey = 0;
188+
187189
const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
188190
{
189191
runtime,
@@ -262,6 +264,7 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
262264
...(outputRef.current ?? []),
263265
...result.map(
264266
(entry): ShellOutputEntry => ({
267+
key: lastKey++,
265268
format: 'output',
266269
type: entry.type,
267270
value: entry.printable,
@@ -354,12 +357,14 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
354357
runtime.setEvaluationListener(listener);
355358
const result = await runtime.evaluate(code);
356359
outputLine = {
360+
key: lastKey++,
357361
format: 'output',
358362
type: result.type,
359363
value: result.printable,
360364
};
361365
} catch (error) {
362366
outputLine = {
367+
key: lastKey++,
363368
format: 'error',
364369
value: error,
365370
};
@@ -380,6 +385,7 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
380385
// don't evaluate empty input, but do add it to the output
381386
if (!code || code.trim() === '') {
382387
newOutputBeforeEval.push({
388+
key: lastKey++,
383389
format: 'input',
384390
value: ' ',
385391
});
@@ -391,6 +397,7 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
391397

392398
// add input to output
393399
newOutputBeforeEval.push({
400+
key: lastKey++,
394401
format: 'input',
395402
value: code,
396403
});

packages/browser-repl/src/sandbox.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,26 @@ class DemoServiceProvider {
151151

152152
const runtime = new IframeRuntime(new DemoServiceProvider() as any);
153153

154+
const lotsOfLines: ShellOutputEntry[] = [];
155+
for (let i = 0; i < 99; i++) {
156+
lotsOfLines.push({ key: `entry-${i}`, format: 'output', value: { i } });
157+
}
158+
154159
const IframeRuntimeExample: React.FunctionComponent = () => {
155160
const [darkMode, setDarkMode] = useState(true);
156161
const [redactInfo, setRedactInfo] = useState(false);
157-
const [maxOutputLength, setMaxOutputLength] = useState(1000);
158-
const [maxHistoryLength, setMaxHistoryLength] = useState(1000);
162+
const [maxOutputLength, setMaxOutputLength] = useState(100);
163+
const [maxHistoryLength, setMaxHistoryLength] = useState(100);
159164
const [initialEvaluate, setInitialEvaluate] = useState<string[]>([]);
160165

161166
const [initialText, setInitialText] = useState('');
162167
const [output, setOutput] = useState<ShellOutputEntry[]>([
163-
{ format: 'output', value: { foo: 1, bar: true, buz: function () {} } },
168+
...lotsOfLines,
169+
{
170+
key: 'test',
171+
format: 'output',
172+
value: { foo: 1, bar: true, buz: function () {} },
173+
},
164174
]);
165175
const [history, setHistory] = useState([
166176
'show dbs',

0 commit comments

Comments
 (0)