From 0455d31b84796ddef837db193fb8105eb64b4498 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 29 Mar 2022 10:25:16 -0600 Subject: [PATCH] Remove Ivy Codemirror (#14659) * setup * fix mode issue * actions * readonly styling * remove ivycodemirror from package json * wip * test coverage for json editor * text fixes * fix tests * fix cursor issue * changelog * clean up * fix * address pr comments * unused css and it overides other styling. * fix * fix comment --- changelog/14659.txt | 3 + ui/app/components/json-editor.js | 46 +++-------- ui/app/modifiers/code-mirror.js | 68 ++++++++++++++++ ui/app/styles/components/codemirror.scss | 32 ++------ .../templates/components/console/log-json.hbs | 5 +- .../components/control-group-success.hbs | 5 +- ui/app/templates/components/json-editor.hbs | 24 ++++-- .../templates/components/secret-form-show.hbs | 2 +- ui/app/templates/components/tool-unwrap.hbs | 2 +- .../components/transit-key-action/decrypt.hbs | 2 +- .../components/transit-key-action/encrypt.hbs | 2 +- .../components/transit-key-action/hmac.hbs | 7 +- .../components/transit-key-action/rewrap.hbs | 2 +- .../components/transit-key-action/sign.hbs | 2 +- .../components/transit-key-action/verify.hbs | 13 +--- .../vault/cluster/policies/create.hbs | 3 +- .../templates/vault/cluster/policy/edit.hbs | 3 +- .../templates/vault/cluster/policy/show.hbs | 3 +- ui/ember-cli-build.js | 7 +- .../addon/templates/components/form-field.hbs | 2 +- ui/package.json | 1 + .../secrets/backend/kv/secret-test.js | 6 +- .../components/console/log-json-test.js | 5 +- .../components/json-editor-test.js | 78 +++++++++++++------ .../components/secret-edit-test.js | 13 ++-- ui/tests/pages/components/form-field.js | 2 +- ui/tests/pages/components/json-editor.js | 6 +- ui/tests/pages/helpers/codemirror.js | 34 -------- .../pages/secrets/backend/kv/edit-secret.js | 5 +- ui/tests/pages/secrets/backend/kv/show.js | 5 +- ui/yarn.lock | 31 +++++++- 31 files changed, 232 insertions(+), 187 deletions(-) create mode 100644 changelog/14659.txt create mode 100644 ui/app/modifiers/code-mirror.js delete mode 100644 ui/tests/pages/helpers/codemirror.js diff --git a/changelog/14659.txt b/changelog/14659.txt new file mode 100644 index 000000000..0468cbcd1 --- /dev/null +++ b/changelog/14659.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: Replaces the IvyCodemirror wrapper with a custom ember modifier. +``` \ No newline at end of file diff --git a/ui/app/components/json-editor.js b/ui/app/components/json-editor.js index 1e57e84ec..c90541037 100644 --- a/ui/app/components/json-editor.js +++ b/ui/app/components/json-editor.js @@ -14,50 +14,24 @@ import { action } from '@ember/object'; * @param {Function} [valueUpdated] - action to preform when you edit the codemirror value. * @param {Function} [onFocusOut] - action to preform when you focus out of codemirror. * @param {string} [helpText] - helper text. - * @param {object} [options] - option object that overrides codemirror default options such as the styling. + * @param {Object} [extraKeys] - Provides keyboard shortcut methods for things like saving on shift + enter. + * @param {Array} [gutters] - An array of CSS class names or class name / CSS string pairs, each of which defines a width (and optionally a background), and which will be used to draw the background of the gutters. + * @param {string} [mode] - The mode defined for styling. Right now we only import ruby so mode must but be ruby or defaults to javascript. If you wanted another language you need to import it into the modifier. + * @param {Boolean} [readOnly] - Sets the view to readOnly, allowing for copying but no editing. It also hides the cursor. Defaults to false. + * @param {String} [theme] - Specify or customize the look via a named "theme" class in scss. + * @param {String} [value] - Value within the display. Generally, a json string. + * @param {String} [viewportMargin] - Size of viewport. Often set to "Infinity" to load/show all text regardless of length. */ -const JSON_EDITOR_DEFAULTS = { - // IMPORTANT: `gutters` must come before `lint` since the presence of - // `gutters` is cached internally when `lint` is toggled - gutters: ['CodeMirror-lint-markers'], - tabSize: 2, - mode: 'application/json', - lineNumbers: true, - lint: { lintOnChange: false }, - theme: 'hashi', - readOnly: false, - showCursorWhenSelecting: true, -}; - export default class JsonEditorComponent extends Component { - value = null; - valueUpdated = null; - onFocusOut = null; - readOnly = false; - options = null; - - constructor() { - super(...arguments); - this.options = { ...JSON_EDITOR_DEFAULTS, ...this.args.options }; - if (this.options.autoHeight) { - this.options.viewportMargin = Infinity; - delete this.options.autoHeight; - } - if (this.options.readOnly) { - this.options.readOnly = 'nocursor'; - this.options.lineNumbers = false; - delete this.options.gutters; - } - } - get getShowToolbar() { return this.args.showToolbar === false ? false : true; } @action - updateValue(...args) { - if (this.args.valueUpdated) { + onUpdate(...args) { + if (!this.args.readOnly) { + // catching a situation in which the user is not readOnly and has not provided a valueUpdated function to the instance this.args.valueUpdated(...args); } } diff --git a/ui/app/modifiers/code-mirror.js b/ui/app/modifiers/code-mirror.js new file mode 100644 index 000000000..f018c0974 --- /dev/null +++ b/ui/app/modifiers/code-mirror.js @@ -0,0 +1,68 @@ +import { action } from '@ember/object'; +import { bind } from '@ember/runloop'; +import codemirror from 'codemirror'; +import Modifier from 'ember-modifier'; + +import 'codemirror/addon/edit/matchbrackets'; +import 'codemirror/addon/selection/active-line'; +import 'codemirror/addon/lint/lint.js'; +import 'codemirror/addon/lint/json-lint.js'; +// right now we only use the ruby and javascript, if you use another mode you'll need to import it. +// https://codemirror.net/mode/ +import 'codemirror/mode/ruby/ruby'; +import 'codemirror/mode/javascript/javascript'; + +export default class CodeMirrorModifier extends Modifier { + didInstall() { + this._setup(); + } + + didUpdateArguments() { + this._editor.setOption('readOnly', this.args.named.readOnly); + if (!this.args.named.content) { + return; + } + if (this._editor.getValue() !== this.args.named.content) { + this._editor.setValue(this.args.named.content); + } + } + + @action + _onChange(editor) { + this.args.named.onUpdate(editor.getValue(), this._editor); + } + + @action + _onFocus(editor) { + this.args.named.onFocus(editor.getValue()); + } + + _setup() { + if (!this.element) { + throw new Error('CodeMirror modifier has no element'); + } + const editor = codemirror(this.element, { + // IMPORTANT: `gutters` must come before `lint` since the presence of + // `gutters` is cached internally when `lint` is toggled + gutters: this.args.named.gutters || ['CodeMirror-lint-markers'], + matchBrackets: true, + lint: { lintOnChange: true }, + showCursorWhenSelecting: true, + styleActiveLine: true, + tabSize: 2, + // all values we can pass into the JsonEditor + extraKeys: this.args.named.extraKeys || '', + lineNumbers: this.args.named.lineNumbers, + mode: this.args.named.mode || 'application/json', + readOnly: this.args.named.readOnly || false, + theme: this.args.named.theme || 'hashi', + value: this.args.named.content || '', + viewportMargin: this.args.named.viewportMargin || '', + }); + + editor.on('change', bind(this, this._onChange)); + editor.on('focus', bind(this, this._onFocus)); + + this._editor = editor; + } +} diff --git a/ui/app/styles/components/codemirror.scss b/ui/app/styles/components/codemirror.scss index 023bed8f7..dfc856387 100644 --- a/ui/app/styles/components/codemirror.scss +++ b/ui/app/styles/components/codemirror.scss @@ -51,7 +51,7 @@ $gutter-grey: #2a2f36; .cm-s-hashi { &.CodeMirror { background-color: $black !important; - resize: vertical; + resize: vertical; color: #cfd2d1 !important; border: none; font-family: $family-monospace; @@ -168,34 +168,14 @@ $gutter-grey: #2a2f36; } .readonly-codemirror { - .CodeMirror-cursors { + .CodeMirror-code { + cursor: default; + } + .CodeMirror-cursor { + // https://github.com/codemirror/CodeMirror/issues/1099 display: none; } - - .cm-s-hashi { - span { - color: $light-grey; - } - - span.cm-string, - span.cm-string-2 { - color: $faded-gray; - } - - span.cm-number { - color: lighten($dark-gray, 30%); - } - - span.cm-property { - color: white; - } - - span.cm-variable-2 { - color: $light-grey-blue; - } - } } - .cm-s-auto-height.CodeMirror { height: auto; } diff --git a/ui/app/templates/components/console/log-json.hbs b/ui/app/templates/components/console/log-json.hbs index 76a5b7c38..e2e8f9a4e 100644 --- a/ui/app/templates/components/console/log-json.hbs +++ b/ui/app/templates/components/console/log-json.hbs @@ -2,7 +2,10 @@ \ No newline at end of file diff --git a/ui/app/templates/components/control-group-success.hbs b/ui/app/templates/components/control-group-success.hbs index fb690830c..69a007717 100644 --- a/ui/app/templates/components/control-group-success.hbs +++ b/ui/app/templates/components/control-group-success.hbs @@ -17,7 +17,10 @@ data-test-json-viewer @showToolbar={{false}} @value={{stringify this.unwrapData}} - @options={{hash readOnly=true lineNumbers=false autoHeight=true gutters=false theme="hashi-read-only auto-height"}} + @readOnly={{true}} + @viewportMargin="Infinity" + @gutters={{false}} + @theme="hashi-read-only auto-height" /> diff --git a/ui/app/templates/components/json-editor.hbs b/ui/app/templates/components/json-editor.hbs index 03fd3295d..620057ff8 100644 --- a/ui/app/templates/components/json-editor.hbs +++ b/ui/app/templates/components/json-editor.hbs @@ -23,14 +23,22 @@ {{/if}} - - +
{{#if @helpText}}
diff --git a/ui/app/templates/components/secret-form-show.hbs b/ui/app/templates/components/secret-form-show.hbs index 05164297d..cf6c99fb8 100644 --- a/ui/app/templates/components/secret-form-show.hbs +++ b/ui/app/templates/components/secret-form-show.hbs @@ -33,7 +33,7 @@
{{else}} diff --git a/ui/app/templates/components/tool-unwrap.hbs b/ui/app/templates/components/tool-unwrap.hbs index 62aa362c6..62e965d96 100644 --- a/ui/app/templates/components/tool-unwrap.hbs +++ b/ui/app/templates/components/tool-unwrap.hbs @@ -45,7 +45,7 @@ {{#if (eq @unwrapActiveTab "data")}}
- +
{{else}} diff --git a/ui/app/templates/components/transit-key-action/decrypt.hbs b/ui/app/templates/components/transit-key-action/decrypt.hbs index d3e022456..85745296e 100644 --- a/ui/app/templates/components/transit-key-action/decrypt.hbs +++ b/ui/app/templates/components/transit-key-action/decrypt.hbs @@ -8,7 +8,7 @@ diff --git a/ui/app/templates/components/transit-key-action/encrypt.hbs b/ui/app/templates/components/transit-key-action/encrypt.hbs index 507898f33..2a51e3d85 100644 --- a/ui/app/templates/components/transit-key-action/encrypt.hbs +++ b/ui/app/templates/components/transit-key-action/encrypt.hbs @@ -16,7 +16,7 @@ @title="Plaintext" @value={{@plaintext}} @valueUpdated={{action (mut @plaintext)}} - @options={{hash mode="ruby"}} + @mode="ruby" @data-test-transit-input="plaintext" /> diff --git a/ui/app/templates/components/transit-key-action/hmac.hbs b/ui/app/templates/components/transit-key-action/hmac.hbs index 426910e82..e739201e9 100644 --- a/ui/app/templates/components/transit-key-action/hmac.hbs +++ b/ui/app/templates/components/transit-key-action/hmac.hbs @@ -11,12 +11,7 @@
- +
diff --git a/ui/app/templates/components/transit-key-action/rewrap.hbs b/ui/app/templates/components/transit-key-action/rewrap.hbs index 7a3972e92..0570b8e1c 100644 --- a/ui/app/templates/components/transit-key-action/rewrap.hbs +++ b/ui/app/templates/components/transit-key-action/rewrap.hbs @@ -11,7 +11,7 @@
- +
{{#if @key.derived}} diff --git a/ui/app/templates/components/transit-key-action/sign.hbs b/ui/app/templates/components/transit-key-action/sign.hbs index 4fff95c62..9c236e2f0 100644 --- a/ui/app/templates/components/transit-key-action/sign.hbs +++ b/ui/app/templates/components/transit-key-action/sign.hbs @@ -28,7 +28,7 @@ @title="Input" @value={{@input}} @valueUpdated={{action (mut @input)}} - @options={{hash mode="ruby"}} + @mode="ruby" @data-test-transit-input="input" />
diff --git a/ui/app/templates/components/transit-key-action/verify.hbs b/ui/app/templates/components/transit-key-action/verify.hbs index 1245cff52..43db065d8 100644 --- a/ui/app/templates/components/transit-key-action/verify.hbs +++ b/ui/app/templates/components/transit-key-action/verify.hbs @@ -23,7 +23,7 @@ @title="Input" @value={{@input}} @valueUpdated={{action (mut @input)}} - @options={{hash mode="ruby"}} + @mode="ruby" @data-test-transit-input="input" /> @@ -140,12 +140,7 @@ {{#if (or (and @verification (eq @verification "HMAC")) @hmac)}}
- +
{{else}} @@ -155,7 +150,7 @@ @title="Signature" @value={{@signature}} @valueUpdated={{action (mut @signature)}} - @options={{hash mode="ruby"}} + @mode="ruby" /> @@ -165,7 +160,7 @@ {{else}}
- +
diff --git a/ui/app/templates/vault/cluster/policies/create.hbs b/ui/app/templates/vault/cluster/policies/create.hbs index 86e5a7bef..a119b7b7b 100644 --- a/ui/app/templates/vault/cluster/policies/create.hbs +++ b/ui/app/templates/vault/cluster/policies/create.hbs @@ -62,7 +62,8 @@ @showToolbar={{false}} @value={{this.model.policy}} @valueUpdated={{action (mut this.model.policy)}} - @options={{hash mode="ruby" extraKeys=(hash Shift-Enter=(action "savePolicy" this.model))}} + @mode="ruby" + @extraKeys={{hash Shift-Enter=(action "savePolicy" this.model)}} /> {{/if}}
diff --git a/ui/app/templates/vault/cluster/policy/edit.hbs b/ui/app/templates/vault/cluster/policy/edit.hbs index 9caddba6f..04933c392 100644 --- a/ui/app/templates/vault/cluster/policy/edit.hbs +++ b/ui/app/templates/vault/cluster/policy/edit.hbs @@ -50,7 +50,8 @@ @title="Policy" @value={{this.model.policy}} @valueUpdated={{action (mut this.model.policy)}} - @options={{hash mode="ruby" extraKeys=(hash Shift-Enter=(action "savePolicy" this.model))}} + @mode="ruby" + @extraKeys={{hash Shift-Enter=(action "savePolicy" this.model)}} />

diff --git a/ui/app/templates/vault/cluster/policy/show.hbs b/ui/app/templates/vault/cluster/policy/show.hbs index 67a705986..27dd87463 100644 --- a/ui/app/templates/vault/cluster/policy/show.hbs +++ b/ui/app/templates/vault/cluster/policy/show.hbs @@ -42,7 +42,8 @@ @title="Policy" @subTitle={{if (eq this.policyType "acl") (concat this.uppercase this.model.format " format")}} @value={{this.model.policy}} - @options={{hash readOnly=true mode="ruby"}} + @readOnly={{true}} + @mode="ruby" />

{{#if this.model.paths}} diff --git a/ui/ember-cli-build.js b/ui/ember-cli-build.js index 9921cf9ac..45eaeeb8c 100644 --- a/ui/ember-cli-build.js +++ b/ui/ember-cli-build.js @@ -26,10 +26,6 @@ const appConfig = { return `${config.rootURL.replace(/\/$/, '')}${filePath}`; }, }, - codemirror: { - modes: ['javascript', 'ruby'], - keyMaps: ['sublime'], - }, babel: { plugins: ['@babel/plugin-proposal-object-rest-spread', ['inline-json-import', {}]], }, @@ -74,8 +70,7 @@ module.exports = function (defaults) { app.import('node_modules/jsonlint/lib/jsonlint.js'); app.import('node_modules/codemirror/addon/lint/lint.css'); - app.import('node_modules/codemirror/addon/lint/lint.js'); - app.import('node_modules/codemirror/addon/lint/json-lint.js'); + app.import('node_modules/codemirror/lib/codemirror.css'); app.import('node_modules/text-encoder-lite/text-encoder-lite.js'); app.import('node_modules/jsondiffpatch/dist/jsondiffpatch.umd.js'); app.import('node_modules/jsondiffpatch/dist/formatters-styles/html.css'); diff --git a/ui/lib/core/addon/templates/components/form-field.hbs b/ui/lib/core/addon/templates/components/form-field.hbs index 2ed0827fa..6cf445825 100644 --- a/ui/lib/core/addon/templates/components/form-field.hbs +++ b/ui/lib/core/addon/templates/components/form-field.hbs @@ -233,7 +233,7 @@ this.attr.options.defaultValue }} @valueUpdated={{action "codemirrorUpdated" this.attr.name "string"}} - @options={{hash theme=(or this.attr.options.theme "hashi")}} + @theme={{or this.attr.options.theme "hashi"}} @helpText={{this.attr.options.helpText}} > {{#if this.attr.options.allowReset}} diff --git a/ui/package.json b/ui/package.json index 0e4e91019..6cc32aaaa 100644 --- a/ui/package.json +++ b/ui/package.json @@ -129,6 +129,7 @@ "ember-maybe-import-regenerator": "^0.1.6", "ember-maybe-in-element": "^2.0.3", "ember-modal-dialog": "^3.0.3", + "ember-modifier": "^3.1.0", "ember-page-title": "^6.0.3", "ember-power-select": "^5.0.3", "ember-promise-helpers": "^1.0.9", diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index 14f06f775..6843d9d74 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -374,13 +374,15 @@ module('Acceptance | secrets/secret/create', function (hooks) { await listPage.visitRoot({ backend: 'secret' }); await listPage.create(); await editPage.path(secretPath).toggleJSON(); - await editPage.editor.fillIn(this, content); + let instance = document.querySelector('.CodeMirror').CodeMirror; + instance.setValue(content); await editPage.save(); assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'redirects to the show page'); assert.ok(showPage.editIsPresent, 'shows the edit button'); + let savedInstance = document.querySelector('.CodeMirror').CodeMirror; assert.equal( - showPage.editor.content(this), + savedInstance.options.value, JSON.stringify({ bar: 'boo', foo: 'fa' }, null, 2), 'saves the content' ); diff --git a/ui/tests/integration/components/console/log-json-test.js b/ui/tests/integration/components/console/log-json-test.js index 1cce65007..0a30352b3 100644 --- a/ui/tests/integration/components/console/log-json-test.js +++ b/ui/tests/integration/components/console/log-json-test.js @@ -19,8 +19,7 @@ module('Integration | Component | console/log json', function (hooks) { this.set('content', objectContent); await render(hbs`{{console/log-json content=content}}`); - const instance = this.codeMirror.instanceFor(find('[data-test-component=json-editor]').id); - - assert.equal(instance.getValue(), expectedText); + const instance = find('[data-test-component=code-mirror-modifier]').innerText; + assert.equal(instance, expectedText); }); }); diff --git a/ui/tests/integration/components/json-editor-test.js b/ui/tests/integration/components/json-editor-test.js index 975fe30af..2bcc6a3b3 100644 --- a/ui/tests/integration/components/json-editor-test.js +++ b/ui/tests/integration/components/json-editor-test.js @@ -1,44 +1,76 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { create } from 'ember-cli-page-object'; -import { render } from '@ember/test-helpers'; +import { render, fillIn, find, waitUntil } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import jsonEditor from '../../pages/components/json-editor'; +import sinon from 'sinon'; const component = create(jsonEditor); module('Integration | Component | json-editor', function (hooks) { setupRenderingTest(hooks); - const setup = async function (context, title, value, options, showToolbar = true) { - context.set('value', JSON.stringify(value)); - context.set('options', options); - context.set('title', title); - context.set('showToolbar', showToolbar); - await render(hbs`{{json-editor title=title value=value options=options showToolbar=showToolbar}}`); - }; + const JSON_BLOB = `{ + "test": "test" + }`; + const BAD_JSON_BLOB = `{ + "test": test + }`; + + hooks.beforeEach(function () { + this.set('valueUpdated', sinon.spy()); + this.set('onFocusOut', sinon.spy()); + this.set('json_blob', JSON_BLOB); + this.set('bad_json_blob', BAD_JSON_BLOB); + this.set('hashi-read-only-theme', 'hashi-read-only auto-height'); + }); test('it renders', async function (assert) { - let value = ''; - await setup(this, 'Test title', value, null); + await render(hbs``); + assert.equal(component.title, 'Test title', 'renders the provided title'); assert.equal(component.hasToolbar, true, 'renders the toolbar'); - assert.equal(component.hasJSONEditor, true, 'renders the ivy code mirror component'); - assert.equal(component.canEdit, true, 'json editor is in read only mode'); + assert.equal(component.hasJSONEditor, true, 'renders the code mirror modifier'); + assert.ok(component.canEdit, 'json editor can be edited'); }); - test('it renders in read only mode', async function (assert) { - let value = ''; - let options = { - readOnly: true, - }; - await setup(this, 'Test title', value, options); - assert.equal(component.canEdit, false, 'editor is in read only mode'); + test('it handles editing and linting and styles to json', async function (assert) { + await render(hbs``); + // check for json styling + assert.dom('.cm-property').hasStyle({ + color: 'rgb(158, 132, 197)', + }); + assert.dom('.cm-string:nth-child(2)').hasStyle({ + color: 'rgb(29, 219, 163)', + }); + + await fillIn('textarea', this.bad_json_blob); + await waitUntil(() => find('.CodeMirror-lint-marker-error')); + assert.dom('.CodeMirror-lint-marker-error').exists('throws linting error'); + assert.dom('.CodeMirror-linenumber').exists('shows line numbers'); }); - test('it renders the editor without toolbar', async function (assert) { - let value = ''; - await setup(this, 'Test title', value, null, false); - assert.equal(component.hasToolbar, false, 'toolbar is not rendered'); + test('it renders the correct theme and expected styling', async function (assert) { + await render(hbs``); + + assert.dom('.cm-s-hashi-read-only').hasStyle({ + background: 'rgb(247, 248, 250) none repeat scroll 0% 0% / auto padding-box border-box', + }); + assert.dom('.CodeMirror-linenumber').doesNotExist('on readOnly does not show line numbers'); }); }); diff --git a/ui/tests/integration/components/secret-edit-test.js b/ui/tests/integration/components/secret-edit-test.js index 57c03d8c7..b35259921 100644 --- a/ui/tests/integration/components/secret-edit-test.js +++ b/ui/tests/integration/components/secret-edit-test.js @@ -1,6 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, find, settled } from '@ember/test-helpers'; +import { render, settled } from '@ember/test-helpers'; import { resolve } from 'rsvp'; import { run } from '@ember/runloop'; import Service from '@ember/service'; @@ -55,15 +55,12 @@ module('Integration | Component | secret edit', function (hooks) { test('it shows an error when creating and data is not an object', async function (assert) { this.set('mode', 'create'); this.set('model', { - secretData: { - int: '2', - null: 'null', - float: '1.234', - }, + secretData: null, }); await render(hbs`{{secret-edit mode=mode model=model preferAdvancedEdit=true }}`); - let instance = this.codeMirror.instanceFor(find('[data-test-component=json-editor]').id); + + let instance = document.querySelector('.CodeMirror').CodeMirror; instance.setValue(JSON.stringify([{ foo: 'bar' }])); await settled(); assert.dom('[data-test-error]').includesText('Vault expects data to be formatted as an JSON object'); @@ -99,7 +96,7 @@ module('Integration | Component | secret edit', function (hooks) { await render(hbs`{{secret-edit mode=mode model=model preferAdvancedEdit=true }}`); - let instance = this.codeMirror.instanceFor(find('[data-test-component=json-editor]').id); + let instance = document.querySelector('.CodeMirror').CodeMirror; instance.setValue(JSON.stringify([{ foo: 'bar' }])); await settled(); assert.dom('[data-test-error]').includesText('Vault expects data to be formatted as an JSON object'); diff --git a/ui/tests/pages/components/form-field.js b/ui/tests/pages/components/form-field.js index b2d52db44..0fb0f43ff 100644 --- a/ui/tests/pages/components/form-field.js +++ b/ui/tests/pages/components/form-field.js @@ -15,7 +15,7 @@ export default { hasSearchSelect: isPresent('[data-test-component=search-select]'), hasTextFile: isPresent('[data-test-component=text-file]'), hasTTLPicker: isPresent('[data-test-toggle-input="Foo"]'), - hasJSONEditor: isPresent('[data-test-component=json-editor]'), + hasJSONEditor: isPresent('[data-test-component="code-mirror-modifier"]'), hasJSONClearButton: isPresent('[data-test-json-clear-button]'), hasSelect: isPresent('select'), hasInput: isPresent('input'), diff --git a/ui/tests/pages/components/json-editor.js b/ui/tests/pages/components/json-editor.js index c36de0292..1208110cb 100644 --- a/ui/tests/pages/components/json-editor.js +++ b/ui/tests/pages/components/json-editor.js @@ -1,8 +1,8 @@ -import { isPresent, isVisible, text } from 'ember-cli-page-object'; +import { isPresent, notHasClass, text } from 'ember-cli-page-object'; export default { title: text('[data-test-component=json-editor-title]'), hasToolbar: isPresent('[data-test-component=json-editor-toolbar]'), - hasJSONEditor: isPresent('[data-test-component=json-editor]'), - canEdit: isVisible('div.CodeMirror-gutters'), + hasJSONEditor: isPresent('[data-test-component="code-mirror-modifier"]'), + canEdit: notHasClass('readonly-codemirror'), }; diff --git a/ui/tests/pages/helpers/codemirror.js b/ui/tests/pages/helpers/codemirror.js deleted file mode 100644 index 2f63f60c4..000000000 --- a/ui/tests/pages/helpers/codemirror.js +++ /dev/null @@ -1,34 +0,0 @@ -import getCodeMirrorInstance from 'vault/tests/helpers/codemirror'; -// Like fillable, but for the CodeMirror editor -// -// Usage: fillIn: codeFillable('[data-test-editor]') -// Page.fillIn(code); -export function codeFillable(selector) { - return { - isDescriptor: true, - - get() { - return function (context, code) { - const cm = getCodeMirrorInstance(context, selector); - cm.setValue(code); - return this; - }; - }, - }; -} - -// Like text, but for the CodeMirror editor -// -// Usage: content: code('[data-test-editor]') -// Page.code(); // some = [ 'string', 'of', 'code' ] -export function code(selector) { - return { - isDescriptor: true, - get() { - return function (context) { - const cm = getCodeMirrorInstance(context, selector); - return cm.getValue(); - }; - }, - }; -} diff --git a/ui/tests/pages/secrets/backend/kv/edit-secret.js b/ui/tests/pages/secrets/backend/kv/edit-secret.js index 6b0d59c88..de7266ad0 100644 --- a/ui/tests/pages/secrets/backend/kv/edit-secret.js +++ b/ui/tests/pages/secrets/backend/kv/edit-secret.js @@ -1,6 +1,6 @@ import { Base } from '../create'; import { isPresent, clickable, visitable, create, fillable } from 'ember-cli-page-object'; -import { codeFillable } from 'vault/tests/pages/helpers/codemirror'; + export default create({ ...Base, path: fillable('[data-test-secret-path="true"]'), @@ -17,9 +17,6 @@ export default create({ hasMetadataFields: isPresent('[data-test-metadata-fields]'), maxVersion: fillable('[data-test-input="maxVersions"]'), startCreateSecret: clickable('[data-test-secret-create]'), - editor: { - fillIn: codeFillable('[data-test-component="json-editor"]'), - }, deleteSecret() { return this.deleteBtn().confirmBtn(); }, diff --git a/ui/tests/pages/secrets/backend/kv/show.js b/ui/tests/pages/secrets/backend/kv/show.js index 49caf8a50..101d55b6c 100644 --- a/ui/tests/pages/secrets/backend/kv/show.js +++ b/ui/tests/pages/secrets/backend/kv/show.js @@ -1,6 +1,5 @@ import { Base } from '../show'; import { create, clickable, collection, isPresent, text } from 'ember-cli-page-object'; -import { code } from 'vault/tests/pages/helpers/codemirror'; export default create({ ...Base, @@ -18,9 +17,7 @@ export default create({ editIsPresent: isPresent('[data-test-secret-edit]'), noReadIsPresent: isPresent('[data-test-write-without-read-empty-message]'), noReadMessage: text('data-test-empty-state-message'), - editor: { - content: code('[data-test-component="json-editor"]'), - }, + deleteSecret() { return this.deleteBtn().confirmBtn(); }, diff --git a/ui/yarn.lock b/ui/yarn.lock index 5613cda18..c5bef8056 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -7974,7 +7974,12 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codemirror@^5.47.0, codemirror@^5.58.2: +codemirror@^5.47.0: + version "5.65.2" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.2.tgz#5799a70cb3d706e10f60e267245e3a75205d3dd9" + integrity sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA== + +codemirror@^5.58.2: version "5.61.0" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.61.0.tgz#318e5b034a707207948b92ffc2862195e8fdb08e" integrity sha512-D3wYH90tYY1BsKlUe0oNj2JAhQ9TepkD51auk3N7q+4uz7A/cgJ5JsWHreT0PqieW1QhOuqxQ2reCXV1YXzecg== @@ -10222,7 +10227,7 @@ ember-cli-typescript@^3.0.0, ember-cli-typescript@^3.1.3, ember-cli-typescript@^ stagehand "^1.0.0" walk-sync "^2.0.0" -ember-cli-typescript@^4.1.0, ember-cli-typescript@^4.2.0: +ember-cli-typescript@^4.1.0, ember-cli-typescript@^4.2.0, ember-cli-typescript@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-4.2.1.tgz#54d08fc90318cc986f3ea562f93ce58a6cc4c24d" integrity sha512-0iKTZ+/wH6UB/VTWKvGuXlmwiE8HSIGcxHamwNhEC5x1mN3z8RfvsFZdQWYUzIWFN2Tek0gmepGRPTwWdBYl/A== @@ -10396,6 +10401,17 @@ ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1, ember-co fs-extra "^9.1.0" semver "^5.4.1" +ember-compatibility-helpers@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.6.tgz#603579ab2fb14be567ef944da3fc2d355f779cd8" + integrity sha512-2UBUa5SAuPg8/kRVaiOfTwlXdeVweal1zdNPibwItrhR0IvPrXpaqwJDlEZnWKEoB+h33V0JIfiWleSG6hGkkA== + dependencies: + babel-plugin-debug-macros "^0.2.0" + ember-cli-version-checker "^5.1.1" + find-up "^5.0.0" + fs-extra "^9.1.0" + semver "^5.4.1" + ember-composable-helpers@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ember-composable-helpers/-/ember-composable-helpers-4.5.0.tgz#94febbdf4348e64f45f7a6f993f326e32540a61e" @@ -10656,6 +10672,17 @@ ember-modifier@^2.1.0: ember-destroyable-polyfill "^2.0.2" ember-modifier-manager-polyfill "^1.2.0" +ember-modifier@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ember-modifier/-/ember-modifier-3.1.0.tgz#ba5b0941302accd787ed3dcfc8d20400b77ffc41" + integrity sha512-G5Lj9jVFsD2sVJcRNQfaGKG1p81wT4LGfClBhCuB4TgwP1NGJKdqI+Q8BW2MptONxQt/71UjjUH0YK7Gm9eahg== + dependencies: + ember-cli-babel "^7.26.6" + ember-cli-normalize-entity-name "^1.0.0" + ember-cli-string-utils "^1.1.0" + ember-cli-typescript "^4.2.1" + ember-compatibility-helpers "^1.2.5" + ember-native-dom-helpers@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/ember-native-dom-helpers/-/ember-native-dom-helpers-0.7.0.tgz#98a87c11a391cec5c12382a4857e59ea2fb4b00a"