Backend: - Add home_team_dice_color and away_team_dice_color to GameState model - Extract dice_color from game metadata in StateManager (default: cc0000) - Add runners_on_base param to roll_ab for chaos check skipping Frontend - Dice Display: - Create DiceShapes.vue with SVG d6 (square) and d20 (hexagon) shapes - Apply home team's dice_color to d6 dice, white for resolution d20 - Show chaos d20 in amber only when WP/PB check triggered - Add automatic text contrast based on color luminance - Reduce blank space and remove info bubble from dice results Frontend - Player Cards: - Consolidate pitcher/batter cards to single location below diamond - Add active card highlighting based on dice roll (d6_one: 1-3=batter, 4-6=pitcher) - New card header format: [Team] Position [Name] with full card image - Remove redundant card displays from GameBoard and GameplayPanel - Enlarge PlayerCardModal on desktop (max-w-3xl at 1024px+) Tests: - Add DiceShapes.spec.ts with 34 tests for color calculations and rendering - Update DiceRoller.spec.ts for new DiceShapes integration - Fix test_roll_dice_success for new runners_on_base parameter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
725 lines
21 KiB
TypeScript
725 lines
21 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
import { mount } from '@vue/test-utils'
|
|
import DiceRoller from '~/components/Gameplay/DiceRoller.vue'
|
|
import DiceShapes from '~/components/Gameplay/DiceShapes.vue'
|
|
import type { RollData } from '~/types'
|
|
|
|
describe('DiceRoller', () => {
|
|
const createRollData = (overrides = {}): RollData => ({
|
|
roll_id: 'test-roll-123',
|
|
d6_one: 3,
|
|
d6_two_a: 2,
|
|
d6_two_b: 4,
|
|
d6_two_total: 6,
|
|
chaos_d20: 15,
|
|
resolution_d20: 8,
|
|
check_wild_pitch: false,
|
|
check_passed_ball: false,
|
|
chaos_check_skipped: false,
|
|
timestamp: '2025-01-13T12:00:00Z',
|
|
...overrides,
|
|
})
|
|
|
|
const defaultProps = {
|
|
canRoll: true,
|
|
pendingRoll: null as RollData | null,
|
|
diceColor: 'cc0000', // Default red
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllTimers()
|
|
vi.useFakeTimers()
|
|
})
|
|
|
|
// ============================================================================
|
|
// Rendering Tests
|
|
// ============================================================================
|
|
|
|
describe('Rendering', () => {
|
|
it('renders roll button when no pending roll', () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
expect(wrapper.find('.roll-button').exists()).toBe(true)
|
|
expect(wrapper.text()).toContain('Roll Dice')
|
|
expect(wrapper.find('.dice-results').exists()).toBe(false)
|
|
})
|
|
|
|
it('renders dice results when pending roll exists', () => {
|
|
const rollData = createRollData()
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
expect(wrapper.find('.roll-button').exists()).toBe(false)
|
|
expect(wrapper.find('.dice-results').exists()).toBe(true)
|
|
expect(wrapper.text()).toContain('Dice Results')
|
|
})
|
|
|
|
it('displays three dice when no WP/PB check triggered (chaos d20 hidden)', () => {
|
|
/**
|
|
* When chaos d20 doesn't trigger WP (1) or PB (2), it's hidden since values 3-20
|
|
* have no game effect. This reduces visual noise in the dice display.
|
|
*/
|
|
const rollData = createRollData({
|
|
d6_one: 5,
|
|
d6_two_total: 8,
|
|
chaos_d20: 17, // Not 1 or 2, so no check triggered
|
|
resolution_d20: 3,
|
|
check_wild_pitch: false,
|
|
check_passed_ball: false,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
// DiceShapes components are rendered for each die
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents).toHaveLength(3) // chaos d20 hidden when no check triggered
|
|
})
|
|
|
|
it('displays all four dice when wild pitch check triggered', () => {
|
|
/**
|
|
* Chaos d20 is shown when it triggers a Wild Pitch check (value == 1),
|
|
* since this affects gameplay and the user needs to see the dice value.
|
|
*/
|
|
const rollData = createRollData({
|
|
d6_one: 5,
|
|
d6_two_total: 8,
|
|
chaos_d20: 1, // Triggers WP check
|
|
resolution_d20: 3,
|
|
check_wild_pitch: true,
|
|
check_passed_ball: false,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents).toHaveLength(4) // chaos d20 shown for WP check
|
|
})
|
|
|
|
it('displays all four dice when passed ball check triggered', () => {
|
|
/**
|
|
* Chaos d20 is shown when it triggers a Passed Ball check (value == 2),
|
|
* since this affects gameplay and the user needs to see the dice value.
|
|
*/
|
|
const rollData = createRollData({
|
|
d6_one: 5,
|
|
d6_two_total: 8,
|
|
chaos_d20: 2, // Triggers PB check
|
|
resolution_d20: 3,
|
|
check_wild_pitch: false,
|
|
check_passed_ball: true,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents).toHaveLength(4) // chaos d20 shown for PB check
|
|
})
|
|
|
|
it('displays d6_two component dice values', () => {
|
|
const rollData = createRollData({
|
|
d6_two_a: 3,
|
|
d6_two_b: 5,
|
|
d6_two_total: 8,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
expect(wrapper.text()).toContain('(3 + 5)')
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Button State Tests
|
|
// ============================================================================
|
|
|
|
describe('Button States', () => {
|
|
it('enables button when canRoll is true', () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
const button = wrapper.find('.roll-button')
|
|
expect(button.classes()).toContain('roll-button-enabled')
|
|
expect(button.classes()).not.toContain('roll-button-disabled')
|
|
expect(button.attributes('disabled')).toBeUndefined()
|
|
})
|
|
|
|
it('disables button when canRoll is false', () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
},
|
|
})
|
|
|
|
const button = wrapper.find('.roll-button')
|
|
expect(button.classes()).toContain('roll-button-disabled')
|
|
expect(button.classes()).not.toContain('roll-button-enabled')
|
|
expect(button.attributes('disabled')).toBeDefined()
|
|
})
|
|
|
|
it('shows loading state when rolling', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
|
|
expect(wrapper.text()).toContain('Rolling...')
|
|
expect(wrapper.find('.animate-spin').exists()).toBe(true)
|
|
})
|
|
|
|
it('disables button during rolling animation', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
const button = wrapper.find('.roll-button')
|
|
|
|
expect(button.attributes('disabled')).toBeDefined()
|
|
})
|
|
|
|
it('resets rolling state after timeout', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
expect(wrapper.text()).toContain('Rolling...')
|
|
|
|
vi.advanceTimersByTime(2000)
|
|
await wrapper.vm.$nextTick()
|
|
|
|
expect(wrapper.text()).not.toContain('Rolling...')
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Event Emission Tests
|
|
// ============================================================================
|
|
|
|
describe('Event Emission', () => {
|
|
it('emits roll event when button clicked', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
|
|
expect(wrapper.emitted('roll')).toBeTruthy()
|
|
expect(wrapper.emitted('roll')).toHaveLength(1)
|
|
})
|
|
|
|
it('does not emit roll when canRoll is false', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
},
|
|
})
|
|
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
|
|
expect(wrapper.emitted('roll')).toBeFalsy()
|
|
})
|
|
|
|
it('does not emit roll during rolling animation', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
await wrapper.find('.roll-button').trigger('click')
|
|
|
|
expect(wrapper.emitted('roll')).toHaveLength(1)
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Special Events Tests
|
|
// ============================================================================
|
|
|
|
describe('Special Events', () => {
|
|
it('shows wild pitch indicator when check_wild_pitch is true', () => {
|
|
const rollData = createRollData({ check_wild_pitch: true })
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
expect(wrapper.find('.wild-pitch').exists()).toBe(true)
|
|
expect(wrapper.text()).toContain('Wild Pitch Check')
|
|
})
|
|
|
|
it('shows passed ball indicator when check_passed_ball is true', () => {
|
|
const rollData = createRollData({ check_passed_ball: true })
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
expect(wrapper.find('.passed-ball').exists()).toBe(true)
|
|
expect(wrapper.text()).toContain('Passed Ball Check')
|
|
})
|
|
|
|
it('shows both indicators when both checks are true', () => {
|
|
const rollData = createRollData({
|
|
check_wild_pitch: true,
|
|
check_passed_ball: true,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
expect(wrapper.find('.wild-pitch').exists()).toBe(true)
|
|
expect(wrapper.find('.passed-ball').exists()).toBe(true)
|
|
})
|
|
|
|
it('hides special events section when no checks are true', () => {
|
|
const rollData = createRollData({
|
|
check_wild_pitch: false,
|
|
check_passed_ball: false,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
expect(wrapper.find('.special-events').exists()).toBe(false)
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Chaos d20 Conditional Display Tests
|
|
// ============================================================================
|
|
|
|
describe('Chaos d20 Conditional Display', () => {
|
|
/**
|
|
* The chaos d20 dice is only displayed when it triggers a Wild Pitch (1)
|
|
* or Passed Ball (2) check. Values 3-20 have no game effect and showing
|
|
* them creates visual noise. When bases are empty, the chaos check is
|
|
* skipped entirely since WP/PB is meaningless without runners.
|
|
*/
|
|
|
|
it('hides chaos d20 when no check triggered (values 3-20)', () => {
|
|
const rollData = createRollData({
|
|
chaos_d20: 15,
|
|
check_wild_pitch: false,
|
|
check_passed_ball: false,
|
|
chaos_check_skipped: false, // Runners on base, but roll was 3-20
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const chaosItem = wrapper.find('.dice-chaos')
|
|
expect(chaosItem.exists()).toBe(false)
|
|
})
|
|
|
|
it('hides chaos d20 when chaos check was skipped (bases empty)', () => {
|
|
const rollData = createRollData({
|
|
chaos_d20: 1, // Would trigger WP but bases empty
|
|
check_wild_pitch: false, // Skipped due to no runners
|
|
check_passed_ball: false,
|
|
chaos_check_skipped: true, // No runners on base
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const chaosItem = wrapper.find('.dice-chaos')
|
|
expect(chaosItem.exists()).toBe(false)
|
|
})
|
|
|
|
it('shows chaos d20 when wild pitch check triggered', () => {
|
|
const rollData = createRollData({
|
|
chaos_d20: 1,
|
|
check_wild_pitch: true,
|
|
check_passed_ball: false,
|
|
chaos_check_skipped: false,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const chaosItem = wrapper.find('.dice-chaos')
|
|
expect(chaosItem.exists()).toBe(true)
|
|
})
|
|
|
|
it('shows chaos d20 when passed ball check triggered', () => {
|
|
const rollData = createRollData({
|
|
chaos_d20: 2,
|
|
check_wild_pitch: false,
|
|
check_passed_ball: true,
|
|
chaos_check_skipped: false,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const chaosItem = wrapper.find('.dice-chaos')
|
|
expect(chaosItem.exists()).toBe(true)
|
|
})
|
|
|
|
it('displays correct chaos d20 value when shown', () => {
|
|
const rollData = createRollData({
|
|
chaos_d20: 1,
|
|
check_wild_pitch: true,
|
|
check_passed_ball: false,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
// Find the chaos d20 component (3rd one when WP/PB triggered)
|
|
const chaosDie = diceComponents[2]
|
|
expect(chaosDie.props('value')).toBe(1)
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Timestamp Formatting Tests
|
|
// ============================================================================
|
|
|
|
describe('Timestamp Formatting', () => {
|
|
it('formats timestamp correctly', () => {
|
|
const rollData = createRollData({
|
|
timestamp: '2025-01-13T14:30:45Z',
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const timestampText = wrapper.find('.dice-header .text-sm').text()
|
|
expect(timestampText).toMatch(/\d{1,2}:\d{2}:\d{2}/)
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Dice Color Tests
|
|
// ============================================================================
|
|
|
|
describe('Dice Color', () => {
|
|
it('passes dice color to d6 DiceShapes components', () => {
|
|
const rollData = createRollData()
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
diceColor: '0066ff', // Blue
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
// First two are d6 dice
|
|
expect(diceComponents[0].props('color')).toBe('0066ff')
|
|
expect(diceComponents[1].props('color')).toBe('0066ff')
|
|
})
|
|
|
|
it('uses white for resolution d20', () => {
|
|
const rollData = createRollData()
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
// Last one is resolution d20 (when no chaos shown)
|
|
const resolutionD20 = diceComponents[diceComponents.length - 1]
|
|
expect(resolutionD20.props('color')).toBe('ffffff')
|
|
})
|
|
|
|
it('uses amber for chaos d20 when shown', () => {
|
|
const rollData = createRollData({
|
|
check_wild_pitch: true,
|
|
chaos_d20: 1,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
// Third one is chaos d20 when WP triggered
|
|
const chaosD20 = diceComponents[2]
|
|
expect(chaosD20.props('color')).toBe('f59e0b')
|
|
})
|
|
|
|
it('uses default red when no diceColor prop provided', () => {
|
|
const rollData = createRollData()
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
// No diceColor prop
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents[0].props('color')).toBe('cc0000')
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Dice Type Tests
|
|
// ============================================================================
|
|
|
|
describe('Dice Types', () => {
|
|
it('renders d6 type for first two dice', () => {
|
|
const rollData = createRollData()
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents[0].props('type')).toBe('d6')
|
|
expect(diceComponents[1].props('type')).toBe('d6')
|
|
})
|
|
|
|
it('renders d20 type for resolution die', () => {
|
|
const rollData = createRollData()
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
// Last one is resolution d20
|
|
const resolutionD20 = diceComponents[diceComponents.length - 1]
|
|
expect(resolutionD20.props('type')).toBe('d20')
|
|
})
|
|
|
|
it('renders d20 type for chaos die when shown', () => {
|
|
const rollData = createRollData({
|
|
check_wild_pitch: true,
|
|
chaos_d20: 1,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
// Third one is chaos d20
|
|
expect(diceComponents[2].props('type')).toBe('d20')
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Layout Tests
|
|
// ============================================================================
|
|
|
|
describe('Layout', () => {
|
|
it('applies compact display class when chaos d20 is hidden', () => {
|
|
const rollData = createRollData() // Default: no WP/PB check
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceDisplay = wrapper.find('.dice-display')
|
|
expect(diceDisplay.classes()).toContain('dice-display-compact')
|
|
})
|
|
|
|
it('does not apply compact display class when chaos d20 is shown', () => {
|
|
const rollData = createRollData({ check_wild_pitch: true, chaos_d20: 1 })
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceDisplay = wrapper.find('.dice-display')
|
|
expect(diceDisplay.classes()).not.toContain('dice-display-compact')
|
|
})
|
|
})
|
|
|
|
// ============================================================================
|
|
// Edge Cases
|
|
// ============================================================================
|
|
|
|
describe('Edge Cases', () => {
|
|
it('handles maximum dice values', () => {
|
|
const rollData = createRollData({
|
|
d6_one: 6,
|
|
d6_two_a: 6,
|
|
d6_two_b: 6,
|
|
d6_two_total: 12,
|
|
chaos_d20: 20,
|
|
resolution_d20: 20,
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents[0].props('value')).toBe(6)
|
|
expect(diceComponents[1].props('value')).toBe(12)
|
|
})
|
|
|
|
it('handles minimum dice values', () => {
|
|
const rollData = createRollData({
|
|
d6_one: 1,
|
|
d6_two_a: 1,
|
|
d6_two_b: 1,
|
|
d6_two_total: 2,
|
|
chaos_d20: 1,
|
|
resolution_d20: 1,
|
|
check_wild_pitch: true, // Show chaos d20
|
|
})
|
|
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: rollData,
|
|
},
|
|
})
|
|
|
|
const diceComponents = wrapper.findAllComponents(DiceShapes)
|
|
expect(diceComponents[0].props('value')).toBe(1)
|
|
expect(diceComponents[1].props('value')).toBe(2)
|
|
expect(diceComponents[2].props('value')).toBe(1) // chaos d20
|
|
expect(diceComponents[3].props('value')).toBe(1) // resolution d20
|
|
})
|
|
|
|
it('transitions from no roll to roll result', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: defaultProps,
|
|
})
|
|
|
|
expect(wrapper.find('.roll-button').exists()).toBe(true)
|
|
expect(wrapper.find('.dice-results').exists()).toBe(false)
|
|
|
|
await wrapper.setProps({ pendingRoll: createRollData(), canRoll: false })
|
|
|
|
expect(wrapper.find('.roll-button').exists()).toBe(false)
|
|
expect(wrapper.find('.dice-results').exists()).toBe(true)
|
|
})
|
|
|
|
it('clears roll result when pendingRoll set to null', async () => {
|
|
const wrapper = mount(DiceRoller, {
|
|
props: {
|
|
...defaultProps,
|
|
canRoll: false,
|
|
pendingRoll: createRollData(),
|
|
},
|
|
})
|
|
|
|
expect(wrapper.find('.dice-results').exists()).toBe(true)
|
|
|
|
await wrapper.setProps({ pendingRoll: null, canRoll: true })
|
|
|
|
expect(wrapper.find('.dice-results').exists()).toBe(false)
|
|
expect(wrapper.find('.roll-button').exists()).toBe(true)
|
|
})
|
|
})
|
|
})
|