-
Notifications
You must be signed in to change notification settings - Fork 822
make db interface async #86
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
Changes from 5 commits
c879c29
93d71f2
7f39f6a
fcc3e59
68018e6
3c5a21f
6a11c05
8b5f334
61813e9
65d0e6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,8 +20,9 @@ jest.mock('koa-socket', () => { | |
| this.broadcast = { emit: jest.fn() }; | ||
| } | ||
|
|
||
| receive(type, ...args) { | ||
| this.callbacks[type](args[0], args[1], args[2], args[3], args[4]); | ||
| async receive(type, ...args) { | ||
| await this.callbacks[type](args[0], args[1], args[2], args[3], args[4]); | ||
| return; | ||
| } | ||
|
|
||
| on(type, callback) { | ||
|
|
@@ -65,7 +66,7 @@ test('basic', () => { | |
| io.socket.receive('disconnect'); | ||
| }); | ||
|
|
||
| test('sync', () => { | ||
| test('sync', async () => { | ||
| const server = Server({ games: [game] }); | ||
| const io = server.context.io; | ||
| expect(server).not.toBe(undefined); | ||
|
|
@@ -74,40 +75,42 @@ test('sync', () => { | |
|
|
||
| // Sync causes the server to respond. | ||
| expect(io.socket.emit).toHaveBeenCalledTimes(0); | ||
| io.socket.receive('sync', 'gameID'); | ||
| await io.socket.receive('sync', 'gameID'); | ||
|
|
||
| expect(io.socket.emit).toHaveBeenCalledTimes(1); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @nicolodavis sorry for my delayed reply
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just use |
||
| expect(spy).toHaveBeenCalled(); | ||
|
|
||
| // Sync a second time does not create a game. | ||
| spy.mockReset(); | ||
| io.socket.receive('sync', 'gameID'); | ||
| await io.socket.receive('sync', 'gameID'); | ||
|
|
||
| expect(io.socket.emit).toHaveBeenCalledTimes(2); | ||
| expect(spy).not.toHaveBeenCalled(); | ||
|
|
||
| spy.mockRestore(); | ||
| }); | ||
|
|
||
| test('action', () => { | ||
| test('action', async () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. async not needed, because not await exist
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, but I forgot to remove it after I clean |
||
| const server = Server({ games: [game] }); | ||
| const io = server.context.io; | ||
| const action = ActionCreators.gameEvent('endTurn'); | ||
|
|
||
| io.socket.receive('action', action); | ||
| await io.socket.receive('action', action); | ||
| expect(io.socket.emit).toHaveBeenCalledTimes(0); | ||
| io.socket.emit.mockReset(); | ||
|
|
||
| io.socket.receive('sync', 'gameID'); | ||
| await io.socket.receive('sync', 'gameID'); | ||
| io.socket.id = 'second'; | ||
| io.socket.receive('sync', 'gameID'); | ||
| await io.socket.receive('sync', 'gameID'); | ||
| io.socket.emit.mockReset(); | ||
|
|
||
| // View-only players cannot send actions. | ||
| io.socket.receive('action', action, 0, 'gameID', null); | ||
| await io.socket.receive('action', action, 0, 'gameID', null); | ||
| expect(io.socket.emit).not.toHaveBeenCalled(); | ||
|
|
||
| // Actions are broadcasted as state updates. | ||
| // The playerID parameter is necessary to account for view-only players. | ||
| io.socket.receive('action', action, 0, 'gameID', '0'); | ||
| await io.socket.receive('action', action, 0, 'gameID', '0'); | ||
| expect(io.socket.emit).lastCalledWith('sync', 'gameID', { | ||
| G: {}, | ||
| _id: 1, | ||
|
|
@@ -141,23 +144,23 @@ test('action', () => { | |
| io.socket.emit.mockReset(); | ||
|
|
||
| // ... but not if the gameID is not known. | ||
| io.socket.receive('action', action, 1, 'unknown', '1'); | ||
| await io.socket.receive('action', action, 1, 'unknown', '1'); | ||
| expect(io.socket.emit).toHaveBeenCalledTimes(0); | ||
|
|
||
| // ... and not if the _id doesn't match the internal state. | ||
| io.socket.receive('action', action, 100, 'gameID', '1'); | ||
| await io.socket.receive('action', action, 100, 'gameID', '1'); | ||
| expect(io.socket.emit).toHaveBeenCalledTimes(0); | ||
|
|
||
| // ... and not if player != currentPlayer | ||
| io.socket.receive('action', action, 1, 'gameID', '100'); | ||
| await io.socket.receive('action', action, 1, 'gameID', '100'); | ||
| expect(io.socket.emit).toHaveBeenCalledTimes(0); | ||
|
|
||
| // Another broadcasted action. | ||
| io.socket.receive('action', action, 1, 'gameID', '1'); | ||
| await io.socket.receive('action', action, 1, 'gameID', '1'); | ||
| expect(io.socket.emit).toHaveBeenCalledTimes(2); | ||
| }); | ||
|
|
||
| test('playerView', () => { | ||
| test('playerView', async () => { | ||
| // Write the player into G. | ||
| const game = Game({ | ||
| playerView: (G, ctx, player) => { | ||
|
|
@@ -168,7 +171,7 @@ test('playerView', () => { | |
| const server = Server({ games: [game] }); | ||
| const io = server.context.io; | ||
|
|
||
| io.socket.receive('sync', 'gameID', 0); | ||
| await io.socket.receive('sync', 'gameID', 0); | ||
| expect(io.socket.emit).lastCalledWith('sync', 'gameID', { | ||
| G: { player: 0 }, | ||
| _id: 0, | ||
|
|
@@ -196,19 +199,26 @@ test('playerView', () => { | |
| }); | ||
| }); | ||
|
|
||
| test('custom db implementation', () => { | ||
| test('custom db implementation', async () => { | ||
| let getId = null; | ||
|
|
||
| class Custom { | ||
| get(id) { | ||
| constructor() { | ||
| this.games = new Map(); | ||
| } | ||
| async get(id) { | ||
| getId = id; | ||
| return await this.games.get(id); | ||
| } | ||
| async set(id, state) { | ||
| return await this.games.set(id, state); | ||
| } | ||
| set() {} | ||
| } | ||
|
|
||
| const game = Game({}); | ||
| const server = Server({ games: [game], db: new Custom() }); | ||
| const io = server.context.io; | ||
|
|
||
| io.socket.receive('sync', 'gameID'); | ||
| await io.socket.receive('sync', 'gameID'); | ||
| expect(getId).toBe('gameID'); | ||
| }); | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to do this without
babel-polyfill? Recent versions of Node support async / await out of the box.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After running examples I got
regeneratorRuntimeerror.I tried to solve it by testing all options from babel docs and finally this one worked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
babel-polyfill shouldn't be used in a library, so we should find another way to do this. Have you tried babel-preset-env?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other option would be to not use Babel on anything in src/server and write it without ES5 features. I can take a look at this later.