009ea560f9
Reshape the lobby UI from a single Overview into a two-level sidebar (games · profile · DEV synthetic-reports) with four games sub-panels (active-past · recruitment · invitations · private-games). Move the `create new game` button into the private-games panel, merge the applications section into recruitment cards as status chips, and add DEV-only synthetic-report loader as a top-level screen. Add a paid-tier gate at backend `lobby.game.create`: free callers get `403 forbidden` before the lobby service is invoked. The UI hides the private-games sub-panel + create button on free tier (DEV affordances flag overrides). Update every integration test that creates a game to use a new `testenv.PromoteToPaid` helper; add a new `TestLobbyFlow_FreeUserCreateGameForbidden`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
89 lines
3.4 KiB
TypeScript
89 lines
3.4 KiB
TypeScript
// Unit tests for `decodeAccountView` — F8-04b adds an `entitlement`
|
|
// projection on the TS Account, sourced from the FBS
|
|
// `EntitlementSnapshot.is_paid` field. The decode must default to
|
|
// `false` when the snapshot is absent, never throw on null.
|
|
|
|
import { Builder, ByteBuffer } from "flatbuffers";
|
|
import { describe, expect, test } from "vitest";
|
|
|
|
import { decodeAccountView } from "../src/api/account";
|
|
import {
|
|
AccountView,
|
|
EntitlementSnapshot,
|
|
} from "../src/proto/galaxy/fbs/user";
|
|
|
|
function buildAccountView(opts: {
|
|
isPaid?: boolean;
|
|
includeEntitlement: boolean;
|
|
}): AccountView {
|
|
const builder = new Builder(256);
|
|
const userIdOff = builder.createString("user-1");
|
|
const emailOff = builder.createString("user@example.com");
|
|
const userNameOff = builder.createString("Player-1");
|
|
const displayNameOff = builder.createString("Display");
|
|
const langOff = builder.createString("en-US");
|
|
const tzOff = builder.createString("UTC");
|
|
const countryOff = builder.createString("US");
|
|
|
|
let entitlementOff = 0;
|
|
if (opts.includeEntitlement) {
|
|
const planOff = builder.createString("free");
|
|
const sourceOff = builder.createString("default");
|
|
const reasonOff = builder.createString("init");
|
|
EntitlementSnapshot.startEntitlementSnapshot(builder);
|
|
EntitlementSnapshot.addPlanCode(builder, planOff);
|
|
EntitlementSnapshot.addIsPaid(builder, opts.isPaid ?? false);
|
|
EntitlementSnapshot.addSource(builder, sourceOff);
|
|
EntitlementSnapshot.addReasonCode(builder, reasonOff);
|
|
entitlementOff = EntitlementSnapshot.endEntitlementSnapshot(builder);
|
|
}
|
|
|
|
AccountView.startAccountView(builder);
|
|
AccountView.addUserId(builder, userIdOff);
|
|
AccountView.addEmail(builder, emailOff);
|
|
AccountView.addUserName(builder, userNameOff);
|
|
AccountView.addDisplayName(builder, displayNameOff);
|
|
AccountView.addPreferredLanguage(builder, langOff);
|
|
AccountView.addTimeZone(builder, tzOff);
|
|
AccountView.addDeclaredCountry(builder, countryOff);
|
|
if (entitlementOff !== 0) {
|
|
AccountView.addEntitlement(builder, entitlementOff);
|
|
}
|
|
const viewOff = AccountView.endAccountView(builder);
|
|
builder.finish(viewOff);
|
|
|
|
return AccountView.getRootAsAccountView(new ByteBuffer(builder.asUint8Array()));
|
|
}
|
|
|
|
describe("decodeAccountView", () => {
|
|
test("extracts entitlement.isPaid=true from FBS EntitlementSnapshot", () => {
|
|
const view = buildAccountView({ includeEntitlement: true, isPaid: true });
|
|
const account = decodeAccountView(view);
|
|
expect(account.entitlement.isPaid).toBe(true);
|
|
});
|
|
|
|
test("extracts entitlement.isPaid=false from FBS EntitlementSnapshot", () => {
|
|
const view = buildAccountView({ includeEntitlement: true, isPaid: false });
|
|
const account = decodeAccountView(view);
|
|
expect(account.entitlement.isPaid).toBe(false);
|
|
});
|
|
|
|
test("defaults entitlement.isPaid to false when snapshot is absent", () => {
|
|
const view = buildAccountView({ includeEntitlement: false });
|
|
const account = decodeAccountView(view);
|
|
expect(account.entitlement.isPaid).toBe(false);
|
|
});
|
|
|
|
test("populates other Account fields verbatim", () => {
|
|
const view = buildAccountView({ includeEntitlement: true, isPaid: true });
|
|
const account = decodeAccountView(view);
|
|
expect(account.userId).toBe("user-1");
|
|
expect(account.email).toBe("user@example.com");
|
|
expect(account.userName).toBe("Player-1");
|
|
expect(account.displayName).toBe("Display");
|
|
expect(account.preferredLanguage).toBe("en-US");
|
|
expect(account.timeZone).toBe("UTC");
|
|
expect(account.declaredCountry).toBe("US");
|
|
});
|
|
});
|