Refactored `search` to return an array with results, implemented `addSearchResults`
This commit is contained in:
parent
939ad792d6
commit
37f2f77124
|
@ -36,13 +36,13 @@ export default class JSONNode extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONObject ({prop, data, search, options, events}) {
|
renderJSONObject ({prop, data, options, events}) {
|
||||||
const childCount = data.props.length
|
const childCount = data.props.length
|
||||||
const contents = [
|
const contents = [
|
||||||
h('div', {class: 'jsoneditor-node jsoneditor-object'}, [
|
h('div', {class: 'jsoneditor-node jsoneditor-object'}, [
|
||||||
this.renderExpandButton(),
|
this.renderExpandButton(),
|
||||||
this.renderActionMenuButton(),
|
this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, data, search, options),
|
this.renderProperty(prop, data, options),
|
||||||
this.renderReadonly(`{${childCount}}`, `Array containing ${childCount} items`),
|
this.renderReadonly(`{${childCount}}`, `Array containing ${childCount} items`),
|
||||||
this.renderError(data.error)
|
this.renderError(data.error)
|
||||||
])
|
])
|
||||||
|
@ -56,7 +56,6 @@ export default class JSONNode extends Component {
|
||||||
parent: this,
|
parent: this,
|
||||||
prop: prop.name,
|
prop: prop.name,
|
||||||
data: prop.value,
|
data: prop.value,
|
||||||
search: prop.search,
|
|
||||||
options,
|
options,
|
||||||
events
|
events
|
||||||
})
|
})
|
||||||
|
@ -74,13 +73,13 @@ export default class JSONNode extends Component {
|
||||||
return h('li', {}, contents)
|
return h('li', {}, contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONArray ({prop, data, search, options, events}) {
|
renderJSONArray ({prop, data, options, events}) {
|
||||||
const childCount = data.items.length
|
const childCount = data.items.length
|
||||||
const contents = [
|
const contents = [
|
||||||
h('div', {class: 'jsoneditor-node jsoneditor-array'}, [
|
h('div', {class: 'jsoneditor-node jsoneditor-array'}, [
|
||||||
this.renderExpandButton(),
|
this.renderExpandButton(),
|
||||||
this.renderActionMenuButton(),
|
this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, data, search, options),
|
this.renderProperty(prop, data, options),
|
||||||
this.renderReadonly(`[${childCount}]`, `Array containing ${childCount} items`),
|
this.renderReadonly(`[${childCount}]`, `Array containing ${childCount} items`),
|
||||||
this.renderError(data.error)
|
this.renderError(data.error)
|
||||||
])
|
])
|
||||||
|
@ -110,14 +109,14 @@ export default class JSONNode extends Component {
|
||||||
return h('li', {}, contents)
|
return h('li', {}, contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONValue ({prop, data, search, options}) {
|
renderJSONValue ({prop, data, options}) {
|
||||||
return h('li', {}, [
|
return h('li', {}, [
|
||||||
h('div', {class: 'jsoneditor-node'}, [
|
h('div', {class: 'jsoneditor-node'}, [
|
||||||
this.renderPlaceholder(),
|
this.renderPlaceholder(),
|
||||||
this.renderActionMenuButton(),
|
this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, data, search, options),
|
this.renderProperty(prop, data, options),
|
||||||
this.renderSeparator(),
|
this.renderSeparator(),
|
||||||
this.renderValue(data.value, data.search, options),
|
this.renderValue(data.value, data.searchValue, options),
|
||||||
this.renderError(data.error)
|
this.renderError(data.error)
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
@ -146,7 +145,7 @@ export default class JSONNode extends Component {
|
||||||
return h('div', {class: 'jsoneditor-readonly', title}, text)
|
return h('div', {class: 'jsoneditor-readonly', title}, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderProperty (prop, data, search, options) {
|
renderProperty (prop, data, options) {
|
||||||
if (prop === null) {
|
if (prop === null) {
|
||||||
// root node
|
// root node
|
||||||
const rootName = JSONNode.getRootName(data, options)
|
const rootName = JSONNode.getRootName(data, options)
|
||||||
|
@ -162,7 +161,7 @@ export default class JSONNode extends Component {
|
||||||
const editable = !isIndex && (!options.isPropertyEditable || options.isPropertyEditable(this.getPath()))
|
const editable = !isIndex && (!options.isPropertyEditable || options.isPropertyEditable(this.getPath()))
|
||||||
|
|
||||||
const emptyClassName = (prop.length === 0 ? ' jsoneditor-empty' : '')
|
const emptyClassName = (prop.length === 0 ? ' jsoneditor-empty' : '')
|
||||||
const searchClassName = search ? ' jsoneditor-highlight': '';
|
const searchClassName = data.searchProperty ? ' jsoneditor-highlight': '';
|
||||||
|
|
||||||
if (editable) {
|
if (editable) {
|
||||||
const escapedProp = escapeHTML(prop, options.escapeUnicode)
|
const escapedProp = escapeHTML(prop, options.escapeUnicode)
|
||||||
|
@ -186,7 +185,7 @@ export default class JSONNode extends Component {
|
||||||
return h('div', {class: 'jsoneditor-separator'}, ':')
|
return h('div', {class: 'jsoneditor-separator'}, ':')
|
||||||
}
|
}
|
||||||
|
|
||||||
renderValue (value, searchResult, options) {
|
renderValue (value, searchValue, options) {
|
||||||
const escapedValue = escapeHTML(value, options.escapeUnicode)
|
const escapedValue = escapeHTML(value, options.escapeUnicode)
|
||||||
const type = valueType (value)
|
const type = valueType (value)
|
||||||
const itsAnUrl = isUrl(value)
|
const itsAnUrl = isUrl(value)
|
||||||
|
@ -195,7 +194,7 @@ export default class JSONNode extends Component {
|
||||||
const editable = !options.isValueEditable || options.isValueEditable(this.getPath())
|
const editable = !options.isValueEditable || options.isValueEditable(this.getPath())
|
||||||
if (editable) {
|
if (editable) {
|
||||||
return h('div', {
|
return h('div', {
|
||||||
class: JSONNode.getValueClass(type, itsAnUrl, isEmpty, searchResult),
|
class: JSONNode.getValueClass(type, itsAnUrl, isEmpty, searchValue),
|
||||||
contentEditable: 'true',
|
contentEditable: 'true',
|
||||||
spellCheck: 'false',
|
spellCheck: 'false',
|
||||||
onBlur: this.handleChangeValue,
|
onBlur: this.handleChangeValue,
|
||||||
|
@ -286,17 +285,16 @@ export default class JSONNode extends Component {
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
* @param {boolean} isUrl
|
* @param {boolean} isUrl
|
||||||
* @param {boolean} isEmpty
|
* @param {boolean} isEmpty
|
||||||
* @param {boolean | 'selected'} [searchResult]
|
* @param {boolean} [searchValue]
|
||||||
* @return {string}
|
* @return {string}
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
static getValueClass (type, isUrl, isEmpty, searchResult) {
|
static getValueClass (type, isUrl, isEmpty, searchValue) {
|
||||||
return 'jsoneditor-value ' +
|
return 'jsoneditor-value ' +
|
||||||
'jsoneditor-' + type +
|
'jsoneditor-' + type +
|
||||||
(isUrl ? ' jsoneditor-url' : '') +
|
(isUrl ? ' jsoneditor-url' : '') +
|
||||||
(isEmpty ? ' jsoneditor-empty' : '') +
|
(isEmpty ? ' jsoneditor-empty' : '') +
|
||||||
(searchResult === 'selected' ? ' jsoneditor-highlight-primary' :
|
(searchValue ? ' jsoneditor-highlight' : '')
|
||||||
searchResult ? ' jsoneditor-highlight' : '')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { parseJSON } from '../utils/jsonUtils'
|
||||||
import { enrichSchemaError } from '../utils/schemaUtils'
|
import { enrichSchemaError } from '../utils/schemaUtils'
|
||||||
import {
|
import {
|
||||||
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
||||||
expand, addErrors, search
|
expand, addErrors, search, addSearchResults
|
||||||
} from '../jsonData'
|
} from '../jsonData'
|
||||||
import {
|
import {
|
||||||
duplicate, insert, append, remove,
|
duplicate, insert, append, remove,
|
||||||
|
@ -66,16 +66,19 @@ export default class TreeMode extends Component {
|
||||||
? JSONNodeForm
|
? JSONNodeForm
|
||||||
: JSONNode
|
: JSONNode
|
||||||
|
|
||||||
// enrich the data with JSON Schema errors and search results
|
// enrich the data with JSON Schema errors
|
||||||
let data = state.data
|
let data = state.data
|
||||||
const errors = this.getErrors()
|
const errors = this.getErrors()
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
data = addErrors(data, this.getErrors())
|
data = addErrors(data, this.getErrors())
|
||||||
}
|
}
|
||||||
if (this.state.search.text) {
|
|
||||||
data = search(data, this.state.search.text)
|
// enrich the data with search results
|
||||||
console.log('data', data)
|
const searchResults = this.state.search.text ? search(data, this.state.search.text) : null
|
||||||
|
if (searchResults) {
|
||||||
|
data = addSearchResults(data, searchResults)
|
||||||
}
|
}
|
||||||
|
// TODO: pass number of search results to search box in top menu
|
||||||
|
|
||||||
return h('div', {
|
return h('div', {
|
||||||
class: `jsoneditor jsoneditor-mode-${props.mode}`,
|
class: `jsoneditor jsoneditor-mode-${props.mode}`,
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default class Search extends Component {
|
||||||
// TODO: show number of search results left from the input box
|
// TODO: show number of search results left from the input box
|
||||||
// TODO: prev/next
|
// TODO: prev/next
|
||||||
// TODO: focus on search results
|
// TODO: focus on search results
|
||||||
// TODO: expand next search result if not expanded
|
// TODO: expand the focused search result if not expanded
|
||||||
|
|
||||||
return h('div', {class: 'jsoneditor-search'},
|
return h('div', {class: 'jsoneditor-search'},
|
||||||
h('input', {type: 'text', value: state.text, onInput: this.handleChange})
|
h('input', {type: 'text', value: state.text, onInput: this.handleChange})
|
||||||
|
|
122
src/jsonData.js
122
src/jsonData.js
|
@ -117,7 +117,7 @@ export function toDataPath (data, path) {
|
||||||
* @param {Array} patch A JSON patch
|
* @param {Array} patch A JSON patch
|
||||||
* @param {function(path: Path)} [expand] Optional function to determine
|
* @param {function(path: Path)} [expand] Optional function to determine
|
||||||
* what nodes must be expanded
|
* what nodes must be expanded
|
||||||
* @return {{data: JSONData, revert: Array.<Object>, error: Error | null}}
|
* @return {{data: JSONData, revert: Object[], error: Error | null}}
|
||||||
*/
|
*/
|
||||||
export function patchData (data, patch, expand = expandAll) {
|
export function patchData (data, patch, expand = expandAll) {
|
||||||
let updatedData = data
|
let updatedData = data
|
||||||
|
@ -486,7 +486,7 @@ export function expand (data, callback, expanded) {
|
||||||
* into the data
|
* into the data
|
||||||
*
|
*
|
||||||
* @param {JSONData} data
|
* @param {JSONData} data
|
||||||
* @param {Array.<JSONSchemaError>} errors
|
* @param {JSONSchemaError[]} errors
|
||||||
*/
|
*/
|
||||||
export function addErrors (data, errors) {
|
export function addErrors (data, errors) {
|
||||||
let updatedData = data
|
let updatedData = data
|
||||||
|
@ -507,38 +507,61 @@ export function addErrors (data, errors) {
|
||||||
*
|
*
|
||||||
* @param {JSONData} data
|
* @param {JSONData} data
|
||||||
* @param {string} text
|
* @param {string} text
|
||||||
* @return {JSONData} Returns an updated `data` object containing the search results
|
* @return {SearchResult[]} Returns a list with search results
|
||||||
*/
|
*/
|
||||||
// TODO: change search to return an array with paths, create a separate method addSearch similar to addErrors
|
|
||||||
export function search (data, text) {
|
export function search (data, text) {
|
||||||
return transform(data, function (value) {
|
let results = []
|
||||||
// search in values
|
|
||||||
if (value.type === 'value') {
|
|
||||||
if (containsCaseInsensitive(value.value, text)) {
|
|
||||||
return setIn(value, ['search'], true)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return deleteIn(value, ['search'])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// search object property names
|
traverse(data, function (value, path) {
|
||||||
if (value.type === 'Object') {
|
// search in values
|
||||||
let updatedProps = value.props
|
if (value.type === 'value') {
|
||||||
updatedProps.forEach((prop, index) => {
|
if (containsCaseInsensitive(value.value, text)) {
|
||||||
if (containsCaseInsensitive(prop.name, text)) {
|
results.push({
|
||||||
updatedProps = setIn(updatedProps, [index, 'search'], true)
|
dataPath: path,
|
||||||
|
value: true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
updatedProps = deleteIn(updatedProps, [index, 'search'])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return setIn(value, ['props'], updatedProps)
|
// search object property names
|
||||||
}
|
if (value.type === 'Object') {
|
||||||
|
value.props.forEach((prop) => {
|
||||||
return value
|
if (containsCaseInsensitive(prop.name, text)) {
|
||||||
|
results.push({
|
||||||
|
dataPath: path.concat(prop.name),
|
||||||
|
property: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge searchResults into the data
|
||||||
|
*
|
||||||
|
* @param {JSONData} data
|
||||||
|
* @param {SearchResult[]} searchResults
|
||||||
|
*/
|
||||||
|
export function addSearchResults (data, searchResults) {
|
||||||
|
let updatedData = data
|
||||||
|
|
||||||
|
if (searchResults) {
|
||||||
|
searchResults.forEach(function (searchResult) {
|
||||||
|
if (searchResult.value) {
|
||||||
|
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchValue')
|
||||||
|
updatedData = setIn(updatedData, dataPath, true)
|
||||||
|
}
|
||||||
|
if (searchResult.property) {
|
||||||
|
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchProperty')
|
||||||
|
updatedData = setIn(updatedData, dataPath, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedData
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -552,7 +575,7 @@ export function containsCaseInsensitive (text, search) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Recursively transform JSONData: a recursive "map" function
|
||||||
* @param {JSONData} data
|
* @param {JSONData} data
|
||||||
* @param {function(value: JSONData, path: Path, root: JSONData)} callback
|
* @param {function(value: JSONData, path: Path, root: JSONData)} callback
|
||||||
* @return {JSONData} Returns the transformed data
|
* @return {JSONData} Returns the transformed data
|
||||||
|
@ -600,12 +623,51 @@ function recurseTransform (value, path, root, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // type 'string' or 'value'
|
default: // type 'string' or 'value'
|
||||||
// don't do anything: a value can't be expanded, only arrays and objects can
|
// no childs to traverse
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatedValue
|
return updatedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively loop over a JSONData object: a recursive "forEach" function.
|
||||||
|
* @param {JSONData} data
|
||||||
|
* @param {function(value: JSONData, path: Path, root: JSONData)} callback
|
||||||
|
*/
|
||||||
|
export function traverse (data, callback) {
|
||||||
|
return recurseTraverse (data, [], data, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively traverse a JSONData object
|
||||||
|
* @param {JSONData} value
|
||||||
|
* @param {Path} path
|
||||||
|
* @param {JSONData | null} root The root object, object at path=[]
|
||||||
|
* @param {function(value: JSONData, path: Path, root: JSONData)} callback
|
||||||
|
*/
|
||||||
|
function recurseTraverse (value, path, root, callback) {
|
||||||
|
callback(value, path, root)
|
||||||
|
|
||||||
|
switch (value.type) {
|
||||||
|
case 'Array': {
|
||||||
|
value.items.forEach((item, index) => {
|
||||||
|
recurseTraverse(item, path.concat(String(index)), root, callback)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'Object': {
|
||||||
|
value.props.forEach((prop) => {
|
||||||
|
recurseTraverse(prop.value, path.concat(prop.name), root, callback)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
default: // type 'string' or 'value'
|
||||||
|
// no childs to traverse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether a path exists in the json data
|
* Test whether a path exists in the json data
|
||||||
* @param {JSONData} data
|
* @param {JSONData} data
|
||||||
|
|
|
@ -59,4 +59,11 @@
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* expand: function (path: Path)?
|
* expand: function (path: Path)?
|
||||||
* }} PatchOptions
|
* }} PatchOptions
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* dataPath: Path,
|
||||||
|
* property: boolean?,
|
||||||
|
* value: boolean?
|
||||||
|
* }} SearchResult
|
||||||
|
* // TODO: SearchResult.dataPath is an array, JSONSchemaError.dataPath is a string -> make this consistent
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import test from 'ava';
|
import test from 'ava';
|
||||||
import {
|
import {
|
||||||
jsonToData, dataToJson, patchData, pathExists, transform, search,
|
jsonToData, dataToJson, patchData, pathExists, transform, traverse,
|
||||||
parseJSONPointer, compileJSONPointer,
|
parseJSONPointer, compileJSONPointer,
|
||||||
expand, addErrors
|
expand, addErrors, search, addSearchResults
|
||||||
} from '../src/jsonData'
|
} from '../src/jsonData'
|
||||||
|
|
||||||
|
|
||||||
const JSON_EXAMPLE = {
|
const JSON_EXAMPLE = {
|
||||||
obj: {
|
obj: {
|
||||||
arr: [1,2, {a:3,b:4}]
|
arr: [1,2, {first:3,last:4}]
|
||||||
},
|
},
|
||||||
str: 'hello world',
|
str: 'hello world',
|
||||||
nill: null,
|
nill: null,
|
||||||
|
@ -44,14 +44,14 @@ const JSON_DATA_EXAMPLE = {
|
||||||
expanded: true,
|
expanded: true,
|
||||||
props: [
|
props: [
|
||||||
{
|
{
|
||||||
name: 'a',
|
name: 'first',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 3
|
value: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'b',
|
name: 'last',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 4
|
value: 4
|
||||||
|
@ -118,14 +118,14 @@ const JSON_DATA_EXAMPLE_COLLAPSED_1 = {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
props: [
|
props: [
|
||||||
{
|
{
|
||||||
name: 'a',
|
name: 'first',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 3
|
value: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'b',
|
name: 'last',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 4
|
value: 4
|
||||||
|
@ -192,14 +192,14 @@ const JSON_DATA_EXAMPLE_COLLAPSED_2 = {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
props: [
|
props: [
|
||||||
{
|
{
|
||||||
name: 'a',
|
name: 'first',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 3
|
value: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'b',
|
name: 'last',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 4
|
value: 4
|
||||||
|
@ -237,14 +237,13 @@ const JSON_DATA_EXAMPLE_COLLAPSED_2 = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// after search for 'O' (case insensitive)
|
// after search for 'L' (case insensitive)
|
||||||
const JSON_DATA_EXAMPLE_SEARCH_1 = {
|
const JSON_DATA_EXAMPLE_SEARCH_L = {
|
||||||
type: 'Object',
|
type: 'Object',
|
||||||
expanded: true,
|
expanded: true,
|
||||||
props: [
|
props: [
|
||||||
{
|
{
|
||||||
name: 'obj',
|
name: 'obj',
|
||||||
search: true,
|
|
||||||
value: {
|
value: {
|
||||||
type: 'Object',
|
type: 'Object',
|
||||||
expanded: true,
|
expanded: true,
|
||||||
|
@ -268,21 +267,22 @@ const JSON_DATA_EXAMPLE_SEARCH_1 = {
|
||||||
expanded: true,
|
expanded: true,
|
||||||
props: [
|
props: [
|
||||||
{
|
{
|
||||||
name: 'a',
|
name: 'first',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 3
|
value: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'b',
|
name: 'last',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 4
|
value: 4,
|
||||||
|
searchProperty: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,98 +294,25 @@ const JSON_DATA_EXAMPLE_SEARCH_1 = {
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 'hello world',
|
value: 'hello world',
|
||||||
search: true
|
searchValue: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'nill',
|
name: 'nill',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: null
|
value: null,
|
||||||
}
|
searchProperty: true,
|
||||||
},
|
searchValue: true
|
||||||
{
|
|
||||||
name: 'bool',
|
|
||||||
search: true,
|
|
||||||
value: {
|
|
||||||
type: 'value',
|
|
||||||
value: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// after search for '2'
|
|
||||||
const JSON_DATA_EXAMPLE_SEARCH_2 = {
|
|
||||||
type: 'Object',
|
|
||||||
expanded: true,
|
|
||||||
props: [
|
|
||||||
{
|
|
||||||
name: 'obj',
|
|
||||||
value: {
|
|
||||||
type: 'Object',
|
|
||||||
expanded: true,
|
|
||||||
props: [
|
|
||||||
{
|
|
||||||
name: 'arr',
|
|
||||||
value: {
|
|
||||||
type: 'Array',
|
|
||||||
expanded: true,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
type: 'value',
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'value',
|
|
||||||
value: 2,
|
|
||||||
search: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'Object',
|
|
||||||
expanded: true,
|
|
||||||
props: [
|
|
||||||
{
|
|
||||||
name: 'a',
|
|
||||||
value: {
|
|
||||||
type: 'value',
|
|
||||||
value: 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'b',
|
|
||||||
value: {
|
|
||||||
type: 'value',
|
|
||||||
value: 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'str',
|
|
||||||
value: {
|
|
||||||
type: 'value',
|
|
||||||
value: 'hello world'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'nill',
|
|
||||||
value: {
|
|
||||||
type: 'value',
|
|
||||||
value: null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'bool',
|
name: 'bool',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: false
|
value: false,
|
||||||
|
searchProperty: true,
|
||||||
|
searchValue: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -426,7 +353,7 @@ const JSON_DATA_SMALL = {
|
||||||
|
|
||||||
|
|
||||||
const JSON_SCHEMA_ERRORS = [
|
const JSON_SCHEMA_ERRORS = [
|
||||||
{dataPath: '/obj/arr/2/b', message: 'String expected'},
|
{dataPath: '/obj/arr/2/last', message: 'String expected'},
|
||||||
{dataPath: '/nill', message: 'Null expected'}
|
{dataPath: '/nill', message: 'Null expected'}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -459,14 +386,14 @@ const JSON_DATA_EXAMPLE_ERRORS = {
|
||||||
expanded: true,
|
expanded: true,
|
||||||
props: [
|
props: [
|
||||||
{
|
{
|
||||||
name: 'a',
|
name: 'first',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 3
|
value: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'b',
|
name: 'last',
|
||||||
value: {
|
value: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
value: 4,
|
value: 4,
|
||||||
|
@ -545,7 +472,7 @@ test('expand a callback should not change the object when nothing happens', t =>
|
||||||
})
|
})
|
||||||
|
|
||||||
test('pathExists', t => {
|
test('pathExists', t => {
|
||||||
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'arr', 2, 'a']), true)
|
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'arr', 2, 'first']), true)
|
||||||
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'foo']), false)
|
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'foo']), false)
|
||||||
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'foo', 'bar']), false)
|
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'foo', 'bar']), false)
|
||||||
t.is(pathExists(JSON_DATA_EXAMPLE, []), true)
|
t.is(pathExists(JSON_DATA_EXAMPLE, []), true)
|
||||||
|
@ -931,7 +858,7 @@ test('transform', t => {
|
||||||
|
|
||||||
let log = []
|
let log = []
|
||||||
const transformed = transform(JSON_DATA_SMALL, function (value, path, root) {
|
const transformed = transform(JSON_DATA_SMALL, function (value, path, root) {
|
||||||
t.truthy(root === JSON_DATA_SMALL)
|
t.is(root, JSON_DATA_SMALL)
|
||||||
|
|
||||||
log.push([value, path, root])
|
log.push([value, path, root])
|
||||||
|
|
||||||
|
@ -958,20 +885,56 @@ test('transform', t => {
|
||||||
// t.deepEqual(log[index], EXPECTED_LOG[index], 'should have equal log at index ' + index )
|
// t.deepEqual(log[index], EXPECTED_LOG[index], 'should have equal log at index ' + index )
|
||||||
// })
|
// })
|
||||||
t.deepEqual(log, EXPECTED_LOG)
|
t.deepEqual(log, EXPECTED_LOG)
|
||||||
t.truthy(transformed !== JSON_DATA_SMALL)
|
t.not(transformed, JSON_DATA_SMALL)
|
||||||
t.truthy(transformed.props[0].value !== JSON_DATA_SMALL.props[0].value)
|
t.not(transformed.props[0].value, JSON_DATA_SMALL.props[0].value)
|
||||||
t.truthy(transformed.props[0].value.props[0].value !== JSON_DATA_SMALL.props[0].value.props[0].value)
|
t.not(transformed.props[0].value.props[0].value, JSON_DATA_SMALL.props[0].value.props[0].value)
|
||||||
t.truthy(JSON_DATA_SMALL.props[1].value === JSON_DATA_SMALL.props[1].value)
|
t.is(transformed.props[1].value, JSON_DATA_SMALL.props[1].value)
|
||||||
t.truthy(JSON_DATA_SMALL.props[1].value.items[0] === JSON_DATA_SMALL.props[1].value.items[0])
|
t.is(transformed.props[1].value.items[0], JSON_DATA_SMALL.props[1].value.items[0])
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('traverse', t => {
|
||||||
|
// {obj: {a: 2}, arr: [3]}
|
||||||
|
|
||||||
|
let log = []
|
||||||
|
const returnValue = traverse(JSON_DATA_SMALL, function (value, path, root) {
|
||||||
|
t.is(root, JSON_DATA_SMALL)
|
||||||
|
|
||||||
|
log.push([value, path, root])
|
||||||
|
})
|
||||||
|
|
||||||
|
t.is(returnValue, undefined)
|
||||||
|
|
||||||
|
const EXPECTED_LOG = [
|
||||||
|
[JSON_DATA_SMALL, [], JSON_DATA_SMALL],
|
||||||
|
[JSON_DATA_SMALL.props[0].value, ['obj'], JSON_DATA_SMALL],
|
||||||
|
[JSON_DATA_SMALL.props[0].value.props[0].value, ['obj', 'a'], JSON_DATA_SMALL],
|
||||||
|
[JSON_DATA_SMALL.props[1].value, ['arr'], JSON_DATA_SMALL],
|
||||||
|
[JSON_DATA_SMALL.props[1].value.items[0], ['arr', '0'], JSON_DATA_SMALL],
|
||||||
|
]
|
||||||
|
|
||||||
|
// log.forEach((row, index) => {
|
||||||
|
// t.deepEqual(log[index], EXPECTED_LOG[index], 'should have equal log at index ' + index )
|
||||||
|
// })
|
||||||
|
t.deepEqual(log, EXPECTED_LOG)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
test('search', t => {
|
test('search', t => {
|
||||||
const result1 = search(JSON_DATA_EXAMPLE, 'O')
|
const searchResults = search(JSON_DATA_EXAMPLE, 'L')
|
||||||
t.deepEqual(result1, JSON_DATA_EXAMPLE_SEARCH_1)
|
// console.log(searchResults)
|
||||||
|
|
||||||
// search for something else. Should clean up earlier search results
|
t.deepEqual(searchResults, [
|
||||||
const result2 = search(result1, '2')
|
{dataPath: ['nill'], property: true},
|
||||||
t.deepEqual(result2, JSON_DATA_EXAMPLE_SEARCH_2)
|
{dataPath: ['bool'], property: true},
|
||||||
|
{dataPath: ['obj', 'arr', '2', 'last'], property: true},
|
||||||
|
{dataPath: ['str'], value: true},
|
||||||
|
{dataPath: ['nill'], value: true},
|
||||||
|
{dataPath: ['bool'], value: true}
|
||||||
|
])
|
||||||
|
|
||||||
|
const updatedData = addSearchResults(JSON_DATA_EXAMPLE, searchResults)
|
||||||
|
// console.log(JSON.stringify(updatedData, null, 2))
|
||||||
|
|
||||||
|
t.deepEqual(updatedData, JSON_DATA_EXAMPLE_SEARCH_L)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue