Skip to content

Commit

Permalink
Lstebner/rtl tests take two (#296)
Browse files Browse the repository at this point in the history
* convert Home test to use rtl

* add tests for go to shop button

* update Workshop to use rtl

    - add some missing props to propTypes
    - convert existing test
    - started to add some more coverage

* move getUpgradesAvailable to separate file to make it mockable + add tests

* break Workshop into smaller pieces

    this commit is a mixture of reorganizing and also refactoring:
    - RecipeList was created for a section of the panel that was
      duplicated between both the forge and the kitchen
    - ForgeTabPanel and KitchenTabPanel were separated from Workshop
      mostly for organizational purposes. they're a little easier to
      grok this way, and Workshop reads a bit more clearly as well
    - some refactoring to Workshop to simplify the separation of
      learnedRecipes into the kitchen and forge lists
  • Loading branch information
lstebner authored Jun 26, 2022
1 parent ec1da22 commit 734284d
Show file tree
Hide file tree
Showing 9 changed files with 450 additions and 195 deletions.
18 changes: 12 additions & 6 deletions src/components/Home/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,21 @@ const getRemainingOnboardingAchievements = memoize(completedAchievements =>
)
)

const environmentAllowsInstall = ['production', 'development'].includes(
process.env.NODE_ENV
)

const VALID_ORIGINS = [
'https://jeremyckahn.github.io',
'https://www.farmhand.life',
'http://localhost:3000',
]

// https://stackoverflow.com/questions/41742390/javascript-to-check-if-pwa-or-mobile-web/41749865#41749865
const isInstallable =
// process.env checks are needed to make tests not fail
(process.env.NODE_ENV === 'production' ||
process.env.NODE_ENV === 'development') &&
environmentAllowsInstall &&
!window.matchMedia('(display-mode: standalone)').matches &&
(window.location.origin === 'https://jeremyckahn.github.io' ||
window.location.origin === 'https://www.farmhand.life' ||
window.location.origin === 'http://localhost:3000') // For debugging
VALID_ORIGINS.includes(window.location.origin)

const Home = ({
completedAchievements,
Expand Down
54 changes: 39 additions & 15 deletions src/components/Home/Home.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
import React from 'react'
import { shallow } from 'enzyme'

import { screen, render } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

import FarmhandContext from '../Farmhand/Farmhand.context'

import Home from './Home'

let component

beforeEach(() => {
component = shallow(
<Home
{...{
completedAchievements: {},
handleViewChangeButtonClick: () => {},
}}
/>
)
})
describe('<Home />', () => {
let handleViewChangeButtonClick

beforeEach(() => {
const gameState = {
completedAchievements: {},
}

handleViewChangeButtonClick = jest.fn()

render(
<FarmhandContext.Provider value={{ gameState, handlers: {} }}>
<Home handleViewChangeButtonClick={handleViewChangeButtonClick} />
</FarmhandContext.Provider>
)
})

test('rendered welcome message', () => {
expect(screen.getByText('Welcome!')).toBeInTheDocument()
})

describe('go to shop', () => {
const shopButton = () =>
screen.getByRole('button', { name: 'Go to the shop' })

test('contains an action to go to the shop', () => {
expect(shopButton()).toBeInTheDocument()
})

test('calls to change view when shop button is clicked', () => {
userEvent.click(shopButton())

test('renders', () => {
expect(component).toHaveLength(1)
expect(handleViewChangeButtonClick).toHaveBeenCalledWith('SHOP')
})
})
})
79 changes: 79 additions & 0 deletions src/components/Workshop/ForgeTabPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react'
import PropTypes from 'prop-types'

import Card from '@material-ui/core/Card'
import CardContent from '@material-ui/core/CardContent'
import Divider from '@material-ui/core/Divider'
import ReactMarkdown from 'react-markdown'

import { recipeType } from '../../enums'

import { recipeCategories } from '../../data/maps'

import UpgradePurchase from '../UpgradePurchase'

import { TabPanel } from './TabPanel'
import { RecipeList } from './RecipeList'

import { getUpgradesAvailable } from './getUpgradesAvailable'

export function ForgeTabPanel({
currentTab,
index,
learnedForgeRecipes,
setCurrentTab,
toolLevels,
}) {
const upgradesAvailable = getUpgradesAvailable({
toolLevels,
learnedForgeRecipes,
})

return (
<TabPanel value={currentTab} index={index}>
<RecipeList
learnedRecipes={learnedForgeRecipes}
allRecipes={recipeCategories[recipeType.FORGE]}
/>
{upgradesAvailable.length ? (
<>
<Divider />
<ul className="card-list">
<li>
<h4>Tool Upgrades</h4>
</li>
{upgradesAvailable.map(upgrade => (
<li key={upgrade.id}>
<UpgradePurchase upgrade={upgrade} />
</li>
))}
</ul>
</>
) : null}
<Divider />
<ul className="card-list">
<li>
<Card>
<CardContent>
<ReactMarkdown
{...{
linkTarget: '_blank',
className: 'markdown',
source: `Forge Recipes are learned by selling resources mined from the field.`,
}}
/>
</CardContent>
</Card>
</li>
</ul>
</TabPanel>
)
}

ForgeTabPanel.propTypes = {
currentTab: PropTypes.number.isRequired,
index: PropTypes.number.isRequired,
learnedForgeRecipes: PropTypes.array.isRequired,
setCurrentTab: PropTypes.func.isRequired,
toolLevels: PropTypes.object.isRequired,
}
53 changes: 53 additions & 0 deletions src/components/Workshop/KitchenTabPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react'
import PropTypes from 'prop-types'

import Card from '@material-ui/core/Card'
import CardContent from '@material-ui/core/CardContent'
import Divider from '@material-ui/core/Divider'
import ReactMarkdown from 'react-markdown'

import { recipeType } from '../../enums'

import { recipeCategories } from '../../data/maps'

import { TabPanel } from './TabPanel'
import { RecipeList } from './RecipeList'

export function KitchenTabPanel({
currentTab,
index,
learnedKitchenRecipes,
setCurrentTab,
}) {
return (
<TabPanel value={currentTab} index={index}>
<RecipeList
learnedRecipes={learnedKitchenRecipes}
allRecipes={recipeCategories[recipeType.KITCHEN]}
/>
<Divider />
<ul className="card-list">
<li>
<Card>
<CardContent>
<ReactMarkdown
{...{
linkTarget: '_blank',
className: 'markdown',
source: `Kitchen recipes are learned by selling crops and animal products. Sell as much as you can of a wide variety of items!`,
}}
/>
</CardContent>
</Card>
</li>
</ul>
</TabPanel>
)
}

KitchenTabPanel.propTypes = {
currentTab: PropTypes.number.isRequired,
index: PropTypes.number.isRequired,
learnedKitchenRecipes: PropTypes.array.isRequired,
setCurrentTab: PropTypes.func.isRequired,
}
33 changes: 33 additions & 0 deletions src/components/Workshop/RecipeList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react'
import PropTypes from 'prop-types'

import Recipe from '../Recipe'

export function RecipeList({ allRecipes, learnedRecipes }) {
const numLearnedRecipes = learnedRecipes.length
const totalRecipes = Object.keys(allRecipes).length

return (
<>
<h3>
Learned Recipes ({numLearnedRecipes} / {totalRecipes})
</h3>
<ul className="card-list">
{learnedRecipes.map(recipeId => (
<li key={recipeId}>
<Recipe
{...{
recipe: allRecipes[recipeId],
}}
/>
</li>
))}
</ul>
</>
)
}

RecipeList.propTypes = {
allRecipes: PropTypes.object.isRequired,
learnedRecipes: PropTypes.array.isRequired,
}
Loading

0 comments on commit 734284d

Please sign in to comment.