-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from emartech/json-badge-feature
improvements for displaying JSON contents Ticket: SUITEDEV-25985
- Loading branch information
Showing
9 changed files
with
291 additions
and
26 deletions.
There are no files selected for viewing
13 changes: 13 additions & 0 deletions
13
src/renderer/components/secret-editor/json-badge/json-badge.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<e-tooltip | ||
:content="tooltipText" | ||
:disabled="!tooltipText" | ||
> | ||
<div | ||
:id="id" | ||
:class="`e-label e-label-${type}`" | ||
:style="style" | ||
@click="$emit('click')" | ||
> | ||
{{ content }} | ||
</div> | ||
</e-tooltip> |
17 changes: 17 additions & 0 deletions
17
src/renderer/components/secret-editor/json-badge/json-badge.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export default { | ||
name: 'json-badge', | ||
template: require('./json-badge.html'), | ||
props: { | ||
id: { type: String, default: '' }, | ||
type: { type: String, default: 'info' }, | ||
content: { type: String, default: 'JSON' }, | ||
tooltipText: { type: String | null, default: null } | ||
}, | ||
computed: { | ||
style() { | ||
return `position: absolute; top: 7px; right: 0; cursor: ${ | ||
this.type === 'info' ? 'pointer' : 'default' | ||
}`; | ||
} | ||
} | ||
}; |
15 changes: 9 additions & 6 deletions
15
src/renderer/components/secret-editor/secret-editor-textarea/secret-editor-textarea.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,18 @@ | ||
<div style="position: relative; padding-right: 70px;"> | ||
<div style="display: flex; position: relative; padding-right: 70px"> | ||
<textarea | ||
class="e-input e-input-textarea e-input-auto_height" | ||
rows="1" | ||
style="white-space: pre; resize: vertical;" | ||
style="white-space: pre; resize: vertical" | ||
:value="value" | ||
@input="changeSecretValue" | ||
wrap="soft" | ||
ref="textarea" | ||
/> | ||
<div class="e-label e-label-info" style="position: absolute; top: 7px; right: 0" | ||
v-if="isValidJson"> | ||
JSON | ||
</div> | ||
<json-badge | ||
v-if="isValidJson || isJsonWithErrors" | ||
id="badge" | ||
:type="isJsonWithErrors ? 'danger' : 'info'" | ||
@click="changeJsonState($event)" | ||
:tooltip-text="isJsonWithErrors ? getJsonParseErrorMessage : ''" | ||
/> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
src/renderer/components/secret-editor/secret-editor-textarea/secret-editor-textarea.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { mount } from '@vue/test-utils'; | ||
import SecretEditorTextarea from './secret-editor-textarea'; | ||
|
||
describe('SecretEditorTextarea', () => { | ||
describe('#changeJsonState', () => { | ||
it('should change JSON formatting from prettified to minified', () => { | ||
const wrapper = mount(SecretEditorTextarea, { | ||
propsData: { | ||
value: `[{\n | ||
"key": "value" | ||
\n}]` | ||
} | ||
}); | ||
|
||
wrapper.find('#badge').trigger('click'); | ||
|
||
const lines = _getNumberOfJsonStringLinesAfterSplittingByNewLine( | ||
wrapper.emitted().change[0][0] | ||
); | ||
expect(lines).to.eql(1); | ||
}); | ||
|
||
it('should change JSON formatting from minified to prettified', () => { | ||
const wrapper = mount(SecretEditorTextarea, { | ||
propsData: { value: '[{ "key": "value" }]' } | ||
}); | ||
|
||
wrapper.find('#badge').trigger('click'); | ||
|
||
const lines = _getNumberOfJsonStringLinesAfterSplittingByNewLine( | ||
wrapper.emitted().change[0][0] | ||
); | ||
expect(lines).to.greaterThan(1); | ||
}); | ||
|
||
it('should not change JSON formatting when value is not a valid JSON', () => { | ||
const value = '{ "key": "value", "key-without-value" }'; | ||
const wrapper = mount(SecretEditorTextarea, { | ||
propsData: { value } | ||
}); | ||
|
||
wrapper.find('#badge').trigger('click'); | ||
|
||
expect(wrapper.emitted()).to.eql({}); | ||
}); | ||
}); | ||
|
||
describe('#getJsonParseErrorMessage', () => { | ||
it('should return an error message when json string is invalid', () => { | ||
const invalidJsonString = '[{ "inv: alid }]'; | ||
const { vm } = mount(SecretEditorTextarea, { | ||
propsData: { value: invalidJsonString } | ||
}); | ||
expect(vm.getJsonParseErrorMessage).to.be.eql('Unexpected end of JSON input'); | ||
}); | ||
|
||
it('should return another error message when json string is invalid differently', () => { | ||
const invalidJsonString = '[{ inv: "alid" }]'; | ||
const { vm } = mount(SecretEditorTextarea, { | ||
propsData: { value: invalidJsonString } | ||
}); | ||
expect(vm.getJsonParseErrorMessage).to.be.eql('Unexpected token i in JSON at position 3'); | ||
}); | ||
|
||
it('should not return anything when json string is valid', () => { | ||
const validJsonString = '[{ "val": "id" }]'; | ||
const { vm } = mount(SecretEditorTextarea, { | ||
propsData: { value: validJsonString } | ||
}); | ||
expect(vm.getJsonParseErrorMessage).to.be.undefined; | ||
}); | ||
}); | ||
|
||
describe('#isJsonWithErrors', () => { | ||
it('should return true when input seems like a json but it contains errors', () => { | ||
const invalidJsonString = '[{ "val: "id }]'; | ||
const { vm } = mount(SecretEditorTextarea, { | ||
propsData: { value: invalidJsonString } | ||
}); | ||
expect(vm.isJsonWithErrors).to.be.true; | ||
}); | ||
|
||
it('should return true when input starts like a json but it is not a valid one', () => { | ||
const invalidJsonString = '[{ "not_json" }]'; | ||
const { vm } = mount(SecretEditorTextarea, { | ||
propsData: { value: invalidJsonString } | ||
}); | ||
expect(vm.isJsonWithErrors).to.be.true; | ||
}); | ||
|
||
it('should return false when input not starts like a valid json', () => { | ||
const invalidJsonString = '] "val": "id" ]'; | ||
const { vm } = mount(SecretEditorTextarea, { | ||
propsData: { value: invalidJsonString } | ||
}); | ||
expect(vm.isJsonWithErrors).to.be.false; | ||
}); | ||
}); | ||
}); | ||
|
||
const _getNumberOfJsonStringLinesAfterSplittingByNewLine = (jsonString) => { | ||
return jsonString.split('\n').length; | ||
}; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
export const isValidJson = (data) => { | ||
if (!_looksLikeJson(data)) return false; | ||
try { | ||
JSON.parse(data); | ||
return true; | ||
} catch (error) { | ||
return false; | ||
} | ||
}; | ||
|
||
export const isJsonWithErrors = (value) => { | ||
return _looksLikeJson(value) && !isValidJson(value); | ||
}; | ||
|
||
const _looksLikeJson = (value) => { | ||
const valueWithoutSpaces = value.toString().replace(/\s/g, ''); | ||
return ( | ||
(valueWithoutSpaces.startsWith('{') && valueWithoutSpaces.endsWith('}')) || | ||
(valueWithoutSpaces.startsWith('[') && valueWithoutSpaces.endsWith(']')) | ||
); | ||
}; | ||
|
||
export const minify = (json) => { | ||
return _formatJson(json); | ||
}; | ||
|
||
export const prettify = (json) => { | ||
return _formatJson(json, 2); | ||
}; | ||
|
||
const _formatJson = (json, spaces = 0) => { | ||
return JSON.stringify(JSON.parse(json), null, spaces); | ||
}; | ||
|
||
export const isJsonMinified = (jsonString) => { | ||
return jsonString.split('\n').length === 1; | ||
}; | ||
|
||
export const getParseErrorMessage = (value) => { | ||
try { | ||
JSON.parse(value); | ||
} catch (error) { | ||
return error.message; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { isValidJson, isJsonWithErrors, minify, prettify } from './json-helper'; | ||
|
||
describe('#isValidJson', () => { | ||
it('should return true when string is a valid JSON', () => { | ||
expect( | ||
isValidJson('{"addressee": "Luke", "message": "I am your father", "response": "Noooo!"}') | ||
).to.be.true; | ||
}); | ||
|
||
it('should return false when string is not a valid JSON', () => { | ||
expect(isValidJson('Noooo!')).to.be.false; | ||
}); | ||
it('should return false when input is a boolean value', () => { | ||
expect(isValidJson(true)).to.be.false; | ||
}); | ||
it('should return false when input is a boolean value as a string', () => { | ||
expect(isValidJson('false')).to.be.false; | ||
}); | ||
it('should return false when input is a number', () => { | ||
expect(isValidJson(1)).to.be.false; | ||
}); | ||
it('should return false when input is a number as string', () => { | ||
expect(isValidJson('1')).to.be.false; | ||
}); | ||
}); | ||
|
||
describe('#isJsonWithErrors', () => { | ||
it('should return true when input seems like a json but it contains errors', () => { | ||
const invalidJsonString = '[{ "val: "id }]'; | ||
|
||
const result = isJsonWithErrors(invalidJsonString); | ||
|
||
expect(result).to.be.true; | ||
}); | ||
|
||
it('should return true when input starts like a json but it is not a valid one', () => { | ||
const invalidJsonString = '[{ "not_json" }]'; | ||
|
||
const result = isJsonWithErrors(invalidJsonString); | ||
|
||
expect(result).to.be.true; | ||
}); | ||
|
||
it('should return false when input not starts like a valid json', () => { | ||
const invalidJsonString = '] "val": "id" ]'; | ||
|
||
const result = isJsonWithErrors(invalidJsonString); | ||
|
||
expect(result).to.be.false; | ||
}); | ||
}); | ||
|
||
describe('#minify and prettify', () => { | ||
it('should minify a stringified json', () => { | ||
const jsonString = `[{\n | ||
"key": "value" | ||
\n}]`; | ||
|
||
const minifiedJsonString = minify(jsonString); | ||
|
||
expect(_getNumberOfLines(jsonString)).to.eql(5); | ||
expect(_getNumberOfLines(minifiedJsonString)).to.eql(1); | ||
}); | ||
|
||
it('should prettify a minified json', () => { | ||
const jsonString = '[{"key":"value"}]'; | ||
|
||
const prettifiedJsonString = prettify(jsonString); | ||
|
||
expect(_getNumberOfLines(jsonString)).to.eql(1); | ||
expect(_getNumberOfLines(prettifiedJsonString)).to.eql(5); | ||
}); | ||
}); | ||
|
||
const _getNumberOfLines = (string) => { | ||
return string.split('\n').length; | ||
}; |