181 lines
4.1 KiB
TypeScript
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],
|
|
],
|
|
})
|
|
})
|