[web] add tests for utils

This commit is contained in:
Jason 2016-06-27 18:36:21 +08:00
parent 28531a4dd7
commit 37c2b47c26
9 changed files with 558 additions and 353 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,9 @@
jest.unmock("../../ducks/ui"); jest.unmock("../../ducks/ui");
// @todo fix it ( this is why I don't like to add tests until our architecture is stable :P ) // @todo fix it ( this is why I don't like to add tests until our architecture is stable :P )
jest.unmock("../../ducks/flows"); jest.unmock("../../ducks/views/main");
import reducer, { setActiveMenu } from '../../ducks/ui'; import reducer, { setActiveMenu } from '../../ducks/ui';
import { SELECT_FLOW } from '../../ducks/flows'; import { SELECT } from '../../ducks/views/main';
describe("ui reducer", () => { describe("ui reducer", () => {
it("should return the initial state", () => { it("should return the initial state", () => {
@ -14,21 +14,21 @@ describe("ui reducer", () => {
}), }),
it("should change the state to Start when deselecting a flow and we a currently at the flow tab", () => { it("should change the state to Start when deselecting a flow and we a currently at the flow tab", () => {
expect(reducer({activeMenu: 'Flow'}, expect(reducer({activeMenu: 'Flow'},
{ type: SELECT_FLOW, { type: SELECT,
currentSelection: '1', currentSelection: '1',
flowId : undefined flowId : undefined
})).toEqual({ activeMenu: 'Start'}) })).toEqual({ activeMenu: 'Start'})
}), }),
it("should change the state to Flow when we selected a flow and no flow was selected before", () => { it("should change the state to Flow when we selected a flow and no flow was selected before", () => {
expect(reducer({activeMenu: 'Start'}, expect(reducer({activeMenu: 'Start'},
{ type: SELECT_FLOW, { type: SELECT,
currentSelection: undefined, currentSelection: undefined,
flowId : '1' flowId : '1'
})).toEqual({ activeMenu: 'Flow'}) })).toEqual({ activeMenu: 'Flow'})
}), }),
it("should not change the state to Flow when OPTIONS tab is selected and we selected a flow and a flow as selected before", () => { it("should not change the state to Flow when OPTIONS tab is selected and we selected a flow and a flow as selected before", () => {
expect(reducer({activeMenu: 'Options'}, expect(reducer({activeMenu: 'Options'},
{ type: SELECT_FLOW, { type: SELECT,
currentSelection: '1', currentSelection: '1',
flowId : '2' flowId : '2'
})).toEqual({ activeMenu: 'Options'}) })).toEqual({ activeMenu: 'Options'})

View File

@ -0,0 +1,63 @@
jest.unmock('lodash')
jest.unmock('../../../ducks/utils/list')
import reduce, * as list from '../../../ducks/utils/list'
describe('list reduce', () => {
it('should add item', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 },
{ id: 2 },
{ id: 3 }
])
expect(reduce(state, list.add({ id: 3 }))).toEqual(result)
})
it('should update item', () => {
const state = createState([
{ id: 1, val: 1 },
{ id: 2, val: 2 }
])
const result = createState([
{ id: 1, val: 1 },
{ id: 2, val: 3 }
])
expect(reduce(state, list.update(2, { id: 2, val: 3 }))).toEqual(result)
})
it('should remove item', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 }
])
result.byId[2] = result.indexOf[2] = null
expect(reduce(state, list.remove(2))).toEqual(result)
})
it('should replace all items', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 }
])
expect(reduce(state, list.receive([{ id: 1 }]))).toEqual(result)
})
})
function createState(items) {
return {
data: items,
byId: _.fromPairs(items.map((item, index) => [item.id, item])),
indexOf: _.fromPairs(items.map((item, index) => [item.id, index]))
}
}

View File

@ -0,0 +1,154 @@
jest.unmock('../../../ducks/utils/view')
jest.unmock('lodash')
import reduce, * as view from '../../../ducks/utils/view'
import _ from 'lodash'
describe('view reduce', () => {
it('should filter items', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 }
])
expect(reduce(state, view.updateFilter(state, item => item.id === 1))).toEqual(result)
})
it('should sort items', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 2 },
{ id: 1 }
])
expect(reduce(state, view.updateSort((a, b) => b.id - a.id))).toEqual(result)
})
it('should add item', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 },
{ id: 2 },
{ id: 3 }
])
expect(reduce(state, view.add({ id: 3 }))).toEqual(result)
})
it('should add item in place', () => {
const state = createState([
{ id: 1 }
])
const result = createState([
{ id: 3 },
{ id: 1 }
])
expect(reduce(state, view.add({ id: 3 }, undefined, (a, b) => b.id - a.id))).toEqual(result)
})
it('should filter added item', () => {
const state = createState([
{ id: 1 }
])
const result = createState([
{ id: 1 }
])
expect(reduce(state, view.add({ id: 3 }, i => i.id === 1))).toEqual(result)
})
it('should update item', () => {
const state = createState([
{ id: 1, val: 1 },
{ id: 2, val: 2 }
])
const result = createState([
{ id: 1, val: 1 },
{ id: 2, val: 3 }
])
expect(reduce(state, view.update(2, { id: 2, val: 3 }))).toEqual(result)
})
it('should sort updated item', () => {
const state = createState([
{ id: 1, val: 1 },
{ id: 2, val: 2 }
])
const result = createState([
{ id: 2, val: 3 },
{ id: 1, val: 1 }
])
expect(reduce(state, view.update(2, { id: 2, val: 3 }, undefined, (a, b) => b.id - a.id))).toEqual(result)
})
it('should filter updated item', () => {
const state = createState([
{ id: 1, val: 1 },
{ id: 2, val: 2 }
])
const result = createState([
{ id: 1, val: 1 }
])
result.indexOf[2] = null
expect(reduce(state, view.update(2, { id: 2, val: 3 }, i => i.id === i.val))).toEqual(result)
})
it('should remove item', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 }
])
result.indexOf[2] = null
expect(reduce(state, view.remove(2))).toEqual(result)
})
it('should replace items', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 }
])
expect(reduce(state, view.receive({ data: [{ id: 1 }] }))).toEqual(result)
})
it('should sort received items', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 2 },
{ id: 1 }
])
expect(reduce(state, view.receive({ data: [{ id: 1 }, { id: 2 }] }, undefined, (a, b) => b.id - a.id))).toEqual(result)
})
it('should filter received', () => {
const state = createState([
{ id: 1 },
{ id: 2 }
])
const result = createState([
{ id: 1 }
])
expect(reduce(state, view.receive({ data: [{ id: 1 }, { id: 2 }] }, i => i.id === 1))).toEqual(result)
})
})
function createState(items) {
return {
data: items,
indexOf: _.fromPairs(items.map((item, index) => [item.id, index]))
}
}

View File

@ -1,15 +0,0 @@
jest.unmock("../utils");
import {formatSize} from "../utils"
describe("utils", () => {
it("formatSize", () => {
expect(formatSize(1024)).toEqual("1kb");
expect(formatSize(0)).toEqual("0");
expect(formatSize(10)).toEqual("10b");
expect(formatSize(1025)).toEqual("1.0kb");
expect(formatSize(1024*1024)).toEqual("1mb");
expect(formatSize(1024*1024+1)).toEqual("1.0mb");
});
});

View File

@ -1,4 +1,4 @@
import {SELECT_FLOW} from "./flows" import {SELECT} from "./views/main"
export const SET_ACTIVE_MENU = 'SET_ACTIVE_MENU'; export const SET_ACTIVE_MENU = 'SET_ACTIVE_MENU';
@ -12,7 +12,7 @@ export default function reducer(state = defaultState, action) {
...state, ...state,
activeMenu: action.activeMenu activeMenu: action.activeMenu
} }
case SELECT_FLOW: case SELECT:
let isNewSelect = (action.flowId && !action.currentSelection) let isNewSelect = (action.flowId && !action.currentSelection)
let isDeselect = (!action.flowId && action.currentSelection) let isDeselect = (!action.flowId && action.currentSelection)
if(isNewSelect) { if(isNewSelect) {

View File

@ -23,33 +23,33 @@ export default function reduce(state = defaultState, action) {
} }
case UPDATE: { case UPDATE: {
const data = [...state.data]
const index = state.indexOf[action.id] const index = state.indexOf[action.id]
// FIXME: We should just swallow this
if (index == null) { if (index == null) {
throw new Error('Item not found') return state
} }
const data = [...state.data]
data[index] = action.item data[index] = action.item
return { return {
...state, ...state,
data, data,
byId: { ...state.byId, [action.item.id]: action.item }, byId: { ...state.byId, [action.id]: action.item }
} }
} }
case REMOVE: { case REMOVE: {
const data = [...state.data] const index = state.indexOf[action.id]
const indexOf = { ...state.indexOf }
const index = indexOf[action.id]
// FIXME: We should just swallow this
if (index == null) { if (index == null) {
throw new Error('Item not found') return state
} }
const data = [...state.data]
const indexOf = { ...state.indexOf, [action.id]: null }
data.splice(index, 1) data.splice(index, 1)
for (let i = data.length - 1; i >= index; i--) { for (let i = data.length - 1; i >= index; i--) {
indexOf[data[i].id] = i indexOf[data[i].id] = i

View File

@ -29,7 +29,7 @@ export default function reduce(state = defaultState, action) {
return { return {
...state, ...state,
data, data,
indexOf: _.fromPairs(data.map((item, index) => [item.id, index])) indexOf: _.fromPairs(data.map((item, index) => [item.id, index])),
} }
} }
@ -43,7 +43,7 @@ export default function reduce(state = defaultState, action) {
} }
case REMOVE: case REMOVE:
if (state.indexOf[action.item.id] == null) { if (state.indexOf[action.id] == null) {
return state return state
} }
return { return {
@ -52,7 +52,7 @@ export default function reduce(state = defaultState, action) {
} }
case UPDATE: { case UPDATE: {
if (state.indexOf[action.item.id] == null) { if (state.indexOf[action.id] == null) {
return return
} }
const nextState = { const nextState = {