diff --git a/.eslintignore b/.eslintignore index e8bab8f..6e5df09 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,5 @@ babel.config.js transformer.js metro.config.js -*scss.d.ts \ No newline at end of file +*scss.d.ts +**/reports/* \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index 15e1bcd..10f28ca 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,11 +1,21 @@ { "extends": ["webstrong/native", "webstrong/typescript", "plugin:@typescript-eslint/base"], + "plugins": ["jest"], "parserOptions": { "project": "./tsconfig.json", "ecmaVersion": 2021, "sourceType": "module" }, + "env": { + "jest/globals": true + }, "rules": { + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + "react/require-default-props": 0, "@typescript-eslint/ban-ts-comment": 0, "react/no-array-index-key": 0, @@ -18,6 +28,7 @@ "react/jsx-indent-props": 0, "react/jsx-wrap-multilines": 0, "react/no-unused-prop-types": 0, - "react/jsx-one-expression-per-line": 0 + "react/jsx-one-expression-per-line": 0, + "@typescript-eslint/no-var-requires": 0 } } diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index c3df28d..770fa0a 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -27,6 +27,9 @@ jobs: - name: Test prettier and eslint run: npm run lint-cleanup + - name: Run tests + run: npm run test + - uses: expo/expo-github-action@v5 with: expo-packager: npm diff --git a/.gitignore b/.gitignore index a7eef9b..b1d62a7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ package-lock.json *.p12 *.key *.mobileprovision -*scss.d.ts \ No newline at end of file +*scss.d.ts +**/reports/* \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index cff3c8a..fc17ed7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ -*scss.d.ts \ No newline at end of file +*scss.d.ts +**/reports/* \ No newline at end of file diff --git a/__tests__/fixtures.ts b/__tests__/fixtures.ts new file mode 100644 index 0000000..064846f --- /dev/null +++ b/__tests__/fixtures.ts @@ -0,0 +1,60 @@ +import { Difficulty, Settings } from '../src/types/settings' +import { Pause } from '../src/types/pause' + +export const defaultSettings: Settings = { + id: 1, + lang: 'en', + level: 1, + points: 0, + difficulty: 'easy', + time: 'medium', + version: '1.0.0', +} + +export const musicExample = { + name: 'Sea', + requiredLevel: 1, +} + +export const exerciseExample = { + name: 'Wall Sit', + difficulty: 'easy' as Difficulty, + iconName: 'wall_sit', + requiredLevel: 1, + time: { + short: { + pauseTime: 20, + exerciseCount: 3, + exerciseTime: 40, + totalTime: 160, + }, + medium: { + pauseTime: 20, + exerciseCount: 4, + exerciseTime: 50, + totalTime: 260, + }, + long: { + pauseTime: 20, + exerciseCount: 6, + exerciseTime: 70, + totalTime: 460, + }, + }, +} + +export const themeExample = { + requiredLevel: 1, + colors: { + primary: '#1A6A73', + secondary: '#FFFFFF', + third: '#C5D1D9', + optional: '#5A5A5A', + progress: '#F2B077', + }, +} + +export const pauseExample: Pause = { + music: musicExample, + exercise: exerciseExample, +} diff --git a/__tests__/utils/helpers.spec.ts b/__tests__/utils/helpers.spec.ts new file mode 100644 index 0000000..666d5cd --- /dev/null +++ b/__tests__/utils/helpers.spec.ts @@ -0,0 +1,26 @@ +import { defaultSettings, pauseExample } from '../fixtures' +import { getNextLevelBenefits, getPointsToLevelUp, getRandomPause } from '../../src/utils/helpers' +import { baseLevelPoints, progressMultiplier } from '../../src/utils/consts' + +describe('Helpers fn', () => { + it('should get pause', () => { + const pause = getRandomPause(pauseExample, defaultSettings) + expect(pause).toMatchObject(pauseExample) + }) + it('should get points to level up', () => { + const pointsToLevelUp = getPointsToLevelUp(1) + expect(pointsToLevelUp).toEqual(baseLevelPoints + progressMultiplier) + }) + it('should get next level benefits', () => { + const matchObject = { + music: {}, + exercises: {}, + themes: {}, + } + + const nextLevelBenefits = getNextLevelBenefits(1) + expect(nextLevelBenefits).toMatchObject(matchObject) + const nextLevelBenefitsTo100Level = getNextLevelBenefits(100) + expect(nextLevelBenefitsTo100Level).toMatchObject(matchObject) + }) +}) diff --git a/app.json b/app.json index e4e1da0..75ce102 100644 --- a/app.json +++ b/app.json @@ -13,6 +13,7 @@ "resizeMode": "cover", "backgroundColor": "#ffffff" }, + "primaryColor": "#1A6A73", "updates": { "fallbackToCacheTimeout": 0 }, diff --git a/database/db.ts b/database/db.ts index 971dea2..428d263 100644 --- a/database/db.ts +++ b/database/db.ts @@ -1,8 +1,8 @@ import { openDatabase } from 'expo-sqlite' -import app from '../app.json' +import { expo } from '../app.json' import { getLocale } from '../src/utils/helpers' -export const VERSION = app.expo.version +export const VERSION = expo.version export const db = openDatabase('pause.db', VERSION) export const initDatabase = (callback: () => void) => { diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..65f023f --- /dev/null +++ b/jest.config.js @@ -0,0 +1,17 @@ +module.exports = { + moduleFileExtensions: ['js', 'ts'], + transform: { + '^.+\\.(ts)$': 'ts-jest', + }, + transformIgnorePatterns: [ + 'node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@sentry/.*)', + ], + testMatch: ['**/__tests__/**/*.spec.(ts)'], + preset: 'jest-expo', + reporters: ['default', ['jest-junit', { outputDirectory: 'reports/tests' }]], + resetMocks: true, + coverageDirectory: 'reports/coverage', + moduleNameMapper: { + '^config(.*)$': '/src/config$1', + }, +} diff --git a/package.json b/package.json index 0be6b40..e17c61c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,11 @@ "eject": "expo eject", "cleanup": "prettier --config .prettierrc --write \"**/*.+(js|jsx|ts|tsx|json|scss|md)\" && npm run eslint", "lint-cleanup": "prettier --config .prettierrc --check \"**/*.+(js|jsx|ts|tsx|json|scss|md)\" && npm run eslint", - "eslint": "eslint --fix ." + "eslint": "eslint --fix .", + "test": "jest --config jest.config.js" + }, + "jest": { + "preset": "jest-expo-enzyme" }, "dependencies": { "@expo/metro-config": "^0.1.54", @@ -46,6 +50,8 @@ }, "devDependencies": { "@babel/core": "~7.9.0", + "@types/enzyme": "^3.10.8", + "@types/jest": "^26.0.20", "@types/react": "~16.9.35", "@types/react-native": "~0.63.2", "@types/react-native-modals": "^0.19.0", @@ -59,14 +65,19 @@ "eslint-config-prettier": "^7.2.0", "eslint-config-webstrong": "^1.1.5", "eslint-plugin-import": "^2.22.1", + "eslint-plugin-jest": "^24.2.1", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-react": "^7.22.0", "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-native": "^3.10.0", + "jest-expo": "^40.0.2", + "jest-expo-enzyme": "^1.0.4", + "jest-junit": "^12.0.0", "node-sass": "^5.0.0", "prettier": "2.2.1", "react-native-typed-sass-transformer": "^0.11.0", + "ts-jest": "^26.5.3", "typescript": "~4.0.0" }, "private": true diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx index 8afa213..1652495 100644 --- a/src/screens/Settings/Settings.tsx +++ b/src/screens/Settings/Settings.tsx @@ -25,7 +25,8 @@ import { import useShowFailureMessage from '../../utils/hooks/useShowFailureMessage' import useShowMessage from '../../utils/hooks/useShowMessage' import Header from '../../components/Header/Header' -import { defaultColor, addBackgroundColor, addTextColor } from '../../utils/helpers' +import { addBackgroundColor, addTextColor } from '../../utils/helpers' +import { defaultColor } from '../../utils/consts' type Props = { navigation: NavigationScreenType diff --git a/src/utils/consts.ts b/src/utils/consts.ts index da5d2fa..fa7cfee 100644 --- a/src/utils/consts.ts +++ b/src/utils/consts.ts @@ -1,4 +1,7 @@ import { Dimensions } from 'react-native' +import { expo } from '../../app.json' + +export const defaultColor = expo.primaryColor export const headerHeight = Dimensions.get('screen').height / 7 export const centerHeight = Dimensions.get('screen').height * 0.4 diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index ebfb155..697136e 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -15,9 +15,9 @@ import { shortTimeMultiplier, } from './consts' -import music from '../config/music.json' -import exercises from '../config/exercises.json' -import themes from '../config/themes.json' +const music = require('../config/music.json') +const exercises = require('../config/exercises.json') +const themes = require('../config/themes.json') export const getLocale = () => { const locale = @@ -30,8 +30,6 @@ export const getLocale = () => { return 'en' } -export const defaultColor = (themes as Theme[])[0].colors.primary - export const getRandomPause = (pause: Pause, settings: Settings): Pause => ({ music: getRandomMusic(pause.music, settings.level), exercise: getRandomExercises(pause.exercise, settings.level, settings.difficulty),