Skip to content

[WIP] V2 integration #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 50 additions & 13 deletions test/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var test = require('tape')
var feathers = require('feathers')
var { keys, any, pipe } = require('ramda')
var memory = require('feathers-memory')
var {createStore, applyMiddleware} = require('redux')
var { createEpicMiddleware, combineEpics } = require('redux-observable')
Expand All @@ -12,7 +13,7 @@ var createModule = require('../')

const serviceNames = ['cats', 'dogs']

test('app works', function (t) {
test('create, update, patch and remove update the store', function (t) {
const app = createApp(serviceNames)
const {cats, dogs} = createModule(serviceNames)
const catActions = cats.actions
Expand All @@ -26,41 +27,77 @@ test('app works', function (t) {

const store = createStore(reducer, applyMiddleware(epicMiddleware))

const cidCreate = Cid()
const cidUpdate = Cid()
const cidPatch = Cid()
const cidRemove = Cid()
const createCid = Cid()
const updateCid = Cid()
const patchCid = Cid()
const removeCid = Cid()

Store$(store)
.filter((store) => store.cats && store.cats.cats[0])
.filter((store) => store.cats.cats[0])
.take(1)
.mergeMap(({cats}) => {
t.equal(cats.cats[0].name, 'fluffy')
store.dispatch(catActions.update(cidUpdate, 0, {name: 'tick'}))
store.dispatch(catActions.update(Cid(), 0, {name: 'tick'}))
return Store$(store)
})
.filter((store) => store.cats && store.cats.cats[0] && store.cats.cats[0].name === 'tick')
.filter((store) => store.cats.cats[0].name === 'tick')
.take(1)
.mergeMap(({cats}) => {
t.equal(cats.cats[0].name, 'tick')
store.dispatch(catActions.patch(cidPatch, 0, {nickName: 'fatboy'}))
store.dispatch(catActions.patch(Cid(), 0, {nickName: 'fatboy'}))
return Store$(store)
})
.filter((store) => store.cats && store.cats.cats[0] && store.cats.cats[0].nickName === 'fatboy')
.filter((store) => store.cats.cats[0] && store.cats.cats[0].nickName === 'fatboy')
.take(1)
.mergeMap(({cats}) => {
t.equal(cats.cats[0].nickName, 'fatboy')
store.dispatch(catActions.remove(cidRemove, 0))
store.dispatch(catActions.remove(Cid(), 0))
return Store$(store)
})
.filter((store) => store.cats && !store.cats.cats[0])
.filter((store) => !store.cats.cats[0])
.take(1)
.subscribe(() => {
t.pass()
t.end()
})

store.dispatch(cats.actions.create(cidCreate, {name: 'fluffy'}))
store.dispatch(cats.actions.create(createCid, {name: 'fluffy'}))
})

test('create optimistically updates store and then sets the id when request succeeds', function (t) {
const app = createApp(serviceNames)
const {cats, dogs} = createModule(serviceNames)
const catActions = cats.actions

const updaters = reduxFp.combine({cats: cats.updater, dogs: dogs.updater})
const epics = combineEpics(cats.epic, dogs.epic)

const reducer = (state, action) => updaters(action)(state)

const epicMiddleware = createEpicMiddleware(epics, {dependencies: {feathers: app}})

const store = createStore(reducer, applyMiddleware(epicMiddleware))

const createCid = Cid()
const keysHaveCidKey = pipe(keys, any(key => key === createCid))

Store$(store)
.filter((store) => store.cats.cats[createCid])
.take(1)
.subscribe(({cats}) => {
t.equal(cats.cats[createCid].name, 'fluffy', 'Cat is created optimistically')
})

Store$(store)
.filter((store) => store.cats.cats[0])
.take(1)
.subscribe(({cats}) => {
t.equal(cats.cats[0].name, 'fluffy', 'Cat is set at the expected id')
t.false(keysHaveCidKey(cats.cats), 'Temporary cid key is deleted')
t.end()
})

store.dispatch(cats.actions.create(createCid, {name: 'fluffy'}))
})

function Store$ (store) {
Expand Down
89 changes: 58 additions & 31 deletions test/epic.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ function createCid () {
test('find', function (t) {
const cid = createCid()
const action$ = Action$.of(cats.actions.find(cid))
const feathers = {
const service = {
find: () => Rx.Observable.of(values(catsData))
}
const feathers = {
service: () => service
}
const expected = [
actionCreators.start(cid, { service, method: 'find', args: { params: {} } }),
actionCreators.set(cid, 0, catsData[0]),
actionCreators.set(cid, 1, catsData[1]),
actionCreators.set(cid, 2, catsData[2]),
actionCreators.start(cid, { service: 'cats', method: 'find', args: { params: {} } }),
actionCreators.setAll(cid, values(catsData)),
actionCreators.complete(cid)
]
cats.epic(action$, undefined, { feathers })
Expand All @@ -53,33 +54,35 @@ test('find with cancel', function (t) {
observer.next(cats.actions.complete(cid))
})
}))
const service = {
find: () => Rx.Observable.of(values(catsData))
}
const feathers = {
find: () => Rx.Observable.create(observer => {
observer.next(values(catsData))
})
service: () => service
}
const expected = [
actionCreators.start(cid, { service, method: 'find', args: { params: {} } }),
actionCreators.set(cid, 0, catsData[0]),
actionCreators.set(cid, 1, catsData[1]),
actionCreators.set(cid, 2, catsData[2])
actionCreators.start(cid, { service: 'cats', method: 'find', args: { params: {} } }),
actionCreators.setAll(cid, values(catsData)),
]
var i = 0
cats.epic(action$, undefined, { feathers })
.subscribe((action) => {
t.deepEqual(action, expected[i++])
if (i === 4) t.end()
if (i === 2) t.end()
})
})

test('get', function (t) {
const cid = createCid()
const action$ = Action$.of(cats.actions.get(cid, 0))
const feathers = {
const service = {
get: (id) => Rx.Observable.of(catsData[id])
}
const feathers = {
service: () => service
}
const expected = [
actionCreators.start(cid, { service, method: 'get', args: { id: 0, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'get', args: { id: 0, params: {} } }),
actionCreators.set(cid, 0, catsData[0]),
actionCreators.complete(cid)
]
Expand All @@ -94,11 +97,14 @@ test('get', function (t) {
test('create', function (t) {
const cid = createCid()
const action$ = Action$.of(cats.actions.create(cid, newCat))
const feathers = {
const service = {
create: () => Rx.Observable.of(catsData[0])
}
const feathers = {
service: () => service
}
const expected = [
actionCreators.start(cid, { service, method: 'create', args: { data: newCat, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'create', args: { data: newCat, params: {} } }),
actionCreators.set(cid, cid, newCat),
actionCreators.set(cid, cid, undefined),
actionCreators.set(cid, 0, catsData[0]),
Expand All @@ -116,11 +122,14 @@ test('create with rollback', function (t) {
const cid = createCid()
const err = new Error('oh no')
const action$ = Action$.of(cats.actions.create(cid, newCat))
const feathers = {
const service = {
create: () => Rx.Observable.throw(err)
}
const feathers = {
service: () => service
}
const expected = [
actionCreators.start(cid, { service, method: 'create', args: { data: newCat, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'create', args: { data: newCat, params: {} } }),
actionCreators.set(cid, cid, newCat),
actionCreators.set(cid, cid, undefined),
actionCreators.error(cid, err)
Expand All @@ -136,14 +145,17 @@ test('create with rollback', function (t) {
test('update', function (t) {
const cid = createCid()
const action$ = Action$.of(cats.actions.update(cid, 0, nextCat))
const feathers = {
const service = {
update: () => Rx.Observable.of(merge({ id: 0, feathers: true }, nextCat))
}
const feathers = {
service: () => service
}
const store = {
getState: () => ({ cats: catsData })
}
const expected = [
actionCreators.start(cid, { service, method: 'update', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'update', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.set(cid, 0, merge({ id: 0 }, nextCat)),
actionCreators.set(cid, 0, merge({ id: 0, feathers: true }, nextCat)),
actionCreators.complete(cid)
Expand All @@ -160,14 +172,17 @@ test('update with rollback', function (t) {
const cid = createCid()
const err = new Error('oh no')
const action$ = Action$.of(cats.actions.update(cid, 0, nextCat))
const feathers = {
const service = {
update: () => Rx.Observable.throw(err)
}
const feathers = {
service: () => service
}
const store = {
getState: () => ({ cats: catsData })
}
const expected = [
actionCreators.start(cid, { service, method: 'update', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'update', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.set(cid, 0, merge({ id: 0 }, nextCat)),
actionCreators.set(cid, 0, catsData[0]),
actionCreators.error(cid, err)
Expand All @@ -183,14 +198,17 @@ test('update with rollback', function (t) {
test('patch', function (t) {
const cid = createCid()
const action$ = Action$.of(cats.actions.patch(cid, 0, nextCat))
const feathers = {
const service = {
patch: () => Rx.Observable.of(mergeAll([catsData[0], { feathers: true }, nextCat]))
}
const feathers = {
service: () => service
}
const store = {
getState: () => ({ cats: catsData })
}
const expected = [
actionCreators.start(cid, { service, method: 'patch', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'patch', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.set(cid, 0, merge(catsData[0], nextCat)),
actionCreators.set(cid, 0, mergeAll([catsData[0], { feathers: true }, nextCat])),
actionCreators.complete(cid)
Expand All @@ -207,14 +225,17 @@ test('patch with rollback', function (t) {
const cid = createCid()
const err = new Error('oh no')
const action$ = Action$.of(cats.actions.patch(cid, 0, nextCat))
const feathers = {
const service = {
patch: () => Rx.Observable.throw(err)
}
const feathers = {
service: () => service
}
const store = {
getState: () => ({ cats: catsData })
}
const expected = [
actionCreators.start(cid, { service, method: 'patch', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'patch', args: { id: 0, data: nextCat, params: {} } }),
actionCreators.set(cid, 0, merge(catsData[0], nextCat)),
actionCreators.set(cid, 0, catsData[0]),
actionCreators.error(cid, err)
Expand All @@ -230,14 +251,17 @@ test('patch with rollback', function (t) {
test('remove', function (t) {
const cid = createCid()
const action$ = Action$.of(cats.actions.remove(cid, 0))
const feathers = {
const service = {
remove: () => Rx.Observable.of(catsData[0])
}
const feathers = {
service: () => service
}
const store = {
getState: () => ({ cats: catsData })
}
const expected = [
actionCreators.start(cid, { service, method: 'remove', args: { id: 0, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'remove', args: { id: 0, params: {} } }),
actionCreators.set(cid, 0, undefined),
actionCreators.set(cid, 0, undefined),
actionCreators.complete(cid)
Expand All @@ -254,14 +278,17 @@ test('remove with rollback', function (t) {
const cid = createCid()
const err = new Error('oh no')
const action$ = Action$.of(cats.actions.remove(cid, 0))
const feathers = {
const service = {
remove: () => Rx.Observable.throw(err)
}
const feathers = {
service: () => service
}
const store = {
getState: () => ({ cats: catsData })
}
const expected = [
actionCreators.start(cid, { service, method: 'remove', args: { id: 0, params: {} } }),
actionCreators.start(cid, { service: 'cats', method: 'remove', args: { id: 0, params: {} } }),
actionCreators.set(cid, 0, undefined),
actionCreators.set(cid, 0, catsData[0]),
actionCreators.error(cid, err)
Expand Down
1 change: 1 addition & 0 deletions updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const assoc = require('ramda/src/assoc')
const assocPath = require('ramda/src/assocPath')
const dissoc = require('ramda/src/dissoc')
const keys = require('ramda/src/keys')
const pipe = require('ramda/src/pipe')
const reduce = require('ramda/src/reduce')
const __ = require('ramda/src/__')
Expand Down