Skip to content

Commit 121288c

Browse files
committed
feat(serverHistory): create a server History class
Allow for server side routing using a history object designed to work without the browser. Switch all the tests to use the serverHistory class instead of the previous mock.
1 parent 3c792dd commit 121288c

File tree

6 files changed

+81
-33
lines changed

6 files changed

+81
-33
lines changed

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export {makeRouterDriver} from './makeRouterDriver'
2-
export {supportsHistory} from './util'
2+
export {supportsHistory, createLocation} from './util'
3+
export {createServerHistory} from './serverHistory'

src/pathFilter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {createAPI} from './api'
22
import {splitPath} from './util'
33

44
function isStrictlyInScope(namespace, path) {
5-
const pathParts = path.split('/').filter(x => x.length > 0)
5+
const pathParts = splitPath(path)
66
return namespace.every((v, i) => {
77
return pathParts[i] === v
88
})

src/serverHistory.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {createLocation} from './util'
2+
3+
function ServerHistory() {}
4+
5+
ServerHistory.prototype.listen = function listen(listener) {
6+
this.listener = listener
7+
}
8+
9+
ServerHistory.prototype.push = function push(location) {
10+
const listener = this.listener
11+
if (!listener) {
12+
throw new Error('There is no active listener')
13+
}
14+
listener(createLocation(location))
15+
}
16+
17+
ServerHistory.prototype.createHref = function createHref(path) {
18+
return path
19+
}
20+
21+
ServerHistory.prototype.createLocation = createLocation
22+
23+
function createServerHistory() {
24+
return new ServerHistory()
25+
}
26+
27+
export {createServerHistory}

src/util.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ function supportsHistory() {
1212

1313
if (typeof window !== `undefined`) {
1414
return window.history && `pushState` in window.history
15+
} else {
16+
return false
1517
}
1618
}
1719

@@ -35,4 +37,26 @@ function makeCreateHref(namespace, createHref) {
3537
}
3638
}
3739

38-
export {supportsHistory, splitPath, filterPath, makeCreateHref}
40+
const locationDefaults = {
41+
pathname: '/',
42+
action: 'POP',
43+
hash: '',
44+
search: '',
45+
state: null,
46+
key: null,
47+
}
48+
49+
function createLocation(location = locationDefaults) {
50+
if (typeof location === 'string') {
51+
return Object.assign(locationDefaults, {pathname: location})
52+
}
53+
return Object.assign(locationDefaults, location)
54+
}
55+
56+
export {
57+
supportsHistory,
58+
splitPath,
59+
filterPath,
60+
makeCreateHref,
61+
createLocation,
62+
}

test/helper/mockHistory.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

test/index.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
/* eslint max-nested-callbacks: 0 */
22
import {describe, it} from 'mocha'
33
import assert from 'assert'
4-
import {createMockHistory} from './helper/mockHistory'
5-
import {makeRouterDriver} from '../src'
4+
import {makeRouterDriver, createServerHistory} from '../src'
65

76
describe('Cyclic Router', () => {
87
describe('makeRouterDriver', () => {
@@ -14,15 +13,15 @@ describe('Cyclic Router', () => {
1413

1514
it('should accept any object with a listen() method', () => {
1615
assert.doesNotThrow(() => {
17-
makeRouterDriver(createMockHistory())
16+
makeRouterDriver(createServerHistory())
1817
})
1918
})
2019

2120
describe('routerDriver', () => {
2221
it('should return an object with `path` `define` `observable` ' +
2322
'`createHref` and `dispose`',
2423
() => {
25-
const router = makeRouterDriver(createMockHistory())()
24+
const router = makeRouterDriver(createServerHistory())()
2625
assert.notStrictEqual(router.path, null)
2726
assert.strictEqual(typeof router.path, 'function')
2827
assert.notStrictEqual(router.define, null)
@@ -42,7 +41,7 @@ describe('Cyclic Router', () => {
4241
it('should return an object with `path` `define` `observable` ' +
4342
'`createHref` and `dispose`',
4443
() => {
45-
const router = makeRouterDriver(createMockHistory())().path('/')
44+
const router = makeRouterDriver(createServerHistory())().path('/')
4645
assert.notStrictEqual(router.path, null)
4746
assert.strictEqual(typeof router.path, 'function')
4847
assert.notStrictEqual(router.define, null)
@@ -61,7 +60,7 @@ describe('Cyclic Router', () => {
6160
'/somewhere/else',
6261
'/path/that/is/correct',
6362
]
64-
const history = createMockHistory(routes)
63+
const history = createServerHistory(routes)
6564
const router = makeRouterDriver(history)().path('/path')
6665

6766
router.observable.subscribe((location) => {
@@ -77,7 +76,7 @@ describe('Cyclic Router', () => {
7776
'/some/really/really/deeply/nested/incorrect/route',
7877
]
7978

80-
const history = createMockHistory(routes)
79+
const history = createServerHistory(routes)
8180
const router = makeRouterDriver(history)()
8281
.path('/some').path('/really').path('/really').path('/deeply')
8382
.path('/nested').path('/route').path('/that')
@@ -95,7 +94,7 @@ describe('Cyclic Router', () => {
9594
'/some/really/really/deeply/nested/incorrect/route',
9695
]
9796

98-
const history = createMockHistory(routes)
97+
const history = createServerHistory(routes)
9998
const router = makeRouterDriver(history)()
10099
.path('/some').path('/really').path('/really').path('/deeply')
101100
.path('/nested').path('/route').path('/that')
@@ -116,7 +115,7 @@ describe('Cyclic Router', () => {
116115
'/some/really/really/deeply/nested/incorrect/route',
117116
]
118117

119-
const history = createMockHistory(routes)
118+
const history = createServerHistory(routes)
120119
const router = makeRouterDriver(history)()
121120
.path('/some').path('/really').path('/really').path('/deeply')
122121
.path('/nested').path('/route').path('/that')
@@ -131,7 +130,7 @@ describe('Cyclic Router', () => {
131130
it('should return an object with `path$` `value$` `fullPath$` ' +
132131
'`createHref` and `dispose`',
133132
() => {
134-
const router = makeRouterDriver(createMockHistory())().define({})
133+
const router = makeRouterDriver(createServerHistory())().define({})
135134
assert.notStrictEqual(router.path$, null)
136135
assert.strictEqual(typeof router.path$, 'object')
137136
assert.strictEqual(typeof router.path$.subscribe, 'function')
@@ -157,7 +156,7 @@ describe('Cyclic Router', () => {
157156
const routes = [
158157
'/some/route',
159158
]
160-
const history = createMockHistory(routes)
159+
const history = createServerHistory()
161160
const {path$, value$, fullPath$} =
162161
makeRouterDriver(history)().define(defintion)
163162

@@ -173,6 +172,8 @@ describe('Cyclic Router', () => {
173172
assert.strictEqual(fullPath, '/some/route')
174173
setTimeout(done, 10)
175174
})
175+
176+
routes.forEach(r => history.push(r))
176177
})
177178

178179
it('should respect prior filtering by path()', done => {
@@ -187,7 +188,7 @@ describe('Cyclic Router', () => {
187188
'/some/nested/correct/route',
188189
'/wrong/route',
189190
]
190-
const history = createMockHistory(routes)
191+
const history = createServerHistory()
191192
const {path$, value$, fullPath$} = makeRouterDriver(history)()
192193
.path('/some').path('/nested').define(defintion)
193194

@@ -203,6 +204,8 @@ describe('Cyclic Router', () => {
203204
assert.strictEqual(fullPath, '/some/nested/correct/route')
204205
setTimeout(done, 10)
205206
})
207+
208+
routes.forEach(r => history.push(r))
206209
})
207210

208211
it('should match a default route if one is not found', done => {
@@ -218,7 +221,7 @@ describe('Cyclic Router', () => {
218221
'/some/nested/incorrect/route',
219222
'/wrong/route',
220223
]
221-
const history = createMockHistory(routes)
224+
const history = createServerHistory()
222225
const {path$, value$, fullPath$} = makeRouterDriver(history)()
223226
.path('/some').path('/nested').define(defintion)
224227

@@ -234,6 +237,8 @@ describe('Cyclic Router', () => {
234237
assert.strictEqual(fullPath, '/some/nested/incorrect/route')
235238
setTimeout(done, 10)
236239
})
240+
241+
routes.forEach(r => history.push(r))
237242
})
238243

239244
it('should create a proper href using createHref()', done => {
@@ -250,7 +255,7 @@ describe('Cyclic Router', () => {
250255
'/wrong/route',
251256
]
252257

253-
const history = createMockHistory(routes)
258+
const history = createServerHistory()
254259
const {fullPath$, createHref} = makeRouterDriver(history)()
255260
.path('/some').path('/nested').define(defintion)
256261

@@ -259,6 +264,8 @@ describe('Cyclic Router', () => {
259264
assert.strictEqual(createHref('/correct/route'), pathname)
260265
setTimeout(done, 5)
261266
})
267+
268+
routes.forEach(r => history.push(r))
262269
})
263270

264271
it('should match partials', done => {
@@ -275,7 +282,7 @@ describe('Cyclic Router', () => {
275282
'/wrong/route',
276283
]
277284

278-
const history = createMockHistory(routes)
285+
const history = createServerHistory()
279286
const {path$, fullPath$} = makeRouterDriver(history)()
280287
.path('/some').path('/nested').define(defintion)
281288

@@ -287,6 +294,8 @@ describe('Cyclic Router', () => {
287294
assert.strictEqual(pathname, '/some/nested/correct/route/partial')
288295
setTimeout(done, 5)
289296
})
297+
298+
routes.forEach(r => history.push(r))
290299
})
291300

292301
it('should not work after being disposed', done => {
@@ -303,12 +312,13 @@ describe('Cyclic Router', () => {
303312
'/wrong/route',
304313
]
305314

306-
const history = createMockHistory(routes)
315+
const history = createServerHistory()
307316
const {fullPath$, dispose} = makeRouterDriver(history)()
308317
.path('/some').path('/nested').define(defintion)
309318

310319
dispose()
311320
fullPath$.subscribe(done.fail)
321+
routes.forEach(r => history.push(r))
312322
setTimeout(done, 10)
313323
})
314324
})

0 commit comments

Comments
 (0)