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
This commit is contained in:
parent
33888c3340
commit
0455d31b84
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
ui: Replaces the IvyCodemirror wrapper with a custom ember modifier.
|
||||
```
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
<JsonEditor
|
||||
@showToolbar={{false}}
|
||||
@value={{stringify this.content}}
|
||||
@options={{hash readOnly=true lineNumbers=false autoHeight=true gutters=false theme="hashi auto-height"}}
|
||||
@readOnly={{true}}
|
||||
@viewportMargin="Infinity"
|
||||
@gutters={{false}}
|
||||
@theme="hashi auto-height"
|
||||
/>
|
||||
<HoverCopyButton @copyValue={{stringify this.content}} />
|
||||
</div>
|
|
@ -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"
|
||||
/>
|
||||
<HoverCopyButton @copyValue={{stringify this.unwrapData}} />
|
||||
</div>
|
||||
|
|
|
@ -23,14 +23,22 @@
|
|||
</Toolbar>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<IvyCodemirror
|
||||
@data-test-component="json-editor"
|
||||
@value={{@value}}
|
||||
@options={{this.options}}
|
||||
@valueUpdated={{action "updateValue"}}
|
||||
@onFocusOut={{action "onFocus"}}
|
||||
/>
|
||||
<div
|
||||
{{code-mirror
|
||||
content=@value
|
||||
extraKeys=@extraKeys
|
||||
gutters=@gutters
|
||||
lineNumbers=(if @readOnly false true)
|
||||
mode=@mode
|
||||
readOnly=@readOnly
|
||||
theme=@theme
|
||||
viewportMarg=@viewportMargin
|
||||
onUpdate=this.onUpdate
|
||||
onFocus=this.onFocus
|
||||
}}
|
||||
class={{if @readOnly "readonly-codemirror"}}
|
||||
data-test-component="code-mirror-modifier"
|
||||
></div>
|
||||
|
||||
{{#if @helpText}}
|
||||
<div class="box is-shadowless is-fullwidth has-short-padding">
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<JsonEditor
|
||||
@title={{if @isV2 "Version Data" "Secret Data"}}
|
||||
@value={{@modelForData.dataAsJSONString}}
|
||||
@options={{hash readOnly=true}}
|
||||
@readOnly={{true}}
|
||||
/>
|
||||
</div>
|
||||
{{else}}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
{{#if (eq @unwrapActiveTab "data")}}
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<JsonEditor @title="Unwrapped Data" @value={{stringify @unwrap_data}} @options={{hash readOnly=true}} />
|
||||
<JsonEditor @title="Unwrapped Data" @value={{stringify @unwrap_data}} @readOnly={{true}} />
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<JsonEditor
|
||||
@title="Ciphertext"
|
||||
@valueUpdated={{action (mut @ciphertext)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="ciphertext"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
@title="Plaintext"
|
||||
@value={{@plaintext}}
|
||||
@valueUpdated={{action (mut @plaintext)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="plaintext"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -11,12 +11,7 @@
|
|||
<KeyVersionSelect @key={{@key}} @onVersionChange={{action (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<div class="field">
|
||||
<div id="input-control" class="control is-relative">
|
||||
<JsonEditor
|
||||
@title="Input"
|
||||
@valueUpdated={{action (mut @input)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
@data-test-transit-input="input"
|
||||
/>
|
||||
<JsonEditor @title="Input" @valueUpdated={{action (mut @input)}} @mode="ruby" @data-test-transit-input="input" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<KeyVersionSelect @key={{@key}} @onVersionChange={{action (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<div class="field">
|
||||
<div class="control is-expanded">
|
||||
<JsonEditor @title="Ciphertext" @valueUpdated={{action (mut @ciphertext)}} @options={{hash mode="ruby"}} />
|
||||
<JsonEditor @title="Ciphertext" @valueUpdated={{action (mut @ciphertext)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
{{#if @key.derived}}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
@title="Input"
|
||||
@value={{@input}}
|
||||
@valueUpdated={{action (mut @input)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="input"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
@title="Input"
|
||||
@value={{@input}}
|
||||
@valueUpdated={{action (mut @input)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="input"
|
||||
/>
|
||||
</div>
|
||||
|
@ -140,12 +140,7 @@
|
|||
{{#if (or (and @verification (eq @verification "HMAC")) @hmac)}}
|
||||
<div class="field is-flex-column is-flex-1">
|
||||
<div class="control is-flex-column is-flex-1">
|
||||
<JsonEditor
|
||||
@title="HMAC"
|
||||
@value={{@hmac}}
|
||||
@valueUpdated={{action (mut @hmac)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
/>
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{action (mut @hmac)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
|
@ -155,7 +150,7 @@
|
|||
@title="Signature"
|
||||
@value={{@signature}}
|
||||
@valueUpdated={{action (mut @signature)}}
|
||||
@options={{hash mode="ruby"}}
|
||||
@mode="ruby"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -165,7 +160,7 @@
|
|||
{{else}}
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{action (mut @hmac)}} @options={{hash mode="ruby"}} />
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{action (mut @hmac)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
|
|
|
@ -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}}
|
||||
</div>
|
||||
|
|
|
@ -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)}}
|
||||
/>
|
||||
<div class="box is-shadowless is-fullwidth has-short-padding">
|
||||
<p class="help-text has-text-grey-dark is-size-7">
|
||||
|
|
|
@ -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"
|
||||
/>
|
||||
</div>
|
||||
{{#if this.model.paths}}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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'
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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`<JsonEditor
|
||||
@value={{"{}"}}
|
||||
@title={{"Test title"}}
|
||||
@showToolbar={{true}}
|
||||
@readOnly={{true}}
|
||||
/>`);
|
||||
|
||||
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`<JsonEditor
|
||||
@value={{this.json_blob}}
|
||||
@readOnly={{false}}
|
||||
@valueUpdated={{this.valueUpdated}}
|
||||
@onFocusOut={{this.onFocusOut}}
|
||||
/>`);
|
||||
// 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`<JsonEditor
|
||||
@value={{this.json_blob}}
|
||||
@theme={{this.hashi-read-only-theme}}
|
||||
@readOnly={{true}}
|
||||
/>`);
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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'),
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
|
@ -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();
|
||||
},
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
|
|
31
ui/yarn.lock
31
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"
|
||||
|
|
Loading…
Reference in New Issue