Skip to content
Prev Previous commit
Next Next commit
setup getProgress tests
Signed-off-by: shmck <[email protected]>
  • Loading branch information
ShMcK committed Jul 31, 2020
commit 79f0fba8625d39c0551b0bee6ce3f1f794472e28
92 changes: 92 additions & 0 deletions web-app/src/containers/Start/getProgress.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as TT from 'typings/tutorial'
import getProgress from './getProgress'

const levels: TT.Level[] = [
{
id: '1',
title: '',
summary: '',
content: '',
steps: [
{
id: '1.1',
content: 'First',
setup: { commits: [] },
},
{
id: '1.2',
content: 'Second',
setup: { commits: [] },
},
{
id: '1.3',
content: 'Last',
setup: { commits: [] },
},
],
},
{
id: '2',
title: '',
summary: '',
content: '',
steps: [
{
id: '2.1',
content: 'First',
setup: { commits: [] },
},
{
id: '2.2',
content: 'Second',
setup: { commits: [] },
},
{
id: '2.3',
content: 'Last',
setup: { commits: [] },
},
],
},
]

describe('getProgress', () => {
it('should accept no progress', () => {
const position = { levelId: '1', stepId: '1.1', complete: false }
const result = getProgress(levels, position)
expect(result).toBe(0)
})
it('should account for a completed level that has not continued', () => {
const position = { levelId: '1', stepId: '1.3', complete: true }
const result = getProgress(levels, position)
expect(result).toBe(50)
})
it('should use the last completed level', () => {
const position = { levelId: '2', stepId: '2.1', complete: false }
const result = getProgress(levels, position)
expect(result).toBe(50)
})
it('should work if a level has no steps', () => {
const noStepLevels = [
{ ...levels[0], steps: [] },
{ ...levels[1], steps: [] },
]
const position = { levelId: '1', stepId: null, complete: false }
const result = getProgress(noStepLevels, position)
expect(result).toBe(0)
})
it('should work if a level has no steps but completed', () => {
const noStepLevels = [
{ ...levels[0], steps: [] },
{ ...levels[1], steps: [] },
]
const position = { levelId: '1', stepId: null, complete: true }
const result = getProgress(noStepLevels, position)
expect(result).toBe(50)
})
it('should accept a completed tutorial', () => {
const position = { levelId: '2', stepId: '2.3', complete: true }
const result = getProgress(levels, position)
expect(result).toBe(100)
})
})
27 changes: 27 additions & 0 deletions web-app/src/containers/Start/getProgress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as T from 'typings'
import * as TT from 'typings/tutorial'

const getProgress = (levels: TT.Level[] = [], position: T.Position): number => {
let progress = 0
let isLevelComplete = false
if (levels && levels.length) {
const totalLevels = levels.length
const findLevel = (level: TT.Level) => level.id === position.levelId
const currentLevel: TT.Level | undefined = levels.find(findLevel)
let currentLevelIndex: number = levels.findIndex(findLevel)
if (!currentLevel) {
throw new Error('Invalid level')
}
// check if the level is complete
if (position.stepId && currentLevel.steps && currentLevel.steps.length) {
const lastStepInLevel: TT.Step | null = currentLevel.steps[currentLevel.steps.length]
isLevelComplete = position.complete && lastStepInLevel.id === position.stepId
} else {
isLevelComplete = position.complete
}
progress = Math.round(((currentLevelIndex + (isLevelComplete ? 1 : 0)) / totalLevels) * 100)
}
return progress
}

export default getProgress
31 changes: 6 additions & 25 deletions web-app/src/containers/Start/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Button from '../../components/Button'
import { Theme } from '../../styles/theme'
import { ADMIN_MODE } from '../../environment'
import AdminToggle from '../../services/admin/AdminToggle'
import getProgress from './getProgress'

const styles = {
page: (theme: Theme) => ({
Expand Down Expand Up @@ -95,8 +96,8 @@ const styles = {
interface Props {
onContinue(): void
onNew(): void
tutorial?: TT.Tutorial
progress?: number
tutorial: TT.Tutorial | null
progress: number
}

export const StartPage = (props: Props) => (
Expand All @@ -122,7 +123,7 @@ export const StartPage = (props: Props) => (
<button onClick={props.onContinue} css={styles.buttonLarge}>
Continue Tutorial
<div css={styles.continueTitle}>"{props.tutorial.summary.title}"</div>
<Progress style={{ marginLeft: '1rem' }} percent={props.progress || 0} hasBorder size="large" />
<Progress style={{ marginLeft: '1rem' }} percent={props.progress} hasBorder size="large" />
</button>
</div>
)}
Expand All @@ -141,32 +142,12 @@ interface ContainerProps {
}

const StartPageContainer = ({ context, send }: ContainerProps) => {
const tutorial = context.tutorial || undefined
let progress
let isLevelComplete = false
if (tutorial) {
const totalLevels = tutorial.levels.length
const { position } = context
const findLevel = (level: TT.Level) => level.id === position.levelId
const currentLevel: TT.Level | undefined = tutorial.levels.find(findLevel)
let currentLevelIndex: number = tutorial.levels.findIndex(findLevel)
if (!currentLevel) {
throw new Error('Invalid level')
}
// check if the level is complete
if (position.stepId && currentLevel.steps && currentLevel.steps.length) {
const lastStepInLevel: TT.Step | null = currentLevel.steps[currentLevel.steps.length]
isLevelComplete = position.complete && lastStepInLevel.id === position.stepId
} else {
isLevelComplete = position.complete
}
progress = Math.round(((currentLevelIndex + (isLevelComplete ? 1 : 0)) / totalLevels) * 100)
}
const progress: number = getProgress(context?.tutorial?.levels, context.position)
return (
<StartPage
onContinue={() => send({ type: 'CONTINUE_TUTORIAL' })}
onNew={() => send({ type: 'NEW_TUTORIAL' })}
tutorial={tutorial}
tutorial={context.tutorial}
progress={progress}
/>
)
Expand Down