diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 1bac6456b88..ae282897763 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -34,6 +34,27 @@
}
}
},
+ "@babel/polyfill": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz",
+ "integrity": "sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg==",
+ "requires": {
+ "core-js": "^2.6.5",
+ "regenerator-runtime": "^0.13.2"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
+ "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
+ },
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
+ }
+ }
+ },
"@babel/runtime": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
@@ -2255,6 +2276,11 @@
}
}
},
+ "brace": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz",
+ "integrity": "sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg="
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -4105,6 +4131,11 @@
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
},
+ "diff-match-patch": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz",
+ "integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg=="
+ },
"diffie-hellman": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -5319,7 +5350,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -5684,7 +5716,8 @@
},
"safe-buffer": {
"version": "5.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -5732,6 +5765,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -5770,11 +5804,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
},
@@ -8418,6 +8454,11 @@
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
"dev": true
},
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+ },
"lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -8433,8 +8474,7 @@
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
- "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
- "dev": true
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
},
"lodash.isfunction": {
"version": "3.0.9",
@@ -11194,6 +11234,36 @@
"scheduler": "^0.12.0"
}
},
+ "react-ace": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-7.0.2.tgz",
+ "integrity": "sha512-+TFuO1nO6dme/q+qEHjb7iOuWI8jRDzeALs9JyH8HoyHb9+A2bC8WHuJyNU3pmPo8623bytgAgzEJAzDMkzjlw==",
+ "requires": {
+ "@babel/polyfill": "^7.4.4",
+ "brace": "^0.11.1",
+ "diff-match-patch": "^1.0.4",
+ "lodash.get": "^4.4.2",
+ "lodash.isequal": "^4.5.0",
+ "prop-types": "^15.7.2"
+ },
+ "dependencies": {
+ "prop-types": {
+ "version": "15.7.2",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
+ "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.8.1"
+ }
+ },
+ "react-is": {
+ "version": "16.9.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
+ "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw=="
+ }
+ }
+ },
"react-codemirror2": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-5.1.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index ee01ec5ea47..168405881c7 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -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",
@@ -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",
diff --git a/frontend/src/components/Editor.test.tsx b/frontend/src/components/Editor.test.tsx
new file mode 100644
index 00000000000..2245fb6ba66
--- /dev/null
+++ b/frontend/src/components/Editor.test.tsx
@@ -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(