mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-18 18:38:08 -05:00
KVv2 json cursor jumps on "enter" (#27569)
* it works...but does it break everything else? * Update code-mirror.js * Update code-mirror.js * return to original * changelog * different approach to move onto parse at create and edit. it breaks things, hopefully fixed in next commits * use onBlur event on codemirrror * maybe? lets run the tests and find out * update comments * wip for conditional to only compare on kvv2 * remove onblur leftovers * missed two * clean up * test coverage * try catch logical operator instead * stringify helper and not native json stringify to maintain object shape * remove comment * Update json-editor.js return brackets do not want issues with backports * Update json-editor.js * Update json-editor.js * Test fix * maybe * more specific cursor test * json-editor test cleanup * Delete ui/testrun1.txt * Delete ui/testrun2.txt * remove non json test it doesn't test anything * update test and comment for how it's testing non-json content * test fix * put shape of json blob back: * send in original without parsing or stringify * welp friday things
This commit is contained in:
parent
ed94318ccd
commit
297f8cb3c3
5 changed files with 67 additions and 5 deletions
3
changelog/27569.txt
Normal file
3
changelog/27569.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
ui: Fix cursor jump on KVv2 json editor that would occur after pressing ENTER.
|
||||
```
|
||||
|
|
@ -7,6 +7,7 @@ import { action } from '@ember/object';
|
|||
import { bind } from '@ember/runloop';
|
||||
import codemirror from 'codemirror';
|
||||
import Modifier from 'ember-modifier';
|
||||
import { stringify } from 'core/helpers/stringify';
|
||||
|
||||
import 'codemirror/addon/edit/matchbrackets';
|
||||
import 'codemirror/addon/selection/active-line';
|
||||
|
|
@ -26,7 +27,19 @@ export default class CodeMirrorModifier extends Modifier {
|
|||
} else {
|
||||
// this hook also fires any time there is a change to tracked state
|
||||
this._editor.setOption('readOnly', namedArgs.readOnly);
|
||||
if (namedArgs.content && this._editor.getValue() !== namedArgs.content) {
|
||||
let value = this._editor.getValue();
|
||||
let content = namedArgs.content;
|
||||
if (!content) return;
|
||||
try {
|
||||
// First parse json to make white space and line breaks consistent between the two items,
|
||||
// then stringify so they can be compared.
|
||||
// We use the stringify helper so we do not flatten the json object
|
||||
value = stringify([JSON.parse(value)], {});
|
||||
content = stringify([JSON.parse(content)], {});
|
||||
} catch {
|
||||
// this catch will occur for non-json content when the mode is not javascript (e.g. ruby).
|
||||
}
|
||||
if (value !== content) {
|
||||
this._editor.setValue(namedArgs.content);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,16 @@
|
|||
/* eslint-disable no-useless-escape */
|
||||
import { module, test } from 'qunit';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { click, currentURL, fillIn, findAll, setupOnerror, typeIn, visit } from '@ember/test-helpers';
|
||||
import {
|
||||
click,
|
||||
currentURL,
|
||||
fillIn,
|
||||
findAll,
|
||||
setupOnerror,
|
||||
typeIn,
|
||||
visit,
|
||||
triggerKeyEvent,
|
||||
} from '@ember/test-helpers';
|
||||
import { setupApplicationTest } from 'vault/tests/helpers';
|
||||
import authPage from 'vault/tests/pages/auth';
|
||||
import {
|
||||
|
|
@ -24,6 +33,7 @@ import {
|
|||
} from 'vault/tests/helpers/kv/policy-generator';
|
||||
import { clearRecords, writeSecret, writeVersionedSecret } from 'vault/tests/helpers/kv/kv-run-commands';
|
||||
import { FORM, PAGE } from 'vault/tests/helpers/kv/kv-selectors';
|
||||
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
||||
import codemirror from 'vault/tests/helpers/codemirror';
|
||||
|
||||
/**
|
||||
|
|
@ -309,6 +319,19 @@ module('Acceptance | kv-v2 workflow | edge cases', function (hooks) {
|
|||
assert.false(codemirror().getValue().includes('*'), 'Values are not obscured on edit view');
|
||||
});
|
||||
|
||||
test('on enter the JSON editor cursor goes to the next line', async function (assert) {
|
||||
// see issue here: https://github.com/hashicorp/vault/issues/27524
|
||||
const predictedCursorPosition = JSON.stringify({ line: 3, ch: 0, sticky: null });
|
||||
await visit(`/vault/secrets/${this.backend}/kv/create`);
|
||||
await fillIn(FORM.inputByAttr('path'), 'json jump');
|
||||
|
||||
await click(FORM.toggleJson);
|
||||
codemirror().setCursor({ line: 2, ch: 1 });
|
||||
await triggerKeyEvent(GENERAL.codemirrorTextarea, 'keydown', 'Enter');
|
||||
const actualCursorPosition = JSON.stringify(codemirror().getCursor());
|
||||
assert.strictEqual(actualCursorPosition, predictedCursorPosition, 'the cursor stayed on the next line');
|
||||
});
|
||||
|
||||
test('viewing advanced secret data versions displays the correct version data', async function (assert) {
|
||||
assert.expect(2);
|
||||
const obscuredDataV1 = `{
|
||||
|
|
|
|||
|
|
@ -81,4 +81,6 @@ export const GENERAL = {
|
|||
cancelButton: '[data-test-cancel]',
|
||||
saveButton: '[data-test-save]',
|
||||
maskedInput: (name: string) => `[data-test-textarea="${name}"]`,
|
||||
codemirror: `[data-test-component="code-mirror-modifier"]`,
|
||||
codemirrorTextarea: `[data-test-component="code-mirror-modifier"] textarea`,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { create } from 'ember-cli-page-object';
|
||||
import { render, fillIn, find, waitUntil, click } from '@ember/test-helpers';
|
||||
import { render, fillIn, find, waitUntil, click, triggerKeyEvent } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import jsonEditor from '../../pages/components/json-editor';
|
||||
import sinon from 'sinon';
|
||||
|
|
@ -122,12 +122,33 @@ module('Integration | Component | json-editor', function (hooks) {
|
|||
assert.dom('.CodeMirror-code').hasText(`{ "test": "********"}`, 'shows data with obscured values');
|
||||
assert.dom('[data-test-toggle-input="revealValues"]').isNotChecked('reveal values toggle is unchecked');
|
||||
await click('[data-test-toggle-input="revealValues"]');
|
||||
assert.dom('.CodeMirror-code').hasText(JSON_BLOB, 'shows data with real values');
|
||||
// we are hardcoding the hasText comparison instead of using the JSON_BLOB because we no longer match passed content (ex: @value) to the tracked codemirror instance (ex: this._editor.getVale()) if there are line-breaks or whitespace differences.
|
||||
assert.dom('.CodeMirror-code').hasText(`{ "test": "test" }`, 'shows data with real values');
|
||||
assert.dom('[data-test-toggle-input="revealValues"]').isChecked('reveal values toggle is checked');
|
||||
// turn obscure back on to ensure readonly overrides reveal setting
|
||||
await click('[data-test-toggle-input="revealValues"]');
|
||||
this.set('readOnly', false);
|
||||
assert.dom('[data-test-toggle-input="revealValues"]').doesNotExist('reveal values toggle is hidden');
|
||||
assert.dom('.CodeMirror-code').hasText(JSON_BLOB, 'shows data with real values on edit mode');
|
||||
assert.dom('.CodeMirror-code').hasText(`{ "test": "test" }`, 'shows data with real values on edit mode');
|
||||
});
|
||||
|
||||
test('code-mirror modifier sets value correctly on non json object', async function (assert) {
|
||||
// this.value is a tracked property, so anytime it changes the modifier is called. We're testing non-json content by setting the mode to ruby and adding a comment
|
||||
this.value = null;
|
||||
await render(hbs`
|
||||
<JsonEditor
|
||||
@value={{this.value}}
|
||||
@mode="ruby"
|
||||
@valueUpdated={{fn (mut this.value)}}
|
||||
/>
|
||||
`);
|
||||
await fillIn('textarea', '#A comment');
|
||||
assert.strictEqual(this.value, '#A comment', 'value is set correctly');
|
||||
await triggerKeyEvent('textarea', 'keydown', 'Enter');
|
||||
assert.strictEqual(
|
||||
this.value,
|
||||
`#A comment\n`,
|
||||
'even after hitting enter the value is still set correctly'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue