Skip to content

Commit

Permalink
Merge pull request #436 from holly-cummins/fix-ui-refresh
Browse files Browse the repository at this point in the history
Ensure list of fights refreshes on a fight
  • Loading branch information
holly-cummins authored Nov 20, 2023
2 parents 8c94968 + 1795996 commit 00d43f8
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import {FightList} from "./fight-list/FightList"
import Fight from "./fight/Fight"
import {useEffect, useState} from "react"
import {getFights} from "./shared/api/fight-service"

function App() {

const [fights, setFights] = useState()

const refreshFights = () => getFights().then(answer => setFights(answer))

useEffect(() => {
refreshFights()
}, []
)

return (
<>
<h1>
Welcome to Super Heroes Fight!
</h1>
<Fight/>
<FightList/>
<Fight onFight={refreshFights}/>
<FightList fights={fights}/>
</>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react"
import {render, screen} from "@testing-library/react"
import {fireEvent, render, screen} from "@testing-library/react"
import App from "./App"
import "@testing-library/jest-dom"
import {act} from "react-dom/test-utils"
import {getFights, getRandomFighters} from "./shared/api/fight-service"
import {getFights, getRandomFighters, startFight} from "./shared/api/fight-service"

jest.mock("./shared/api/fight-service")

Expand Down Expand Up @@ -47,7 +47,12 @@ const fight = {
describe("renders the elements", () => {
beforeEach(() => {
getRandomFighters.mockResolvedValue(fighters)
getFights.mockResolvedValue([fight])
startFight.mockResolvedValue(fight)

// To make the row-counting test work, we need the behaviour of getFights to change on each call
getFights.mockResolvedValueOnce([fight])
getFights.mockResolvedValueOnce([{...fight, id: 201}, fight])
getFights.mockResolvedValueOnce([{...fight, id: 202}, {...fight, id: 201}, fight])
})

afterAll(() => {
Expand Down Expand Up @@ -77,4 +82,33 @@ describe("renders the elements", () => {
expect(screen.getByText("Fake villain")).toBeInTheDocument()
expect(screen.getByText(/FIGHT !/)).toBeInTheDocument()
})

it("refreshes the fight list on a fight", async () => {
await act(async () => {
render(<App/>)
})
const getFightCallCount = getFights.mock.calls.length
await act(async () => {
fireEvent.click(screen.getByText(/FIGHT !/i))
})
expect(getFights).toHaveBeenCalledTimes(getFightCallCount + 1)
})

it("renders a new fight row on a fight", async () => {
await act(async () => {
render(<App/>)
})

// Do a fight, to get all the fight output populated so we can count properly
await act(async () => {
fireEvent.click(screen.getByText(/FIGHT !/i))
})

const winnerCount = screen.queryAllByText("Some villain").length
await act(async () => {
fireEvent.click(screen.getByText(/FIGHT !/i))
})
// There should be an extra row, which means an extra occurence of the villain name
expect(screen.queryAllByText("Some villain")).toHaveLength(winnerCount + 1)
})
})
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
import {useEffect, useState} from "react"
import {getFights} from "../shared/api/fight-service"

export function FightList() {


const [fights, setFights] = useState()

useEffect(() => {
getFights().then(answer => setFights(answer))
}, []
)
export function FightList({fights}) {

return (
<table className="table table-striped">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ import React from "react"
import {render, screen, within} from "@testing-library/react"
import "@testing-library/jest-dom"
import {FightList} from "./FightList"
import {getFights} from "../shared/api/fight-service"
import {act} from "react-dom/test-utils"

jest.mock("../shared/api/fight-service")

const fight = {
fightDate: "2023-10-24T21:34:47.617598Z",
id: 200,
Expand All @@ -23,18 +20,18 @@ const fight = {
}

describe("the fight list", () => {
beforeEach(() => {
getFights.mockResolvedValue([fight])
})

afterAll(() => {
jest.resetAllMocks()
})
it("handles missing fights gracefully", async () => {
await act(async () => {
render(<FightList/>)
})

// We don't care too much if it renders headings or shows blank, we just want there not to be an error
})

it("renders a table with column headings", async () => {
await act(async () => {
render(<FightList/>)
render(<FightList fights={[fight]}/>)
})

const table = screen.getByRole("table")
Expand Down Expand Up @@ -65,7 +62,7 @@ describe("the fight list", () => {

it("renders rows for the fights", async () => {
await act(async () => {
render(<FightList/>)
render(<FightList fights={[fight]}/>)
})

expect(screen.getByText("Fake hero")).toBeInTheDocument()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {faComment} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"


function Fight() {
function Fight({onFight}) {
const [fighters, setFighters] = useState()
const [fightResult, setFightResult] = useState()
const [narration, setNarration] = useState()
Expand All @@ -21,7 +21,10 @@ function Fight() {
}

const fight = () => {
startFight(fighters).then(response => setFightResult(response))
startFight(fighters).then(response => {
setFightResult(response)
onFight()
})
}

// This initialises the component on its initial load with a call to get fighters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ describe("the fight visualisation", () => {
})

describe("when a back end is available", () => {
const onFight = jest.fn()

beforeEach(() => {
getRandomFighters.mockResolvedValue(fighters)
startFight.mockResolvedValue(fight)
Expand All @@ -73,23 +75,23 @@ describe("the fight visualisation", () => {

it("renders fighters", async () => {
await act(async () => {
render(<Fight/>)
render(<Fight onFight={onFight}/>)
})
expect(screen.getByText("Fake hero")).toBeInTheDocument()
expect(screen.getByText("Fake villain")).toBeInTheDocument()
})

it("renders a fight button", async () => {
await act(async () => {
render(<Fight/>)
render(<Fight onFight={onFight}/>)
})
const button = screen.getByText(/FIGHT !/i)
expect(button).toBeInTheDocument()
})

it("renders winners when the fight button is clicked", async () => {
await act(async () => {
render(<Fight/>)
render(<Fight onFight={onFight}/>)
})

const nameCount = screen.getAllByText("Fake villain").length
Expand All @@ -105,7 +107,7 @@ describe("the fight visualisation", () => {

it("renders narration when the narrate button is clicked", async () => {
await act(async () => {
render(<Fight/>)
render(<Fight onFight={onFight}/>)
})

const nameCount = screen.getAllByText("Fake villain").length
Expand All @@ -121,6 +123,18 @@ describe("the fight visualisation", () => {
expect(screen.getByText(narration)).toBeInTheDocument()
})

it("triggers the onFight callback", async () => {
await act(async () => {
render(<Fight onFight={onFight}/>)
})

const nameCount = screen.getAllByText("Fake villain").length

await act(async () => {
fireEvent.click(screen.getByText(/FIGHT !/i))
})
expect(onFight).toHaveBeenCalled()
})

})

Expand Down

0 comments on commit 00d43f8

Please sign in to comment.