diff --git a/src/apps/golf/components/GolfTable.tsx b/src/apps/golf/components/GolfTable.tsx
index e4829bb7..e3c03cab 100644
--- a/src/apps/golf/components/GolfTable.tsx
+++ b/src/apps/golf/components/GolfTable.tsx
@@ -29,11 +29,8 @@ const GolfTable = ({ playerId, connected, view, table, shareUrl = null }: GolfTa
const acting = isMyTurn && connected
const inPlay = view.gamePhase === 'playing' || view.gamePhase === 'knocked'
- const isWinner = (player: Player | undefined) => {
- if (player === undefined || ended === null) return false
- if (ended.winners.length > 0) return ended.winners.includes(player.id)
- return player.id === ended.winner
- }
+ const isWinner = (player: Player | undefined) =>
+ player !== undefined && ended !== null && ended.winners.includes(player.id)
useEffect(() => {
if (view.gamePhase === 'ended') {
diff --git a/src/apps/golf/components/__tests__/GolfTable.test.tsx b/src/apps/golf/components/__tests__/GolfTable.test.tsx
index 782f4cb8..a19abb96 100644
--- a/src/apps/golf/components/__tests__/GolfTable.test.tsx
+++ b/src/apps/golf/components/__tests__/GolfTable.test.tsx
@@ -147,6 +147,18 @@ describe('GolfTable', () => {
expect(screen.getAllByText('👑')).toHaveLength(2)
})
+ // The contract requires winners (golf.smithy GameEnded); winner is only
+ // display text, so it never crowns anyone on its own.
+ it('only the winners list crowns; the display string does not', () => {
+ vi.useFakeTimers()
+ const t = table({ ended: { winner: 'alice', winners: [] } })
+ render()
+ expect(screen.queryByText('You won!')).toBeNull()
+ expect(screen.getByText('alice wins!')).toBeTruthy()
+ act(() => vi.advanceTimersByTime(3000))
+ expect(screen.queryByText('👑')).toBeNull()
+ })
+
it('an ended table with no result yet is just over', () => {
render()
expect(screen.getByText('Game over')).toBeTruthy()