Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 0 additions & 54 deletions src/components/academy/__tests__/Missions.tsx

This file was deleted.

35 changes: 29 additions & 6 deletions src/components/academy/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/* tslint:disable: jsx-no-lambda */

import * as qs from 'query-string'
import * as React from 'react'
import { Redirect, Route, RouteComponentProps, Switch } from 'react-router'

import MissionsContainer from '../../containers/academy/MissionsContainer'
import AssessmentListingContainer from '../../containers/assessment/AssessmentListingContainer'
import Game from '../../containers/GameContainer'
import { isAcademyRe } from '../../reducers/session'
import { HistoryHelper } from '../../utils/history'
import { AssessmentCategories, AssessmentCategory } from '../assessment/assessmentShape'
import AcademyNavigationBar from './NavigationBar'

interface IAcademyProps extends IDispatchProps, IOwnProps, IStateProps, RouteComponentProps<{}> {}
Expand All @@ -23,17 +26,37 @@ export interface IStateProps {
historyHelper: HistoryHelper
}

const assessmentListingRenderFactory = (cat: AssessmentCategory) => (
routerProps: RouteComponentProps<any>
) => <AssessmentListingContainer assessmentCategory={cat} />

export const Academy: React.SFC<IAcademyProps> = props => (
<div className="Academy">
<AcademyNavigationBar />
<Switch>
{checkLoggedIn(props)}
<Route path="/academy/contests" component={MissionsContainer} />
<Route
path="/academy/contests"
render={assessmentListingRenderFactory(AssessmentCategories.CONTEST)}
/>
<Route path="/academy/game" component={Game} />
<Route exact={true} path="/academy/missions" component={MissionsContainer} />
<Route path="/academy/missions/:missionId" component={MissionsContainer} />
<Route path="/academy/paths" component={MissionsContainer} />
<Route path="/academy/sidequests" component={MissionsContainer} />
<Route
exact={true}
path="/academy/missions"
render={assessmentListingRenderFactory(AssessmentCategories.MISSION)}
/>
<Route
path="/academy/missions/:assessmentId"
render={assessmentListingRenderFactory(AssessmentCategories.MISSION)}
/>
<Route
path="/academy/paths"
render={assessmentListingRenderFactory(AssessmentCategories.PATH)}
/>
<Route
path="/academy/sidequests"
render={assessmentListingRenderFactory(AssessmentCategories.SIDEQUEST)}
/>
<Route exact={true} path="/academy" component={dynamicRedirect(props)} />
<Route component={redirectTo404} />
</Switch>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,50 @@ import * as React from 'react'
import { RouteComponentProps } from 'react-router'
import { NavLink } from 'react-router-dom'

import AssessmentContainer from '../../containers/AssessmentContainer'
import AssessmentContainer from '../../containers/assessment'
import { OwnProps as AssessmentProps } from '../assessment'
import { AssessmentCategory } from '../assessment/assessmentShape'
import { IAssessmentOverview } from '../assessment/assessmentShape'
import ContentDisplay, { IContentDisplayProps } from '../commons/ContentDisplay'

export interface IMissionParams {
missionId?: string
export interface IAssessmentParams {
assessmentId?: string
}

export interface IMissionsProps extends RouteComponentProps<IMissionParams> {
export interface IAssessmentListingProps extends RouteComponentProps<IAssessmentParams> {
assessmentOverviews?: IAssessmentOverview[]
assessmentCategory: AssessmentCategory
handleAssessmentOverviewFetch: () => void
}

export type StateProps = Pick<IMissionsProps, 'assessmentOverviews'>
export type DispatchProps = Pick<IMissionsProps, 'handleAssessmentOverviewFetch'>
export type DispatchProps = Pick<IAssessmentListingProps, 'handleAssessmentOverviewFetch'>
export type OwnProps = Pick<IAssessmentListingProps, 'assessmentCategory'>
export type StateProps = Pick<IAssessmentListingProps, 'assessmentOverviews'>

class Missions extends React.Component<IMissionsProps, {}> {
class AssessmentListing extends React.Component<IAssessmentListingProps, {}> {
public render() {
// make missionIdParam a number
let missionIdParam: number | null =
this.props.match.params.missionId === undefined
// make assessmentId a number
let assessmentIdParam: number | null =
this.props.match.params.assessmentId === undefined
? NaN
: parseInt(this.props.match.params.missionId, 10)
: parseInt(this.props.match.params.assessmentId, 10)
// set as null if the parsing failed
missionIdParam = Number.isInteger(missionIdParam) ? missionIdParam : null
assessmentIdParam = Number.isInteger(assessmentIdParam) ? assessmentIdParam : null

// if there is no mission specified, Render only information.
if (missionIdParam === null) {
// if there is no assessmentId specified, Render only information.
if (assessmentIdParam === null) {
const props: IContentDisplayProps = {
display: <AssessmentOverviewCard assessmentOverviews={this.props.assessmentOverviews} />,
loadContentDispatch: this.props.handleAssessmentOverviewFetch
}
return (
<div className="Missions">
<div className="AssessmentListing">
<ContentDisplay {...props} />
</div>
)
} else {
const props: AssessmentProps = {
missionId: missionIdParam
assessmentId: assessmentIdParam
}
return <AssessmentContainer {...props} />
}
Expand All @@ -61,31 +64,31 @@ export const AssessmentOverviewCard: React.SFC<IAssessmentOverviewCardProps> = p
} else if (props.assessmentOverviews.length === 0) {
return <NonIdealState title="There are no assessments." visual={IconNames.FLAME} />
}
const cards = props.assessmentOverviews.map((mission, index) => (
const cards = props.assessmentOverviews.map((overview, index) => (
<div key={index}>
<Card className="row mission-info">
<div className="col-xs-3 mission-info-picture">PICTURE</div>
<div className="col-xs-9 mission-info-text">
<div className="row mission-info-title">
<h4>{mission.title}</h4>
<Card className="row listing">
<div className="col-xs-3 listing-picture">PICTURE</div>
<div className="col-xs-9 listing-text">
<div className="row listing-title">
<h4>{overview.title}</h4>
</div>
<div className="row mission-info-order">
<div className="row listing-order">
<h6>Mission 0 : 123123 XP (hardcoded)</h6>
</div>
<div className="row mission-info-description">
<p className="col-xs-12">{mission.shortSummary}</p>
<div className="row listing-description">
<p className="col-xs-12">{overview.shortSummary}</p>
</div>
<div className="row between-xs middle-xs mission-info-controls">
<div className="col-xs-8 mission-info-due-date-parent">
<Text className="mission-info-due-date">
<Icon className="mission-info-due-icon" iconSize={14} icon={IconNames.TIME} />
<div className="row between-xs middle-xs listing-controls">
<div className="col-xs-8 listing-due-date-parent">
<Text className="listing-due-date">
<Icon className="listing-due-icon" iconSize={14} icon={IconNames.TIME} />
Due: 12/12/12
</Text>
</div>
<div className="col-xs">
<NavLink to={`/academy/missions/${mission.id.toString()}`}>
<NavLink to={`/academy/missions/${overview.id.toString()}`}>
<Button
className="mission-info-skip-button"
className="listing-skip-button"
minimal={true}
intent={Intent.PRIMARY}
icon={IconNames.FLAME}
Expand All @@ -102,4 +105,4 @@ export const AssessmentOverviewCard: React.SFC<IAssessmentOverviewCardProps> = p
return <>{cards}</>
}

export default Missions
export default AssessmentListing
58 changes: 58 additions & 0 deletions src/components/assessment/__tests__/AssessmentListing.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { mount } from 'enzyme'
import * as React from 'react'
import { MemoryRouter } from 'react-router'

import { mockAssessmentOverviews } from '../../../mocks/api'
import { mockRouterProps } from '../../../mocks/components'
import AssessmentListing, { IAssessmentListingProps } from '../AssessmentListing'
import { AssessmentCategories } from '../assessmentShape'

const mockUndefinedAssessmentListing: IAssessmentListingProps = {
...mockRouterProps('/academy/missions', {}),
handleAssessmentOverviewFetch: () => {},
assessmentCategory: AssessmentCategories.MISSION
}

const mockEmptyAssessmentListing: IAssessmentListingProps = {
...mockRouterProps('/academy/missions', {}),
assessmentOverviews: [],
handleAssessmentOverviewFetch: () => {},
assessmentCategory: AssessmentCategories.MISSION
}

const mockPresentAssessmentListing: IAssessmentListingProps = {
...mockRouterProps('/academy/missions', {}),
assessmentOverviews: mockAssessmentOverviews,
handleAssessmentOverviewFetch: () => {},
assessmentCategory: AssessmentCategories.MISSION
}

test('AssessmentListing page "loading" content renders correctly', () => {
const app = (
<MemoryRouter initialEntries={['/unknown']}>
<AssessmentListing {...mockUndefinedAssessmentListing} />
</MemoryRouter>
)
const tree = mount(app)
expect(tree.debug()).toMatchSnapshot()
})

test('AssessmentListing page with 0 missions renders correctly', () => {
const app = (
<MemoryRouter initialEntries={['/unknown']}>
<AssessmentListing {...mockEmptyAssessmentListing} />
</MemoryRouter>
)
const tree = mount(app)
expect(tree.debug()).toMatchSnapshot()
})

test('AssessmentListing page with multiple loaded missions renders correctly', () => {
const app = (
<MemoryRouter initialEntries={['/unknown']}>
<AssessmentListing {...mockPresentAssessmentListing} />
</MemoryRouter>
)
const tree = mount(app)
expect(tree.debug()).toMatchSnapshot()
})
Loading