Skip to content

Commit

Permalink
Merge pull request #1536 from samjacobclift/entries-method-for-observ…
Browse files Browse the repository at this point in the history
…able-map

add entries method to observable object api [WIP]
  • Loading branch information
mweststrate authored May 22, 2018
2 parents ac79559 + d9d8ef4 commit 524045d
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 2 deletions.
19 changes: 19 additions & 0 deletions src/api/object-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ export function values(obj: any): string[] {
)
}

export function entries<K, T>(map: ObservableMap<K, T>): ReadonlyArray<T>
export function entries<T>(ar: IObservableArray<T>): ReadonlyArray<T>
export function entries<T = any>(obj: T): ReadonlyArray<any>
export function entries(obj: any): string[][] {
if (isObservableObject(obj)) {
return keys(obj).map(key => [key, obj[key]])
}
if (isObservableMap(obj)) {
return keys(obj).map(key => [key, obj.get(key)])
}
if (isObservableArray(obj)) {
return obj.map((key, index) => [index.toString(), key])
}
return fail(
process.env.NODE_ENV !== "production" &&
"'entries()' can only be used on observable objects, arrays and maps"
)
}

export function set<V>(obj: ObservableMap<string, V>, values: { [key: string]: V })
export function set<K, V>(obj: ObservableMap<K, V>, key: K, value: V)
export function set<T>(obj: IObservableArray<T>, index: number, value: T)
Expand Down
2 changes: 1 addition & 1 deletion src/mobx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export { autorun, reaction, IReactionOptions } from "./api/autorun"
export { when, IWhenOptions } from "./api/when"

export { action, isAction, runInAction, IActionFactory } from "./api/action"
export { keys, values, set, remove, has, get } from "./api/object-api"
export { keys, values, entries, set, remove, has, get } from "./api/object-api"
export { decorate } from "./api/decorate"
export { configure } from "./api/configure"
export { onBecomeObserved, onBecomeUnobserved } from "./api/become-observed"
Expand Down
1 change: 1 addition & 0 deletions test/base/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ test("correct api should be exposed", function() {
"transaction",
"untracked",
"values",
"entries",
"when"
].sort()
)
Expand Down
81 changes: 80 additions & 1 deletion test/base/object-api.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
const mobx = require("../../src/mobx")
const { keys, when, set, remove, values, reaction, observable, extendObservable, has, get } = mobx
const {
keys,
when,
set,
remove,
values,
entries,
reaction,
observable,
extendObservable,
has,
get
} = mobx

test("keys should be observable when extending", () => {
const todos = observable({})
Expand Down Expand Up @@ -66,6 +78,25 @@ test("object - set, remove, values are reactive", () => {
expect(snapshots).toEqual([[3], [3, 4], [5, 4], [5]])
})

test("object - set, remove, entries are reactive", () => {
const todos = observable({})
const snapshots = []

reaction(() => entries(todos), entries => snapshots.push(entries))

expect(has(todos, "x")).toBe(false)
expect(get(todos, "x")).toBe(undefined)
set(todos, "x", 3)
expect(has(todos, "x")).toBe(true)
expect(get(todos, "x")).toBe(3)
remove(todos, "y")
set(todos, "z", 4)
set(todos, "x", 5)
remove(todos, "z")

expect(snapshots).toEqual([[["x", 3]], [["x", 3], ["z", 4]], [["x", 5], ["z", 4]], [["x", 5]]])
})

test("object - set, remove, keys are reactive", () => {
const todos = observable({ a: 3 })
const snapshots = []
Expand Down Expand Up @@ -101,6 +132,25 @@ test("map - set, remove, values are reactive", () => {
expect(snapshots).toEqual([[3], [3, 4], [5, 4], [5]])
})

test("map - set, remove, entries are reactive", () => {
const todos = observable.map({})
const snapshots = []

reaction(() => entries(todos), entries => snapshots.push(entries))

expect(has(todos, "x")).toBe(false)
expect(get(todos, "x")).toBe(undefined)
set(todos, "x", 3)
expect(has(todos, "x")).toBe(true)
expect(get(todos, "x")).toBe(3)
remove(todos, "y")
set(todos, "z", 4)
set(todos, "x", 5)
remove(todos, "z")

expect(snapshots).toEqual([[["x", 3]], [["x", 3], ["z", 4]], [["x", 5], ["z", 4]], [["x", 5]]])
})

test("map - set, remove, keys are reactive", () => {
const todos = observable.map({ a: 3 })
const snapshots = []
Expand Down Expand Up @@ -145,6 +195,34 @@ test("array - set, remove, values are reactive", () => {
])
})

test("array - set, remove, entries are reactive", () => {
const todos = observable.array()
const snapshots = []

reaction(() => entries(todos), entries => snapshots.push(entries))

expect(has(todos, 0)).toBe(false)
expect(get(todos, 0)).toBe(undefined)
set(todos, 0, 2)
expect(has(todos, 0)).toBe(true)
expect(get(todos, 0)).toBe(2)

set(todos, "1", 4)
set(todos, 3, 4)
set(todos, 1, 3)
remove(todos, 2)
remove(todos, "0")

expect(snapshots).toEqual([
[["0", 2]],
[["0", 2], ["1", 4]],
[["0", 2], ["1", 4], ["2", undefined], ["3", 4]],
[["0", 2], ["1", 3], ["2", undefined], ["3", 4]],
[["0", 2], ["1", 3], ["2", 4]],
[["0", 3], ["1", 4]]
])
})

test("observe & intercept", () => {
let events = []
const todos = observable(
Expand Down Expand Up @@ -235,4 +313,5 @@ test("computed props are not considered part of collections", () => {
expect(get(x, "y")).toBe(undefined) // disputable?
expect(keys(x)).toEqual([])
expect(values(x)).toEqual([])
expect(entries(x)).toEqual([])
})

0 comments on commit 524045d

Please sign in to comment.