Skip to content

Commit

Permalink
feat: lägg till empty state för barnlistan (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
believer authored Feb 16, 2021
1 parent 6f63998 commit 0cb24fe
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 28 deletions.
186 changes: 186 additions & 0 deletions packages/app/components/__tests__/Children.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import {
useChildList,
useCalendar,
useClassmates,
useNews,
useNotifications,
useSchedule,
} from '@skolplattformen/api-hooks'
import { render } from '../../utils/testHelpers'
import React from 'react'
import { Children } from '../children.component.js'

jest.mock('@skolplattformen/api-hooks')

const setup = () => {
return render(<Children />)
}

beforeEach(() => {
useCalendar.mockReturnValueOnce({ data: [], status: 'loaded' })
useNotifications.mockReturnValueOnce({ data: [], status: 'loaded' })
useNews.mockReturnValueOnce({ data: [], status: 'loaded' })
useClassmates.mockReturnValueOnce({ data: [], status: 'loaded' })
useSchedule.mockReturnValueOnce({ data: [], status: 'loaded' })
})

test('renders loading state', () => {
useChildList.mockImplementationOnce(() => ({
data: [],
status: 'loading',
}))

const screen = setup()

expect(screen.getByText(/laddar/i)).toBeTruthy()
})

test('renders empty state message', () => {
useChildList.mockImplementationOnce(() => ({
data: [],
status: 'loaded',
}))

const screen = setup()

expect(
screen.getByText(
'Det finns inga barn registrerade för ditt personnummer i Stockholms Stad'
)
).toBeTruthy()
})

test('renders child in preschool', () => {
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Test Testsson',
status: 'F',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Test Testsson')).toBeTruthy()
expect(screen.getByText('Förskoleklass')).toBeTruthy()
})

test('renders child in elementary school', () => {
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Test Testsson',
status: 'GR',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Test Testsson')).toBeTruthy()
expect(screen.getByText('Grundskolan')).toBeTruthy()
})

test('renders child in high school', () => {
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Test Testsson',
status: 'G',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Test Testsson')).toBeTruthy()
expect(screen.getByText('Gymnasiet')).toBeTruthy()
})

test('renders multiple children', () => {
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Storasyster Testsson',
status: 'G',
},
{
name: 'Lillebror Testsson',
status: 'GR',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Storasyster Testsson')).toBeTruthy()
expect(screen.getByText('Gymnasiet')).toBeTruthy()

expect(screen.getByText('Lillebror Testsson')).toBeTruthy()
expect(screen.getByText('Grundskolan')).toBeTruthy()
})

test('displays class name if child has class mates', () => {
useClassmates.mockReset()
useClassmates.mockReturnValueOnce({
data: [
{
className: '8C',
},
],
status: 'loaded',
})
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Test Testsson',
status: 'G',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Test Testsson')).toBeTruthy()
expect(screen.getByText('8C')).toBeTruthy()
expect(screen.queryByText('Gymnasiet')).toBeFalsy()
})

test('removes any parenthesis from name', () => {
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Test Testsson(något annat)',
status: 'G',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Test Testsson')).toBeTruthy()
})

test('handles multiple statuses for a child', () => {
useChildList.mockImplementationOnce(() => ({
data: [
{
name: 'Test Testsson(något annat)',
status: 'G;GR;F',
},
],
status: 'loaded',
}))

const screen = setup()

expect(screen.getByText('Test Testsson')).toBeTruthy()
expect(screen.getByText('Gymnasiet, Grundskolan, Förskoleklass')).toBeTruthy()
})
10 changes: 2 additions & 8 deletions packages/app/components/__tests__/Notification.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react'
import { render } from '@testing-library/react-native'
import { render } from '../../utils/testHelpers'
import { Notification } from '../notification.component.js'
import { ApplicationProvider } from '@ui-kitten/components'
import * as eva from '@eva-design/eva'
import MockDate from 'mockdate'

const defaultItem = {
Expand All @@ -17,11 +15,7 @@ const setup = (customProps = {}) => {
...customProps,
}

return render(
<ApplicationProvider {...eva} theme={eva.light}>
<Notification {...props} />
</ApplicationProvider>
)
return render(<Notification {...props} />)
}

beforeEach(() => {
Expand Down
5 changes: 2 additions & 3 deletions packages/app/components/childListItem.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export const ChildListItem = ({ navigation, child, color }) => {

return (
<Card
style={{ ...styles.card }}
style={styles.card}
appearance="filled"
status={color}
header={Header}
Expand Down Expand Up @@ -168,8 +168,7 @@ export const ChildListItem = ({ navigation, child, color }) => {

const styles = StyleSheet.create({
card: {
flex: 1,
margin: 10,
marginBottom: 20,
},
itemFooter: {
flexDirection: 'row',
Expand Down
90 changes: 75 additions & 15 deletions packages/app/components/children.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import {
Divider,
Icon,
Layout,
List,
Spinner,
Text,
TopNavigation,
TopNavigationAction,
} from '@ui-kitten/components'
import React from 'react'
import { Image, SafeAreaView, StyleSheet, View } from 'react-native'
import { Dimensions, Image, SafeAreaView, StyleSheet, View } from 'react-native'
import { ChildListItem } from './childListItem.component'

const { width } = Dimensions.get('window')
const colors = ['primary', 'success', 'info', 'warning', 'danger']

const BackIcon = (props) => <Icon {...props} name="arrow-back" />

export const Children = ({ navigation }) => {
const { data: childList, status } = useChildList()
const navigateBack = () => {
Expand All @@ -32,27 +36,46 @@ export const Children = ({ navigation }) => {
accessoryLeft={BackAction}
/>
<Divider />
<Layout style={{ flex: 1 }}>
<Layout style={styles.fullFlex}>
{status === 'loaded' ? (
<Layout style={styles.childList}>
{childList.map((child, i) => (
<ChildListItem
key={child.id}
child={child}
color={colors[i % colors.length]}
navigation={navigation}
/>
))}
<Layout style={styles.childListWrap}>
<List
contentContainerStyle={styles.childList}
data={childList}
ListEmptyComponent={
<View style={styles.emptyState}>
<Text category="h2">Inga barn</Text>
<Text style={styles.emptyStateDescription}>
Det finns inga barn registrerade för ditt personnummer i
Stockholms Stad
</Text>
<Image
source={require('../assets/children.png')}
style={styles.emptyStateImage}
/>
</View>
}
renderItem={({ item: child, index }) => {
return (
<ChildListItem
child={child}
color={colors[index % colors.length]}
key={child.id}
navigation={navigation}
/>
)
}}
/>
</Layout>
) : (
<Layout style={styles.loading}>
<Image
source={require('../assets/girls.png')}
style={{ height: 400, width: '100%' }}
style={styles.loadingImage}
/>
<View style={{ flexDirection: 'row' }}>
<View style={styles.loadingMessage}>
<Spinner size="large" status="warning" />
<Text category="h1" style={{ marginLeft: 10, marginTop: -7 }}>
<Text category="h1" style={styles.loadingText}>
Laddar...
</Text>
</View>
Expand All @@ -64,6 +87,9 @@ export const Children = ({ navigation }) => {
}

const styles = StyleSheet.create({
fullFlex: {
flex: 1,
},
topContainer: {
flex: 1,
backgroundColor: '#fff',
Expand All @@ -73,8 +99,42 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center',
},
childList: {
loadingImage: {
height: (width / 16) * 9,
width: width,
},
loadingMessage: {
alignItems: 'center',
flexDirection: 'row',
marginTop: 8,
},
loadingText: {
marginLeft: 20,
},
childListWrap: {
flex: 1,
justifyContent: 'flex-start',
},
childList: {
flex: 1,
padding: 20,
},
emptyState: {
backgroundColor: '#fff',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 20,
},
emptyStateDescription: {
lineHeight: 21,
marginTop: 8,
textAlign: 'center',
},
emptyStateImage: {
// 80% size and 16:9 aspect ratio
height: ((width * 0.8) / 16) * 9,
marginTop: 20,
width: width * 0.8,
},
})
4 changes: 2 additions & 2 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"ios": "react-native-fix-image && react-native run-ios",
"pod": "npx pod-install",
"start": "react-native start",
"test": "jest --passWithNoTests",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
Expand Down Expand Up @@ -68,7 +68,7 @@
"jest": {
"preset": "react-native",
"setupFilesAfterEnv": [
"react-native-gesture-handler/jestSetup",
"<rootDir>/setupTests.js",
"@testing-library/jest-native/extend-expect"
],
"transformIgnorePatterns": [
Expand Down
4 changes: 4 additions & 0 deletions packages/app/setupTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'react-native-gesture-handler/jestSetup'

// Silence useNativeDriver error
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper')
Loading

0 comments on commit 0cb24fe

Please sign in to comment.