space/packages/ketchup-common/index.spec.ts
2021-05-15 15:49:14 +10:00

181 lines
4.1 KiB
TypeScript

import { KetchupSynced } from '.'
interface TTTState {
board: ('X' | 'O' | undefined)[][]
}
const tttInitial = {
board: [
[undefined, undefined, undefined],
[undefined, undefined, undefined],
[undefined, undefined, undefined],
],
}
interface TTTAction {
row: number
col: number
mark: 'X' | 'O'
}
function tttReducer(state: TTTState, { row, col, mark }: TTTAction): TTTState {
if (state.board[row][col] !== undefined) {
return state
}
return {
board: state.board.map((rArr, rIdx) =>
rArr.map((cell, cIdx) => rIdx === row && cIdx === col ? mark : cell)
),
}
}
test('Basic linear', () => {
const s = new KetchupSynced(tttInitial, 1000, tttReducer)
expect(s.tryProcess({
action: { row: 0, col: 0, mark: 'X' },
timestamp: 1010,
clientId: 0,
})).toBe(true)
expect(s.tryProcess({
action: { row: 1, col: 2, mark: 'O' },
timestamp: 1020,
clientId: 0,
})).toBe(true)
expect(s.tryProcess({
action: { row: 2, col: 1, mark: 'X' },
timestamp: 1030,
clientId: 0,
})).toBe(true)
expect(s.projState).toEqual({
board: [
['X', undefined, undefined],
[undefined, undefined, 'O'],
[undefined, 'X', undefined],
],
})
})
test('Out-of-order', () => {
const s = new KetchupSynced(tttInitial, 1000, tttReducer)
expect(s.tryProcess({
action: { row: 0, col: 0, mark: 'X' },
timestamp: 1010,
clientId: 0,
})).toBe(true)
expect(s.tryProcess({
action: { row: 1, col: 2, mark: 'X' },
timestamp: 1040,
clientId: 0,
})).toBe(true)
expect(s.projState).toEqual({
board: [
['X', undefined, undefined],
[undefined, undefined, 'X'],
[undefined, undefined, undefined],
],
})
expect(s.tryProcess({
action: { row: 1, col: 2, mark: 'O' },
timestamp: 1030,
clientId: 0,
})).toBe(true)
expect(s.tryProcess({
action: { row: 2, col: 1, mark: 'X' },
timestamp: 1020,
clientId: 0,
})).toBe(true)
expect(s.projState).toEqual({
board: [
['X', undefined, undefined],
[undefined, undefined, 'O'],
[undefined, 'X', undefined],
],
})
})
test('Out-of-order with confirms', () => {
const s = new KetchupSynced(tttInitial, 1000, tttReducer)
expect(s.tryProcess({
action: { row: 0, col: 0, mark: 'X' },
timestamp: 1010,
clientId: 0,
})).toBe(true)
expect(s.confirmBefore(1010)).toBe(0)
expect(s.confState).toEqual(tttInitial)
expect(s.projs).toEqual([{
action: { row: 0, col: 0, mark: 'X' },
timestamp: 1010,
clientId: 0,
state: {
board: [
['X', undefined, undefined],
[undefined, undefined, undefined],
[undefined, undefined, undefined],
],
},
}])
expect(s.confirmBefore(1011)).toBe(1)
expect(s.confState).toEqual({
board: [
['X', undefined, undefined],
[undefined, undefined, undefined],
[undefined, undefined, undefined],
],
})
expect(s.projs).toEqual([])
expect(s.tryProcess({
action: { row: 0, col: 1, mark: 'X' },
timestamp: 1040,
clientId: 0,
})).toBe(true)
expect(s.tryProcess({
action: { row: 0, col: 2, mark: 'O' },
timestamp: 1030,
clientId: 0,
})).toBe(true)
expect(s.tryProcess({
action: { row: 1, col: 0, mark: 'X' },
timestamp: 1020,
clientId: 0,
})).toBe(true)
expect(s.confirmBefore(1021)).toBe(1)
expect(s.confState).toEqual({
board: [
['X', undefined, undefined],
['X', undefined, undefined],
[undefined, undefined, undefined],
],
})
expect(s.projs).toEqual([{
action: { row: 0, col: 2, mark: 'O' },
timestamp: 1030,
clientId: 0,
state: {
board: [
['X', undefined, 'O'],
['X', undefined, undefined],
[undefined, undefined, undefined],
],
},
}, {
action: { row: 0, col: 1, mark: 'X' },
timestamp: 1040,
clientId: 0,
state: {
board: [
['X', 'X', 'O'],
['X', undefined, undefined],
[undefined, undefined, undefined],
],
},
}])
expect(s.projState).toEqual({
board: [
['X', 'X', 'O'],
['X', undefined, undefined],
[undefined, undefined, undefined],
],
})
})