Fix many small issues in the UI

This commit is contained in:
jos 2017-12-16 14:13:52 +01:00
parent 7064578b31
commit e979e0f016
7 changed files with 126 additions and 110 deletions

View File

@ -27,7 +27,7 @@ export function changeValue (eson, path, value) {
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: value, value: value,
jsoneditor: { jsoneditor: {
type: oldDataValue.type type: oldDataValue[META].type
} }
}] }]
} }
@ -102,14 +102,14 @@ export function duplicate (eson, selection) {
const { maxIndex } = findSelectionIndices(root, rootPath, selection) const { maxIndex } = findSelectionIndices(root, rootPath, selection)
const paths = pathsFromSelection(eson, selection) const paths = pathsFromSelection(eson, selection)
if (root.type === 'Array') { if (root[META].type === 'Array') {
return paths.map((path, offset) => ({ return paths.map((path, offset) => ({
op: 'copy', op: 'copy',
from: compileJSONPointer(path), from: compileJSONPointer(path),
path: compileJSONPointer(rootPath.concat(maxIndex + offset)) path: compileJSONPointer(rootPath.concat(maxIndex + offset))
})) }))
} }
else { // object.type === 'Object' else { // root[META].type === 'Object'
const before = root[META].props[maxIndex] || null const before = root[META].props[maxIndex] || null
return paths.map(path => { return paths.map(path => {
@ -144,7 +144,7 @@ export function insertBefore (eson, path, values) { // TODO: find a better name
const parentPath = initial(path) const parentPath = initial(path)
const parent = getIn(eson, parentPath) const parent = getIn(eson, parentPath)
if (parent.type === 'Array') { if (parent[META].type === 'Array') {
const startIndex = parseInt(last(path)) const startIndex = parseInt(last(path))
return values.map((entry, offset) => ({ return values.map((entry, offset) => ({
op: 'add', op: 'add',
@ -155,7 +155,7 @@ export function insertBefore (eson, path, values) { // TODO: find a better name
} }
})) }))
} }
else { // object.type === 'Object' else { // parent[META].type === 'Object'
const before = last(path) const before = last(path)
return values.map(entry => { return values.map(entry => {
const newProp = findUniqueName(entry.name, parent[META].props) const newProp = findUniqueName(entry.name, parent[META].props)
@ -189,7 +189,7 @@ export function replace (eson, selection, values) { // TODO: find a better name
const root = getIn(eson, rootPath) const root = getIn(eson, rootPath)
const { minIndex, maxIndex } = findSelectionIndices(root, rootPath, selection) const { minIndex, maxIndex } = findSelectionIndices(root, rootPath, selection)
if (root.type === 'Array') { if (root[META].type === 'Array') {
const removeActions = removeAll(pathsFromSelection(eson, selection)) const removeActions = removeAll(pathsFromSelection(eson, selection))
const insertActions = values.map((entry, offset) => ({ const insertActions = values.map((entry, offset) => ({
op: 'add', op: 'add',
@ -202,7 +202,7 @@ export function replace (eson, selection, values) { // TODO: find a better name
return removeActions.concat(insertActions) return removeActions.concat(insertActions)
} }
else { // object.type === 'Object' else { // root[META].type === 'Object'
const before = root[META].props[maxIndex] || null const before = root[META].props[maxIndex] || null
const removeActions = removeAll(pathsFromSelection(eson, selection)) const removeActions = removeAll(pathsFromSelection(eson, selection))
@ -241,7 +241,7 @@ export function append (eson, parentPath, type) {
const parent = getIn(eson, parentPath) const parent = getIn(eson, parentPath)
const value = createEntry(type) const value = createEntry(type)
if (parent.type === 'Array') { if (parent[META].type === 'Array') {
return [{ return [{
op: 'add', op: 'add',
path: compileJSONPointer(parentPath.concat('-')), path: compileJSONPointer(parentPath.concat('-')),
@ -251,7 +251,7 @@ export function append (eson, parentPath, type) {
} }
}] }]
} }
else { // object.type === 'Object' else { // parent[META].type === 'Object'
const newProp = findUniqueName('', parent[META].props) const newProp = findUniqueName('', parent[META].props)
return [{ return [{
@ -306,11 +306,11 @@ export function sort (eson, path, order = null) {
const compare = order === 'desc' ? compareDesc : compareAsc const compare = order === 'desc' ? compareDesc : compareAsc
const object = getIn(eson, path) const object = getIn(eson, path)
if (object.type === 'Array') { if (object[META].type === 'Array') {
const orderedItems = object.slice() const orderedItems = cloneWithSymbols(object)
// order the items by value // order the items by value
orderedItems.sort((a, b) => compare(a.value, b.value)) orderedItems.sort((a, b) => compare(a[META].value, b[META].value))
// when no order is provided, test whether ordering ascending // when no order is provided, test whether ordering ascending
// changed anything. If not, sort descending // changed anything. If not, sort descending
@ -318,16 +318,18 @@ export function sort (eson, path, order = null) {
orderedItems.reverse() orderedItems.reverse()
} }
// TODO: refactor into a set of move actions, so we keep eson state of the items
return [{ return [{
op: 'replace', op: 'replace',
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: orderedItems value: esonToJson(orderedItems)
}] }]
} }
else { // object.type === 'Object' else { // object[META].type === 'Object'
// order the properties by key // order the properties by key
const orderedProps = object[META].props.slice().sort((a, b) => compare(a.name, b.name)) const orderedProps = object[META].props.slice().sort(compare)
// when no order is provided, test whether ordering ascending // when no order is provided, test whether ordering ascending
// changed anything. If not, sort descending // changed anything. If not, sort descending
@ -338,12 +340,14 @@ export function sort (eson, path, order = null) {
const orderedObject = cloneWithSymbols(object) const orderedObject = cloneWithSymbols(object)
orderedObject[META] = setIn(object[META], ['props'], orderedProps) orderedObject[META] = setIn(object[META], ['props'], orderedProps)
// TODO: refactor into a set of move actions, so we keep eson state of the items
return [{ return [{
op: 'replace', op: 'replace',
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: esonToJson(orderedObject), value: esonToJson(orderedObject),
jsoneditor: { jsoneditor: {
order: orderedProps.map(prop => prop.name) order: orderedProps // TODO: order isn't used right now in patchEson.
} }
}] }]
} }

View File

@ -254,10 +254,11 @@ export default class JSONNode extends PureComponent {
} }
// TODO: simplify the method renderProperty // TODO: simplify the method renderProperty
renderProperty (prop?: ESONObjectProperty, index?: number, eson: ESON, options: {escapeUnicode: boolean, isPropertyEditable: (Path) => boolean}) { renderProperty (prop?: String, index?: number, eson: ESON, options: {escapeUnicode: boolean, isPropertyEditable: (Path) => boolean}) {
const isIndex = typeof index === 'number' const isIndex = typeof index === 'number'
const isProp = typeof prop === 'string'
if (!prop && !isIndex) { if (!isProp && !isIndex) {
// root node // root node
const rootName = JSONNode.getRootName(eson, options) const rootName = JSONNode.getRootName(eson, options)
@ -604,7 +605,7 @@ export default class JSONNode extends PureComponent {
/** @private */ /** @private */
handleChangeProperty = (event) => { handleChangeProperty = (event) => {
const parentPath = initial(this.props.eson[META].path) const parentPath = initial(this.props.eson[META].path)
const oldProp = this.props.prop.name const oldProp = this.props.prop
const newProp = unescapeHTML(getInnerText(event.target)) const newProp = unescapeHTML(getInnerText(event.target))
if (newProp !== oldProp) { if (newProp !== oldProp) {

View File

@ -111,7 +111,7 @@ export default class TreeMode extends Component {
findKeyBinding: this.handleFindKeyBinding findKeyBinding: this.handleFindKeyBinding
}, },
search: { searchResult: {
text: '', text: '',
matches: null, matches: null,
active: null // active search result active: null // active search result
@ -287,13 +287,13 @@ export default class TreeMode extends Component {
]) ])
} }
if (this.props.search !== false) { if (this.props.searchResult !== false) {
// option search is true or undefined // option search is true or undefined
items = items.concat([ items = items.concat([
h('div', {key: 'search', className: 'jsoneditor-menu-panel-right'}, h('div', {key: 'search', className: 'jsoneditor-menu-panel-right'},
h(Search, { h(Search, {
text: this.state.search.text, text: this.state.searchResult.text,
resultCount: this.state.search.matches ? this.state.search.matches.length : 0, resultCount: this.state.searchResult.matches ? this.state.searchResult.matches.length : 0,
onChange: this.handleSearch, onChange: this.handleSearch,
onNext: this.handleNext, onNext: this.handleNext,
onPrevious: this.handlePrevious, onPrevious: this.handlePrevious,
@ -584,20 +584,20 @@ export default class TreeMode extends Component {
handleSearch = (text) => { handleSearch = (text) => {
// FIXME: also apply search when eson is changed // FIXME: also apply search when eson is changed
const { eson, matches, active } = search(this.state.eson, text) const { eson, searchResult } = search(this.state.eson, text)
if (matches.length > 0) { if (searchResult.matches.length > 0) {
this.setState({ this.setState({
search: { text, active, matches }, eson: expandPath(eson, initial(searchResult.active.path)),
eson: expandPath(eson, initial(active.path)) searchResult
}) })
// scroll to active search result (on next tick, after this path has been expanded) // scroll to active search result (on next tick, after this path has been expanded)
setTimeout(() => this.scrollTo(active.path)) setTimeout(() => this.scrollTo(searchResult.active.path))
} }
else { else {
this.setState({ this.setState({
search: { text, active, matches }, eson,
eson searchResult
}) })
} }
} }
@ -610,22 +610,22 @@ export default class TreeMode extends Component {
handleNext = (event) => { handleNext = (event) => {
event.preventDefault() event.preventDefault()
if (this.state.search) { if (this.state.searchResult) {
const { eson, active } = nextSearchResult(this.state.eson, this.state.search.matches, this.state.search.active) const { eson, searchResult } = nextSearchResult(this.state.eson, this.state.searchResult)
this.setState({ this.setState({
search: setIn(this.state.search, ['active'], active), eson,
eson searchResult
}) })
// scroll to the active result (on next tick, after this path has been expanded) // scroll to the active result (on next tick, after this path has been expanded)
// TODO: this code is duplicate with handlePrevious, move into a separate function // TODO: this code is duplicate with handlePrevious, move into a separate function
setTimeout(() => { setTimeout(() => {
if (active && active.path) { if (searchResult.active && searchResult.active.path) {
this.scrollTo(active.path) this.scrollTo(searchResult.active.path)
if (!searchHasFocus()) { if (!searchHasFocus()) {
setSelection(this.refs.contents, active.path, active.area) setSelection(this.refs.contents, searchResult.active.path, searchResult.active.area)
} }
} }
}) })
@ -635,21 +635,21 @@ export default class TreeMode extends Component {
handlePrevious = (event) => { handlePrevious = (event) => {
event.preventDefault() event.preventDefault()
if (this.state.search) { if (this.state.searchResult) {
const { eson, active } = previousSearchResult(this.state.eson, this.state.search.matches, this.state.search.active) const { eson, searchResult } = previousSearchResult(this.state.eson, this.state.searchResult)
this.setState({ this.setState({
search: setIn(this.state.search, ['active'], active), eson,
eson searchResult
}) })
// scroll to the active result (on next tick, after this path has been expanded) // scroll to the active result (on next tick, after this path has been expanded)
setTimeout(() => { setTimeout(() => {
if (active && active.path) { if (searchResult.active && searchResult.active.path) {
this.scrollTo(active.path) this.scrollTo(searchResult.active.path)
if (!searchHasFocus()) { if (!searchHasFocus()) {
setSelection(this.refs.contents, active.path, active.area) setSelection(this.refs.contents, searchResult.active.path, searchResult.active.area)
} }
} }
}) })
@ -800,6 +800,7 @@ export default class TreeMode extends Component {
const result = patchEson(this.state.eson, historyItem.undo) const result = patchEson(this.state.eson, historyItem.undo)
// FIXME: apply search
this.setState({ this.setState({
eson: result.data, eson: result.data,
history, history,
@ -818,6 +819,7 @@ export default class TreeMode extends Component {
const result = patchEson(this.state.eson, historyItem.redo) const result = patchEson(this.state.eson, historyItem.redo)
// FIXME: apply search
this.setState({ this.setState({
eson: result.data, eson: result.data,
history, history,
@ -859,6 +861,7 @@ export default class TreeMode extends Component {
.concat(this.state.history.slice(this.state.historyIndex)) .concat(this.state.history.slice(this.state.historyIndex))
.slice(0, MAX_HISTORY_ITEMS) .slice(0, MAX_HISTORY_ITEMS)
// FIXME: apply search
this.setState({ this.setState({
eson, eson,
history, history,
@ -867,6 +870,7 @@ export default class TreeMode extends Component {
} }
else { else {
// update data and don't store history // update data and don't store history
// FIXME: apply search
this.setState({ eson }) this.setState({ eson })
} }
@ -887,6 +891,7 @@ export default class TreeMode extends Component {
// TODO: document option expand // TODO: document option expand
const expandCallback = this.props.expand || TreeMode.expandRoot const expandCallback = this.props.expand || TreeMode.expandRoot
// FIXME: apply search
this.setState({ this.setState({
json: json, json: json,
eson: expand(jsonToEson(json), expandCallback), eson: expand(jsonToEson(json), expandCallback),
@ -902,7 +907,8 @@ export default class TreeMode extends Component {
* @returns {Object | Array | string | number | boolean | null} json * @returns {Object | Array | string | number | boolean | null} json
*/ */
get () { get () {
return this.state.json // FIXME: keep a copy of the json file up to date with the internal eson
return esonToJson(this.state.eson)
} }
/** /**

View File

@ -15,13 +15,11 @@ import initial from 'lodash/initial'
import last from 'lodash/last' import last from 'lodash/last'
import type { import type {
ESON, ESONObject, ESONArrayItem, ESONPointer, Selection, ESONPath, ESON, ESONPointer, Selection,
Path, Path,
JSONPath, JSONType JSONPath, JSONType
} from './types' } from './types'
type RecurseCallback = (value: ESON, path: Path, root: ESON) => ESON
export const SELECTED = 1 export const SELECTED = 1
export const SELECTED_END = 2 export const SELECTED_END = 2
export const SELECTED_BEFORE = 3 export const SELECTED_BEFORE = 3
@ -245,7 +243,7 @@ export function cleanupMetaData(eson, field, ignorePaths = []) {
* Search some text in all properties and values * Search some text in all properties and values
* @param {ESON} eson * @param {ESON} eson
* @param {String} text Search text * @param {String} text Search text
* @return {{eson: ESON, matches: ESONPointer[], active: ESONPointer}} Returns search result: * @return {SearchResult} Returns search result:
* An updated eson object containing the search results, * An updated eson object containing the search results,
* and an array with the paths of all matches * and an array with the paths of all matches
*/ */
@ -281,7 +279,14 @@ export function search (eson, text) {
return updatedValue return updatedValue
}) })
return { eson: updatedEson, matches, active: matches[0] || null } return {
eson: updatedEson,
searchResult: {
text,
matches,
active: matches[0] || null
}
}
} }
/** /**
@ -290,26 +295,24 @@ export function search (eson, text) {
* and return the last result as next. * and return the last result as next.
* *
* @param {ESON} eson * @param {ESON} eson
* @param {ESONPointer[]} matches * @param {SearchResult} searchResult
* @param {ESONPointer} active * @return {{eson: ESON, searchResult: SearchResult}}
* @return {{eson: ESON, matches: ESONPointer[], active: ESONPointer}}
*/ */
export function previousSearchResult (eson, matches, active) { export function previousSearchResult (eson, searchResult) {
if (matches.length === 0) { if (searchResult.matches.length === 0) {
return { eson, matches, active } return { eson, searchResult }
} }
const index = matches.findIndex(searchResult => isEqual(searchResult, active)) const index = searchResult.matches.findIndex(match => isEqual(match, searchResult.active))
const previous = (index !== -1) const previous = (index !== -1)
? index > 0 ? index > 0
? matches[index - 1] ? searchResult.matches[index - 1]
: last(matches) : last(searchResult.matches)
: matches[0] : searchResult.matches[0]
return { return {
eson: setSearchStatus(setSearchStatus(eson, active, 'normal'), previous, 'active'), eson: setSearchStatus(setSearchStatus(eson, searchResult.active, 'normal'), previous, 'active'),
matches, searchResult: Object.assign({}, searchResult, { active: previous})
active: previous
} }
} }
@ -319,26 +322,24 @@ export function previousSearchResult (eson, matches, active) {
* and return the first result as next. * and return the first result as next.
* *
* @param {ESON} eson * @param {ESON} eson
* @param {ESONPointer[]} matches * @param {SearchResult} searchResult
* @param {ESONPointer} active * @return {{eson: ESON, searchResult: SearchResult}}
* @return {{eson: ESON, matches: ESONPointer[], active: ESONPointer}}
*/ */
export function nextSearchResult (eson, matches, active) { export function nextSearchResult (eson, searchResult) {
if (isEmpty(matches)) { if (isEmpty(searchResult.matches)) {
return { eson, matches, active } return { eson, searchResult }
} }
const index = matches.findIndex(match => isEqual(match, active)) const index = searchResult.matches.findIndex(match => isEqual(match, searchResult.active))
const next = (index !== -1) const next = (index !== -1)
? index < matches.length - 1 ? index < searchResult.matches.length - 1
? matches[index + 1] ? searchResult.matches[index + 1]
: matches[0] : searchResult.matches[0]
: matches[0] : searchResult.matches[0]
return { return {
eson: setSearchStatus(setSearchStatus(eson, active, 'normal'), next, 'active'), eson: setSearchStatus(setSearchStatus(eson, searchResult.active, 'normal'), next, 'active'),
matches, searchResult: Object.assign({}, searchResult, { active: next})
active: next
} }
} }
@ -463,7 +464,7 @@ export function pathsFromSelection (eson, selection: Selection): JSONPath[] {
if (root[META].type === 'Object') { if (root[META].type === 'Object') {
return times(maxIndex - minIndex, i => rootPath.concat(root[META].props[i + minIndex])) return times(maxIndex - minIndex, i => rootPath.concat(root[META].props[i + minIndex]))
} }
else { // root.type === 'Array' else { // root[META].type === 'Array'
return times(maxIndex - minIndex, i => rootPath.concat(String(i + minIndex))) return times(maxIndex - minIndex, i => rootPath.concat(String(i + minIndex)))
} }
} }
@ -477,7 +478,7 @@ export function pathsFromSelection (eson, selection: Selection): JSONPath[] {
export function contentsFromPaths (data: ESON, paths: JSONPath[]) { export function contentsFromPaths (data: ESON, paths: JSONPath[]) {
return paths.map(path => { return paths.map(path => {
return { return {
name: getIn(data, last(path)), name: last(path),
value: esonToJson(getIn(data, path)) value: esonToJson(getIn(data, path))
// FIXME: also store the type and expanded state // FIXME: also store the type and expanded state
} }
@ -544,7 +545,7 @@ export function pathExists (eson, path) {
// index of an array // index of an array
return pathExists(eson[parseInt(path[0])], path.slice(1)) return pathExists(eson[parseInt(path[0])], path.slice(1))
} }
else { // eson.type === 'Object' else { // Object
// object property. find the index of this property // object property. find the index of this property
return pathExists(eson[path[0]], path.slice(1)) return pathExists(eson[path[0]], path.slice(1))
} }

View File

@ -177,7 +177,7 @@ export function remove (data, path) {
}] }]
} }
} }
else { // object.type === 'Object' else { // parent[META].type === 'Object'
const prop = last(pathArray) const prop = last(pathArray)
const index = parent[META].props.indexOf(prop) const index = parent[META].props.indexOf(prop)
const nextProp = parent[META].props[index + 1] || null const nextProp = parent[META].props[index + 1] || null
@ -221,7 +221,7 @@ export function add (data, path, value, options) {
if (parent[META].type === 'Array') { if (parent[META].type === 'Array') {
updatedEson = updatePaths(insertAt(data, resolvedPath, value)) updatedEson = updatePaths(insertAt(data, resolvedPath, value))
} }
else { // parent.type === 'Object' else { // parent[META].type === 'Object'
updatedEson = updateIn(data, parentPath, (parent) => { updatedEson = updateIn(data, parentPath, (parent) => {
const oldValue = getIn(data, pathArray) const oldValue = getIn(data, pathArray)
const props = parent[META].props const props = parent[META].props

View File

@ -22,6 +22,8 @@
* *
* @typedef {string[]} Path * @typedef {string[]} Path
* *
* @typedef {{matches: ESONPointer[], active: ESONPointer, text: String}} SearchResult
*
*/ */
// FIXME: redefine all ESON related types // FIXME: redefine all ESON related types

View File

@ -1,3 +1,5 @@
'use strict'
import { readFileSync } from 'fs' import { readFileSync } from 'fs'
import test from 'ava' import test from 'ava'
import { setIn, getIn, deleteIn } from '../src/utils/immutabilityHelpers' import { setIn, getIn, deleteIn } from '../src/utils/immutabilityHelpers'
@ -243,10 +245,10 @@ test('search', t => {
"nill": null, "nill": null,
"bool": false "bool": false
}) })
const searchResult = search(eson, 'L') const result = search(eson, 'L')
const esonWithSearch = searchResult.eson const esonWithSearch = result.eson
const matches = searchResult.matches const matches = result.searchResult.matches
const active = searchResult.active const active = result.searchResult.active
t.deepEqual(matches, [ t.deepEqual(matches, [
{path: ['obj', 'arr', '2', 'last'], area: 'property'}, {path: ['obj', 'arr', '2', 'last'], area: 'property'},
@ -278,33 +280,33 @@ test('nextSearchResult', t => {
"nill": null, "nill": null,
"bool": false "bool": false
}) })
const searchResult = search(eson, 'A') const first = search(eson, 'A')
t.deepEqual(searchResult.matches, [ t.deepEqual(first.searchResult.matches, [
{path: ['obj', 'arr'], area: 'property'}, {path: ['obj', 'arr'], area: 'property'},
{path: ['obj', 'arr', '2', 'last'], area: 'property'}, {path: ['obj', 'arr', '2', 'last'], area: 'property'},
{path: ['bool'], area: 'value'} {path: ['bool'], area: 'value'}
]) ])
t.deepEqual(searchResult.active, {path: ['obj', 'arr'], area: 'property'}) t.deepEqual(first.searchResult.active, {path: ['obj', 'arr'], area: 'property'})
t.is(getIn(searchResult.eson, ['obj', 'arr', META, 'searchProperty']), 'active') t.is(getIn(first.eson, ['obj', 'arr', META, 'searchProperty']), 'active')
t.is(getIn(searchResult.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal') t.is(getIn(first.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal')
t.is(getIn(searchResult.eson, ['bool', META, 'searchValue']), 'normal') t.is(getIn(first.eson, ['bool', META, 'searchValue']), 'normal')
const second = nextSearchResult(searchResult.eson, searchResult.matches, searchResult.active) const second = nextSearchResult(first.eson, first.searchResult)
t.deepEqual(second.active, {path: ['obj', 'arr', '2', 'last'], area: 'property'}) t.deepEqual(second.searchResult.active, {path: ['obj', 'arr', '2', 'last'], area: 'property'})
t.is(getIn(second.eson, ['obj', 'arr', META, 'searchProperty']), 'normal') t.is(getIn(second.eson, ['obj', 'arr', META, 'searchProperty']), 'normal')
t.is(getIn(second.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'active') t.is(getIn(second.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'active')
t.is(getIn(second.eson, ['bool', META, 'searchValue']), 'normal') t.is(getIn(second.eson, ['bool', META, 'searchValue']), 'normal')
const third = nextSearchResult(second.eson, second.matches, second.active) const third = nextSearchResult(second.eson, second.searchResult)
t.deepEqual(third.active, {path: ['bool'], area: 'value'}) t.deepEqual(third.searchResult.active, {path: ['bool'], area: 'value'})
t.is(getIn(third.eson, ['obj', 'arr', META, 'searchProperty']), 'normal') t.is(getIn(third.eson, ['obj', 'arr', META, 'searchProperty']), 'normal')
t.is(getIn(third.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal') t.is(getIn(third.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal')
t.is(getIn(third.eson, ['bool', META, 'searchValue']), 'active') t.is(getIn(third.eson, ['bool', META, 'searchValue']), 'active')
const wrappedAround = nextSearchResult(third.eson, third.matches, third.active) const wrappedAround = nextSearchResult(third.eson, third.searchResult)
t.deepEqual(wrappedAround.active, {path: ['obj', 'arr'], area: 'property'}) t.deepEqual(wrappedAround.searchResult.active, {path: ['obj', 'arr'], area: 'property'})
t.is(getIn(wrappedAround.eson, ['obj', 'arr', META, 'searchProperty']), 'active') t.is(getIn(wrappedAround.eson, ['obj', 'arr', META, 'searchProperty']), 'active')
t.is(getIn(wrappedAround.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal') t.is(getIn(wrappedAround.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal')
t.is(getIn(wrappedAround.eson, ['bool', META, 'searchValue']), 'normal') t.is(getIn(wrappedAround.eson, ['bool', META, 'searchValue']), 'normal')
@ -319,33 +321,33 @@ test('previousSearchResult', t => {
"nill": null, "nill": null,
"bool": false "bool": false
}) })
const searchResult = search(eson, 'A') const init = search(eson, 'A')
t.deepEqual(searchResult.matches, [ t.deepEqual(init.searchResult.matches, [
{path: ['obj', 'arr'], area: 'property'}, {path: ['obj', 'arr'], area: 'property'},
{path: ['obj', 'arr', '2', 'last'], area: 'property'}, {path: ['obj', 'arr', '2', 'last'], area: 'property'},
{path: ['bool'], area: 'value'} {path: ['bool'], area: 'value'}
]) ])
t.deepEqual(searchResult.active, {path: ['obj', 'arr'], area: 'property'}) t.deepEqual(init.searchResult.active, {path: ['obj', 'arr'], area: 'property'})
t.is(getIn(searchResult.eson, ['obj', 'arr', META, 'searchProperty']), 'active') t.is(getIn(init.eson, ['obj', 'arr', META, 'searchProperty']), 'active')
t.is(getIn(searchResult.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal') t.is(getIn(init.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal')
t.is(getIn(searchResult.eson, ['bool', META, 'searchValue']), 'normal') t.is(getIn(init.eson, ['bool', META, 'searchValue']), 'normal')
const third = previousSearchResult(searchResult.eson, searchResult.matches, searchResult.active) const third = previousSearchResult(init.eson, init.searchResult)
t.deepEqual(third.active, {path: ['bool'], area: 'value'}) t.deepEqual(third.searchResult.active, {path: ['bool'], area: 'value'})
t.is(getIn(third.eson, ['obj', 'arr', META, 'searchProperty']), 'normal') t.is(getIn(third.eson, ['obj', 'arr', META, 'searchProperty']), 'normal')
t.is(getIn(third.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal') t.is(getIn(third.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal')
t.is(getIn(third.eson, ['bool', META, 'searchValue']), 'active') t.is(getIn(third.eson, ['bool', META, 'searchValue']), 'active')
const second = previousSearchResult(third.eson, third.matches, third.active) const second = previousSearchResult(third.eson, third.searchResult)
t.deepEqual(second.active, {path: ['obj', 'arr', '2', 'last'], area: 'property'}) t.deepEqual(second.searchResult.active, {path: ['obj', 'arr', '2', 'last'], area: 'property'})
t.is(getIn(second.eson, ['obj', 'arr', META, 'searchProperty']), 'normal') t.is(getIn(second.eson, ['obj', 'arr', META, 'searchProperty']), 'normal')
t.is(getIn(second.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'active') t.is(getIn(second.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'active')
t.is(getIn(second.eson, ['bool', META, 'searchValue']), 'normal') t.is(getIn(second.eson, ['bool', META, 'searchValue']), 'normal')
const first = previousSearchResult(second.eson, second.matches, second.active) const first = previousSearchResult(second.eson, second.searchResult)
t.deepEqual(first.active, {path: ['obj', 'arr'], area: 'property'}) t.deepEqual(first.searchResult.active, {path: ['obj', 'arr'], area: 'property'})
t.is(getIn(first.eson, ['obj', 'arr', META, 'searchProperty']), 'active') t.is(getIn(first.eson, ['obj', 'arr', META, 'searchProperty']), 'active')
t.is(getIn(first.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal') t.is(getIn(first.eson, ['obj', 'arr', '2', 'last', META, 'searchProperty']), 'normal')
t.is(getIn(first.eson, ['bool', META, 'searchValue']), 'normal') t.is(getIn(first.eson, ['bool', META, 'searchValue']), 'normal')