diff --git a/packages/app/components/__tests__/Children.test.js b/packages/app/components/__tests__/Children.test.js
new file mode 100644
index 000000000..488aa861d
--- /dev/null
+++ b/packages/app/components/__tests__/Children.test.js
@@ -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()
+}
+
+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()
+})
diff --git a/packages/app/components/__tests__/Notification.test.js b/packages/app/components/__tests__/Notification.test.js
index e3d3c4fc1..69a804dd8 100644
--- a/packages/app/components/__tests__/Notification.test.js
+++ b/packages/app/components/__tests__/Notification.test.js
@@ -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 = {
@@ -17,11 +15,7 @@ const setup = (customProps = {}) => {
...customProps,
}
- return render(
-
-
-
- )
+ return render()
}
beforeEach(() => {
diff --git a/packages/app/components/childListItem.component.js b/packages/app/components/childListItem.component.js
index a15e0742e..b3418546b 100644
--- a/packages/app/components/childListItem.component.js
+++ b/packages/app/components/childListItem.component.js
@@ -134,7 +134,7 @@ export const ChildListItem = ({ navigation, child, color }) => {
return (
{
const styles = StyleSheet.create({
card: {
- flex: 1,
- margin: 10,
+ marginBottom: 20,
},
itemFooter: {
flexDirection: 'row',
diff --git a/packages/app/components/children.component.js b/packages/app/components/children.component.js
index d627d1ce6..c9865aacc 100644
--- a/packages/app/components/children.component.js
+++ b/packages/app/components/children.component.js
@@ -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) =>
+
export const Children = ({ navigation }) => {
const { data: childList, status } = useChildList()
const navigateBack = () => {
@@ -32,27 +36,46 @@ export const Children = ({ navigation }) => {
accessoryLeft={BackAction}
/>
-
+
{status === 'loaded' ? (
-
- {childList.map((child, i) => (
-
- ))}
+
+
+ Inga barn
+
+ Det finns inga barn registrerade för ditt personnummer i
+ Stockholms Stad
+
+
+
+ }
+ renderItem={({ item: child, index }) => {
+ return (
+
+ )
+ }}
+ />
) : (
-
+
-
+
Laddar...
@@ -64,6 +87,9 @@ export const Children = ({ navigation }) => {
}
const styles = StyleSheet.create({
+ fullFlex: {
+ flex: 1,
+ },
topContainer: {
flex: 1,
backgroundColor: '#fff',
@@ -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,
+ },
})
diff --git a/packages/app/package.json b/packages/app/package.json
index 919981a0e..eda663918 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -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": {
@@ -68,7 +68,7 @@
"jest": {
"preset": "react-native",
"setupFilesAfterEnv": [
- "react-native-gesture-handler/jestSetup",
+ "/setupTests.js",
"@testing-library/jest-native/extend-expect"
],
"transformIgnorePatterns": [
diff --git a/packages/app/setupTests.js b/packages/app/setupTests.js
new file mode 100644
index 000000000..f16555f23
--- /dev/null
+++ b/packages/app/setupTests.js
@@ -0,0 +1,4 @@
+import 'react-native-gesture-handler/jestSetup'
+
+// Silence useNativeDriver error
+jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper')
diff --git a/packages/app/utils/testHelpers.js b/packages/app/utils/testHelpers.js
new file mode 100644
index 000000000..b60d38b45
--- /dev/null
+++ b/packages/app/utils/testHelpers.js
@@ -0,0 +1,16 @@
+import * as eva from '@eva-design/eva'
+import { render as rtlRender } from '@testing-library/react-native'
+import { ApplicationProvider, IconRegistry } from '@ui-kitten/components'
+import { EvaIconsPack } from '@ui-kitten/eva-icons'
+import React from 'react'
+
+export const render = (children) => {
+ return rtlRender(
+ <>
+
+
+ {children}
+
+ >
+ )
+}