Skip to content

Commit

Permalink
LUN-357: Use own vocabulary detail route instead of modal
Browse files Browse the repository at this point in the history
  • Loading branch information
steffenkleinle committed May 30, 2022
1 parent fa4f629 commit c4dfe41
Show file tree
Hide file tree
Showing 15 changed files with 191 additions and 260 deletions.
26 changes: 4 additions & 22 deletions src/components/VocabularyList.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { useState } from 'react'
import React from 'react'
import { FlatList } from 'react-native'
import styled from 'styled-components/native'

import { Document } from '../constants/endpoints'
import labels from '../constants/labels.json'
import Title from './Title'
import VocabularyListItem from './VocabularyListItem'
import VocabularyListModal from './VocabularyListModal'

const Root = styled.View`
background-color: ${props => props.theme.colors.background};
Expand All @@ -17,33 +16,16 @@ const Root = styled.View`

interface VocabularyListScreenProps {
documents: Document[]
onItemPress: (index: number) => void
}

const VocabularyList = ({ documents }: VocabularyListScreenProps): JSX.Element => {
const [isModalVisible, setIsModalVisible] = useState(false)
const [selectedDocumentIndex, setSelectedDocumentIndex] = useState<number>(0)

const VocabularyList = ({ documents, onItemPress }: VocabularyListScreenProps): JSX.Element => {
const renderItem = ({ item, index }: { item: Document; index: number }): JSX.Element => (
<VocabularyListItem
document={item}
setIsModalVisible={() => {
setIsModalVisible(true)
setSelectedDocumentIndex(index)
}}
/>
<VocabularyListItem document={item} onPress={() => onItemPress(index)} />
)

return (
<Root>
{documents[selectedDocumentIndex] && (
<VocabularyListModal
documents={documents}
isModalVisible={isModalVisible}
setIsModalVisible={setIsModalVisible}
selectedDocumentIndex={selectedDocumentIndex}
setSelectedDocumentIndex={setSelectedDocumentIndex}
/>
)}
<Title
title={labels.exercises.vocabularyList.title}
description={`${documents.length} ${documents.length === 1 ? labels.general.word : labels.general.words}`}
Expand Down
8 changes: 3 additions & 5 deletions src/components/VocabularyListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ const Speaker = styled.View`

export interface VocabularyListItemProp {
document: Document
setIsModalVisible?: () => void
onPress: () => void
}

const VocabularyListItem = ({ document, setIsModalVisible }: VocabularyListItemProp): ReactElement => {
const VocabularyListItem = ({ document, onPress }: VocabularyListItemProp): ReactElement => {
const { article, word, document_image: documentImage } = document

const title = <StyledTitle articleColor={getArticleColor(article)}>{article.value}</StyledTitle>
Expand All @@ -43,13 +43,11 @@ const VocabularyListItem = ({ document, setIsModalVisible }: VocabularyListItemP
<StyledImage testID='image' source={{ uri: documentImage[0].image }} width={24} height={24} />
) : undefined

const noop = () => undefined

return (
<ListItem
title={title}
description={word}
onPress={setIsModalVisible ?? noop}
onPress={onPress}
icon={icon}
rightChildren={
<Speaker>
Expand Down
101 changes: 0 additions & 101 deletions src/components/VocabularyListModal.tsx

This file was deleted.

55 changes: 55 additions & 0 deletions src/components/__tests__/VocabularyList.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { fireEvent } from '@testing-library/react-native'
import React from 'react'

import labels from '../../constants/labels.json'
import DocumentBuilder from '../../testing/DocumentBuilder'
import { mockUseLoadAsyncWithData } from '../../testing/mockUseLoadFromEndpoint'
import render from '../../testing/render'
import VocabularyList from '../VocabularyList'

jest.mock('../AudioPlayer', () => {
const Text = require('react-native').Text
return () => <Text>AudioPlayer</Text>
})

describe('VocabularyList', () => {
beforeEach(() => {
jest.clearAllMocks()
})

const onItemPress = jest.fn()
const documents = new DocumentBuilder(2).build()

it('should display vocabulary list', () => {
mockUseLoadAsyncWithData(documents)

const { getByText, getAllByText, getAllByTestId } = render(
<VocabularyList documents={documents} onItemPress={onItemPress} />
)

expect(getByText(labels.exercises.vocabularyList.title)).toBeTruthy()
expect(getByText(`2 ${labels.general.words}`)).toBeTruthy()
expect(getByText('Der')).toBeTruthy()
expect(getByText('Spachtel')).toBeTruthy()
expect(getByText('Das')).toBeTruthy()
expect(getByText('Auto')).toBeTruthy()
expect(getAllByText('AudioPlayer')).toHaveLength(2)
expect(getAllByTestId('image')).toHaveLength(2)
})

it('should call onItemPress with correct index', () => {
const { getByText } = render(<VocabularyList documents={documents} onItemPress={onItemPress} />)

expect(onItemPress).toHaveBeenCalledTimes(0)

fireEvent.press(getByText('Auto'))

expect(onItemPress).toHaveBeenCalledTimes(1)
expect(onItemPress).toHaveBeenCalledWith(1)

fireEvent.press(getByText('Spachtel'))

expect(onItemPress).toHaveBeenCalledTimes(2)
expect(onItemPress).toHaveBeenCalledWith(0)
})
})
17 changes: 12 additions & 5 deletions src/components/__tests__/VocabularyListItem.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fireEvent } from '@testing-library/react-native'
import React from 'react'
import 'react-native'

Expand All @@ -6,9 +7,11 @@ import { Document } from '../../constants/endpoints'
import render from '../../testing/render'
import VocabularyListItem from '../VocabularyListItem'

jest.mock('../../../../components/AudioPlayer', () => () => null)
jest.mock('../AudioPlayer', () => () => null)

describe('VocabularyListItem', () => {
const onPress = jest.fn()

const document: Document = {
article: ARTICLES[1],
audio: '',
Expand All @@ -19,17 +22,21 @@ describe('VocabularyListItem', () => {
}

it('should display image passed to it', () => {
const { getByTestId } = render(<VocabularyListItem document={document} />)
const { getByTestId } = render(<VocabularyListItem document={document} onPress={onPress} />)
expect(getByTestId('image')).toHaveProp('source', { uri: document.document_image[0].image })
})

it('should display article passed to it', () => {
const { queryByText } = render(<VocabularyListItem document={document} />)
const { queryByText } = render(<VocabularyListItem document={document} onPress={onPress} />)
expect(queryByText(document.article.value)).toBeTruthy()
})

it('should display word passed to it', () => {
const { queryByText } = render(<VocabularyListItem document={document} />)
expect(queryByText(document.word)).toBeTruthy()
const { getByText } = render(<VocabularyListItem document={document} onPress={onPress} />)
expect(getByText(document.word)).toBeTruthy()

expect(onPress).toHaveBeenCalledTimes(0)
fireEvent.press(getByText(document.word))
expect(onPress).toHaveBeenCalledTimes(1)
})
})
51 changes: 0 additions & 51 deletions src/components/__tests__/VocabularyListModal.spec.tsx

This file was deleted.

9 changes: 9 additions & 0 deletions src/navigation/NavigationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ interface ExerciseParams {
closeExerciseAction: CommonNavigationAction
}

interface DetailExerciseParams {
disciplineId: number
disciplineTitle: string
documents: Document[]
documentIndex: number
closeExerciseAction: CommonNavigationAction
}

export interface ExercisesParams extends Omit<ExerciseParams, 'documents' | 'closeExerciseAction'> {
discipline: Discipline
documents: Document[] | null
Expand Down Expand Up @@ -47,6 +55,7 @@ export type RoutesParams = {
discipline: Discipline
initialSelection: boolean
}
VocabularyDetail: DetailExerciseParams
Exercises: ExercisesParams
VocabularyList: ExerciseParams
WordChoiceExercise: ExerciseParams
Expand Down
6 changes: 6 additions & 0 deletions src/navigation/Navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import labels from '../constants/labels.json'
import { useTabletHeaderHeight } from '../hooks/useTabletHeaderHeight'
import ResultDetailScreen from '../routes/ResultDetailScreen'
import ResultScreen from '../routes/ResultScreen'
import VocabularyDetailScreen from '../routes/VocabularyDetailScreen'
import VocabularyListScreen from '../routes/VocabularyListScreen'
import ArticleChoiceExerciseScreen from '../routes/choice-exercises/ArticleChoiceExerciseScreen'
import WordChoiceExerciseScreen from '../routes/choice-exercises/WordChoiceExerciseScreen'
Expand All @@ -33,6 +34,11 @@ const HomeStackNavigator = (): JSX.Element | null => {
component={VocabularyListScreen}
options={({ navigation }) => options(overviewExercises, navigation, false)}
/>
<Stack.Screen
name='VocabularyDetail'
component={VocabularyDetailScreen}
options={({ navigation }) => options('', navigation, true)}
/>
<Stack.Screen
name='WordChoiceExercise'
component={WordChoiceExerciseScreen}
Expand Down
7 changes: 6 additions & 1 deletion src/routes/ResultDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ const ResultDetailScreen = ({ route, navigation }: ResultScreenProps): JSX.Eleme
/>
)

const Item = ({ item }: { item: DocumentResult }): JSX.Element => <VocabularyListItem document={item.document} />
const Item = ({ item, index }: { item: DocumentResult; index: number }): JSX.Element => (
<VocabularyListItem
document={item.document}
onPress={() => navigation.navigate('VocabularyDetail', { ...route.params, documentIndex: index })}
/>
)

const repeatIncorrectEntries = (): void =>
navigation.navigate('WriteExercise', {
Expand Down
Loading

0 comments on commit c4dfe41

Please sign in to comment.