Compare commits
No commits in common. 'master' and 'part6' have entirely different histories.
@ -1,17 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: JokesApp
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: sonar-analyses
|
|
||||||
image: hub.codefirst.iut.uca.fr/camille.petitalot/drone-sonarplugin-reactnative:latest
|
|
||||||
commands:
|
|
||||||
- cd src
|
|
||||||
- npm install
|
|
||||||
- sonar-scanner -Dsonar.projectKey=JokesAppReact_A-PE -Dsonar.sources=. -Dsonar.host.url=$${PLUGIN_SONAR_HOST}
|
|
||||||
-Dsonar.login=$${PLUGIN_SONAR_TOKEN}
|
|
||||||
secrets: [ SECRET_SONAR_LOGIN ]
|
|
||||||
settings:
|
|
||||||
sonar_host: https://codefirst.iut.uca.fr/sonar/
|
|
||||||
sonar_token:
|
|
||||||
from_secret: SECRET_SONAR_LOGIN
|
|
@ -1,32 +1,5 @@
|
|||||||
import {Theme} from "@react-navigation/native";
|
|
||||||
|
|
||||||
export const indigoColor = "rgba(14, 14, 44, 1)";
|
export const indigoColor = "rgba(14, 14, 44, 1)";
|
||||||
export const purpleColor = "rgba(74, 74, 104, 1)";
|
export const purpleColor = "rgba(74, 74, 104, 1)";
|
||||||
export const darksalmonColor = "rgba(233, 150, 122, 1)";
|
export const darksalmonColor = "rgba(233, 150, 122, 1)";
|
||||||
export const greyColor = "rgba(140, 140, 161, 1)";
|
export const greyColor = "rgba(140, 140, 161, 1)";
|
||||||
export const whiteColor = "rgba(239, 239, 253, 1)";
|
export const whiteColor = "rgba(239, 239, 253, 1)";
|
||||||
|
|
||||||
|
|
||||||
export const LightTheme: Theme = {
|
|
||||||
dark: false,
|
|
||||||
colors: {
|
|
||||||
primary: darksalmonColor,
|
|
||||||
background: whiteColor,
|
|
||||||
card: greyColor,
|
|
||||||
text: "black",
|
|
||||||
border: whiteColor,
|
|
||||||
notification: 'rgb(255, 59, 48)',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DarkTheme: Theme = {
|
|
||||||
dark: true,
|
|
||||||
colors: {
|
|
||||||
primary: darksalmonColor,
|
|
||||||
background: purpleColor,
|
|
||||||
card: indigoColor,
|
|
||||||
text: whiteColor,
|
|
||||||
border: greyColor,
|
|
||||||
notification: 'rgb(255, 69, 58)',
|
|
||||||
},
|
|
||||||
};
|
|
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 315 B |
Before Width: | Height: | Size: 301 B |
@ -1,26 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import Categ from './Categ';
|
|
||||||
import { Text, View } from 'react-native';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Categ Component', () => {
|
|
||||||
it('renders correctly', () => {
|
|
||||||
const category = { name: 'Test Category' };
|
|
||||||
const wrapper = shallow(<Categ category={category} />);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('displays category name', () => {
|
|
||||||
const category = { name: 'Test Category' };
|
|
||||||
const wrapper = shallow(<Categ category={category} />);
|
|
||||||
expect(wrapper.find(Text).prop('children')).toEqual(category.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('applies correct styles', () => {
|
|
||||||
const category = { name: 'Test Category' };
|
|
||||||
const wrapper = shallow(<Categ category={category} />);
|
|
||||||
const containerStyle = wrapper.find(View).prop('style');
|
|
||||||
expect(containerStyle).toEqual(expect.objectContaining(styles.bottomContainer));
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,36 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import Categs from './Categs';
|
|
||||||
import { FlatList } from 'react-native';
|
|
||||||
import Categ from './Categ';
|
|
||||||
import { Category } from '../model/Category';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Categs Component', () => {
|
|
||||||
const categories: Category[] = [
|
|
||||||
new Category('Category 1', 10),
|
|
||||||
new Category('Category 2', 5),
|
|
||||||
new Category('Category 3', 15),
|
|
||||||
];
|
|
||||||
|
|
||||||
it('renders correctly', () => {
|
|
||||||
const wrapper = shallow(<Categs categories={categories} />);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders FlatList with correct props', () => {
|
|
||||||
const wrapper = shallow(<Categs categories={categories} />);
|
|
||||||
const flatList = wrapper.find(FlatList);
|
|
||||||
expect(flatList.exists()).toBeTruthy();
|
|
||||||
expect(flatList.prop('showsHorizontalScrollIndicator')).toBe(false);
|
|
||||||
expect(flatList.prop('horizontal')).toBe(true);
|
|
||||||
expect(flatList.prop('data')).toEqual(categories.sort((a, b) => b.number - a.number));
|
|
||||||
expect(flatList.prop('keyExtractor')).toBeInstanceOf(Function);
|
|
||||||
expect(flatList.prop('renderItem')).toBeInstanceOf(Function);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders correct number of Categ components', () => {
|
|
||||||
const wrapper = shallow(<Categs categories={categories} />);
|
|
||||||
expect(wrapper.find(Categ)).toHaveLength(categories.length);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,54 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { render, fireEvent } from '@testing-library/react-native';
|
|
||||||
import JokeDetail from '../path/to/JokeDetail';
|
|
||||||
import {describe} from "@jest/globals"; // Remplacez le chemin par le bon chemin
|
|
||||||
|
|
||||||
describe('JokeDetail Component', () => {
|
|
||||||
const sampleJoke = {
|
|
||||||
id: '1',
|
|
||||||
type: 'Sample',
|
|
||||||
image: 'sample-image-url',
|
|
||||||
description: () => 'Sample Joke Description'
|
|
||||||
};
|
|
||||||
|
|
||||||
const customJoke = {
|
|
||||||
id: '2',
|
|
||||||
type: 'Custom',
|
|
||||||
image: 'custom-image-url',
|
|
||||||
description: () => 'Custom Joke Description'
|
|
||||||
};
|
|
||||||
|
|
||||||
test('renders joke image', () => {
|
|
||||||
const { getByTestId } = render(<JokeDetail joke={sampleJoke} />);
|
|
||||||
const jokeImage = getByTestId('joke-image');
|
|
||||||
expect(jokeImage).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('renders joke description when toggled', () => {
|
|
||||||
const { getByText } = render(<JokeDetail joke={sampleJoke} />);
|
|
||||||
const toggleButton = getByText('LA CHUTE');
|
|
||||||
fireEvent.press(toggleButton);
|
|
||||||
const jokeDescription = getByText('Sample Joke Description');
|
|
||||||
expect(jokeDescription).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('toggles favorite icon when pressed', () => {
|
|
||||||
const { getByTestId } = render(<JokeDetail joke={sampleJoke} />);
|
|
||||||
const favoriteButton = getByTestId('favorite-button');
|
|
||||||
fireEvent.press(favoriteButton);
|
|
||||||
expect(favoriteButton.props.source).toEqual(require('../assets/plain_favorite_icon.png'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('calls deleteCustomJokes and updates list when delete button is pressed for custom joke', () => {
|
|
||||||
const deleteMock = jest.fn();
|
|
||||||
const dispatchMock = jest.fn();
|
|
||||||
jest.mock('../redux/thunk/DeleteThunk', () => ({ deleteCustomJoke: deleteMock }));
|
|
||||||
jest.mock('react-redux', () => ({ useDispatch: () => dispatchMock }));
|
|
||||||
|
|
||||||
const { getByTestId } = render(<JokeDetail joke={customJoke} />);
|
|
||||||
const deleteButton = getByTestId('delete-button');
|
|
||||||
fireEvent.press(deleteButton);
|
|
||||||
expect(deleteMock).toHaveBeenCalledWith(customJoke.id);
|
|
||||||
expect(dispatchMock).toHaveBeenCalledTimes(2); // Assuming one dispatch for delete and one for update list
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,25 +0,0 @@
|
|||||||
import { Category } from './Category';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Category Class Constructor', () => {
|
|
||||||
it('should create a new Category object', () => {
|
|
||||||
const category = new Category('name', 5);
|
|
||||||
expect(category).toBeDefined();
|
|
||||||
expect(category.name).toBe('name');
|
|
||||||
expect(category.number).toBe(5);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Category Class Accessors', () => {
|
|
||||||
it('should set and get the name correctly', () => {
|
|
||||||
const category = new Category('name', 5);
|
|
||||||
category.name = 'newName';
|
|
||||||
expect(category.name).toBe('newName');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set and get the number correctly', () => {
|
|
||||||
const category = new Category('name', 5);
|
|
||||||
category.number = 10;
|
|
||||||
expect(category.number).toBe(10);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
import { CustomJoke } from './CustomJoke';
|
|
||||||
import {describe, expect, test} from "@jest/globals"; // Remplacez le chemin par le bon chemin
|
|
||||||
|
|
||||||
describe('CustomJoke Class', () => {
|
|
||||||
const id = '1';
|
|
||||||
const type = 'Custom';
|
|
||||||
const setup = 'Why did the developer go broke?';
|
|
||||||
const image = 'custom-image-url';
|
|
||||||
const punchline = 'Because he used up all his cache';
|
|
||||||
|
|
||||||
test('creates a new instance of CustomJoke', () => {
|
|
||||||
const customJoke = new CustomJoke(id, type, setup, image, punchline);
|
|
||||||
expect(customJoke).toBeInstanceOf(CustomJoke);
|
|
||||||
expect(customJoke.id).toEqual(id);
|
|
||||||
expect(customJoke.type).toEqual(type);
|
|
||||||
expect(customJoke.setup).toEqual(setup);
|
|
||||||
expect(customJoke.punchline).toEqual(punchline);
|
|
||||||
expect(customJoke.image).toEqual(image);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('updates CustomJoke properties', () => {
|
|
||||||
const newSetup = 'Why do programmers prefer dark mode?';
|
|
||||||
const newImage = 'new-custom-image-url';
|
|
||||||
const newPunchline = 'Because light attracts bugs';
|
|
||||||
const customJoke = new CustomJoke(id, type, setup, image, punchline);
|
|
||||||
|
|
||||||
customJoke.setup = newSetup;
|
|
||||||
customJoke.image = newImage;
|
|
||||||
customJoke.punchline = newPunchline;
|
|
||||||
|
|
||||||
expect(customJoke.setup).toEqual(newSetup);
|
|
||||||
expect(customJoke.image).toEqual(newImage);
|
|
||||||
expect(customJoke.punchline).toEqual(newPunchline);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,61 +0,0 @@
|
|||||||
const { Joke } = require('./Joke');
|
|
||||||
const {expect, it, beforeEach, describe} = require("@jest/globals");
|
|
||||||
|
|
||||||
// Mock class extending the abstract Joke class
|
|
||||||
class MockJoke extends Joke {
|
|
||||||
constructor(type, setup, punchline, image) {
|
|
||||||
super(type, setup, punchline, image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the Joke class
|
|
||||||
describe('Joke Class', () => {
|
|
||||||
let joke;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
joke = new MockJoke('type', 'setup', 'punchline', 'image');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test the constructor
|
|
||||||
it('should create a new Joke object', () => {
|
|
||||||
expect(joke).toBeDefined();
|
|
||||||
expect(joke.type).toBe('type');
|
|
||||||
expect(joke.setup).toBe('setup');
|
|
||||||
expect(joke.punchline).toBe('punchline');
|
|
||||||
expect(joke.image).toBe('image');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test the summary() method
|
|
||||||
it('should return a summary of the joke', () => {
|
|
||||||
expect(joke.summary()).toBe('punchline');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test the description() method
|
|
||||||
it('should return a textual description of the joke', () => {
|
|
||||||
expect(joke.description()).toBe('type, punchline');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test setting and getting the type
|
|
||||||
it('should set and get the type correctly', () => {
|
|
||||||
joke.type = 'newType';
|
|
||||||
expect(joke.type).toBe('newType');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test setting and getting the setup
|
|
||||||
it('should set and get the setup correctly', () => {
|
|
||||||
joke.setup = 'newSetup';
|
|
||||||
expect(joke.setup).toBe('newSetup');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test setting and getting the punchline
|
|
||||||
it('should set and get the punchline correctly', () => {
|
|
||||||
joke.punchline = 'newPunchline';
|
|
||||||
expect(joke.punchline).toBe('newPunchline');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test setting and getting the image
|
|
||||||
it('should set and get the image correctly', () => {
|
|
||||||
joke.image = 'newImage';
|
|
||||||
expect(joke.image).toBe('newImage');
|
|
||||||
});
|
|
||||||
});
|
|
File diff suppressed because it is too large
Load Diff
@ -1,23 +0,0 @@
|
|||||||
import { ActionType, Action, setCategoriesList } from './CategoryAction';
|
|
||||||
import { Category } from '../../model/Category';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Actions', () => {
|
|
||||||
describe('setCategoriesList', () => {
|
|
||||||
it('should create an action to set categories list', () => {
|
|
||||||
const categoriesList: Category[] = [
|
|
||||||
new Category('Category 1', 1),
|
|
||||||
new Category('Category 2', 2)
|
|
||||||
];
|
|
||||||
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.FETCH_CATEGORIES,
|
|
||||||
payload: categoriesList,
|
|
||||||
};
|
|
||||||
|
|
||||||
const action = setCategoriesList(categoriesList);
|
|
||||||
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
import { ActionType, Action, setPostJoke, setCustomJokesList, setCustomJokeById, setDeleteJoke } from './CustomJoke';
|
|
||||||
import { CustomJoke } from '../../model/CustomJoke';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Actions', () => {
|
|
||||||
describe('setPostJoke', () => {
|
|
||||||
it('should create an action to post a custom joke', () => {
|
|
||||||
const customJoke: CustomJoke = new CustomJoke('1', 'pun', 'Setup', 'https://example.com/image.jpg', 'Punchline');
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.POST_CUSTOM_JOKE,
|
|
||||||
payload: customJoke,
|
|
||||||
};
|
|
||||||
const action = setPostJoke(customJoke);
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setCustomJokesList', () => {
|
|
||||||
it('should create an action to set custom jokes list', () => {
|
|
||||||
const customJokesList: CustomJoke[] = [
|
|
||||||
new CustomJoke('1', 'pun', 'Setup 1', 'https://example.com/image1.jpg', 'Punchline 1'),
|
|
||||||
new CustomJoke('2', 'pun', 'Setup 2', 'https://example.com/image2.jpg', 'Punchline 2')
|
|
||||||
];
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.FETCH_CUSTOM_JOKES,
|
|
||||||
payload: customJokesList,
|
|
||||||
};
|
|
||||||
const action = setCustomJokesList(customJokesList);
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setCustomJokeById', () => {
|
|
||||||
it('should create an action to set custom joke by ID', () => {
|
|
||||||
const customJoke: CustomJoke = new CustomJoke('1', 'pun', 'Setup', 'https://example.com/image.jpg', 'Punchline');
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.FETCH_JOKES_BY_ID,
|
|
||||||
payload: customJoke,
|
|
||||||
};
|
|
||||||
const action = setCustomJokeById(customJoke);
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setDeleteJoke', () => {
|
|
||||||
it('should create an action to delete a custom joke', () => {
|
|
||||||
const jokeId = '1';
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.DELETE_CUSTOM_JOKE,
|
|
||||||
payload: jokeId,
|
|
||||||
};
|
|
||||||
const action = setDeleteJoke(jokeId);
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
export enum ActionType {
|
|
||||||
SET_THEME = 'SET_THEME',
|
|
||||||
}
|
|
||||||
|
|
||||||
type actionFetch = {
|
|
||||||
type: ActionType.SET_THEME;
|
|
||||||
payload: String;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Action = actionFetch;
|
|
||||||
|
|
||||||
export const setTheme = (theme) => {
|
|
||||||
return {
|
|
||||||
type: ActionType.SET_THEME,
|
|
||||||
payload: theme,
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
import {CustomJoke} from "../../model/CustomJoke";
|
|
||||||
import {SampleJoke} from "../../model/SampleJoke";
|
|
||||||
|
|
||||||
export enum ActionType {
|
|
||||||
ADD_FAVORITE = 'ADD_CUSTOM_FAVORITE',
|
|
||||||
REMOVE_FAVORITE = "REMOVE_CUSTOM_FAVORITE"
|
|
||||||
}
|
|
||||||
|
|
||||||
type actionAddFetch = {
|
|
||||||
type: ActionType.ADD_FAVORITE;
|
|
||||||
payload: string;
|
|
||||||
}
|
|
||||||
type actionRemoveFetch = {
|
|
||||||
type: ActionType.REMOVE_FAVORITE;
|
|
||||||
payload: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Action = actionAddFetch | actionRemoveFetch;
|
|
||||||
|
|
||||||
export const addFavorite = (joke: CustomJoke | SampleJoke) => ({
|
|
||||||
type: ActionType.ADD_FAVORITE,
|
|
||||||
payload: joke,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const removeFavorite = (joke: CustomJoke | SampleJoke) => ({
|
|
||||||
type: ActionType.REMOVE_FAVORITE,
|
|
||||||
payload: joke,
|
|
||||||
});
|
|
@ -1,32 +0,0 @@
|
|||||||
import { ActionType, Action, setJokesList, setJokeById } from './SampleAction';
|
|
||||||
import { SampleJoke } from '../../model/SampleJoke';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Actions', () => {
|
|
||||||
describe('setJokesList', () => {
|
|
||||||
it('should create an action to set jokes list', () => {
|
|
||||||
const jokesList: SampleJoke[] = [
|
|
||||||
new SampleJoke(1, 'pun', 'Setup 1', 'https://example.com/image1.jpg', 'Punchline 1'),
|
|
||||||
new SampleJoke(2, 'pun', 'Setup 2', 'https://example.com/image2.jpg', 'Punchline 2')
|
|
||||||
];
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.FETCH_JOKES,
|
|
||||||
payload: jokesList,
|
|
||||||
};
|
|
||||||
const action = setJokesList(jokesList);
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setJokeById', () => {
|
|
||||||
it('should create an action to set joke by ID', () => {
|
|
||||||
const joke: SampleJoke = new SampleJoke(1, 'pun', 'Setup', 'https://example.com/image.jpg', 'Punchline');
|
|
||||||
const expectedAction: Action = {
|
|
||||||
type: ActionType.FETCH_JOKES_BY_ID,
|
|
||||||
payload: joke,
|
|
||||||
};
|
|
||||||
const action = setJokeById(joke);
|
|
||||||
expect(action).toEqual(expectedAction);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,23 +0,0 @@
|
|||||||
import categoryReducer from './CategoryReducer';
|
|
||||||
import { ActionType as CategoryActionType } from '../actions/CategoryAction';
|
|
||||||
import { Category } from '../../model/Category';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Category Reducer', () => {
|
|
||||||
|
|
||||||
it('should handle FETCH_CATEGORIES', () => {
|
|
||||||
const categories = [
|
|
||||||
new Category('Category 1', 1),
|
|
||||||
new Category('Category 2', 2)
|
|
||||||
];
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: CategoryActionType.FETCH_CATEGORIES,
|
|
||||||
payload: categories
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(categoryReducer(undefined, action)).toEqual({
|
|
||||||
categories: categories
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,29 +0,0 @@
|
|||||||
import customReducer from './CustomReducer';
|
|
||||||
import { ActionType } from '../actions/CustomJoke';
|
|
||||||
import { CustomJoke } from '../../model/CustomJoke';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Custom Reducer', () => {
|
|
||||||
it('should return the initial state', () => {
|
|
||||||
expect(customReducer(undefined, {})).toEqual({
|
|
||||||
customJokes: [],
|
|
||||||
customJoke: null,
|
|
||||||
jokeId: ''
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle POST_CUSTOM_JOKE', () => {
|
|
||||||
const customJoke: CustomJoke = new CustomJoke('1', 'pun', 'Setup', 'https://example.com/image.jpg', 'Punchline');
|
|
||||||
|
|
||||||
const action = {
|
|
||||||
type: ActionType.POST_CUSTOM_JOKE,
|
|
||||||
payload: customJoke
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(customReducer(undefined, action)).toEqual({
|
|
||||||
customJokes: [],
|
|
||||||
customJoke: customJoke,
|
|
||||||
jokeId: ''
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,21 +0,0 @@
|
|||||||
import {Action, ActionType} from "../actions/DarkModeAction";
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
theme: String
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
theme: 'dark'
|
|
||||||
}
|
|
||||||
|
|
||||||
const themeReducer = (state: State = initialState, action: Action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case ActionType.SET_THEME:
|
|
||||||
// @ts-ignore
|
|
||||||
return {...state, theme: action.payload};
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default themeReducer;
|
|
@ -1,22 +0,0 @@
|
|||||||
import themeReducer from './DarkModeReducer';
|
|
||||||
import { ActionType } from '../actions/DarkModeAction';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Theme Reducer', () => {
|
|
||||||
// it('should return the initial state', () => {
|
|
||||||
// expect(themeReducer(undefined, {})).toEqual({
|
|
||||||
// theme: 'dark'
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should handle SET_THEME', () => {
|
|
||||||
const action = {
|
|
||||||
type: ActionType.SET_THEME,
|
|
||||||
payload: 'light'
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(themeReducer(undefined, action)).toEqual({
|
|
||||||
theme: 'light'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,26 +0,0 @@
|
|||||||
import {Action, ActionType} from "../actions/FavoriteAction";
|
|
||||||
import {CustomJoke} from "../../model/CustomJoke";
|
|
||||||
import {SampleJoke} from "../../model/SampleJoke";
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
joke: CustomJoke | SampleJoke
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
joke: new CustomJoke('', '', '', '', '')
|
|
||||||
}
|
|
||||||
|
|
||||||
const favoriteReducer = (state: State = initialState, action: Action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case ActionType.ADD_FAVORITE:
|
|
||||||
// @ts-ignore
|
|
||||||
return {...state, joke: action.payload};
|
|
||||||
case ActionType.REMOVE_FAVORITE:
|
|
||||||
// @ts-ignore
|
|
||||||
return {...state, joke: action.payload};
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default favoriteReducer;
|
|
@ -1,61 +0,0 @@
|
|||||||
// Importez les réducteurs et les types d'action appropriés
|
|
||||||
import categoryReducer from './CategoryReducer';
|
|
||||||
import customReducer from './CustomReducer';
|
|
||||||
import themeReducer from './DarkModeReducer';
|
|
||||||
import sampleReducer from './SampleReducer';
|
|
||||||
import { ActionType as CategoryActionType } from '../actions/CategoryAction';
|
|
||||||
import { ActionType as CustomActionType } from '../actions/CustomJoke';
|
|
||||||
import { ActionType as ThemeActionType } from '../actions/DarkModeAction';
|
|
||||||
import { ActionType as SampleActionType } from '../actions/SampleAction';
|
|
||||||
import { Category } from '../../model/Category';
|
|
||||||
import { CustomJoke } from '../../model/CustomJoke';
|
|
||||||
import { SampleJoke } from '../../model/SampleJoke';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
// Tester categoryReducer
|
|
||||||
describe('Category Reducer', () => {
|
|
||||||
it('should return the initial state', () => {
|
|
||||||
expect(categoryReducer(undefined, {})).toEqual({
|
|
||||||
categories: []
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter d'autres tests pour categoryReducer si nécessaire...
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tester customReducer
|
|
||||||
describe('Custom Reducer', () => {
|
|
||||||
it('should return the initial state', () => {
|
|
||||||
expect(customReducer(undefined, {})).toEqual({
|
|
||||||
customJokes: [],
|
|
||||||
customJoke: null,
|
|
||||||
jokeId: ''
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter d'autres tests pour customReducer si nécessaire...
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tester themeReducer
|
|
||||||
describe('Theme Reducer', () => {
|
|
||||||
it('should return the initial state', () => {
|
|
||||||
expect(themeReducer(undefined, {})).toEqual({
|
|
||||||
theme: 'dark'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter d'autres tests pour themeReducer si nécessaire...
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tester sampleReducer
|
|
||||||
describe('Sample Reducer', () => {
|
|
||||||
it('should return the initial state', () => {
|
|
||||||
expect(sampleReducer(undefined, {})).toEqual({
|
|
||||||
jokes: [],
|
|
||||||
favoriteJokes: [],
|
|
||||||
joke: null,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter d'autres tests pour sampleReducer si nécessaire...
|
|
||||||
});
|
|
@ -1,29 +0,0 @@
|
|||||||
import store from './store';
|
|
||||||
import {describe, expect, it} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('Redux Store Configuration', () => {
|
|
||||||
it('should have sampleReducer', () => {
|
|
||||||
expect(store.getState().sampleReducer).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have categoryReducer', () => {
|
|
||||||
expect(store.getState().categoryReducer).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have customReducer', () => {
|
|
||||||
expect(store.getState().customReducer).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have themeReducer', () => {
|
|
||||||
expect(store.getState().theme).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have favoriteReducer', () => {
|
|
||||||
expect(store.getState().favorite).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have a configured store', () => {
|
|
||||||
expect(store).toBeDefined();
|
|
||||||
expect(store.getState()).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
import { setDeleteJoke } from "../actions/CustomJoke";
|
|
||||||
|
|
||||||
export const deleteItem = (id: string) => {
|
|
||||||
return async dispatch => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`https://iut-weather-api.azurewebsites.net/jokes/${id}`, {
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: {
|
|
||||||
Accept: "application/json",
|
|
||||||
"Content-Type": 'application/json',
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
dispatch(setDeleteJoke(id)); // Supprimer la blague dans le store Redux
|
|
||||||
console.log('Suppression de la blague réussie');
|
|
||||||
} else {
|
|
||||||
console.log('Erreur lors de la requête DELETE');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log('Erreur :', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteCustomJoke = (jokeId) => {
|
|
||||||
return deleteItem(jokeId)
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
import fetchMock from 'fetch-mock';
|
|
||||||
import thunk from 'redux-thunk';
|
|
||||||
import configureMockStore from 'redux-mock-store';
|
|
||||||
import { deleteItem } from './DeleteThunk'; // Assurez-vous d'importer correctement votre thunk
|
|
||||||
import { setDeleteJoke } from '../actions/CustomJoke';
|
|
||||||
import {afterEach, describe, expect, it, jest} from "@jest/globals";
|
|
||||||
|
|
||||||
const middlewares = [thunk];
|
|
||||||
// @ts-ignore
|
|
||||||
const mockStore = configureMockStore(middlewares);
|
|
||||||
|
|
||||||
describe('deleteItem Thunk', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
fetchMock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('dispatches setDeleteJoke after successful DELETE request', async () => {
|
|
||||||
const jokeId = '123';
|
|
||||||
const expectedActions = [setDeleteJoke(jokeId)];
|
|
||||||
|
|
||||||
fetchMock.deleteOnce(`https://iut-weather-api.azurewebsites.net/jokes/${jokeId}`, {
|
|
||||||
status: 200,
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(deleteItem(jokeId));
|
|
||||||
|
|
||||||
expect(store.getActions()).toEqual(expectedActions);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs an error message if DELETE request fails', async () => {
|
|
||||||
const jokeId = '123';
|
|
||||||
|
|
||||||
fetchMock.deleteOnce(`https://iut-weather-api.azurewebsites.net/jokes/${jokeId}`, {
|
|
||||||
status: 500,
|
|
||||||
});
|
|
||||||
|
|
||||||
const consoleSpy = jest.spyOn(console, 'log');
|
|
||||||
consoleSpy.mockImplementation(() => {});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(deleteItem(jokeId));
|
|
||||||
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith('Erreur lors de la requête DELETE');
|
|
||||||
|
|
||||||
consoleSpy.mockRestore();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,47 +0,0 @@
|
|||||||
// Fonction pour ajouter une blague aux favoris
|
|
||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
||||||
import {SampleJoke} from "../../model/SampleJoke";
|
|
||||||
import {CustomJoke} from "../../model/CustomJoke";
|
|
||||||
|
|
||||||
const addFavorite = async (joke: SampleJoke | CustomJoke) => {
|
|
||||||
try {
|
|
||||||
let favorites: { sampleJokes: SampleJoke[], customJokes: CustomJoke[] } = await AsyncStorage.getItem('@favorites');
|
|
||||||
if (!favorites) {
|
|
||||||
favorites = { sampleJokes: [], customJokes: [] };
|
|
||||||
}
|
|
||||||
if (joke instanceof SampleJoke) {
|
|
||||||
favorites.sampleJokes.push(joke);
|
|
||||||
} else if (joke instanceof CustomJoke) {
|
|
||||||
favorites.customJokes.push(joke);
|
|
||||||
}
|
|
||||||
await AsyncStorage.setItem('@favorites', JSON.stringify(favorites));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error adding favorite:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeFavorite = async (jokeId: string | number) => {
|
|
||||||
try {
|
|
||||||
var favorites: { sampleJokes: SampleJoke[], customJokes: CustomJoke[] } = await AsyncStorage.getItem('@favorites');
|
|
||||||
if (!favorites) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
favorites.sampleJokes = favorites.sampleJokes.filter(joke => joke.id !== jokeId);
|
|
||||||
favorites.customJokes = favorites.customJokes.filter(joke => joke.id !== jokeId);
|
|
||||||
await AsyncStorage.setItem('@favorites', JSON.stringify(favorites));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error removing favorite:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getFavorites = async () => {
|
|
||||||
try {
|
|
||||||
const favoritesString = await AsyncStorage.getItem('@favorites');
|
|
||||||
if (favoritesString !== null) {
|
|
||||||
return JSON.parse(favoritesString);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error getting favorites:', error);
|
|
||||||
}
|
|
||||||
return { sampleJokes: [], customJokes: [] };
|
|
||||||
};
|
|
@ -1,81 +0,0 @@
|
|||||||
import fetchMock from 'fetch-mock';
|
|
||||||
import thunk from 'redux-thunk';
|
|
||||||
import configureMockStore from 'redux-mock-store';
|
|
||||||
import { getItem, getJokeById, getCustomJokeById } from './GetByThunk'; // Assurez-vous d'importer correctement vos thunks
|
|
||||||
import { setJokeById } from '../actions/SampleAction';
|
|
||||||
import {setCustomJokeById} from "../actions/CustomJoke";
|
|
||||||
import { SampleJoke } from '../../model/SampleJoke';
|
|
||||||
import { CustomJoke } from '../../model/CustomJoke';
|
|
||||||
import {afterEach, describe, expect, it, jest} from "@jest/globals";
|
|
||||||
|
|
||||||
const middlewares = [thunk];
|
|
||||||
// @ts-ignore
|
|
||||||
const mockStore = configureMockStore(middlewares);
|
|
||||||
|
|
||||||
describe('getItem Thunk', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
fetchMock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('dispatches setJokeById after successful GET request for SampleJoke', async () => {
|
|
||||||
const jokeId = 1;
|
|
||||||
const expectedJoke = new SampleJoke(jokeId, 'type', 'setup', 'image');
|
|
||||||
|
|
||||||
fetchMock.getOnce(`https://iut-weather-api.azurewebsites.net/jokes/samples/${jokeId}`, {
|
|
||||||
status: 200,
|
|
||||||
body: {
|
|
||||||
id: jokeId,
|
|
||||||
type: 'type',
|
|
||||||
setup: 'setup',
|
|
||||||
image: 'image',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(getJokeById(parseInt(jokeId)));
|
|
||||||
|
|
||||||
expect(store.getActions()).toEqual([setJokeById(expectedJoke)]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('dispatches setCustomJokeById after successful GET request for CustomJoke', async () => {
|
|
||||||
const jokeId = '1';
|
|
||||||
const expectedJoke = new CustomJoke(jokeId, 'type', 'setup', 'image');
|
|
||||||
|
|
||||||
fetchMock.getOnce(`https://iut-weather-api.azurewebsites.net/jokes/${jokeId}`, {
|
|
||||||
status: 200,
|
|
||||||
body: {
|
|
||||||
id: jokeId,
|
|
||||||
type: 'type',
|
|
||||||
setup: 'setup',
|
|
||||||
image: 'image',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(getCustomJokeById(jokeId));
|
|
||||||
|
|
||||||
expect(store.getActions()).toEqual([setCustomJokeById(expectedJoke)]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs an error message if GET request fails', async () => {
|
|
||||||
const jokeId = '1';
|
|
||||||
|
|
||||||
fetchMock.getOnce(`https://iut-weather-api.azurewebsites.net/jokes/samples/${jokeId}`, {
|
|
||||||
status: 500,
|
|
||||||
});
|
|
||||||
|
|
||||||
const consoleSpy = jest.spyOn(console, 'log');
|
|
||||||
consoleSpy.mockImplementation(() => {});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(getJokeById(parseInt(jokeId)));
|
|
||||||
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith('Error---------');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,84 +0,0 @@
|
|||||||
import fetchMock from 'fetch-mock';
|
|
||||||
import configureMockStore from 'redux-mock-store';
|
|
||||||
import { getLastSampleJokesList, getCategoriesList } from './GetThunk';
|
|
||||||
import { setCategoriesList } from '../actions/CategoryAction';
|
|
||||||
|
|
||||||
import { SampleJoke } from '../../model/SampleJoke';
|
|
||||||
import { Category } from '../../model/Category';
|
|
||||||
import {afterEach, describe, expect, it, jest} from "@jest/globals";
|
|
||||||
import {setJokesList} from "../actions/SampleAction";
|
|
||||||
import thunk from "redux-thunk";
|
|
||||||
|
|
||||||
const middlewares = [thunk];
|
|
||||||
// @ts-ignore
|
|
||||||
const mockStore = configureMockStore(middlewares);
|
|
||||||
|
|
||||||
describe('getList Thunk', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
fetchMock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('dispatches setJokesList after successful GET request for LastSampleJokesList', async () => {
|
|
||||||
const expectedJokesList = [
|
|
||||||
new SampleJoke('1', 'type1', 'setup1', 'image1'),
|
|
||||||
new SampleJoke('2', 'type2', 'setup2', 'image2'),
|
|
||||||
];
|
|
||||||
|
|
||||||
fetchMock.getOnce('https://iut-weather-api.azurewebsites.net/jokes/lasts', {
|
|
||||||
status: 200,
|
|
||||||
body: expectedJokesList.map(joke => ({
|
|
||||||
id: joke.id,
|
|
||||||
type: joke.type,
|
|
||||||
setup: joke.setup,
|
|
||||||
image: joke.image,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(getLastSampleJokesList());
|
|
||||||
|
|
||||||
expect(store.getActions()).toEqual([setJokesList(expectedJokesList)]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('dispatches setCategoriesList after successful GET request for CategoriesList', async () => {
|
|
||||||
const expectedCategoriesList = [
|
|
||||||
new Category('Category1', 1),
|
|
||||||
new Category('Category2', 2),
|
|
||||||
];
|
|
||||||
|
|
||||||
fetchMock.getOnce('https://iut-weather-api.azurewebsites.net/jokes/categories/top', {
|
|
||||||
status: 200,
|
|
||||||
body: expectedCategoriesList.map(category => ({
|
|
||||||
name: category.name,
|
|
||||||
number: category.number,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(getCategoriesList());
|
|
||||||
|
|
||||||
expect(store.getActions()).toEqual([setCategoriesList(expectedCategoriesList)]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tests similaires pour les autres fonctions thunks
|
|
||||||
|
|
||||||
it('logs an error message if GET request fails', async () => {
|
|
||||||
fetchMock.getOnce('https://iut-weather-api.azurewebsites.net/jokes/lasts', {
|
|
||||||
status: 500,
|
|
||||||
});
|
|
||||||
|
|
||||||
const consoleSpy = jest.spyOn(console, 'log');
|
|
||||||
consoleSpy.mockImplementation(() => {});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
await store.dispatch(getLastSampleJokesList());
|
|
||||||
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Error In getList'));
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,67 +0,0 @@
|
|||||||
import configureMockStore from 'redux-mock-store';
|
|
||||||
import thunk from 'redux-thunk';
|
|
||||||
import fetchMock from 'fetch-mock';
|
|
||||||
import { setPostJoke } from '../actions/CustomJoke';
|
|
||||||
import { setItem, postCustomJoke } from './PostThunk';
|
|
||||||
import {afterEach, describe, expect, it, jest} from "@jest/globals";
|
|
||||||
|
|
||||||
const middlewares = [thunk];
|
|
||||||
const mockStore = configureMockStore(middlewares);
|
|
||||||
|
|
||||||
describe('setItem Thunk', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
fetchMock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('dispatches setPostJoke after successful POST request', async () => {
|
|
||||||
const mockResponse = { id: '123', type: 'pun', setup: 'Why was the math book sad?', punchline: 'Because it had too many problems.' };
|
|
||||||
fetchMock.postOnce('https://iut-weather-api.azurewebsites.net/jokes', {
|
|
||||||
body: mockResponse,
|
|
||||||
headers: { 'content-type': 'application/json' }
|
|
||||||
});
|
|
||||||
|
|
||||||
const expectedActions = [
|
|
||||||
setPostJoke(mockResponse)
|
|
||||||
];
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
await store.dispatch(setItem('https://iut-weather-api.azurewebsites.net/jokes', 'pun', 'Why was the math book sad?', 'Because it had too many problems.'));
|
|
||||||
expect(store.getActions()).toEqual(expectedActions);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs an error message if POST request fails', async () => {
|
|
||||||
fetchMock.postOnce('https://iut-weather-api.azurewebsites.net/jokes', 404);
|
|
||||||
|
|
||||||
const consoleSpy = jest.spyOn(console, 'log');
|
|
||||||
consoleSpy.mockImplementation(() => {});
|
|
||||||
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
await store.dispatch(setItem('https://iut-weather-api.azurewebsites.net/jokes', 'pun', 'Why was the math book sad?', 'Because it had too many problems.'));
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith('Erreur lors de la requête POST');
|
|
||||||
|
|
||||||
consoleSpy.mockRestore();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('postCustomJoke Thunk', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
fetchMock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls setItem with correct parameters', async () => {
|
|
||||||
const uri = 'https://iut-weather-api.azurewebsites.net/jokes';
|
|
||||||
const type = 'pun';
|
|
||||||
const setup = 'Why was the math book sad?';
|
|
||||||
const punchline = 'Because it had too many problems.';
|
|
||||||
const store = mockStore({});
|
|
||||||
|
|
||||||
const setItemSpy = jest.spyOn(global, 'setItem');
|
|
||||||
setItemSpy.mockResolvedValueOnce();
|
|
||||||
|
|
||||||
await store.dispatch(postCustomJoke(type, setup, punchline));
|
|
||||||
expect(setItemSpy).toHaveBeenCalledWith(uri, type, setup, punchline);
|
|
||||||
|
|
||||||
setItemSpy.mockRestore();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,21 +0,0 @@
|
|||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
||||||
import {Theme} from "@react-navigation/native";
|
|
||||||
|
|
||||||
export const storeTheme = async (theme) => {
|
|
||||||
try {
|
|
||||||
const jsonValue = JSON.stringify(theme)
|
|
||||||
await AsyncStorage.setItem('@theme', jsonValue)
|
|
||||||
console.log("theme stored")
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getTheme = async () => {
|
|
||||||
try {
|
|
||||||
const jsonValue = await AsyncStorage.getItem('@theme')
|
|
||||||
return jsonValue != null ? JSON.parse(jsonValue) as Theme : null;
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
||||||
import { storeTheme, getTheme } from "./ThemeThunk";
|
|
||||||
import {afterEach, describe, expect, it, jest} from "@jest/globals";
|
|
||||||
|
|
||||||
describe('storeTheme Function', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('stores theme in AsyncStorage', async () => {
|
|
||||||
const theme = { colors: { background: 'white', text: 'black' } };
|
|
||||||
const jsonValue = JSON.stringify(theme);
|
|
||||||
AsyncStorage.setItem = jest.fn().mockResolvedValueOnce();
|
|
||||||
console.log = jest.fn();
|
|
||||||
|
|
||||||
await storeTheme(theme);
|
|
||||||
expect(AsyncStorage.setItem).toHaveBeenCalledWith('@theme', jsonValue);
|
|
||||||
expect(console.log).toHaveBeenCalledWith("theme stored");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs error if theme storage fails', async () => {
|
|
||||||
const theme = { colors: { background: 'white', text: 'black' } };
|
|
||||||
AsyncStorage.setItem = jest.fn().mockRejectedValueOnce('Storage error');
|
|
||||||
console.error = jest.fn();
|
|
||||||
|
|
||||||
await storeTheme(theme);
|
|
||||||
expect(console.error).toHaveBeenCalledWith('Storage error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getTheme Function', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('retrieves theme from AsyncStorage', async () => {
|
|
||||||
const theme = { colors: { background: 'white', text: 'black' } };
|
|
||||||
const jsonValue = JSON.stringify(theme);
|
|
||||||
AsyncStorage.getItem = jest.fn().mockResolvedValueOnce(jsonValue);
|
|
||||||
|
|
||||||
const result = await getTheme();
|
|
||||||
expect(result).toEqual(theme);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns null if theme is not found in AsyncStorage', async () => {
|
|
||||||
AsyncStorage.getItem = jest.fn().mockResolvedValueOnce(null);
|
|
||||||
|
|
||||||
const result = await getTheme();
|
|
||||||
expect(result).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs error if theme retrieval fails', async () => {
|
|
||||||
AsyncStorage.getItem = jest.fn().mockRejectedValueOnce('Retrieval error');
|
|
||||||
console.error = jest.fn();
|
|
||||||
|
|
||||||
await getTheme();
|
|
||||||
expect(console.error).toHaveBeenCalledWith('Retrieval error');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,115 +1,21 @@
|
|||||||
|
import { customJokeStub } from '../data/stub/CustomJokeStub';
|
||||||
|
import { sampleJokeStub } from '../data/stub/SampleJokeStub';
|
||||||
import JokeItems from "../components/JokeItems";
|
import JokeItems from "../components/JokeItems";
|
||||||
import '../types/extension';
|
import '../types/extension';
|
||||||
import {Image, SafeAreaView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
|
import {StyleSheet, View} from "react-native";
|
||||||
import {darksalmonColor, purpleColor, whiteColor} from "../assets/Theme";
|
import {purpleColor} from "../assets/Theme";
|
||||||
import {useDispatch, useSelector} from "react-redux";
|
|
||||||
import React, {useEffect, useState} from "react";
|
|
||||||
import {getCustomJokesList, getSampleJokesList} from "../redux/thunk/GetThunk";
|
|
||||||
import {useTheme} from "@react-navigation/native";
|
|
||||||
|
|
||||||
export default function Favorites() {
|
|
||||||
// @ts-ignore
|
|
||||||
const sampleJokes = useSelector(state => state.sampleReducer.jokes);
|
|
||||||
// @ts-ignore
|
|
||||||
const customJokes = useSelector(state => state.customReducer.customJokes);
|
|
||||||
const [joke, setJoke] = useState([])
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
const eye = require("../assets/eye_icon.png")
|
|
||||||
const hideEye = require("../assets/eye_off_icon.png")
|
|
||||||
|
|
||||||
const [showCustomJoke, setCustomJoke] = useState(false); // état local pour contrôler la visibilité de la description
|
|
||||||
const toggleDescription = () => {
|
|
||||||
setCustomJoke(!showCustomJoke);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(!showCustomJoke) {
|
|
||||||
const loadSamplesJokes = async () => {
|
|
||||||
// @ts-ignore
|
|
||||||
await dispatch(getFavorites());
|
|
||||||
};
|
|
||||||
loadSamplesJokes();
|
|
||||||
setJoke(sampleJokes)
|
|
||||||
} else {
|
|
||||||
const loadCustomJokes = async () => {
|
|
||||||
// @ts-ignore
|
|
||||||
await dispatch(getCustomJokesList());
|
|
||||||
};
|
|
||||||
loadCustomJokes();
|
|
||||||
setJoke(customJokes)
|
|
||||||
}
|
|
||||||
}, [dispatch, customJokes, sampleJokes]);
|
|
||||||
|
|
||||||
const styles = themeSettings()
|
|
||||||
|
|
||||||
|
export default function Catalogue() {
|
||||||
|
const allJokes = [...customJokeStub, ...sampleJokeStub];
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container}>
|
|
||||||
<View style={styles.columnContainer}>
|
|
||||||
<Text style={styles.TextButton}>Afficher les exemples</Text>
|
|
||||||
<TouchableOpacity style={styles.Button} onPress={toggleDescription}>
|
|
||||||
<View style={styles.jokeTypeContainer}>
|
|
||||||
<Image
|
|
||||||
source={showCustomJoke ? hideEye : eye}
|
|
||||||
style={styles.imageButton}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<JokeItems jokes={joke}/>
|
<JokeItems jokes={allJokes}/>
|
||||||
</View>
|
</View>
|
||||||
</SafeAreaView>
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export function themeSettings() {
|
|
||||||
const theme = useTheme();
|
|
||||||
const colors = theme.colors;
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
backgroundColor: colors.background,
|
backgroundColor: purpleColor
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
Button: {
|
|
||||||
borderRadius: 5,
|
|
||||||
backgroundColor: colors.background,
|
|
||||||
height: 40,
|
|
||||||
width: 60,
|
|
||||||
flexDirection: "row"
|
|
||||||
},
|
|
||||||
jokeTypeContainer: {
|
|
||||||
display: "flex",
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
},
|
|
||||||
imageButton: {
|
|
||||||
margin: 10,
|
|
||||||
width: 40,
|
|
||||||
height: 30,
|
|
||||||
top: 5,
|
|
||||||
alignSelf: "center",
|
|
||||||
backgroundColor: "none",
|
|
||||||
tintColor: colors.notification,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
TextButton: {
|
|
||||||
fontSize: 18,
|
|
||||||
color: colors.notification,
|
|
||||||
textAlign: 'center',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
margin: 10,
|
|
||||||
},
|
|
||||||
columnContainer: {
|
|
||||||
marginLeft: 20,
|
|
||||||
marginRight: 20,
|
|
||||||
width: '90%',
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return styles
|
|
||||||
}
|
|
@ -1,102 +1,21 @@
|
|||||||
|
import { customJokeStub } from '../data/stub/CustomJokeStub';
|
||||||
|
import { sampleJokeStub } from '../data/stub/SampleJokeStub';
|
||||||
|
import JokeItems from "../components/JokeItems";
|
||||||
import '../types/extension';
|
import '../types/extension';
|
||||||
import {Image, StyleSheet, Switch, Text, View} from "react-native";
|
import {StyleSheet, View} from "react-native";
|
||||||
import {
|
import {purpleColor} from "../assets/Theme";
|
||||||
darksalmonColor, DarkTheme,
|
|
||||||
whiteColor
|
|
||||||
} from "../assets/Theme";
|
|
||||||
import React from "react";
|
|
||||||
import {DefaultTheme, useTheme} from "@react-navigation/native";
|
|
||||||
import {storeTheme} from "../redux/thunk/ThemeThunk";
|
|
||||||
|
|
||||||
export default function Catalogue() {
|
export default function Catalogue() {
|
||||||
const light_mode = require("../assets/light_mode.png")
|
const allJokes = [...customJokeStub, ...sampleJokeStub];
|
||||||
const dark_mode = require("../assets/dark_mode.png")
|
|
||||||
const [isDark, setDark] = React.useState(false)
|
|
||||||
|
|
||||||
const toggleTheme = () => {
|
|
||||||
setDark(previousState => {
|
|
||||||
const theme = !previousState;
|
|
||||||
const newTheme = theme ? DarkTheme : DefaultTheme;
|
|
||||||
storeTheme(newTheme);
|
|
||||||
return theme;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const styles = themeSettings();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.topText}>
|
<JokeItems jokes={allJokes}/>
|
||||||
<Text style={styles.title}>Réglages</Text>
|
|
||||||
<View style={styles.switchMode}>
|
|
||||||
<View style={styles.textContainer}>
|
|
||||||
<Image
|
|
||||||
source={isDark? dark_mode: light_mode}
|
|
||||||
style={styles.imageButton} />
|
|
||||||
<Text style={styles.darkModeText}>Dark Mode</Text>
|
|
||||||
</View>
|
|
||||||
<Switch
|
|
||||||
value={isDark}
|
|
||||||
onValueChange={toggleTheme}
|
|
||||||
style={styles.switchMode}
|
|
||||||
trackColor={{false: darksalmonColor, true: darksalmonColor}}
|
|
||||||
thumbColor={whiteColor} />
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
)
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function themeSettings() {
|
|
||||||
const theme = useTheme();
|
|
||||||
const colors = theme.colors;
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|
||||||
container: {
|
container: {
|
||||||
paddingTop: 10,
|
backgroundColor: purpleColor
|
||||||
paddingBottom: 10,
|
|
||||||
paddingLeft: 10,
|
|
||||||
paddingRight: 10,
|
|
||||||
flex: 1,
|
|
||||||
justifyContent: 'center',
|
|
||||||
backgroundColor: colors.background,
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
topText: {
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
padding: 10,
|
|
||||||
fontSize: 20,
|
|
||||||
color: colors.text,
|
|
||||||
fontWeight: 'bold'
|
|
||||||
},
|
|
||||||
imageButton : {
|
|
||||||
width: 30,
|
|
||||||
height:30,
|
|
||||||
alignSelf : "center",
|
|
||||||
tintColor: colors.primary,
|
|
||||||
},
|
|
||||||
switchMode: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
backgroundColor: colors.card,
|
|
||||||
padding: 20,
|
|
||||||
margin: 10,
|
|
||||||
},
|
|
||||||
darkModeText: {
|
|
||||||
color: colors.text,
|
|
||||||
fontSize: 20,
|
|
||||||
marginLeft: 10,
|
|
||||||
paddingTop: 5,
|
|
||||||
},
|
|
||||||
textContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return styles;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue