Skip to content
Open
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
7 changes: 5 additions & 2 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import Home from "./screens/Home";
import Quizz from "./screens/Quizz";
import Results from "./screens/Results";
import { RootStackParamList } from "./types/navigation";
import { Provider } from "react-redux";
import { Provider, useDispatch } from "react-redux";
import { createSharedElementStackNavigator } from "react-navigation-shared-element";
import store from "./store";
import { human } from "react-native-typography";
import HeaderRight from "./components/HeaderRight";
import { Dispatch } from "./store";
type AppProps = Record<string, unknown>;

const Stack = createSharedElementStackNavigator<RootStackParamList>();
const App: React.FunctionComponent<AppProps> = () => {
const dispatch = useDispatch<Dispatch>();

return (
<Provider store={store}>
<NavigationContainer>
Expand All @@ -25,7 +28,7 @@ const App: React.FunctionComponent<AppProps> = () => {
headerRight: ({ tintColor }: { tintColor?: string }) => (
<HeaderRight
tintColor={tintColor}
toggleMusic={store.dispatch.settings.toggleMusic}
toggleMusic={dispatch.settings.toggleMusic}
/>
),
headerTitleStyle: human.title2White,
Expand Down
10 changes: 9 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
module.exports = {
preset: "react-native",
preset: "jest-expo",
transform: {
"^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$": require.resolve(
"jest-expo/src/preset/assetFileTransformer.js"
),
},
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/.*)",
],
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@react-native-community/masked-view": "0.1.10",
"@react-navigation/native": "^5.0.9",
"@react-navigation/stack": "^5.1.1",
"@rematch/core": "^2.0.0-next.1",
"@rematch/core": "^2.0.0-next.4",
"axios": "^0.19.2",
"expo": "~38.0.8",
"expo-av": "~8.2.1",
Expand Down Expand Up @@ -51,6 +51,7 @@
"eslint-plugin-react": "^7.20.5",
"husky": ">=4",
"jest": "^26.3.0",
"jest-expo": "^38.0.2",
"lint-staged": ">=10",
"prettier": "2.0.5",
"typescript": "^3.9.7"
Expand Down
11 changes: 6 additions & 5 deletions store/__tests__/questions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { init } from "@rematch/core";
import { questions } from "../models/questions";
import { models } from "../models";
import api from "../../utils/api";

const mockedApi = api as jest.Mocked<typeof api>;
Expand All @@ -16,16 +16,17 @@ jest.mock("../../utils/api.ts", () => {
describe("Questions Model", () => {
it("Questions should be loaded from the api and stored in the state correctly", async () => {
const store = init({
models: { questions },
models,
});

await store.dispatch.questions.loadQuestions({ categoryId: "mixed" });
const questionsState = store.getState().questions;
expect(questionsState.questions.length).toBe(questionsState.amount);
});
it("Errors should be gracefully handled when loading questions", async () => {
const errorMessage = "Network Error";
const store = init({
models: { questions },
models,
});

mockedApi.get.mockImplementation(async () => {
Expand All @@ -41,7 +42,7 @@ describe("Questions Model", () => {
describe("Incrementing questions when passing the quizz", () => {
it("Increments the question when below 10", async () => {
const store = init({
models: { questions },
models,
});
await store.dispatch.questions.loadQuestions({ categoryId: "mixed" });
store.dispatch.questions.incrementQuestion();
Expand All @@ -50,7 +51,7 @@ describe("Incrementing questions when passing the quizz", () => {
});
it("Increments the question is a noop when index = 10", async () => {
const store = init({
models: { questions },
models,
});
await store.dispatch.questions.loadQuestions({ categoryId: "mixed" });
for (let i = 0; i < 11; i++) {
Expand Down
2 changes: 1 addition & 1 deletion store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ export type Store = typeof store;
export type Dispatch = RematchDispatch<RootModel>;
export type RootState = RematchRootState<RootModel>;

export default store;
export default store;
2 changes: 1 addition & 1 deletion store/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Models } from "@rematch/core";
import { questions } from "./questions";
import { settings } from "./settings";

export interface RootModel extends Models {
export interface RootModel extends Models<RootModel> {
questions: typeof questions;
settings: typeof settings;
}
Expand Down
13 changes: 6 additions & 7 deletions store/models/questions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { createModel } from "@rematch/core";
import { Dispatch, RootState } from "..";
import api from "../../utils/api";
import config from "../../utils/config";
import { RootModel } from "./";

const initialState: QuestionsState = {
questions: [],
Expand All @@ -15,7 +15,8 @@ const initialState: QuestionsState = {
loading: false,
error: "",
};
export const questions = createModel<QuestionsState>()({

export const questions = createModel<RootModel>()({
state: initialState, // initial state
reducers: {
reset() {
Expand Down Expand Up @@ -52,13 +53,13 @@ export const questions = createModel<QuestionsState>()({
effects: (dispatch) => ({
// handle state changes with impure functions.
// use async/await for async actions
async loadQuestions({ categoryId }: { categoryId: string }, rootState) {
async loadQuestions({ categoryId }: { categoryId: string }, state) {
const {
questions: { reset, setLoading, setError, setQuestions },
} = dispatch as Dispatch;
} = dispatch;
const {
questions: { amount, type, difficulty },
} = rootState as RootState;
} = state;

// useful when using the back button to go to the
// home screen when the quizz is in progress
Expand All @@ -81,8 +82,6 @@ export const questions = createModel<QuestionsState>()({
setLoading(false);
setError(error.message);
}

// typedDispatch.questions.setQuestions(result)
},
}),
});
19 changes: 10 additions & 9 deletions store/models/settings.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { createModel } from "@rematch/core";
import { Dispatch, RootState } from "..";
import { Audio } from "expo-av";
import { RootModel } from ".";
const soundTrack = require("../../assets/sounds/music.mp3");
const clickSound = require("../../assets/sounds/click.wav");

Expand All @@ -10,7 +10,8 @@ const soundObject = new Audio.Sound();
const initialState: SettingsState = {
isMusicOn: true,
};
export const settings = createModel<SettingsState>()({

export const settings = createModel<RootModel>()({
state: initialState, // initial state
reducers: {
reset() {
Expand All @@ -26,7 +27,7 @@ export const settings = createModel<SettingsState>()({
async playMusic() {
const {
settings: { setMusicState },
} = dispatch as Dispatch;
} = dispatch;

const { isLoaded } = await soundObject.getStatusAsync();
if (!isLoaded) {
Expand All @@ -41,13 +42,13 @@ export const settings = createModel<SettingsState>()({
// when you are done using the Sound object
// await soundObject.unloadAsync();
},
async toggleMusic(_, rootState) {
async toggleMusic(_, state) {
const {
settings: { stopMusic, playMusic, setMusicState },
} = dispatch as Dispatch;
} = dispatch;
const {
settings: { isMusicOn },
} = rootState as RootState;
} = state;

if (isMusicOn) {
setMusicState(false);
Expand All @@ -60,15 +61,15 @@ export const settings = createModel<SettingsState>()({
async stopMusic() {
const {
settings: { setMusicState },
} = dispatch as Dispatch;
} = dispatch;

await soundObject.pauseAsync();
setMusicState(false);
},
async playClickSound(_, rootState) {
async playClickSound(_, state) {
const {
settings: { isMusicOn },
} = rootState as RootState;
} = state;
if (!isMusicOn) {
return;
}
Expand Down
Loading