217 lines
7.7 KiB
TypeScript
217 lines
7.7 KiB
TypeScript
import { Builder, ByteBuffer } from 'flatbuffers';
|
|
import { describe, expect, it } from 'vitest';
|
|
import * as fb from '../gen/fbs/scrabblefb';
|
|
import {
|
|
decodeFriendList,
|
|
decodeGameList,
|
|
decodeInvitation,
|
|
decodeLinkResult,
|
|
decodeSession,
|
|
decodeStats,
|
|
encodeSubmitPlay,
|
|
encodeTarget,
|
|
} from './codec';
|
|
|
|
describe('codec', () => {
|
|
it('encodes a SubmitPlayRequest the gateway can read', () => {
|
|
const buf = encodeSubmitPlay('g1', 'H', [
|
|
{ row: 7, col: 7, letter: 'A', blank: false },
|
|
{ row: 7, col: 8, letter: 'B', blank: true },
|
|
]);
|
|
const r = fb.SubmitPlayRequest.getRootAsSubmitPlayRequest(new ByteBuffer(buf));
|
|
expect(r.gameId()).toBe('g1');
|
|
expect(r.dir()).toBe('H');
|
|
expect(r.tilesLength()).toBe(2);
|
|
expect(r.tiles(0)?.letter()).toBe('A');
|
|
expect(r.tiles(1)?.blank()).toBe(true);
|
|
});
|
|
|
|
it('decodes a Session', () => {
|
|
const b = new Builder(64);
|
|
const token = b.createString('tok');
|
|
const uid = b.createString('u1');
|
|
const name = b.createString('Me');
|
|
fb.Session.startSession(b);
|
|
fb.Session.addToken(b, token);
|
|
fb.Session.addUserId(b, uid);
|
|
fb.Session.addIsGuest(b, true);
|
|
fb.Session.addDisplayName(b, name);
|
|
b.finish(fb.Session.endSession(b));
|
|
expect(decodeSession(b.asUint8Array())).toEqual({
|
|
token: 'tok',
|
|
userId: 'u1',
|
|
isGuest: true,
|
|
displayName: 'Me',
|
|
});
|
|
});
|
|
|
|
it('decodes a GameList including nested seat display names', () => {
|
|
const b = new Builder(256);
|
|
const aid = b.createString('a1');
|
|
const dn = b.createString('Ann');
|
|
fb.SeatView.startSeatView(b);
|
|
fb.SeatView.addSeat(b, 1);
|
|
fb.SeatView.addAccountId(b, aid);
|
|
fb.SeatView.addScore(b, 13);
|
|
fb.SeatView.addHintsUsed(b, 0);
|
|
fb.SeatView.addIsWinner(b, false);
|
|
fb.SeatView.addDisplayName(b, dn);
|
|
const seat = fb.SeatView.endSeatView(b);
|
|
const seats = fb.GameView.createSeatsVector(b, [seat]);
|
|
const id = b.createString('g1');
|
|
const variant = b.createString('english');
|
|
const dv = b.createString('v1');
|
|
const status = b.createString('active');
|
|
const er = b.createString('');
|
|
fb.GameView.startGameView(b);
|
|
fb.GameView.addId(b, id);
|
|
fb.GameView.addVariant(b, variant);
|
|
fb.GameView.addDictVersion(b, dv);
|
|
fb.GameView.addStatus(b, status);
|
|
fb.GameView.addPlayers(b, 2);
|
|
fb.GameView.addToMove(b, 0);
|
|
fb.GameView.addTurnTimeoutSecs(b, 86400);
|
|
fb.GameView.addMoveCount(b, 4);
|
|
fb.GameView.addEndReason(b, er);
|
|
fb.GameView.addSeats(b, seats);
|
|
const game = fb.GameView.endGameView(b);
|
|
const games = fb.GameList.createGamesVector(b, [game]);
|
|
fb.GameList.startGameList(b);
|
|
fb.GameList.addGames(b, games);
|
|
b.finish(fb.GameList.endGameList(b));
|
|
|
|
const gl = decodeGameList(b.asUint8Array());
|
|
expect(gl.games).toHaveLength(1);
|
|
expect(gl.games[0].id).toBe('g1');
|
|
expect(gl.games[0].seats[0].displayName).toBe('Ann');
|
|
expect(gl.games[0].seats[0].score).toBe(13);
|
|
});
|
|
|
|
it('encodes a TargetRequest', () => {
|
|
const r = fb.TargetRequest.getRootAsTargetRequest(new ByteBuffer(encodeTarget('a-1')));
|
|
expect(r.accountId()).toBe('a-1');
|
|
});
|
|
|
|
it('decodes a StatsView', () => {
|
|
const b = new Builder(64);
|
|
fb.StatsView.startStatsView(b);
|
|
fb.StatsView.addWins(b, 7);
|
|
fb.StatsView.addLosses(b, 4);
|
|
fb.StatsView.addDraws(b, 1);
|
|
fb.StatsView.addMaxGamePoints(b, 420);
|
|
fb.StatsView.addMaxWordPoints(b, 90);
|
|
b.finish(fb.StatsView.endStatsView(b));
|
|
expect(decodeStats(b.asUint8Array())).toEqual({
|
|
wins: 7,
|
|
losses: 4,
|
|
draws: 1,
|
|
maxGamePoints: 420,
|
|
maxWordPoints: 90,
|
|
});
|
|
});
|
|
|
|
it('decodes a FriendList of account refs', () => {
|
|
const b = new Builder(128);
|
|
const id = b.createString('a-1');
|
|
const dn = b.createString('Ann');
|
|
fb.AccountRef.startAccountRef(b);
|
|
fb.AccountRef.addAccountId(b, id);
|
|
fb.AccountRef.addDisplayName(b, dn);
|
|
const ref = fb.AccountRef.endAccountRef(b);
|
|
const vec = fb.FriendList.createFriendsVector(b, [ref]);
|
|
fb.FriendList.startFriendList(b);
|
|
fb.FriendList.addFriends(b, vec);
|
|
b.finish(fb.FriendList.endFriendList(b));
|
|
expect(decodeFriendList(b.asUint8Array())).toEqual([{ accountId: 'a-1', displayName: 'Ann' }]);
|
|
});
|
|
|
|
it('decodes a merge_required LinkResult without a session', () => {
|
|
const b = new Builder(128);
|
|
const status = b.createString('merge_required');
|
|
const sid = b.createString('b-1');
|
|
const sname = b.createString('Ann');
|
|
fb.LinkResult.startLinkResult(b);
|
|
fb.LinkResult.addStatus(b, status);
|
|
fb.LinkResult.addSecondaryUserId(b, sid);
|
|
fb.LinkResult.addSecondaryDisplayName(b, sname);
|
|
fb.LinkResult.addSecondaryGames(b, 7);
|
|
fb.LinkResult.addSecondaryFriends(b, 3);
|
|
b.finish(fb.LinkResult.endLinkResult(b));
|
|
expect(decodeLinkResult(b.asUint8Array())).toEqual({
|
|
status: 'merge_required',
|
|
secondaryUserId: 'b-1',
|
|
secondaryDisplayName: 'Ann',
|
|
secondaryGames: 7,
|
|
secondaryFriends: 3,
|
|
session: null,
|
|
});
|
|
});
|
|
|
|
it('decodes a merged LinkResult carrying a switched session', () => {
|
|
const b = new Builder(128);
|
|
const token = b.createString('tok-9');
|
|
const uid = b.createString('a-1');
|
|
const dn = b.createString('Kaya');
|
|
fb.Session.startSession(b);
|
|
fb.Session.addToken(b, token);
|
|
fb.Session.addUserId(b, uid);
|
|
fb.Session.addIsGuest(b, false);
|
|
fb.Session.addDisplayName(b, dn);
|
|
const sess = fb.Session.endSession(b);
|
|
const status = b.createString('merged');
|
|
fb.LinkResult.startLinkResult(b);
|
|
fb.LinkResult.addStatus(b, status);
|
|
fb.LinkResult.addSession(b, sess);
|
|
b.finish(fb.LinkResult.endLinkResult(b));
|
|
const r = decodeLinkResult(b.asUint8Array());
|
|
expect(r.status).toBe('merged');
|
|
expect(r.session).toEqual({ token: 'tok-9', userId: 'a-1', isGuest: false, displayName: 'Kaya' });
|
|
});
|
|
|
|
it('decodes an Invitation with inviter and invitees', () => {
|
|
const b = new Builder(256);
|
|
const iid = b.createString('u-1');
|
|
const idn = b.createString('Me');
|
|
fb.AccountRef.startAccountRef(b);
|
|
fb.AccountRef.addAccountId(b, iid);
|
|
fb.AccountRef.addDisplayName(b, idn);
|
|
const inviter = fb.AccountRef.endAccountRef(b);
|
|
|
|
const aid = b.createString('inv-1');
|
|
const adn = b.createString('Friend');
|
|
const resp = b.createString('pending');
|
|
fb.InvitationInvitee.startInvitationInvitee(b);
|
|
fb.InvitationInvitee.addAccountId(b, aid);
|
|
fb.InvitationInvitee.addDisplayName(b, adn);
|
|
fb.InvitationInvitee.addSeat(b, 1);
|
|
fb.InvitationInvitee.addResponse(b, resp);
|
|
const invitee = fb.InvitationInvitee.endInvitationInvitee(b);
|
|
const invitees = fb.Invitation.createInviteesVector(b, [invitee]);
|
|
|
|
const id = b.createString('i-1');
|
|
const variant = b.createString('english');
|
|
const dropout = b.createString('remove');
|
|
const status = b.createString('pending');
|
|
const gid = b.createString('');
|
|
fb.Invitation.startInvitation(b);
|
|
fb.Invitation.addId(b, id);
|
|
fb.Invitation.addInviter(b, inviter);
|
|
fb.Invitation.addInvitees(b, invitees);
|
|
fb.Invitation.addVariant(b, variant);
|
|
fb.Invitation.addTurnTimeoutSecs(b, 86400);
|
|
fb.Invitation.addHintsAllowed(b, true);
|
|
fb.Invitation.addHintsPerPlayer(b, 1);
|
|
fb.Invitation.addDropoutTiles(b, dropout);
|
|
fb.Invitation.addStatus(b, status);
|
|
fb.Invitation.addGameId(b, gid);
|
|
b.finish(fb.Invitation.endInvitation(b));
|
|
|
|
const inv = decodeInvitation(b.asUint8Array());
|
|
expect(inv.id).toBe('i-1');
|
|
expect(inv.inviter).toEqual({ accountId: 'u-1', displayName: 'Me' });
|
|
expect(inv.invitees).toHaveLength(1);
|
|
expect(inv.invitees[0]).toEqual({ accountId: 'inv-1', displayName: 'Friend', seat: 1, response: 'pending' });
|
|
expect(inv.variant).toBe('english');
|
|
});
|
|
});
|