Skip to content

Commit

Permalink
Created extensible code editor based on react-ace (kubeflow#1855)
Browse files Browse the repository at this point in the history
* Created extensible code editor based on react-ace

* Installed dependencies

* Updated unit tests for Editor.tsx to test placeholder and value in simplified manner

* Updated Editor unit tests to use snapshot testing where applicable
  • Loading branch information
ajchili authored and k8s-ci-robot committed Aug 21, 2019
1 parent d11fae7 commit 7b442f4
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 6 deletions.
82 changes: 76 additions & 6 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@material-ui/core": "3.7.1",
"@material-ui/icons": "^3.0.1",
"@types/js-yaml": "^3.11.2",
"brace": "^0.11.1",
"codemirror": "^5.40.2",
"d3": "^5.7.0",
"d3-dsv": "^1.0.10",
Expand All @@ -18,6 +19,7 @@
"portable-fetch": "^3.0.0",
"re-resizable": "^4.9.0",
"react": "^16.7.0",
"react-ace": "^7.0.2",
"react-codemirror2": "^5.1.0",
"react-dom": "^16.5.2",
"react-dropzone": "^5.1.0",
Expand Down
52 changes: 52 additions & 0 deletions frontend/src/components/Editor.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as React from 'react';
import { mount } from 'enzyme';
import Editor from './Editor';

/*
These tests mimic https://github.com/securingsincity/react-ace/blob/master/tests/src/ace.spec.js
to ensure that editor properties (placeholder and value) can be properly
tested.
*/

describe('Editor', () => {
it('renders without a placeholder and value', () => {
const tree = mount(<Editor />);
expect(tree.html()).toMatchSnapshot();
});

it('renders with a placeholder', () => {
const placeholder = 'I am a placeholder.';
const tree = mount(<Editor placeholder={placeholder} />);
expect(tree.html()).toMatchSnapshot();
});

it ('renders a placeholder that contains HTML', () => {
const placeholder = 'I am a placeholder with <strong>HTML</strong>.';
const tree = mount(<Editor placeholder={placeholder} />);
expect(tree.html()).toMatchSnapshot();
});

it('has its value set to the provided value', () => {
const value = 'I am a value.';
const tree = mount(<Editor value={value} />);
expect(tree).not.toBeNull();
const editor = (tree.instance() as any).editor;
expect(editor.getValue()).toBe(value);
});
});
45 changes: 45 additions & 0 deletions frontend/src/components/Editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import AceEditor from 'react-ace';

// Modified AceEditor that supports HTML within provided placeholder. This is
// important because it allows for the usage of multi-line placeholders.
class Editor extends AceEditor {
public updatePlaceholder(): void {
const editor = this.editor;
const { placeholder } = this.props;

const showPlaceholder = !editor.session.getValue().length;
let node = editor.renderer.placeholderNode;
if (!showPlaceholder && node) {
editor.renderer.scroller.removeChild(editor.renderer.placeholderNode);
editor.renderer.placeholderNode = null;
} else if (showPlaceholder && !node) {
node = editor.renderer.placeholderNode = document.createElement('div');
node.innerHTML = placeholder || '';
node.className = 'ace_comment ace_placeholder';
node.style.padding = '0 9px';
node.style.position = 'absolute';
node.style.zIndex = '3';
editor.renderer.scroller.appendChild(node);
} else if (showPlaceholder && node) {
node.innerHTML = placeholder;
}
}
}

export default Editor;
7 changes: 7 additions & 0 deletions frontend/src/components/__snapshots__/Editor.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Editor renders a placeholder that contains HTML 1`] = `"<div id=\\"brace-editor\\" style=\\"width: 500px; height: 500px;\\" class=\\" ace_editor ace-tm\\"><textarea class=\\"ace_text-input\\" wrap=\\"off\\" autocorrect=\\"off\\" autocapitalize=\\"off\\" spellcheck=\\"false\\" style=\\"opacity: 0;\\"></textarea><div class=\\"ace_gutter\\" aria-hidden=\\"true\\"><div class=\\"ace_layer ace_gutter-layer ace_folding-enabled\\"></div><div class=\\"ace_gutter-active-line\\"></div></div><div class=\\"ace_scroller\\"><div class=\\"ace_content\\"><div class=\\"ace_layer ace_print-margin-layer\\"><div class=\\"ace_print-margin\\" style=\\"left: 4px; visibility: visible;\\"></div></div><div class=\\"ace_layer ace_marker-layer\\"></div><div class=\\"ace_layer ace_text-layer\\" style=\\"padding: 0px 4px;\\"></div><div class=\\"ace_layer ace_marker-layer\\"></div><div class=\\"ace_layer ace_cursor-layer ace_hidden-cursors\\"><div class=\\"ace_cursor\\"></div></div></div><div class=\\"ace_comment ace_placeholder\\" style=\\"padding: 0px 9px; position: absolute; z-index: 3;\\">I am a placeholder with <strong>HTML</strong>.</div></div><div class=\\"ace_scrollbar ace_scrollbar-v\\" style=\\"display: none; width: 20px;\\"><div class=\\"ace_scrollbar-inner\\" style=\\"width: 20px;\\"></div></div><div class=\\"ace_scrollbar ace_scrollbar-h\\" style=\\"display: none; height: 20px;\\"><div class=\\"ace_scrollbar-inner\\" style=\\"height: 20px;\\"></div></div><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;\\"><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;\\"></div><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;\\">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div></div></div>"`;

exports[`Editor renders with a placeholder 1`] = `"<div id=\\"brace-editor\\" style=\\"width: 500px; height: 500px;\\" class=\\" ace_editor ace-tm\\"><textarea class=\\"ace_text-input\\" wrap=\\"off\\" autocorrect=\\"off\\" autocapitalize=\\"off\\" spellcheck=\\"false\\" style=\\"opacity: 0;\\"></textarea><div class=\\"ace_gutter\\" aria-hidden=\\"true\\"><div class=\\"ace_layer ace_gutter-layer ace_folding-enabled\\"></div><div class=\\"ace_gutter-active-line\\"></div></div><div class=\\"ace_scroller\\"><div class=\\"ace_content\\"><div class=\\"ace_layer ace_print-margin-layer\\"><div class=\\"ace_print-margin\\" style=\\"left: 4px; visibility: visible;\\"></div></div><div class=\\"ace_layer ace_marker-layer\\"></div><div class=\\"ace_layer ace_text-layer\\" style=\\"padding: 0px 4px;\\"></div><div class=\\"ace_layer ace_marker-layer\\"></div><div class=\\"ace_layer ace_cursor-layer ace_hidden-cursors\\"><div class=\\"ace_cursor\\"></div></div></div><div class=\\"ace_comment ace_placeholder\\" style=\\"padding: 0px 9px; position: absolute; z-index: 3;\\">I am a placeholder.</div></div><div class=\\"ace_scrollbar ace_scrollbar-v\\" style=\\"display: none; width: 20px;\\"><div class=\\"ace_scrollbar-inner\\" style=\\"width: 20px;\\"></div></div><div class=\\"ace_scrollbar ace_scrollbar-h\\" style=\\"display: none; height: 20px;\\"><div class=\\"ace_scrollbar-inner\\" style=\\"height: 20px;\\"></div></div><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;\\"><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;\\"></div><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;\\">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div></div></div>"`;

exports[`Editor renders without a placeholder and value 1`] = `"<div id=\\"brace-editor\\" style=\\"width: 500px; height: 500px;\\" class=\\" ace_editor ace-tm\\"><textarea class=\\"ace_text-input\\" wrap=\\"off\\" autocorrect=\\"off\\" autocapitalize=\\"off\\" spellcheck=\\"false\\" style=\\"opacity: 0;\\"></textarea><div class=\\"ace_gutter\\" aria-hidden=\\"true\\"><div class=\\"ace_layer ace_gutter-layer ace_folding-enabled\\"></div><div class=\\"ace_gutter-active-line\\"></div></div><div class=\\"ace_scroller\\"><div class=\\"ace_content\\"><div class=\\"ace_layer ace_print-margin-layer\\"><div class=\\"ace_print-margin\\" style=\\"left: 4px; visibility: visible;\\"></div></div><div class=\\"ace_layer ace_marker-layer\\"></div><div class=\\"ace_layer ace_text-layer\\" style=\\"padding: 0px 4px;\\"></div><div class=\\"ace_layer ace_marker-layer\\"></div><div class=\\"ace_layer ace_cursor-layer ace_hidden-cursors\\"><div class=\\"ace_cursor\\"></div></div></div></div><div class=\\"ace_scrollbar ace_scrollbar-v\\" style=\\"display: none; width: 20px;\\"><div class=\\"ace_scrollbar-inner\\" style=\\"width: 20px;\\"></div></div><div class=\\"ace_scrollbar ace_scrollbar-h\\" style=\\"display: none; height: 20px;\\"><div class=\\"ace_scrollbar-inner\\" style=\\"height: 20px;\\"></div></div><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;\\"><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;\\"></div><div style=\\"height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;\\">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div></div></div>"`;

0 comments on commit 7b442f4

Please sign in to comment.