abstract-state-router
Version:
The basics of a client-side state router ala the AngularJS ui-router, but without any DOM interactions
250 lines (211 loc) • 6.01 kB
JavaScript
var test = require('tape-catch')
var StateState = require('../lib/state-state.js')
var stateComparison = require('../lib/state-comparison.js')
function simpleState(name, querystringParameters, route) {
return {
name: name,
querystringParameters: querystringParameters,
route: route || ''
}
}
function setup() {
var stateContainer = new StateState()
var states = [
simpleState('app', ['appParam1']),
simpleState('app.main', ['main1'], '/:routeParam'),
simpleState('app.main.tab1', ['main1', 'main2']),
simpleState('app.main.tab2', ['main2', 'main3']),
simpleState('login'),
simpleState('logout')
]
states.forEach(function(state) {
stateContainer.add(state.name, state)
})
return stateComparison(stateContainer)
}
function compareAllElements(t, expected, result) {
t.equal(result.length, expected.length, 'Correct number of items in the result array')
expected.forEach(function(obj, index) {
t.deepEqual(obj, result[index], 'element ' + index + ' is correct')
})
}
test('only changing the grandchild', function(t) {
var results = setup()('app.main.tab1', {}, 'app.main.tab2', {})
compareAllElements(t, [{
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app.main',
nameAfter: 'app.main'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main.tab1',
nameAfter: 'app.main.tab2'
}], results)
t.end()
})
test('login to a nested state', function(t) {
var results = setup()('login', {}, 'app.main.tab1', {})
compareAllElements(t, [{
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'login',
nameAfter: 'app'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: undefined,
nameAfter: 'app.main'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: undefined,
nameAfter: 'app.main.tab1'
}], results)
t.end()
})
test('a nested state to logout', function(t) {
var results = setup()('app.main.tab2', {}, 'logout', {})
compareAllElements(t, [{
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'logout'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main',
nameAfter: undefined
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main.tab2',
nameAfter: undefined
}], results)
t.end()
})
test('changing parameters but not the name', function(t) {
var results = setup()('app.main.tab1', { main1: 'first' }, 'app.main.tab1', { main1: 'second' })
compareAllElements(t, [{
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: false,
stateParametersChanged: true,
nameBefore: 'app.main',
nameAfter: 'app.main'
}, {
stateNameChanged: false,
stateParametersChanged: true,
nameBefore: 'app.main.tab1',
nameAfter: 'app.main.tab1'
}], results)
t.end()
})
test('changing name but not parameters', function(t) {
var results = setup()('app.main.tab1', { main2: 'no change', doesntMatter: 'lol' },
'app.main.tab2', { main2: 'no change', doesntMatter: 'butts' })
compareAllElements(t, [{
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app.main',
nameAfter: 'app.main'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main.tab1',
nameAfter: 'app.main.tab2'
}], results)
t.end()
})
test('changing mid-level parameter and low-level name', function(t) {
var results = setup()('app.main.tab1', { main1: 'will change', main2: 'no change' },
'app.main.tab2', { main1: 'changed', main2: 'no change' })
compareAllElements(t, [{
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: false,
stateParametersChanged: true,
nameBefore: 'app.main',
nameAfter: 'app.main'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main.tab1',
nameAfter: 'app.main.tab2'
}], results)
t.end()
})
test('changing highest-level parameter', function(t) {
var results = setup()('app.main.tab1', { appParam1: 'will change', main2: 'no change' },
'app.main.tab1', { appParam1: 'changed', main2: 'no change' })
compareAllElements(t, [{
stateNameChanged: false,
stateParametersChanged: true,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app.main',
nameAfter: 'app.main'
}, {
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app.main.tab1',
nameAfter: 'app.main.tab1'
}], results)
t.end()
})
test('changing from app.main.tab1 to just main', function(t) {
var results = setup()('app.main.tab1', { main1: 'wut' }, 'app', {})
compareAllElements(t, [{
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main',
nameAfter: undefined
}, {
stateNameChanged: true,
stateParametersChanged: false,
nameBefore: 'app.main.tab1',
nameAfter: undefined
}], results)
t.end()
})
test('changing states by modifying only a route parameter', function(t) {
var compare = setup()
var expected = [{
stateNameChanged: false,
stateParametersChanged: false,
nameBefore: 'app',
nameAfter: 'app'
}, {
stateNameChanged: false,
stateParametersChanged: true,
nameBefore: 'app.main',
nameAfter: 'app.main'
}]
compareAllElements(t, expected, compare('app.main', { main1: 'nothing' }, 'app.main', { main1: 'nothing', routeParam: 'something-new' }))
compareAllElements(t, expected, compare('app.main', { routeParam: 'something' }, 'app.main', { routeParam: 'something-new' }))
t.end()
})