Skip to content

Commit

Permalink
fix: set a consistent key for output elements rather than using the a…
Browse files Browse the repository at this point in the history
…rray index MONGOSH-2021 (#2382)

* set a consistent key for output elements rather than using the array index

* make key required

* fix tests
  • Loading branch information
lerouxb authored Feb 24, 2025
1 parent 6b662ef commit 1765a50
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 12 deletions.
1 change: 1 addition & 0 deletions packages/browser-repl/src/components/shell-output-line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type ShellOutputEntryValue = any;
type Glyph = 'ChevronRight' | 'XWithCircle' | 'ChevronLeft';

export interface ShellOutputEntry {
key: number | string;
format: 'input' | 'output' | 'error';
type?: string | null;
value: ShellOutputEntryValue;
Expand Down
4 changes: 2 additions & 2 deletions packages/browser-repl/src/components/shell-output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export class ShellOutput extends Component<ShellOutputProps> {
output: PropTypes.arrayOf(PropTypes.any).isRequired,
};

renderLine = (entry: ShellOutputEntry, index: number): JSX.Element => {
renderLine = (entry: ShellOutputEntry): JSX.Element => {
return (
<ShellOutputLine key={`shell-output-entry-${index}`} entry={entry} />
<ShellOutputLine key={`shell-output-entry-${entry.key}`} entry={entry} />
);
};

Expand Down
25 changes: 18 additions & 7 deletions packages/browser-repl/src/components/shell.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _ from 'lodash';
import React, { useState, useEffect } from 'react';
import sinon from 'sinon';
import { render, screen, waitFor, configure } from '@testing-library/react';
Expand Down Expand Up @@ -37,6 +38,14 @@ function filterEvaluateCalls(calls: any) {
});
}

let lastKey = 0;

function stripKeys(output: ShellOutputEntry[]) {
return output.map((entry) => {
return _.omit(entry, ['key']);
});
}

describe('shell', function () {
let fakeRuntime;
let scrollIntoView;
Expand Down Expand Up @@ -79,7 +88,7 @@ describe('shell', function () {

it('takes output', function () {
const output: ShellOutputEntry[] = [
{ format: 'output', value: 'Welcome message goes here' },
{ key: lastKey++, format: 'output', value: 'Welcome message goes here' },
];

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

await waitFor(() => {
expect(output).to.deep.equal([
expect(stripKeys(output)).to.deep.equal([
{
format: 'input',
value: 'my command',
Expand Down Expand Up @@ -262,7 +271,7 @@ describe('shell', function () {
);

await waitFor(() => {
expect(output).to.deep.equal([
expect(stripKeys(output)).to.deep.equal([
{
format: 'input',
value: ' ',
Expand Down Expand Up @@ -293,7 +302,7 @@ describe('shell', function () {
);

await waitFor(() => {
expect(output).to.deep.equal([
expect(stripKeys(output)).to.deep.equal([
{
format: 'input',
value: 'my command',
Expand All @@ -312,6 +321,7 @@ describe('shell', function () {
let output: ShellOutputEntry[] = [];
for (let i = 0; i < 1000; i++) {
output.push({
key: lastKey++,
format: 'output',
type: undefined,
value: 'some result',
Expand All @@ -333,7 +343,7 @@ describe('shell', function () {
);

await waitFor(() => {
expect(output).to.deep.equal([
expect(stripKeys(output)).to.deep.equal([
{
format: 'output',
type: undefined,
Expand Down Expand Up @@ -405,14 +415,14 @@ describe('shell', function () {
);

await waitFor(() => {
expect(output[output.length - 1]).to.deep.equal({
expect(stripKeys(output)[output.length - 1]).to.deep.equal({
format: 'output',
type: undefined,
value: 'some result',
});
});

expect(output).to.deep.equal([
expect(stripKeys(output)).to.deep.equal([
// we typed "my command"
{ format: 'input', value: 'my command' },
// while evaluating it printed something
Expand All @@ -425,6 +435,7 @@ describe('shell', function () {
it('clears the output when onClearCommand is called', async function () {
let output: ShellOutputEntry[] = [
{
key: lastKey++,
format: 'output',
type: undefined,
value: 'some result',
Expand Down
7 changes: 7 additions & 0 deletions packages/browser-repl/src/components/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ const capLengthStart = (elements: unknown[], maxLength: number) => {
elements.splice(maxLength);
};

let lastKey = 0;

const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
{
runtime,
Expand Down Expand Up @@ -262,6 +264,7 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
...(outputRef.current ?? []),
...result.map(
(entry): ShellOutputEntry => ({
key: lastKey++,
format: 'output',
type: entry.type,
value: entry.printable,
Expand Down Expand Up @@ -354,12 +357,14 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
runtime.setEvaluationListener(listener);
const result = await runtime.evaluate(code);
outputLine = {
key: lastKey++,
format: 'output',
type: result.type,
value: result.printable,
};
} catch (error) {
outputLine = {
key: lastKey++,
format: 'error',
value: error,
};
Expand All @@ -380,6 +385,7 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (
// don't evaluate empty input, but do add it to the output
if (!code || code.trim() === '') {
newOutputBeforeEval.push({
key: lastKey++,
format: 'input',
value: ' ',
});
Expand All @@ -391,6 +397,7 @@ const _Shell: ForwardRefRenderFunction<EditorRef | null, ShellProps> = (

// add input to output
newOutputBeforeEval.push({
key: lastKey++,
format: 'input',
value: code,
});
Expand Down
16 changes: 13 additions & 3 deletions packages/browser-repl/src/sandbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,26 @@ class DemoServiceProvider {

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

const lotsOfLines: ShellOutputEntry[] = [];
for (let i = 0; i < 99; i++) {
lotsOfLines.push({ key: `entry-${i}`, format: 'output', value: { i } });
}

const IframeRuntimeExample: React.FunctionComponent = () => {
const [darkMode, setDarkMode] = useState(true);
const [redactInfo, setRedactInfo] = useState(false);
const [maxOutputLength, setMaxOutputLength] = useState(1000);
const [maxHistoryLength, setMaxHistoryLength] = useState(1000);
const [maxOutputLength, setMaxOutputLength] = useState(100);
const [maxHistoryLength, setMaxHistoryLength] = useState(100);
const [initialEvaluate, setInitialEvaluate] = useState<string[]>([]);

const [initialText, setInitialText] = useState('');
const [output, setOutput] = useState<ShellOutputEntry[]>([
{ format: 'output', value: { foo: 1, bar: true, buz: function () {} } },
...lotsOfLines,
{
key: 'test',
format: 'output',
value: { foo: 1, bar: true, buz: function () {} },
},
]);
const [history, setHistory] = useState([
'show dbs',
Expand Down

0 comments on commit 1765a50

Please sign in to comment.