Skip to content

Commit 1acd0b6

Browse files
committed
test(collections): Add mock + tests for simple collections
1 parent 9642e47 commit 1acd0b6

File tree

6 files changed

+245
-46
lines changed

6 files changed

+245
-46
lines changed

src/index.js

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
function createDoc (doc) {
2-
// defaults everything to false, so no need to set
3-
console.log('create', doc.data())
4-
return Object.defineProperty(doc.data(), 'id', {
5-
value: doc.id,
6-
})
7-
}
1+
import { createSnapshot } from './utils'
82

93
function bindCollection({
104
vm,
@@ -16,11 +10,11 @@ function bindCollection({
1610

1711
const change = {
1812
added: ({ newIndex, doc }) => {
19-
array.splice(newIndex, 0, createDoc(doc))
13+
array.splice(newIndex, 0, createSnapshot(doc))
2014
},
2115
modified: ({ oldIndex, newIndex, doc }) => {
2216
array.splice(oldIndex, 1)
23-
array.splice(newIndex, 0, createDoc(doc))
17+
array.splice(newIndex, 0, createSnapshot(doc))
2418
},
2519
removed: ({ oldIndex }) => {
2620
array.splice(oldIndex, 1)
@@ -46,11 +40,16 @@ function install (Vue, options) {
4640
const { firestore } = this.$options
4741
if (!firestore) return
4842
Object.keys(firestore).forEach(key => {
49-
bindCollection({
50-
vm: this,
51-
key,
52-
collection: firestore[key],
53-
})
43+
const ref = firestore[key]
44+
if (ref.add) {
45+
bindCollection({
46+
vm: this,
47+
key,
48+
collection: ref,
49+
})
50+
} else {
51+
// TODO
52+
}
5453
})
5554
}
5655
})

src/utils.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export function createSnapshot (doc) {
2+
// defaults everything to false, so no need to set
3+
return Object.defineProperty(doc.data(), 'id', {
4+
value: doc.id,
5+
})
6+
}

test/collection.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import test from 'ava'
2+
import Vuefire from '../src'
3+
import {
4+
createSnapshot
5+
} from '../src/utils'
6+
import {
7+
db,
8+
tick,
9+
Vue
10+
} from './helpers'
11+
12+
Vue.use(Vuefire)
13+
14+
test.beforeEach(async t => {
15+
t.context.collection = db.collection()
16+
t.context.vm = new Vue({
17+
render (h) {
18+
return h('ul', this.items.map(
19+
item => h('li', [item])
20+
))
21+
},
22+
data: () => ({ items: null }),
23+
firestore: {
24+
items: t.context.collection
25+
}
26+
}).$mount()
27+
await tick()
28+
})
29+
30+
test('initialise the array', t => {
31+
t.deepEqual(t.context.vm.items, [])
32+
})
33+
34+
test('add elements', async t => {
35+
await t.context.collection.add({ text: 'foo' })
36+
t.deepEqual(t.context.vm.items, [{ text: 'foo' }])
37+
await t.context.collection.add({ text: 'bar' })
38+
t.deepEqual(t.context.vm.items, [{ text: 'foo' }, { text: 'bar' }])
39+
})
40+
41+
test('delets items', async t => {
42+
await t.context.collection.add({ text: 'foo' })
43+
await t.context.collection.doc(t.context.vm.items[0].id).delete()
44+
t.deepEqual(t.context.vm.items, [])
45+
})
46+
47+
test('update items', async t => {
48+
const doc = await t.context.collection.add({ text: 'foo' })
49+
await doc.update({ text: 'bar' })
50+
t.deepEqual(t.context.vm.items[0], { text: 'bar' })
51+
})
52+
53+
test('add properties', async t => {
54+
const doc = await t.context.collection.add({ text: 'foo' })
55+
await doc.update({ other: 'bar' })
56+
t.deepEqual(t.context.vm.items[0], { text: 'foo', other: 'bar' })
57+
})

test/helpers/mock.js

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ DocumentSnapshot.prototype.data = function () {
44
return this._document
55
}
66

7-
let id = 0
8-
class Key {
7+
export { DocumentSnapshot }
8+
9+
const noop = _ => null
10+
11+
export let id = 0
12+
export class Key {
913
constructor () {
1014
this.id = id++
1115
}
@@ -17,22 +21,97 @@ class Key {
1721
}
1822
}
1923

20-
export const collection = {
21-
data: [],
24+
class DocumentReference {
25+
constructor ({ collection, id, data, index }) {
26+
this.collection = collection
27+
this.id = id
28+
this.data = data
29+
this.index = index
30+
}
31+
32+
async delete () {
33+
return this.collection._remove(this.id)
34+
}
35+
36+
async update (data) {
37+
Object.assign(this.data, data)
38+
return this.collection._modify(this.id, this.data)
39+
}
40+
}
41+
42+
class CollectionReference {
43+
constructor () {
44+
this.data = {}
45+
this.cb = this.onError = noop
46+
}
47+
2248
onSnapshot (cb, onError) {
2349
this.cb = cb
2450
this.onError = onError
25-
},
51+
}
2652

27-
add (item) {
28-
this.data.push(item)
53+
async add (data) {
54+
const id = new Key()
55+
this.data[id] = new DocumentReference({
56+
collection: this,
57+
id,
58+
data,
59+
index: Object.keys(this.data).length
60+
})
2961
this.cb({
3062
docChanges: [{
31-
doc: new DocumentSnapshot(null, new Key(), item), // TODO docsnapshot
32-
newIndex: this.data.length - 1,
33-
oldIndex: -1,
3463
type: 'added',
64+
doc: new DocumentSnapshot(null, id, data),
65+
newIndex: Object.keys(this.data).length,
66+
oldIndex: -1,
67+
}]
68+
})
69+
return this.data[id]
70+
}
71+
72+
doc (id) {
73+
id = id || new Key()
74+
return this.data[id] = this.data[id] || new DocumentReference({
75+
collection: this,
76+
id,
77+
data: {},
78+
index: Object.keys(this.data).length
79+
})
80+
}
81+
82+
async _remove (id) {
83+
const ref = this.data[id]
84+
delete this.data[id]
85+
this.cb({
86+
docChanges: [{
87+
doc: new DocumentSnapshot(null, id, ref.data),
88+
type: 'removed',
89+
}]
90+
})
91+
ref.collection = null
92+
ref.data = null
93+
}
94+
95+
async _modify (id, data) {
96+
this.cb({
97+
docChanges: [{
98+
type: 'modified',
99+
doc: new DocumentSnapshot(null, id, data),
100+
oldIndex: this.data[id].index,
101+
newIndex: this.data[id].index,
35102
}]
36103
})
104+
105+
}
106+
}
107+
108+
export const db = {
109+
db: {},
110+
n: 0,
111+
112+
collection (name) {
113+
// create a collection if no name provided
114+
name = name || `random__${this.n++}`
115+
return db[name] = db[name] || new CollectionReference()
37116
}
38117
}

test/index.js

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,54 @@
11
import test from 'ava'
22
import Vuefire from '../src'
3-
import { tick, Vue } from './helpers'
4-
import { collection } from './helpers'
3+
import {
4+
createSnapshot
5+
} from '../src/utils'
6+
import {
7+
db,
8+
tick,
9+
Vue
10+
} from './helpers'
511

612
Vue.use(Vuefire)
713

8-
const vm = new Vue({
9-
render (h) {
10-
return h('ul', this.items.map(
11-
item => h('li', [item])
12-
))
13-
},
14-
data: () => ({ items: [] }),
15-
firestore: {
16-
items: collection
17-
}
18-
}).$mount()
19-
20-
Vue.use(Vuefire)
21-
22-
test('foo', async t => {
14+
test.beforeEach(async t => {
15+
t.context.collection = db.collection()
16+
t.context.document = t.context.collection.doc()
17+
t.context.vm = new Vue({
18+
render (h) {
19+
return h('ul', this.items.map(
20+
item => h('li', [item])
21+
))
22+
},
23+
// purposely set items as null
24+
// but it's a good practice to set it to an empty array
25+
data: () => ({ items: null }),
26+
firestore: {
27+
items: t.context.collection,
28+
item: t.context.document
29+
}
30+
}).$mount()
2331
await tick()
24-
t.deepEqual(vm.items, [])
25-
t.pass()
2632
})
2733

28-
test('bar', async t => {
29-
const bar = Promise.resolve('bar')
34+
test('detects collections', async t => {
35+
await t.context.document.update({ foo: 'foo' })
36+
t.deepEqual(t.context.vm.item, { foo: 'foo' })
37+
})
38+
39+
test('detects documents', async t => {
40+
await t.context.collection.add({ foo: 'foo' })
41+
t.deepEqual(t.context.vm.items, [{ foo: 'foo' }])
42+
})
3043

31-
t.is(await bar, 'bar')
44+
test('does nothing with no firestore', t => {
45+
const vm = new Vue({
46+
render (h) {
47+
return h('ul', this.items.map(
48+
item => h('li', [item])
49+
))
50+
},
51+
data: () => ({ items: null }),
52+
})
53+
t.deepEqual(t.context.vm.items, null)
3254
})

test/utils.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import test from 'ava'
2+
import {
3+
createSnapshot,
4+
} from '../src/utils'
5+
import {
6+
collection,
7+
Key,
8+
id,
9+
DocumentSnapshot
10+
} from './helpers'
11+
12+
test.beforeEach(t => {
13+
t.context.id = id
14+
t.context.doc = new DocumentSnapshot(null, new Key(), {
15+
n: 42,
16+
is: true,
17+
items: [{ text: 'foo' }]
18+
})
19+
t.context.snapshot = createSnapshot(t.context.doc)
20+
})
21+
22+
test('createSnapshot adds an id', t => {
23+
t.is(t.context.snapshot.id, t.context.id)
24+
})
25+
26+
test('id is not enumerable', t => {
27+
t.false(Object.keys(t.context.snapshot).includes('id'))
28+
})
29+
30+
test('contains all the data', t => {
31+
t.deepEqual(t.context.snapshot, {
32+
n: 42,
33+
is: true,
34+
items: [{ text: 'foo' }]
35+
})
36+
})

0 commit comments

Comments
 (0)