diff --git a/.vscode/settings.json b/.vscode/settings.json index 655e7ed46f08f4474853672468d6312ea586bee1..379318f79a5162c138c561f6cbc3a4899dab5d2a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -113,6 +113,7 @@ "Picto", "PIV'EAU", "profileecogesture", + "PROFILEECOGESTURE", "profiletype", "PROFILETYPE", "pseudonymisées", @@ -124,6 +125,7 @@ "Téléo", "testid", "Tétris", + "TIMESTEP", "timestep", "UNSTARTED", "usageevent", diff --git a/src/components/Action/ActionBegin.tsx b/src/components/Action/ActionBegin.tsx index c1c45183ba142f9e4552d53a5763289372bbbee7..546036e699ff8e1b973822b95b31a1655ffac714 100644 --- a/src/components/Action/ActionBegin.tsx +++ b/src/components/Action/ActionBegin.tsx @@ -26,10 +26,10 @@ const ActionBegin: React.FC<ActionBeginProps> = ({ }: ActionBeginProps) => { const client: Client = useClient() const { t } = useI18n() - const { isProfileTypeCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile - ) - const { fluidTypes } = useSelector((state: AppStore) => state.ecolyo.global) + const { + global: { fluidTypes }, + profile: { isProfileTypeCompleted }, + } = useSelector((state: AppStore) => state.ecolyo) const [currentAction, setCurrentAction] = useState<Ecogesture>() const [actionIcon, setActionIcon] = useState<string>('') const [openLaunchModal, setOpenLaunchModal] = useState<boolean>(false) diff --git a/src/components/Action/ActionDone.tsx b/src/components/Action/ActionDone.tsx index c483853482883d01cfecc473b6a0474a3107eb6f..1d94980dc928cb805053a714e54311329c086e66 100644 --- a/src/components/Action/ActionDone.tsx +++ b/src/components/Action/ActionDone.tsx @@ -6,11 +6,12 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch } from 'react-redux' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import { toggleChallengeActionNotification } from 'store/global/global.actions' import './actionDone.scss' @@ -23,7 +24,7 @@ const ActionDone: React.FC<ActionDoneProps> = ({ }: ActionDoneProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const handleEndAction = useCallback(async () => { const challengeService = new ChallengeService(client) diff --git a/src/components/Action/ActionList.tsx b/src/components/Action/ActionList.tsx index 8997a3568a96c54ce47c0ee2fcbdfd51b56546fe..447ca9aee3975db6449a2c6cf59115a50531830e 100644 --- a/src/components/Action/ActionList.tsx +++ b/src/components/Action/ActionList.tsx @@ -17,10 +17,10 @@ const ActionList: React.FC<ActionListProps> = ({ setShowList, }: ActionListProps) => { const client: Client = useClient() - const { isProfileTypeCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile - ) - const { fluidTypes } = useSelector((state: AppStore) => state.ecolyo.global) + const { + global: { fluidTypes }, + profile: { isProfileTypeCompleted }, + } = useSelector((state: AppStore) => state.ecolyo) const [actions, setActions] = useState<Ecogesture[]>() useEffect(() => { diff --git a/src/components/Action/ActionModal.tsx b/src/components/Action/ActionModal.tsx index 982d724b60e8cdad27141c496ddec2857f291e7f..cb209b25e13a42f4eaa1091e940078fb5c0f02c5 100644 --- a/src/components/Action/ActionModal.tsx +++ b/src/components/Action/ActionModal.tsx @@ -6,9 +6,10 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { Ecogesture, UserChallenge } from 'models' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch } from 'react-redux' import ChallengeService from 'services/challenge.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import './actionModal.scss' @@ -25,7 +26,7 @@ const ActionModal: React.FC<ActionModalProps> = ({ handleCloseClick, userChallenge, }: ActionModalProps) => { - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const client = useClient() const { t } = useI18n() const launchAction = useCallback(async () => { diff --git a/src/components/Analysis/AnalysisConsumption.tsx b/src/components/Analysis/AnalysisConsumption.tsx index f1703e78eb1aaadee463687a1b63babc79c3dc2a..8cee0f4f4d930260f160dd845c156ae8b6591b0c 100644 --- a/src/components/Analysis/AnalysisConsumption.tsx +++ b/src/components/Analysis/AnalysisConsumption.tsx @@ -15,7 +15,7 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' -import { PerformanceIndicator, Profile } from 'models' +import { PerformanceIndicator } from 'models' import { MonthlyForecast, ProfileType } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' import { useSelector } from 'react-redux' @@ -41,10 +41,10 @@ const AnalysisConsumption: React.FC<AnalysisConsumptionProps> = ({ const navigate = useNavigate() const client: Client = useClient() const userPriceConsumption: number = aggregatedPerformanceIndicator.value || 0 - const profile: Profile = useSelector( - (state: AppStore) => state.ecolyo.profile - ) - const { fluidTypes } = useSelector((state: AppStore) => state.ecolyo.global) + const { + global: { fluidTypes }, + profile, + } = useSelector((state: AppStore) => state.ecolyo) const [homePriceConsumption, setHomePriceConsumption] = useState<number>(0) const [forecast, setForecast] = useState<MonthlyForecast | null>(null) const [isLoading, setIsLoading] = useState<boolean>(true) diff --git a/src/components/Analysis/AnalysisView.spec.tsx b/src/components/Analysis/AnalysisView.spec.tsx index 32c67dbd856468e65bcfcfb7f1c996362c5a846d..87e6fb72a27e4b34cffba80e29d52832dd259c78 100644 --- a/src/components/Analysis/AnalysisView.spec.tsx +++ b/src/components/Analysis/AnalysisView.spec.tsx @@ -8,8 +8,8 @@ import * as profileActions from 'store/profile/profile.actions' import { globalStateData } from '../../../tests/__mocks__/globalStateData.mock' import { profileData } from '../../../tests/__mocks__/profileData.mock' import { - createMockStore, - mockInitialEcolyoState, + createMockEcolyoStore, + mockInitialChartState, } from '../../../tests/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -43,10 +43,9 @@ const toggleAnalysisNotificationSpy = jest.spyOn( const updateProfileSpy = jest.spyOn(profileActions, 'updateProfile') describe('AnalysisView component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useSelectorSpy.mockClear() useDispatchSpy.mockClear() toggleAnalysisNotificationSpy.mockClear() @@ -57,6 +56,7 @@ describe('AnalysisView component', () => { useSelectorSpy.mockReturnValue({ global: globalStateData, profile: profileData, + chart: mockInitialChartState, }) useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( @@ -80,6 +80,7 @@ describe('AnalysisView component', () => { ...profileData, haveSeenLastAnalysis: false, }, + chart: mockInitialChartState, }) useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( diff --git a/src/components/Analysis/AnalysisView.tsx b/src/components/Analysis/AnalysisView.tsx index 2274e2d987d098cbfb9e6c02e11b9ba60258612e..55dd0fcc29038ebaa1fb8b5549cfb6a6f107d9a1 100644 --- a/src/components/Analysis/AnalysisView.tsx +++ b/src/components/Analysis/AnalysisView.tsx @@ -6,11 +6,11 @@ import Header from 'components/Header/Header' import { useClient } from 'cozy-client' import { UsageEventType } from 'enum/usageEvent.enum' import { DateTime } from 'luxon' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useLocation } from 'react-router-dom' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { toggleAnalysisNotification } from 'store/global/global.actions' import { updateProfile } from 'store/profile/profile.actions' import './analysisView.scss' @@ -19,16 +19,14 @@ const AnalysisView: React.FC = () => { const client = useClient() const [headerHeight, setHeaderHeight] = useState<number>(0) const { + chart: { selectedDate }, global: { analysisNotification }, - profile: { monthlyAnalysisDate }, + profile: { monthlyAnalysisDate, mailToken }, } = useSelector((state: AppStore) => state.ecolyo) - const { selectedDate } = useSelector((state: AppStore) => state.ecolyo.chart) const [currentAnalysisDate, setCurrentAnalysisDate] = useState<DateTime>(monthlyAnalysisDate) - const { mailToken } = useSelector((state: AppStore) => state.ecolyo.profile) - const dispatch = useDispatch() - + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) }, []) diff --git a/src/components/Analysis/TotalAnalysisChart.spec.tsx b/src/components/Analysis/TotalAnalysisChart.spec.tsx index e79e862b6bac344f1016122fc1c96f631b78daf7..352503150f34a937bd30dd5c614dbc6a2b477542 100644 --- a/src/components/Analysis/TotalAnalysisChart.spec.tsx +++ b/src/components/Analysis/TotalAnalysisChart.spec.tsx @@ -7,10 +7,7 @@ import React from 'react' import { act } from 'react-dom/test-utils' import { Provider } from 'react-redux' import { graphMonthData } from '../../../tests/__mocks__/chartData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import TotalAnalysisChart from './TotalAnalysisChart' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -33,10 +30,9 @@ jest.mock('services/consumption.service', () => { jest.mock('components/Analysis/PieChart', () => 'mock-piechart') describe('TotalAnalysisChart component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/App.tsx b/src/components/App.tsx index 577bf36e403bfc8253d3806f871283cf1862fd90..8fada099d1c4dc912c144f9c682b210829c97474 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -15,8 +15,10 @@ interface AppProps { export const App = ({ tracker }: AppProps) => { const location = useLocation() - const { onboarding } = useSelector((state: AppStore) => state.ecolyo.profile) - const { termsStatus } = useSelector((state: AppStore) => state.ecolyo.global) + const { + global: { termsStatus }, + profile: { onboarding }, + } = useSelector((state: AppStore) => state.ecolyo) useEffect(() => { tracker?.track(location) diff --git a/src/components/Challenge/ChallengeCardOnGoing.tsx b/src/components/Challenge/ChallengeCardOnGoing.tsx index db3d34996690bbed0888fd88ce623fef860d0652..6fd07442333c2af42f1dfdbea61e479f6ee55560 100644 --- a/src/components/Challenge/ChallengeCardOnGoing.tsx +++ b/src/components/Challenge/ChallengeCardOnGoing.tsx @@ -15,11 +15,11 @@ import { UserDuelState } from 'enum/userDuel.enum' import { UserExplorationState } from 'enum/userExploration.enum' import { UserQuizState } from 'enum/userQuiz.enum' import { UserChallenge } from 'models' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import { getChallengeTitleWithLineReturn, importIconById } from 'utils/utils' import './challengeCardOnGoing.scss' @@ -34,7 +34,7 @@ const ChallengeCardOnGoing: React.FC<ChallengeCardOnGoingProps> = ({ }: ChallengeCardOnGoingProps) => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const [isOneFluidUp, setIsOneFluidUp] = useState<boolean>(true) const [challengeIcon, setChallengeIcon] = useState<string>(defaultIcon) diff --git a/src/components/Challenge/ChallengeCardUnlocked.tsx b/src/components/Challenge/ChallengeCardUnlocked.tsx index 60603710c92b10e56596abbe4ef31e78dcf017fe..68cfcd89f0dfbedb7bf825ba236900cf0531ecf2 100644 --- a/src/components/Challenge/ChallengeCardUnlocked.tsx +++ b/src/components/Challenge/ChallengeCardUnlocked.tsx @@ -6,11 +6,11 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidState } from 'enum/fluid.enum' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallenge } from 'models' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import { getChallengeTitleWithLineReturn, importIconById } from 'utils/utils' import './challengeCardUnlocked.scss' @@ -23,12 +23,13 @@ const ChallengeCardUnlocked: React.FC<ChallengeCardUnlockedProps> = ({ userChallenge, }: ChallengeCardUnlockedProps) => { const client: Client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { t } = useI18n() const [openNoFluidModal, setopenNoFluidModal] = useState(false) - const { fluidTypes } = useSelector((state: AppStore) => state.ecolyo.global) - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + const { fluidTypes, fluidStatus } = useSelector( + (state: AppStore) => state.ecolyo.global + ) const [challengeIcon, setChallengeIcon] = useState(defaultIcon) let statusRequirementOk = false diff --git a/src/components/Challenge/ChallengeView.spec.tsx b/src/components/Challenge/ChallengeView.spec.tsx index ddae531e629c51015fb73b4e385313f97ae91cf8..69768b00c7885b39864b855b745c867689018fe5 100644 --- a/src/components/Challenge/ChallengeView.spec.tsx +++ b/src/components/Challenge/ChallengeView.spec.tsx @@ -4,10 +4,7 @@ import toJson from 'enzyme-to-json' import React from 'react' import * as reactRedux from 'react-redux' import { challengeStateDataFull } from '../../../tests/__mocks__/challengeStateData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') @@ -26,13 +23,13 @@ jest.mock('components/Header/Header', () => 'mock-header') jest.mock('components/Content/Content', () => 'mock-content') jest.mock('components/Challenge/ChallengeCard', () => 'mock-challengecard') +// TODO unused ? const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') describe('ChallengeView component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useSelectorSpy.mockClear() }) diff --git a/src/components/Charts/AxisBottom.spec.tsx b/src/components/Charts/AxisBottom.spec.tsx index 233093039279952b5126f9cca8e8986a192e2a5d..e6e5a7f13c77b92e4eaa707dc522ccf9b2b0dbd4 100644 --- a/src/components/Charts/AxisBottom.spec.tsx +++ b/src/components/Charts/AxisBottom.spec.tsx @@ -6,10 +6,7 @@ import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { graphData } from '../../../tests/__mocks__/chartData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import AxisBottom from './AxisBottom' const mockXScale: ScaleBand<string> = scaleBand() @@ -29,10 +26,9 @@ const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') describe('AxisBottom component test', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useDispatchSpy.mockClear() }) diff --git a/src/components/Charts/Bar.spec.tsx b/src/components/Charts/Bar.spec.tsx index 671f64325c0043a0c330f4655bf8745e550a3af1..6880d2f3940f15a12b246c4095b613acc581b038 100644 --- a/src/components/Charts/Bar.spec.tsx +++ b/src/components/Charts/Bar.spec.tsx @@ -8,10 +8,7 @@ import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import * as chartActions from 'store/chart/chart.actions' import { graphData } from '../../../tests/__mocks__/chartData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import Bar from './Bar' const mockXScale: ScaleBand<string> = scaleBand() @@ -46,10 +43,9 @@ const setCurrentDatachartIndexSpy = jest.spyOn( ) describe('Bar component test', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useDispatchSpy.mockClear() setSelectedDateSpy.mockClear() setCurrentDatachartIndexSpy.mockClear() diff --git a/src/components/Charts/Bar.tsx b/src/components/Charts/Bar.tsx index 6cb7877b4a96217d05f9e48d0e1d456f81d5809a..06ff85fdb1968737121662015cb7bb0cbd3e6e4f 100644 --- a/src/components/Charts/Bar.tsx +++ b/src/components/Charts/Bar.tsx @@ -4,10 +4,10 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Dataload } from 'models' -import React, { useEffect, useState } from 'react' +import React, { Dispatch, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import DateChartService from 'services/dateChart.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentDatachartIndex, setSelectedDate, @@ -44,7 +44,7 @@ const Bar = ({ isMultiMissingFluid, weekdays, }: BarProps) => { - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { selectedDate } = useSelector((state: AppStore) => state.ecolyo.chart) const [clicked, setClicked] = useState(false) const [animationEnded, setAnimationEnded] = useState(false) diff --git a/src/components/Connection/Connection.tsx b/src/components/Connection/Connection.tsx index 3da86c44de6389db1eefe6aabe3fbf4e89a9a053..184c158670a6ad6e76b1b7a5e9e6f41fee4670ce 100644 --- a/src/components/Connection/Connection.tsx +++ b/src/components/Connection/Connection.tsx @@ -1,7 +1,8 @@ import { FluidType } from 'enum/fluid.enum' import { FluidConnection, FluidStatus } from 'models' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch } from 'react-redux' +import { AppActionsTypes } from 'store' import { updatedFluidConnection } from 'store/global/global.actions' import './connection.scss' import EpglInit from './EPGLConnect/EpglInit' @@ -14,7 +15,7 @@ interface ConnectionProps { const Connection: React.FC<ConnectionProps> = ({ fluidStatus, }: ConnectionProps) => { - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const handleSuccess = useCallback(async () => { const updatedConnection: FluidConnection = { diff --git a/src/components/Connection/ConnectionResult.tsx b/src/components/Connection/ConnectionResult.tsx index 6a2fccce49ef0223a3da74d504a2520ec936b3e3..fcd29bd19c42fd9ed53bafb4cd65057920f2d273 100644 --- a/src/components/Connection/ConnectionResult.tsx +++ b/src/components/Connection/ConnectionResult.tsx @@ -13,11 +13,12 @@ import { FluidStatus, Trigger, } from 'models' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch } from 'react-redux' import AccountService from 'services/account.service' import DateChartService from 'services/dateChart.service' import TriggerService from 'services/triggers.service' +import { AppActionsTypes } from 'store' import { setShouldRefreshConsent, updatedFluidConnection, @@ -40,7 +41,7 @@ const ConnectionResult: React.FC<ConnectionResultProps> = ({ }: ConnectionResultProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const account: Account | null = fluidStatus.connection.account const [deleting, setDeleting] = useState<boolean>(false) diff --git a/src/components/Connection/ExpiredConsentModal.tsx b/src/components/Connection/ExpiredConsentModal.tsx index ef0c9c5ee1e79676fdf55d944776d9c241b6cb56..6a6dcc5c5d784090b3e7a4a92f2830fdd6c7798e 100644 --- a/src/components/Connection/ExpiredConsentModal.tsx +++ b/src/components/Connection/ExpiredConsentModal.tsx @@ -7,10 +7,10 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { FluidType } from 'enum/fluid.enum' import { AccountSgeData } from 'models' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setShouldRefreshConsent, updateSgeStore, @@ -32,7 +32,7 @@ const ExpiredConsentModal: React.FC<ExpiredConsentModalProps> = ({ }: ExpiredConsentModalProps) => { const { t } = useI18n() const navigate = useNavigate() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) const launchUpdateConsent = useCallback(() => { diff --git a/src/components/Connection/FormOAuth.tsx b/src/components/Connection/FormOAuth.tsx index 93eb4226d71030e257ce674a95612e72073ae415..a732fd9602217b91a113405a21be2da274c86e63 100644 --- a/src/components/Connection/FormOAuth.tsx +++ b/src/components/Connection/FormOAuth.tsx @@ -4,10 +4,10 @@ import { OAuthWindow } from 'cozy-harvest-lib/dist/components/OAuthWindow' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { FluidStatus, Konnector } from 'models' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setShouldRefreshConsent } from 'store/global/global.actions' interface FormOAuthProps { @@ -30,7 +30,7 @@ const FormOAuth: React.FC<FormOAuthProps> = ({ const { shouldRefreshConsent } = useSelector( (state: AppStore) => state.ecolyo.global ) - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const endOAuth = useCallback(() => { setStatus(IDLE) // Set back to false the variable that allows to automatically refresh the consent (deletes and recreates the account) diff --git a/src/components/Connection/GRDFConnect/GrdfInit.tsx b/src/components/Connection/GRDFConnect/GrdfInit.tsx index 4414d9b035d381ced015ec9e8e43395a5c5d4e1e..3e580a9f40ee3796252fc15d69e75ddc39ca17bd 100644 --- a/src/components/Connection/GRDFConnect/GrdfInit.tsx +++ b/src/components/Connection/GRDFConnect/GrdfInit.tsx @@ -2,11 +2,12 @@ import GrdfConnectModal from 'components/Connection/PartnerConnectModal/GrdfConn import { useClient } from 'cozy-client' import { UsageEventType } from 'enum/usageEvent.enum' import { FluidConnection, FluidStatus, Konnector, Trigger } from 'models' -import React, { useCallback, useState } from 'react' +import React, { Dispatch, useCallback, useState } from 'react' import { useDispatch } from 'react-redux' import AccountService from 'services/account.service' import TriggerService from 'services/triggers.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { updatedFluidConnection } from 'store/global/global.actions' import '../connection.scss' import GrdfBill from './GrdfBill' @@ -22,7 +23,7 @@ const GrdfInit: React.FC<GrdfInitProps> = ({ onSuccess, }: GrdfInitProps) => { const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const [openModal, setOpenModal] = useState(false) const [showForm, setShowForm] = useState(false) diff --git a/src/components/Connection/SGEConnect/SgeConnectView.tsx b/src/components/Connection/SGEConnect/SgeConnectView.tsx index d1e6d89d20e3af078f36ee46cadee431e20613e0..8a78148b0ff6eec6a04f93c754b8104d4935d016 100644 --- a/src/components/Connection/SGEConnect/SgeConnectView.tsx +++ b/src/components/Connection/SGEConnect/SgeConnectView.tsx @@ -5,9 +5,9 @@ import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import { SgeStep } from 'enum/sgeStep.enum' import { SgeStore } from 'models/sgeStore.model' -import React, { useCallback, useState } from 'react' +import React, { Dispatch, useCallback, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateSgeStore } from 'store/global/global.actions' import './SgeConnect.scss' import StepAddress from './StepAddress' @@ -27,7 +27,7 @@ export type SGEKeysForm = const SgeConnectView: React.FC = () => { const [headerHeight, setHeaderHeight] = useState<number>(0) const { sgeConnect } = useSelector((state: AppStore) => state.ecolyo.global) - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const [currentStep, setCurrentStep] = useState<SgeStep>( sgeConnect.currentStep ) diff --git a/src/components/Connection/SGEConnect/SgeInit.tsx b/src/components/Connection/SGEConnect/SgeInit.tsx index 259324ac27e7d96c2973435dd07edeff4e3eda7f..c882678e44e8138c06aaff4ebd237fa53779c7cd 100644 --- a/src/components/Connection/SGEConnect/SgeInit.tsx +++ b/src/components/Connection/SGEConnect/SgeInit.tsx @@ -4,10 +4,10 @@ import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import useKonnectorAuth from 'components/Hooks/useKonnectorAuth' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { Account, FluidStatus } from 'models' -import React, { useEffect } from 'react' +import React, { Dispatch, useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setShouldRefreshConsent, updateSgeStore, @@ -24,7 +24,7 @@ const SgeInit: React.FC<SgeInitProps> = ({ fluidStatus }: SgeInitProps) => { const account: Account | null = fluidStatus.connection.account const { sgeConnect } = useSelector((state: AppStore) => state.ecolyo.global) - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const [connect, update] = useKonnectorAuth(fluidStatus) useEffect(() => { diff --git a/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx index eab7e13b49e302fd06c4851bf88aac47e540c354..a2d879851348987052f1f257fdc47a96ef31d273 100644 --- a/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx @@ -18,12 +18,11 @@ const ConsumptionVisualizer: React.FC<ConsumptionVisualizerProps> = ({ showCompare, setActive, }: ConsumptionVisualizerProps) => { - const { fluidStatus, fluidTypes } = useSelector( - (state: AppStore) => state.ecolyo.global - ) - const { currentDatachart, currentDatachartIndex } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) + const { + chart: { currentDatachart, currentDatachartIndex }, + global: { fluidStatus, fluidTypes }, + } = useSelector((state: AppStore) => state.ecolyo) + const dataload: Dataload = currentDatachart.actualData[currentDatachartIndex] const compareDataload: Dataload | null = currentDatachart.comparisonData ? currentDatachart.comparisonData[currentDatachartIndex] diff --git a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx index a091b18772342f80b39cec39b5c07e78a27246d6..b56ed2c52da501873dbe9514d7614c24938f119f 100644 --- a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx +++ b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx @@ -8,10 +8,7 @@ import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { baseDataLoad } from '../../../tests/__mocks__/chartData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import InfoDataConsumptionVisualizer from './InfoDataConsumptionVisualizer' import NoDataModal from './NoDataModal' @@ -33,10 +30,9 @@ describe('InfoDataConsumptionVisualizer component', () => { }) const mockDataload: Dataload = baseDataLoad - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should render correctly when data valid', () => { diff --git a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx index b69f82c0633574be35413988de5cf3a3de4fb474..b4524da551ebc4fafe33f835a41b6b3b131ed7ae 100644 --- a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx @@ -3,10 +3,10 @@ import { DataloadState } from 'enum/dataload.enum' import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' import { Dataload } from 'models' -import React, { useCallback, useState } from 'react' +import React, { Dispatch, useCallback, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import DateChartService from 'services/dateChart.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.actions' import './infoDataConsumptionVisualizer.scss' import NoDataModal from './NoDataModal' @@ -23,7 +23,7 @@ const InfoDataConsumptionVisualizer = ({ lastDataDate, }: InfoDataConsumptionVisualizerProps) => { const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { currentTimeStep } = useSelector( (state: AppStore) => state.ecolyo.chart ) diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx index 3f7e11a9aa3a6058a2cd7f223edf86427a51306f..cfef2245f554a0da3adbb4faffc3a5a6314c4244 100644 --- a/src/components/Content/Content.tsx +++ b/src/components/Content/Content.tsx @@ -1,10 +1,10 @@ import FeedbackModal from 'components/Feedback/FeedbackModal' import { ScreenType } from 'enum/screen.enum' -import React, { useCallback, useEffect } from 'react' +import React, { Dispatch, useCallback, useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { changeScreenType } from 'store/global/global.actions' -import { updateModalIsFeedbacksOpen } from 'store/modal/modal.actions' +import { openFeedbackModal } from 'store/modal/modal.actions' import './content.scss' interface ContentProps { children?: React.ReactNode @@ -17,17 +17,17 @@ const Content: React.FC<ContentProps> = ({ height = 0, background = 'inherit', }: ContentProps) => { - const dispatch = useDispatch() - const { screenType } = useSelector((state: AppStore) => state.ecolyo.global) - const { isFeedbacksOpen } = useSelector( - (state: AppStore) => state.ecolyo.modal - ) + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const { + global: { screenType }, + modal: { isFeedbacksOpen }, + } = useSelector((state: AppStore) => state.ecolyo) const cozyBarHeight = 48 const cozyNavHeight = 56 const handleFeedbackModalClose = useCallback(() => { - dispatch(updateModalIsFeedbacksOpen(false)) + dispatch(openFeedbackModal(false)) }, [dispatch]) // Set listeners for scroll diff --git a/src/components/DateNavigator/DateNavigator.tsx b/src/components/DateNavigator/DateNavigator.tsx index 42d12bd030489ab6fb1e7196b4ecddb9b43feedb..9bdb35a7e6d6f32912b0a016cd17974d8ee138f1 100644 --- a/src/components/DateNavigator/DateNavigator.tsx +++ b/src/components/DateNavigator/DateNavigator.tsx @@ -8,10 +8,10 @@ import Icon from 'cozy-ui/transpiled/react/Icon' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' -import React from 'react' +import React, { Dispatch } from 'react' import { useDispatch, useSelector } from 'react-redux' import DateChartService from 'services/dateChart.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.actions' import { isLastDateReached } from 'utils/date' import { isKonnectorActive } from 'utils/utils' @@ -29,11 +29,11 @@ const DateNavigator: React.FC<DateNavigatorProps> = ({ inlineDateDisplay = false, }: DateNavigatorProps) => { const { t } = useI18n() - const dispatch = useDispatch() - const { currentTimeStep, selectedDate, currentIndex } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const { + chart: { currentTimeStep, selectedDate, currentIndex }, + global: { fluidStatus }, + } = useSelector((state: AppStore) => state.ecolyo) const disablePrev = selectedDate < diff --git a/src/components/Duel/DuelOngoing.tsx b/src/components/Duel/DuelOngoing.tsx index 9e6646353bb28780b793e278761ecaf60a6de765..80ad04c31c9cd32b24b0c834dc588f85e1a15389 100644 --- a/src/components/Duel/DuelOngoing.tsx +++ b/src/components/Duel/DuelOngoing.tsx @@ -14,12 +14,19 @@ import { } from 'enum/userChallenge.enum' import { UserDuelState } from 'enum/userDuel.enum' import { Dataload, UserChallenge, UserDuel } from 'models' -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import React, { + Dispatch, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { unlockNextUserChallenge, updateUserChallengeList, @@ -39,22 +46,19 @@ const DuelOngoing: React.FC<DuelOngoingProps> = ({ }: DuelOngoingProps) => { const client: Client = useClient() const { t } = useI18n() - const { currentDataload } = useSelector( + const { currentDataload, userChallengeList } = useSelector( (state: AppStore) => state.ecolyo.challenge ) - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const [resultModal, setResultModal] = useState<boolean>(false) const [winChallenge, setWinChallenge] = useState<boolean>(false) const [isLastDuel, setIsLastDuel] = useState<boolean>(false) const [width, setWidth] = useState<number>(0) const [height, setHeight] = useState<number>(0) - const [finishedDataLoad, setfinishedDataLoad] = useState<Dataload[]>() + const [finishedDataLoad, setFinishedDataLoad] = useState<Dataload[]>() const chartContainer = useRef<HTMLDivElement>(null) const challengeService = useMemo(() => new ChallengeService(client), [client]) - const { userChallengeList } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const duel: UserDuel = userChallenge.duel const title: string = duel.title @@ -157,7 +161,7 @@ const DuelOngoing: React.FC<DuelOngoingProps> = ({ const dataloads: Dataload[] = await challengeService.getUserChallengeDataload(userChallenge) if (subscribed) { - setfinishedDataLoad(dataloads) + setFinishedDataLoad(dataloads) } } } diff --git a/src/components/Duel/DuelUnlocked.tsx b/src/components/Duel/DuelUnlocked.tsx index 3f58c2ac72246a3ef6cecf97e8da1a27e3f8c4a6..8128a5539b3a88afaad6e58948667c2d0c0639f2 100644 --- a/src/components/Duel/DuelUnlocked.tsx +++ b/src/components/Duel/DuelUnlocked.tsx @@ -7,10 +7,11 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch } from 'react-redux' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { setChallengeConsumption } from 'store/challenge/challenge.actions' import { formatNumberValues, importIconById } from 'utils/utils' import './duelUnlocked.scss' @@ -23,7 +24,7 @@ const DuelUnlocked: React.FC<DuelUnlockedProps> = ({ userChallenge, }: DuelUnlockedProps) => { const client: Client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { t } = useI18n() const [duelIcon, setDuelIcon] = useState(defaultIcon) diff --git a/src/components/Ecogesture/EcogestureView.spec.tsx b/src/components/Ecogesture/EcogestureView.spec.tsx index 8a25aa6a6495e4623f2b1293f67afa5961956ab9..04f4eb18e8e38fe7704a9bfe585a2866e2fef7d5 100644 --- a/src/components/Ecogesture/EcogestureView.spec.tsx +++ b/src/components/Ecogesture/EcogestureView.spec.tsx @@ -9,8 +9,8 @@ import { Provider } from 'react-redux' import * as profileActions from 'store/profile/profile.actions' import { ecogesturesData } from '../../../tests/__mocks__/ecogesturesData.mock' import { - createMockStore, - mockInitialEcolyoState, + createMockEcolyoStore, + mockInitialProfileState, } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' import EcogestureEmptyList from './EcogestureEmptyList' @@ -25,22 +25,22 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => { }), } }) -const mockgetAllEcogestures = jest.fn() +const mockGetAllEcogestures = jest.fn() const mockGetEcogestureListByProfile = jest.fn() jest.mock('services/ecogesture.service', () => { return jest.fn(() => { return { - getAllEcogestures: mockgetAllEcogestures, + getAllEcogestures: mockGetAllEcogestures, getEcogestureListByProfile: mockGetEcogestureListByProfile, } }) }) -const mockgetProfile = jest.fn() +const mockGetProfile = jest.fn() const mockUpdateProfile = jest.fn() jest.mock('services/profile.service', () => { return jest.fn(() => { return { - getProfile: mockgetProfile, + getProfile: mockGetProfile, updateProfile: mockUpdateProfile, } }) @@ -50,11 +50,11 @@ jest.mock('components/Header/CozyBar', () => 'mock-cozybar') jest.mock('components/Header/Header', () => 'mock-header') jest.mock('components/Ecogesture/EcogestureList', () => 'mock-ecogesturelist') jest.mock('components/Content/Content', () => 'mock-content') -const mockgetSeason = jest.fn() +const mockGetSeason = jest.fn() jest.mock('utils/utils', () => { return { getSeason: jest.fn(() => { - return mockgetSeason + return mockGetSeason }), } }) @@ -71,23 +71,22 @@ jest.mock('react-router-dom', () => ({ })) describe('EcogestureView component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) - mockgetSeason.mockClear() - mockgetAllEcogestures.mockClear() + store.clearActions() + mockGetSeason.mockClear() + mockGetAllEcogestures.mockClear() mockGetEcogestureListByProfile.mockClear() }) it('should be rendered correctly', async () => { useSelectorSpy.mockReturnValue({ - ...mockInitialEcolyoState.profile, + profile: mockInitialProfileState, isProfileTypeCompleted: true, haveSeenEcogestureModal: true, }) - mockgetSeason.mockReturnValue(Season.WINTER) - mockgetAllEcogestures.mockResolvedValueOnce(ecogesturesData) + mockGetSeason.mockReturnValue(Season.WINTER) + mockGetAllEcogestures.mockResolvedValueOnce(ecogesturesData) mockGetEcogestureListByProfile.mockResolvedValue([]) const wrapper = mount( <Provider store={store}> @@ -103,12 +102,12 @@ describe('EcogestureView component', () => { const updateProfileSpy = jest.spyOn(profileActions, 'updateProfile') useSelectorSpy.mockReturnValue({ - ...mockInitialEcolyoState.profile, + profile: mockInitialProfileState, isProfileTypeCompleted: true, haveSeenEcogestureModal: false, }) - mockgetSeason.mockReturnValue(Season.WINTER) - mockgetAllEcogestures.mockResolvedValueOnce(ecogesturesData) + mockGetSeason.mockReturnValue(Season.WINTER) + mockGetAllEcogestures.mockResolvedValueOnce(ecogesturesData) mockGetEcogestureListByProfile.mockResolvedValueOnce([]) const wrapper = mount( <Provider store={store}> @@ -128,12 +127,12 @@ describe('EcogestureView component', () => { it('should render empty list', async () => { useSelectorSpy.mockReturnValue({ - ...mockInitialEcolyoState.profile, + profile: mockInitialProfileState, isProfileTypeCompleted: true, haveSeenEcogestureModal: false, }) - mockgetSeason.mockReturnValue(Season.WINTER) - mockgetAllEcogestures.mockResolvedValueOnce([]) + mockGetSeason.mockReturnValue(Season.WINTER) + mockGetAllEcogestures.mockResolvedValueOnce([]) mockGetEcogestureListByProfile.mockResolvedValueOnce([]) const wrapper = mount( <Provider store={store}> @@ -146,12 +145,12 @@ describe('EcogestureView component', () => { }) it('should change tab', async () => { useSelectorSpy.mockReturnValue({ - ...mockInitialEcolyoState.profile, + profile: mockInitialProfileState, isProfileTypeCompleted: true, haveSeenEcogestureModal: true, }) - mockgetSeason.mockReturnValue(Season.WINTER) - mockgetAllEcogestures.mockResolvedValueOnce(ecogesturesData) + mockGetSeason.mockReturnValue(Season.WINTER) + mockGetAllEcogestures.mockResolvedValueOnce(ecogesturesData) mockGetEcogestureListByProfile.mockResolvedValueOnce([]) const wrapper = mount( <Provider store={store}> @@ -161,7 +160,7 @@ describe('EcogestureView component', () => { await waitForComponentToPaint(wrapper) wrapper.find(Tab).first().simulate('click') - mockgetAllEcogestures.mockResolvedValueOnce([]) + mockGetAllEcogestures.mockResolvedValueOnce([]) await waitForComponentToPaint(wrapper) diff --git a/src/components/Ecogesture/EcogestureView.tsx b/src/components/Ecogesture/EcogestureView.tsx index 7e3ce5e0aa11a4e4569c93544b636a6cdd826cb2..626ddc4635e43da3dd48983843c89421a9a1c5cb 100644 --- a/src/components/Ecogesture/EcogestureView.tsx +++ b/src/components/Ecogesture/EcogestureView.tsx @@ -9,12 +9,11 @@ import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { EcogestureTab } from 'enum/ecogesture.enum' import { Ecogesture } from 'models' -import { ProfileEcogesture } from 'models/profileEcogesture.model' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useLocation, useNavigate } from 'react-router-dom' import EcogestureService from 'services/ecogesture.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateProfile } from 'store/profile/profile.actions' import { getSeason } from 'utils/utils' import EcogestureEmptyList from './EcogestureEmptyList' @@ -51,17 +50,15 @@ const EcogestureView: React.FC = () => { } const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const tab = new URLSearchParams(useLocation().search).get('tab') - const profileType = useSelector((state: AppStore) => state.ecolyo.profileType) - const profileEcogesture: ProfileEcogesture = useSelector( - (state: AppStore) => state.ecolyo.profileEcogesture - ) + const { + profile: { haveSeenEcogestureModal, isProfileEcogestureCompleted }, + profileEcogesture, + profileType, + } = useSelector((state: AppStore) => state.ecolyo) - const { haveSeenEcogestureModal, isProfileEcogestureCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile - ) const [tabValue, setTabValue] = useState<EcogestureTab>( tab ? parseInt(tab) : EcogestureTab.OBJECTIVE ) diff --git a/src/components/Ecogesture/__snapshots__/EcogestureView.spec.tsx.snap b/src/components/Ecogesture/__snapshots__/EcogestureView.spec.tsx.snap index 98a75e6b7513ef027fccc39474ee4e0de3be28f2..d47df12610c87982a5271683ae4bad81ad318af7 100644 --- a/src/components/Ecogesture/__snapshots__/EcogestureView.spec.tsx.snap +++ b/src/components/Ecogesture/__snapshots__/EcogestureView.spec.tsx.snap @@ -1353,6 +1353,1132 @@ exports[`EcogestureView component should be rendered correctly 1`] = ` </div> </TabPanel> </mock-content> + <EcogestureInitModal + handleCloseClick={[Function]} + handleLaunchForm={[Function]} + open={true} + > + <WithStyles(ForwardRef(Dialog)) + aria-labelledby="accessibility-title" + classes={ + Object { + "paper": "modal-paper", + "root": "modal-root", + } + } + onClose={[Function]} + open={true} + > + <ForwardRef(Dialog) + aria-labelledby="accessibility-title" + classes={ + Object { + "container": "MuiDialog-container", + "paper": "MuiDialog-paper modal-paper", + "paperFullScreen": "MuiDialog-paperFullScreen", + "paperFullWidth": "MuiDialog-paperFullWidth", + "paperScrollBody": "MuiDialog-paperScrollBody", + "paperScrollPaper": "MuiDialog-paperScrollPaper", + "paperWidthFalse": "MuiDialog-paperWidthFalse", + "paperWidthLg": "MuiDialog-paperWidthLg", + "paperWidthMd": "MuiDialog-paperWidthMd", + "paperWidthSm": "MuiDialog-paperWidthSm", + "paperWidthXl": "MuiDialog-paperWidthXl", + "paperWidthXs": "MuiDialog-paperWidthXs", + "root": "MuiDialog-root modal-root", + "scrollBody": "MuiDialog-scrollBody", + "scrollPaper": "MuiDialog-scrollPaper", + } + } + onClose={[Function]} + open={true} + > + <ForwardRef(Modal) + BackdropComponent={ + Object { + "$$typeof": Symbol(react.forward_ref), + "Naked": Object { + "$$typeof": Symbol(react.forward_ref), + "propTypes": Object { + "children": [Function], + "className": [Function], + "classes": [Function], + "invisible": [Function], + "open": [Function], + "transitionDuration": [Function], + }, + "render": [Function], + }, + "displayName": "WithStyles(ForwardRef(Backdrop))", + "options": Object { + "defaultTheme": Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "activatedOpacity": 0.12, + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "disabledOpacity": 0.38, + "focus": "rgba(0, 0, 0, 0.12)", + "focusOpacity": 0.12, + "hover": "rgba(0, 0, 0, 0.04)", + "hoverOpacity": 0.04, + "selected": "rgba(0, 0, 0, 0.08)", + "selectedOpacity": 0.08, + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "info": Object { + "contrastText": "#fff", + "dark": "#1976d2", + "light": "#64b5f6", + "main": "#2196f3", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "success": Object { + "contrastText": "rgba(0, 0, 0, 0.87)", + "dark": "#388e3c", + "light": "#81c784", + "main": "#4caf50", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + "warning": Object { + "contrastText": "rgba(0, 0, 0, 0.87)", + "dark": "#f57c00", + "light": "#ffb74d", + "main": "#ff9800", + }, + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)", + "0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)", + "0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)", + "0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)", + "0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)", + "0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)", + "0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)", + "0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)", + "0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)", + "0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px rgba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)", + "0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px rgba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)", + "0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px rgba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)", + "0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px rgba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)", + "0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px rgba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)", + "0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px rgba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)", + "0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2px rgba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)", + "0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2px rgba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)", + "0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2px rgba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)", + "0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2px rgba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)", + "0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3px rgba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)", + "0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3px rgba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)", + "0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3px rgba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)", + "0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3px rgba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)", + "0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3px rgba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": [Function], + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "letterSpacing": "0.00938em", + "lineHeight": 1.5, + }, + "body2": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "letterSpacing": "0.01071em", + "lineHeight": 1.43, + }, + "button": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "letterSpacing": "0.02857em", + "lineHeight": 1.75, + "textTransform": "uppercase", + }, + "caption": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "letterSpacing": "0.03333em", + "lineHeight": 1.66, + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightBold": 700, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "h1": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "6rem", + "fontWeight": 300, + "letterSpacing": "-0.01562em", + "lineHeight": 1.167, + }, + "h2": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.75rem", + "fontWeight": 300, + "letterSpacing": "-0.00833em", + "lineHeight": 1.2, + }, + "h3": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3rem", + "fontWeight": 400, + "letterSpacing": "0em", + "lineHeight": 1.167, + }, + "h4": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "letterSpacing": "0.00735em", + "lineHeight": 1.235, + }, + "h5": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "letterSpacing": "0em", + "lineHeight": 1.334, + }, + "h6": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.25rem", + "fontWeight": 500, + "letterSpacing": "0.0075em", + "lineHeight": 1.6, + }, + "htmlFontSize": 16, + "overline": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "letterSpacing": "0.08333em", + "lineHeight": 2.66, + "textTransform": "uppercase", + }, + "pxToRem": [Function], + "round": [Function], + "subtitle1": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "letterSpacing": "0.00938em", + "lineHeight": 1.75, + }, + "subtitle2": Object { + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "letterSpacing": "0.00714em", + "lineHeight": 1.57, + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "speedDial": 1050, + "tooltip": 1500, + }, + }, + "name": "MuiBackdrop", + }, + "propTypes": Object { + "classes": [Function], + "innerRef": [Function], + }, + "render": [Function], + "useStyles": [Function], + } + } + BackdropProps={ + Object { + "transitionDuration": Object { + "enter": 225, + "exit": 195, + }, + } + } + className="MuiDialog-root modal-root" + closeAfterTransition={true} + disableEscapeKeyDown={false} + onClose={[Function]} + open={true} + > + <ForwardRef(Portal) + disablePortal={false} + > + <Portal + containerInfo={ + <body + style="padding-right: 0px; overflow: hidden;" + > + <div + class="MuiDialog-root modal-root" + role="presentation" + style="position: fixed; z-index: 1300; right: 0px; bottom: 0px; top: 0px; left: 0px;" + > + <div + aria-hidden="true" + class="MuiBackdrop-root" + style="opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;" + /> + <div + data-test="sentinelStart" + tabindex="0" + /> + <div + class="MuiDialog-container MuiDialog-scrollPaper" + role="none presentation" + style="opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;" + tabindex="-1" + > + <div + aria-labelledby="accessibility-title" + class="MuiPaper-root MuiDialog-paper modal-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm MuiPaper-elevation24 MuiPaper-rounded" + role="dialog" + > + <div + id="accessibility-title" + > + feedback.accessibility.window_title + </div> + <button + aria-label="feedback.accessibility.button_close" + class="MuiButtonBase-root MuiIconButton-root modal-paper-close-button" + tabindex="0" + type="button" + > + <span + class="MuiIconButton-label" + > + <svg + class="styles__icon___23x3R" + height="16" + width="16" + > + <use + xlink:href="#test-file-stub" + /> + </svg> + </span> + <span + class="MuiTouchRipple-root" + /> + </button> + <div + class="eg-init-modal" + > + <div + class="title text-20-bold" + > + ecogesture.initModal.title + </div> + <div + class="text-16-normal text" + > + ecogesture.initModal.text1 + </div> + <div + class="text-16-normal text" + > + ecogesture.initModal.text2 + </div> + <div + class="buttons-container" + > + <button + aria-label="ecogesture.initModal.btn1" + class="MuiButtonBase-root MuiButton-root btn-secondary-negative MuiButton-text btn1" + tabindex="0" + type="button" + > + <span + class="MuiButton-label text-16-bold" + > + ecogesture.initModal.btn1 + </span> + <span + class="MuiTouchRipple-root" + /> + </button> + <button + aria-label="ecogesture.initModal.btn2" + class="MuiButtonBase-root MuiButton-root btn-profile-next rounded MuiButton-text" + tabindex="0" + type="button" + > + <span + class="MuiButton-label text-16-bold" + > + ecogesture.initModal.btn2 + </span> + <span + class="MuiTouchRipple-root" + /> + </button> + </div> + </div> + </div> + </div> + <div + data-test="sentinelEnd" + tabindex="0" + /> + </div> + </body> + } + > + <div + className="MuiDialog-root modal-root" + onKeyDown={[Function]} + role="presentation" + style={ + Object { + "bottom": 0, + "left": 0, + "position": "fixed", + "right": 0, + "top": 0, + "zIndex": 1300, + } + } + > + <WithStyles(ForwardRef(Backdrop)) + onClick={[Function]} + open={true} + transitionDuration={ + Object { + "enter": 225, + "exit": 195, + } + } + > + <ForwardRef(Backdrop) + classes={ + Object { + "invisible": "MuiBackdrop-invisible", + "root": "MuiBackdrop-root", + } + } + onClick={[Function]} + open={true} + transitionDuration={ + Object { + "enter": 225, + "exit": 195, + } + } + > + <ForwardRef(Fade) + in={true} + onClick={[Function]} + timeout={ + Object { + "enter": 225, + "exit": 195, + } + } + > + <Transition + appear={true} + enter={true} + exit={true} + in={true} + mountOnEnter={false} + onClick={[Function]} + onEnter={[Function]} + onEntered={[Function]} + onEntering={[Function]} + onExit={[Function]} + onExited={[Function]} + onExiting={[Function]} + timeout={ + Object { + "enter": 225, + "exit": 195, + } + } + unmountOnExit={false} + > + <div + aria-hidden={true} + className="MuiBackdrop-root" + onClick={[Function]} + style={ + Object { + "opacity": 1, + "visibility": undefined, + } + } + /> + </Transition> + </ForwardRef(Fade)> + </ForwardRef(Backdrop)> + </WithStyles(ForwardRef(Backdrop))> + <Unstable_TrapFocus + disableAutoFocus={false} + disableEnforceFocus={false} + disableRestoreFocus={false} + getDoc={[Function]} + isEnabled={[Function]} + open={true} + > + <div + data-test="sentinelStart" + tabIndex={0} + /> + <ForwardRef(Fade) + appear={true} + in={true} + onEnter={[Function]} + onExited={[Function]} + role="none presentation" + tabIndex="-1" + timeout={ + Object { + "enter": 225, + "exit": 195, + } + } + > + <Transition + appear={true} + enter={true} + exit={true} + in={true} + mountOnEnter={false} + onEnter={[Function]} + onEntered={[Function]} + onEntering={[Function]} + onExit={[Function]} + onExited={[Function]} + onExiting={[Function]} + role="none presentation" + tabIndex="-1" + timeout={ + Object { + "enter": 225, + "exit": 195, + } + } + unmountOnExit={false} + > + <div + className="MuiDialog-container MuiDialog-scrollPaper" + onMouseDown={[Function]} + onMouseUp={[Function]} + role="none presentation" + style={ + Object { + "opacity": 1, + "visibility": undefined, + } + } + tabIndex="-1" + > + <WithStyles(ForwardRef(Paper)) + aria-labelledby="accessibility-title" + className="MuiDialog-paper modal-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm" + elevation={24} + role="dialog" + > + <ForwardRef(Paper) + aria-labelledby="accessibility-title" + className="MuiDialog-paper modal-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm" + classes={ + Object { + "elevation0": "MuiPaper-elevation0", + "elevation1": "MuiPaper-elevation1", + "elevation10": "MuiPaper-elevation10", + "elevation11": "MuiPaper-elevation11", + "elevation12": "MuiPaper-elevation12", + "elevation13": "MuiPaper-elevation13", + "elevation14": "MuiPaper-elevation14", + "elevation15": "MuiPaper-elevation15", + "elevation16": "MuiPaper-elevation16", + "elevation17": "MuiPaper-elevation17", + "elevation18": "MuiPaper-elevation18", + "elevation19": "MuiPaper-elevation19", + "elevation2": "MuiPaper-elevation2", + "elevation20": "MuiPaper-elevation20", + "elevation21": "MuiPaper-elevation21", + "elevation22": "MuiPaper-elevation22", + "elevation23": "MuiPaper-elevation23", + "elevation24": "MuiPaper-elevation24", + "elevation3": "MuiPaper-elevation3", + "elevation4": "MuiPaper-elevation4", + "elevation5": "MuiPaper-elevation5", + "elevation6": "MuiPaper-elevation6", + "elevation7": "MuiPaper-elevation7", + "elevation8": "MuiPaper-elevation8", + "elevation9": "MuiPaper-elevation9", + "outlined": "MuiPaper-outlined", + "root": "MuiPaper-root", + "rounded": "MuiPaper-rounded", + } + } + elevation={24} + role="dialog" + > + <div + aria-labelledby="accessibility-title" + className="MuiPaper-root MuiDialog-paper modal-paper MuiDialog-paperScrollPaper MuiDialog-paperWidthSm MuiPaper-elevation24 MuiPaper-rounded" + role="dialog" + > + <div + id="accessibility-title" + > + feedback.accessibility.window_title + </div> + <WithStyles(ForwardRef(IconButton)) + aria-label="feedback.accessibility.button_close" + className="modal-paper-close-button" + onClick={[Function]} + > + <ForwardRef(IconButton) + aria-label="feedback.accessibility.button_close" + className="modal-paper-close-button" + classes={ + Object { + "colorInherit": "MuiIconButton-colorInherit", + "colorPrimary": "MuiIconButton-colorPrimary", + "colorSecondary": "MuiIconButton-colorSecondary", + "disabled": "Mui-disabled", + "edgeEnd": "MuiIconButton-edgeEnd", + "edgeStart": "MuiIconButton-edgeStart", + "label": "MuiIconButton-label", + "root": "MuiIconButton-root", + "sizeSmall": "MuiIconButton-sizeSmall", + } + } + onClick={[Function]} + > + <WithStyles(ForwardRef(ButtonBase)) + aria-label="feedback.accessibility.button_close" + centerRipple={true} + className="MuiIconButton-root modal-paper-close-button" + disabled={false} + focusRipple={true} + onClick={[Function]} + > + <ForwardRef(ButtonBase) + aria-label="feedback.accessibility.button_close" + centerRipple={true} + className="MuiIconButton-root modal-paper-close-button" + classes={ + Object { + "disabled": "Mui-disabled", + "focusVisible": "Mui-focusVisible", + "root": "MuiButtonBase-root", + } + } + disabled={false} + focusRipple={true} + onClick={[Function]} + > + <button + aria-label="feedback.accessibility.button_close" + className="MuiButtonBase-root MuiIconButton-root modal-paper-close-button" + disabled={false} + onBlur={[Function]} + onClick={[Function]} + onDragLeave={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + onMouseLeave={[Function]} + onMouseUp={[Function]} + onTouchEnd={[Function]} + onTouchMove={[Function]} + onTouchStart={[Function]} + tabIndex={0} + type="button" + > + <span + className="MuiIconButton-label" + > + <Icon + icon="test-file-stub" + size={16} + spin={false} + > + <Component + className="styles__icon___23x3R" + height={16} + style={Object {}} + width={16} + > + <svg + className="styles__icon___23x3R" + height={16} + style={Object {}} + width={16} + > + <use + xlinkHref="#test-file-stub" + /> + </svg> + </Component> + </Icon> + </span> + <WithStyles(memo) + center={true} + > + <ForwardRef(TouchRipple) + center={true} + classes={ + Object { + "child": "MuiTouchRipple-child", + "childLeaving": "MuiTouchRipple-childLeaving", + "childPulsate": "MuiTouchRipple-childPulsate", + "ripple": "MuiTouchRipple-ripple", + "ripplePulsate": "MuiTouchRipple-ripplePulsate", + "rippleVisible": "MuiTouchRipple-rippleVisible", + "root": "MuiTouchRipple-root", + } + } + > + <span + className="MuiTouchRipple-root" + > + <TransitionGroup + childFactory={[Function]} + component={null} + exit={true} + /> + </span> + </ForwardRef(TouchRipple)> + </WithStyles(memo)> + </button> + </ForwardRef(ButtonBase)> + </WithStyles(ForwardRef(ButtonBase))> + </ForwardRef(IconButton)> + </WithStyles(ForwardRef(IconButton))> + <div + className="eg-init-modal" + > + <div + className="title text-20-bold" + > + ecogesture.initModal.title + </div> + <div + className="text-16-normal text" + > + ecogesture.initModal.text1 + </div> + <div + className="text-16-normal text" + > + ecogesture.initModal.text2 + </div> + <div + className="buttons-container" + > + <WithStyles(ForwardRef(Button)) + aria-label="ecogesture.initModal.btn1" + className="btn1" + classes={ + Object { + "label": "text-16-bold", + "root": "btn-secondary-negative", + } + } + onClick={[Function]} + > + <ForwardRef(Button) + aria-label="ecogesture.initModal.btn1" + className="btn1" + classes={ + Object { + "colorInherit": "MuiButton-colorInherit", + "contained": "MuiButton-contained", + "containedPrimary": "MuiButton-containedPrimary", + "containedSecondary": "MuiButton-containedSecondary", + "containedSizeLarge": "MuiButton-containedSizeLarge", + "containedSizeSmall": "MuiButton-containedSizeSmall", + "disableElevation": "MuiButton-disableElevation", + "disabled": "Mui-disabled", + "endIcon": "MuiButton-endIcon", + "focusVisible": "Mui-focusVisible", + "fullWidth": "MuiButton-fullWidth", + "iconSizeLarge": "MuiButton-iconSizeLarge", + "iconSizeMedium": "MuiButton-iconSizeMedium", + "iconSizeSmall": "MuiButton-iconSizeSmall", + "label": "MuiButton-label text-16-bold", + "outlined": "MuiButton-outlined", + "outlinedPrimary": "MuiButton-outlinedPrimary", + "outlinedSecondary": "MuiButton-outlinedSecondary", + "outlinedSizeLarge": "MuiButton-outlinedSizeLarge", + "outlinedSizeSmall": "MuiButton-outlinedSizeSmall", + "root": "MuiButton-root btn-secondary-negative", + "sizeLarge": "MuiButton-sizeLarge", + "sizeSmall": "MuiButton-sizeSmall", + "startIcon": "MuiButton-startIcon", + "text": "MuiButton-text", + "textPrimary": "MuiButton-textPrimary", + "textSecondary": "MuiButton-textSecondary", + "textSizeLarge": "MuiButton-textSizeLarge", + "textSizeSmall": "MuiButton-textSizeSmall", + } + } + onClick={[Function]} + > + <WithStyles(ForwardRef(ButtonBase)) + aria-label="ecogesture.initModal.btn1" + className="MuiButton-root btn-secondary-negative MuiButton-text btn1" + component="button" + disabled={false} + focusRipple={true} + focusVisibleClassName="Mui-focusVisible" + onClick={[Function]} + type="button" + > + <ForwardRef(ButtonBase) + aria-label="ecogesture.initModal.btn1" + className="MuiButton-root btn-secondary-negative MuiButton-text btn1" + classes={ + Object { + "disabled": "Mui-disabled", + "focusVisible": "Mui-focusVisible", + "root": "MuiButtonBase-root", + } + } + component="button" + disabled={false} + focusRipple={true} + focusVisibleClassName="Mui-focusVisible" + onClick={[Function]} + type="button" + > + <button + aria-label="ecogesture.initModal.btn1" + className="MuiButtonBase-root MuiButton-root btn-secondary-negative MuiButton-text btn1" + disabled={false} + onBlur={[Function]} + onClick={[Function]} + onDragLeave={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + onMouseLeave={[Function]} + onMouseUp={[Function]} + onTouchEnd={[Function]} + onTouchMove={[Function]} + onTouchStart={[Function]} + tabIndex={0} + type="button" + > + <span + className="MuiButton-label text-16-bold" + > + ecogesture.initModal.btn1 + </span> + <WithStyles(memo) + center={false} + > + <ForwardRef(TouchRipple) + center={false} + classes={ + Object { + "child": "MuiTouchRipple-child", + "childLeaving": "MuiTouchRipple-childLeaving", + "childPulsate": "MuiTouchRipple-childPulsate", + "ripple": "MuiTouchRipple-ripple", + "ripplePulsate": "MuiTouchRipple-ripplePulsate", + "rippleVisible": "MuiTouchRipple-rippleVisible", + "root": "MuiTouchRipple-root", + } + } + > + <span + className="MuiTouchRipple-root" + > + <TransitionGroup + childFactory={[Function]} + component={null} + exit={true} + /> + </span> + </ForwardRef(TouchRipple)> + </WithStyles(memo)> + </button> + </ForwardRef(ButtonBase)> + </WithStyles(ForwardRef(ButtonBase))> + </ForwardRef(Button)> + </WithStyles(ForwardRef(Button))> + <WithStyles(ForwardRef(Button)) + aria-label="ecogesture.initModal.btn2" + classes={ + Object { + "label": "text-16-bold", + "root": "btn-profile-next rounded", + } + } + onClick={[Function]} + > + <ForwardRef(Button) + aria-label="ecogesture.initModal.btn2" + classes={ + Object { + "colorInherit": "MuiButton-colorInherit", + "contained": "MuiButton-contained", + "containedPrimary": "MuiButton-containedPrimary", + "containedSecondary": "MuiButton-containedSecondary", + "containedSizeLarge": "MuiButton-containedSizeLarge", + "containedSizeSmall": "MuiButton-containedSizeSmall", + "disableElevation": "MuiButton-disableElevation", + "disabled": "Mui-disabled", + "endIcon": "MuiButton-endIcon", + "focusVisible": "Mui-focusVisible", + "fullWidth": "MuiButton-fullWidth", + "iconSizeLarge": "MuiButton-iconSizeLarge", + "iconSizeMedium": "MuiButton-iconSizeMedium", + "iconSizeSmall": "MuiButton-iconSizeSmall", + "label": "MuiButton-label text-16-bold", + "outlined": "MuiButton-outlined", + "outlinedPrimary": "MuiButton-outlinedPrimary", + "outlinedSecondary": "MuiButton-outlinedSecondary", + "outlinedSizeLarge": "MuiButton-outlinedSizeLarge", + "outlinedSizeSmall": "MuiButton-outlinedSizeSmall", + "root": "MuiButton-root btn-profile-next rounded", + "sizeLarge": "MuiButton-sizeLarge", + "sizeSmall": "MuiButton-sizeSmall", + "startIcon": "MuiButton-startIcon", + "text": "MuiButton-text", + "textPrimary": "MuiButton-textPrimary", + "textSecondary": "MuiButton-textSecondary", + "textSizeLarge": "MuiButton-textSizeLarge", + "textSizeSmall": "MuiButton-textSizeSmall", + } + } + onClick={[Function]} + > + <WithStyles(ForwardRef(ButtonBase)) + aria-label="ecogesture.initModal.btn2" + className="MuiButton-root btn-profile-next rounded MuiButton-text" + component="button" + disabled={false} + focusRipple={true} + focusVisibleClassName="Mui-focusVisible" + onClick={[Function]} + type="button" + > + <ForwardRef(ButtonBase) + aria-label="ecogesture.initModal.btn2" + className="MuiButton-root btn-profile-next rounded MuiButton-text" + classes={ + Object { + "disabled": "Mui-disabled", + "focusVisible": "Mui-focusVisible", + "root": "MuiButtonBase-root", + } + } + component="button" + disabled={false} + focusRipple={true} + focusVisibleClassName="Mui-focusVisible" + onClick={[Function]} + type="button" + > + <button + aria-label="ecogesture.initModal.btn2" + className="MuiButtonBase-root MuiButton-root btn-profile-next rounded MuiButton-text" + disabled={false} + onBlur={[Function]} + onClick={[Function]} + onDragLeave={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + onKeyUp={[Function]} + onMouseDown={[Function]} + onMouseLeave={[Function]} + onMouseUp={[Function]} + onTouchEnd={[Function]} + onTouchMove={[Function]} + onTouchStart={[Function]} + tabIndex={0} + type="button" + > + <span + className="MuiButton-label text-16-bold" + > + ecogesture.initModal.btn2 + </span> + <WithStyles(memo) + center={false} + > + <ForwardRef(TouchRipple) + center={false} + classes={ + Object { + "child": "MuiTouchRipple-child", + "childLeaving": "MuiTouchRipple-childLeaving", + "childPulsate": "MuiTouchRipple-childPulsate", + "ripple": "MuiTouchRipple-ripple", + "ripplePulsate": "MuiTouchRipple-ripplePulsate", + "rippleVisible": "MuiTouchRipple-rippleVisible", + "root": "MuiTouchRipple-root", + } + } + > + <span + className="MuiTouchRipple-root" + > + <TransitionGroup + childFactory={[Function]} + component={null} + exit={true} + /> + </span> + </ForwardRef(TouchRipple)> + </WithStyles(memo)> + </button> + </ForwardRef(ButtonBase)> + </WithStyles(ForwardRef(ButtonBase))> + </ForwardRef(Button)> + </WithStyles(ForwardRef(Button))> + </div> + </div> + </div> + </ForwardRef(Paper)> + </WithStyles(ForwardRef(Paper))> + </div> + </Transition> + </ForwardRef(Fade)> + <div + data-test="sentinelEnd" + tabIndex={0} + /> + </Unstable_TrapFocus> + </div> + </Portal> + </ForwardRef(Portal)> + </ForwardRef(Modal)> + </ForwardRef(Dialog)> + </WithStyles(ForwardRef(Dialog))> + </EcogestureInitModal> </EcogestureView> </Provider> `; diff --git a/src/components/EcogestureForm/EcogestureFormEquipment.tsx b/src/components/EcogestureForm/EcogestureFormEquipment.tsx index be3df67a96b06cbf522253624af53be6340f522d..83a2009cadea5160deca61d7eda4fd5f862adb9c 100644 --- a/src/components/EcogestureForm/EcogestureFormEquipment.tsx +++ b/src/components/EcogestureForm/EcogestureFormEquipment.tsx @@ -5,10 +5,10 @@ import { EquipmentType } from 'enum/ecogesture.enum' import { EcogestureStepForm } from 'enum/ecogestureForm.enum' import { ProfileTypeStepForm } from 'enum/profileType.enum' import { ProfileEcogesture } from 'models/profileEcogesture.model' -import React, { useCallback, useState } from 'react' +import React, { Dispatch, useCallback, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateProfile } from 'store/profile/profile.actions' import { newProfileEcogestureEntry, @@ -31,7 +31,7 @@ const EcogestureFormEquipment: React.FC<EcogestureFormEquipmentProps> = ({ step, }: EcogestureFormEquipmentProps) => { const { t } = useI18n() - const dispatch = useDispatch() + const dispatch: Dispatch<AppActionsTypes> = useDispatch() const navigate = useNavigate() const { isProfileEcogestureCompleted } = useSelector( (state: AppStore) => state.ecolyo.profile diff --git a/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx b/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx index 469666600f0e86963c115e2f82dbd1d564d925ae..161e0d8bada00a748a121d800dbe126b0df2d3b2 100644 --- a/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx +++ b/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx @@ -8,10 +8,7 @@ import { mockEcogestureAnswer, mockProfileEcogesture, } from '../../../tests/__mocks__/profileEcogesture.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' import EcogestureFormSingleChoice from './EcogestureFormSingleChoice' @@ -38,10 +35,9 @@ jest.mock( const mockHandleNextStep = jest.fn() const mockHandlePreviousStep = jest.fn() describe('EcogestureFormSingleChoice component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', async () => { diff --git a/src/components/EcogestureForm/EcogestureFormView.spec.tsx b/src/components/EcogestureForm/EcogestureFormView.spec.tsx index ced14d322584a1e305bf25e77408304d441950b2..d8588e3e67171fccb5620bbee49c33052cacb65d 100644 --- a/src/components/EcogestureForm/EcogestureFormView.spec.tsx +++ b/src/components/EcogestureForm/EcogestureFormView.spec.tsx @@ -6,7 +6,7 @@ import { Profile } from 'models' import React from 'react' import { Provider } from 'react-redux' import { - createMockStore, + createMockEcolyoStore, mockInitialEcolyoState, } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' @@ -41,10 +41,9 @@ jest.mock('react-router-dom', () => ({ })) describe('EcogestureFormView component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', async () => { @@ -72,7 +71,7 @@ describe('EcogestureFormView component', () => { } const updatedStore = { ...mockInitialEcolyoState, profile: updatedProfile } const wrapper = mount( - <Provider store={createMockStore(updatedStore)}> + <Provider store={createMockEcolyoStore(updatedStore)}> <EcogestureFormView /> </Provider> ) diff --git a/src/components/EcogestureForm/EcogestureFormView.tsx b/src/components/EcogestureForm/EcogestureFormView.tsx index c052ddf9a020ed73d597c606b5967454d1040716..22bfb91abba7f4887f790dfd9cc30ad7d7a88802 100644 --- a/src/components/EcogestureForm/EcogestureFormView.tsx +++ b/src/components/EcogestureForm/EcogestureFormView.tsx @@ -10,7 +10,6 @@ import { EcogestureStepForm, ProfileEcogestureAnswerType, } from 'enum/ecogestureForm.enum' -import { Profile } from 'models' import { ProfileEcogesture, ProfileEcogestureAnswer, @@ -26,12 +25,11 @@ const EcogestureFormView: React.FC = () => { const defineHeaderHeight = (height: number) => { setHeaderHeight(height) } - const { isProfileTypeCompleted }: Profile = useSelector( - (state: AppStore) => state.ecolyo.profile - ) - const curProfileEcogesture: ProfileEcogesture = useSelector( - (state: AppStore) => state.ecolyo.profileEcogesture - ) + const { + profile: { isProfileTypeCompleted }, + profileEcogesture: curProfileEcogesture, + } = useSelector((state: AppStore) => state.ecolyo) + const shouldOpenModal = new URLSearchParams(useLocation().search).get('modal') const [step, setStep] = useState<EcogestureStepForm>( EcogestureStepForm.HEATING_TYPE diff --git a/src/components/EcogestureSelection/EcogestureSelection.spec.tsx b/src/components/EcogestureSelection/EcogestureSelection.spec.tsx index e11981ae1848632a70c52bbff62a4918520803d7..ea641c50adec0a2b9d5d8714214185ac1023e532 100644 --- a/src/components/EcogestureSelection/EcogestureSelection.spec.tsx +++ b/src/components/EcogestureSelection/EcogestureSelection.spec.tsx @@ -5,10 +5,7 @@ import React from 'react' import { Provider } from 'react-redux' import mockClient from '../../../tests/__mocks__/client' import { ecogesturesData } from '../../../tests/__mocks__/ecogesturesData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' import EcogestureSelection from './EcogestureSelection' @@ -70,10 +67,9 @@ jest.mock( ) describe('EcogestureSelection component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() mockGetEcogestureListByProfile.mockClear() }) diff --git a/src/components/EcogestureSelection/EcogestureSelection.tsx b/src/components/EcogestureSelection/EcogestureSelection.tsx index c9e3e71143f87fbb915ff6f3f874c42c266a233c..3250748c75c143b4b54a1fd2aae658c9f1614499 100644 --- a/src/components/EcogestureSelection/EcogestureSelection.tsx +++ b/src/components/EcogestureSelection/EcogestureSelection.tsx @@ -9,7 +9,6 @@ import Loader from 'components/Loader/Loader' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { Ecogesture } from 'models' -import { ProfileEcogesture } from 'models/profileEcogesture.model' import React, { useCallback, useEffect, useMemo, useState } from 'react' import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' @@ -38,7 +37,7 @@ const EcogestureSelection: React.FC = () => { () => new EcogestureService(client), [client] ) - const profileEcogesture: ProfileEcogesture = useSelector( + const profileEcogesture = useSelector( (state: AppStore) => state.ecolyo.profileEcogesture ) diff --git a/src/components/Exploration/ExplorationFinished.tsx b/src/components/Exploration/ExplorationFinished.tsx index 78256d909f14f1696770746f729bf3fec00be10b..09b753bf24cef157536e9c76d17214255ca62a4e 100644 --- a/src/components/Exploration/ExplorationFinished.tsx +++ b/src/components/Exploration/ExplorationFinished.tsx @@ -7,11 +7,12 @@ import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserExplorationState } from 'enum/userExploration.enum' import { UserChallenge } from 'models' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch } from 'react-redux' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import { toggleChallengeExplorationNotification } from 'store/global/global.actions' import './explorationFinished.scss' @@ -25,7 +26,7 @@ const ExplorationFinished: React.FC<ExplorationFinishedProps> = ({ }: ExplorationFinishedProps) => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const checkNotificationToEnd = useCallback(async () => { diff --git a/src/components/Exploration/ExplorationOngoing.tsx b/src/components/Exploration/ExplorationOngoing.tsx index 640514c1dad200258f869dc55a37b3a0001dd219..29eadebfcb8d76af3356bd02dc736665d02c8412 100644 --- a/src/components/Exploration/ExplorationOngoing.tsx +++ b/src/components/Exploration/ExplorationOngoing.tsx @@ -11,11 +11,12 @@ import { UserExplorationType, } from 'enum/userExploration.enum' import { UserChallenge } from 'models' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch } from 'react-redux' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import './explorationOngoing.scss' @@ -28,7 +29,7 @@ const ExplorationOngoing: React.FC<ExplorationOngoingProps> = ({ }: ExplorationOngoingProps) => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const goBack = useCallback(() => { navigate(-1) diff --git a/src/components/Export/exportDoneModal.spec.tsx b/src/components/Export/exportDoneModal.spec.tsx index 533054ebc6506904d7238e3b6a96d090457d80b5..ea6d5625d2f9570ca37c5b5486d1f71ff9cf3ed4 100644 --- a/src/components/Export/exportDoneModal.spec.tsx +++ b/src/components/Export/exportDoneModal.spec.tsx @@ -4,10 +4,7 @@ import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => { return { @@ -22,9 +19,9 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => { const mockHandleClose = jest.fn() describe('exportDoneModal component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Export/exportLoadingModal.spec.tsx b/src/components/Export/exportLoadingModal.spec.tsx index c016d8938fd90c8d9ac85e1c95ad6fb09c6fd7b2..57534eb6592db6f7070dcdaac677b07ad8b3ba54 100644 --- a/src/components/Export/exportLoadingModal.spec.tsx +++ b/src/components/Export/exportLoadingModal.spec.tsx @@ -4,10 +4,7 @@ import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => { return { @@ -24,9 +21,9 @@ const mockHandleDone = jest.fn() const mockSelectedFluids: Array<any> = [0, 1, 2] describe('ExportLoadingModal component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Export/exportStartModal.spec.tsx b/src/components/Export/exportStartModal.spec.tsx index 8e5fd37bd03404f1232befcd308b4cfe0f3236e9..d23c4598b958c6ab24b3576c5b82d47e5faaa872 100644 --- a/src/components/Export/exportStartModal.spec.tsx +++ b/src/components/Export/exportStartModal.spec.tsx @@ -4,10 +4,7 @@ import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => { return { @@ -23,9 +20,9 @@ const mockHandleClose = jest.fn() const mockHandleDownloadClick = jest.fn() describe('exportStartModal component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Feedback/FeedbackModal.spec.tsx b/src/components/Feedback/FeedbackModal.spec.tsx index b54a2f9fc40eeeaab177d02ef4a8bf8e064d8f39..9b51acb66e2c99983e009d128924f86d8d4b6041 100644 --- a/src/components/Feedback/FeedbackModal.spec.tsx +++ b/src/components/Feedback/FeedbackModal.spec.tsx @@ -5,10 +5,7 @@ import { act } from 'react-dom/test-utils' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { BrowserRouter } from 'react-router-dom' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { userChallengeExplo1OnGoing } from '../../../tests/__mocks__/userChallengeData.mock' // Value coming from jest.config @@ -38,9 +35,9 @@ const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') describe('FeedbackModal component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should render the component', () => { mockUseDispatch.mockReturnValue(jest.fn()) @@ -57,10 +54,10 @@ describe('FeedbackModal component', () => { expect(component).toMatchSnapshot() }) }) -describe('FeedbackModal functionnalities', () => { - let store: any +describe('FeedbackModal functionalities', () => { + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should close the modal', async () => { diff --git a/src/components/FluidChart/FluidChart.tsx b/src/components/FluidChart/FluidChart.tsx index c3257a3245a907111dae927a396301085d141e53..ad566e29d622bda5513781c48fd8a1ef655b8dd0 100644 --- a/src/components/FluidChart/FluidChart.tsx +++ b/src/components/FluidChart/FluidChart.tsx @@ -27,10 +27,11 @@ const FluidChart: React.FC<FluidChartProps> = ({ }: FluidChartProps) => { const { t } = useI18n() const client = useClient() - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) - const { currentTimeStep, selectedDate } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) + const { + chart: { currentTimeStep, selectedDate }, + global: { fluidStatus }, + } = useSelector((state: AppStore) => state.ecolyo) + const [, setValidExploration] = useExploration() const [isLoaded, setIsLoaded] = useState<boolean>(false) const [showCompare, setShowCompare] = useState<boolean>(false) diff --git a/src/components/FluidChart/FluidChartSlide.tsx b/src/components/FluidChart/FluidChartSlide.tsx index 1a60fb84ad09dbba3a7183343d8b690536dddacb..0497c9d27028e89378f6764a629364002f681f8e 100644 --- a/src/components/FluidChart/FluidChartSlide.tsx +++ b/src/components/FluidChart/FluidChartSlide.tsx @@ -6,11 +6,11 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Datachart } from 'models' -import React, { useEffect, useState } from 'react' +import React, { Dispatch, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import ConsumptionService from 'services/consumption.service' import DateChartService from 'services/dateChart.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentDatachart, setLoading } from 'store/chart/chart.actions' import './fluidChartSlide.scss' @@ -34,13 +34,12 @@ const FluidChartSlide: React.FC<FluidChartSlideProps> = ({ setActive, }: FluidChartSlideProps) => { const client = useClient() - const dispatch = useDispatch() - const { currentTimeStep, currentIndex } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) - const { fluidTypes, fluidStatus } = useSelector( - (state: AppStore) => state.ecolyo.global - ) + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const { + chart: { currentTimeStep, currentIndex }, + global: { fluidStatus, fluidTypes }, + } = useSelector((state: AppStore) => state.ecolyo) + const [chartData, setChartData] = useState<Datachart>({ actualData: [], comparisonData: null, diff --git a/src/components/FluidChart/FluidChartSwipe.tsx b/src/components/FluidChart/FluidChartSwipe.tsx index c453578d42b9297a442a333b5f54c2a120ee29f4..269979d0c6b36a2dd797f63bfcb8cf2d75d262a2 100644 --- a/src/components/FluidChart/FluidChartSwipe.tsx +++ b/src/components/FluidChart/FluidChartSwipe.tsx @@ -1,12 +1,12 @@ import FluidChartSlide from 'components/FluidChart/FluidChartSlide' import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' -import React, { useEffect, useRef, useState } from 'react' +import React, { Dispatch, useEffect, useRef, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import SwipeableViews from 'react-swipeable-views' import { virtualize } from 'react-swipeable-views-utils' import DateChartService from 'services/dateChart.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.actions' import './fluidChartSwipe.scss' @@ -23,7 +23,7 @@ const FluidChartSwipe: React.FC<FluidChartSwipeProps> = ({ showCompare, setActive, }: FluidChartSwipeProps) => { - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { currentIndex, currentTimeStep, selectedDate, loading } = useSelector( (state: AppStore) => state.ecolyo.chart ) diff --git a/src/components/FormGlobal/FormNavigation.spec.tsx b/src/components/FormGlobal/FormNavigation.spec.tsx index 0da82c679f399ff48f30a27fad09d5e3f2782199..d620db074e9130ad3e8b184669fd3ec36560e011 100644 --- a/src/components/FormGlobal/FormNavigation.spec.tsx +++ b/src/components/FormGlobal/FormNavigation.spec.tsx @@ -3,10 +3,7 @@ import { ProfileTypeStepForm } from 'enum/profileType.enum' import { mount } from 'enzyme' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import FormNavigation from './FormNavigation' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -26,9 +23,9 @@ jest.mock('react-router-dom', () => ({ })) describe('FormNavigation component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Header/CozyBar.spec.tsx b/src/components/Header/CozyBar.spec.tsx index 23cddd5774882eed6e2d9e2e784771efa578bd61..da3522ebfbeaa608af401197e4d4144179ed7e0d 100644 --- a/src/components/Header/CozyBar.spec.tsx +++ b/src/components/Header/CozyBar.spec.tsx @@ -70,7 +70,7 @@ describe('CozyBar component', () => { <CozyBar /> </Provider> ) - const updateModalSpy = jest.spyOn(ModalAction, 'updateModalIsFeedbacksOpen') + const updateModalSpy = jest.spyOn(ModalAction, 'openFeedbackModal') wrapper.find('BarRight').find('.cv-button').first().simulate('click') expect(updateModalSpy).toHaveBeenCalledWith(true) }) diff --git a/src/components/Header/CozyBar.tsx b/src/components/Header/CozyBar.tsx index 6fbac78f5ec70175dd85d37e4a0c815d1376a94a..891266275d9d3111ed92d26c3c938e9f353e5783 100644 --- a/src/components/Header/CozyBar.tsx +++ b/src/components/Header/CozyBar.tsx @@ -3,11 +3,11 @@ import FeedbackIcon from 'assets/icons/ico/feedback.svg' import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { ScreenType } from 'enum/screen.enum' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' -import { updateModalIsFeedbacksOpen } from 'store/modal/modal.actions' +import { AppActionsTypes, AppStore } from 'store' +import { openFeedbackModal } from 'store/modal/modal.actions' declare const cozy: { bar: { @@ -31,7 +31,7 @@ const CozyBar = ({ }: CozyBarProps) => { const { t } = useI18n() const navigate = useNavigate() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { BarLeft, BarCenter, BarRight } = cozy.bar const { screenType } = useSelector((state: AppStore) => state.ecolyo.global) @@ -44,7 +44,7 @@ const CozyBar = ({ }, [backFunction, navigate]) const handleClickFeedbacks = () => { - dispatch(updateModalIsFeedbacksOpen(true)) + dispatch(openFeedbackModal(true)) } const cozyBarCustom = (screen?: ScreenType) => { diff --git a/src/components/Header/Header.spec.tsx b/src/components/Header/Header.spec.tsx index 7405f33ceda4add6941fc1d299ce317e66ce3470..68c619a57a15e2f928c36a9d6ef08296172c96b7 100644 --- a/src/components/Header/Header.spec.tsx +++ b/src/components/Header/Header.spec.tsx @@ -24,7 +24,7 @@ jest.mock('react-router-dom', () => ({ useNavigate: () => mockedNavigate, })) -const mocksetHeaderHeight = jest.fn() +const mockSetHeaderHeight = jest.fn() const mockStore = configureStore([]) describe('Header component', () => { @@ -37,7 +37,7 @@ describe('Header component', () => { const wrapper = mount( <Provider store={store}> <Header - setHeaderHeight={mocksetHeaderHeight} + setHeaderHeight={mockSetHeaderHeight} desktopTitleKey="mockKey" /> </Provider> @@ -56,7 +56,7 @@ describe('Header component', () => { <Header desktopTitleKey={'KEY'} displayBackArrow={true} - setHeaderHeight={mocksetHeaderHeight} + setHeaderHeight={mockSetHeaderHeight} /> </Provider> ) @@ -77,7 +77,7 @@ describe('Header component', () => { <Header desktopTitleKey={'KEY'} displayBackArrow={true} - setHeaderHeight={mocksetHeaderHeight} + setHeaderHeight={mockSetHeaderHeight} /> </Provider> ) @@ -101,12 +101,12 @@ describe('Header component', () => { const wrapper = mount( <Provider store={store}> <Header - setHeaderHeight={mocksetHeaderHeight} + setHeaderHeight={mockSetHeaderHeight} desktopTitleKey="mockKey" /> </Provider> ) - const updateModalSpy = jest.spyOn(ModalAction, 'updateModalIsFeedbacksOpen') + const updateModalSpy = jest.spyOn(ModalAction, 'openFeedbackModal') wrapper .find(IconButton) .find('.header-feedbacks-button') diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 049abd6ebec48acb848a2d76d467a047318b9dec..81cab9dfae017377a5e07033bd492474a4cd557f 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -4,11 +4,11 @@ import FeedbackIcon from 'assets/icons/ico/feedback.svg' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { ScreenType } from 'enum/screen.enum' -import React, { useCallback, useEffect, useRef } from 'react' +import React, { Dispatch, useCallback, useEffect, useRef } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' -import { updateModalIsFeedbacksOpen } from 'store/modal/modal.actions' +import { AppActionsTypes, AppStore } from 'store' +import { openFeedbackModal } from 'store/modal/modal.actions' import './header.scss' interface HeaderProps { @@ -31,7 +31,7 @@ const Header: React.FC<HeaderProps> = ({ const { t } = useI18n() const navigate = useNavigate() const header = useRef<HTMLDivElement>(null) - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { screenType } = useSelector((state: AppStore) => state.ecolyo.global) const cozyBarHeight = 48 @@ -45,7 +45,7 @@ const Header: React.FC<HeaderProps> = ({ }, [backFunction, navigate]) const handleClickFeedbacks = () => { - dispatch(updateModalIsFeedbacksOpen(true)) + dispatch(openFeedbackModal(true)) } useEffect(() => { diff --git a/src/components/Home/ConsumptionDetails.spec.tsx b/src/components/Home/ConsumptionDetails.spec.tsx index cdccdd9750aa47d5395dd493cfa7ca928fcb9e91..93fcb20809868df503fbf9ebe155ff98829c95d3 100644 --- a/src/components/Home/ConsumptionDetails.spec.tsx +++ b/src/components/Home/ConsumptionDetails.spec.tsx @@ -6,9 +6,8 @@ import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { BrowserRouter } from 'react-router-dom' import { - createMockStore, + createMockEcolyoStore, mockInitialChartState, - mockInitialEcolyoState, mockInitialGlobalState, } from '../../../tests/__mocks__/store' import ConsumptionDetails from './ConsumptionDetails' @@ -26,11 +25,9 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => { const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') describe('ConsumptionDetails component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any - + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() mockUseSelector.mockClear() }) it('should be rendered correctly', () => { diff --git a/src/components/Home/ConsumptionView.spec.tsx b/src/components/Home/ConsumptionView.spec.tsx index b8ac9f486ce1abddb7ffaaae82a13cb85648c1d1..63d30b40b750f89f1d3d6d2ee2927d8c15e19160 100644 --- a/src/components/Home/ConsumptionView.spec.tsx +++ b/src/components/Home/ConsumptionView.spec.tsx @@ -2,15 +2,14 @@ import Loader from 'components/Loader/Loader' import { FluidState, FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { mount } from 'enzyme' -import { ChartState, FluidStatus, GlobalState } from 'models' +import { FluidStatus } from 'models' import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' -import { MockStoreEnhanced } from 'redux-mock-store' import * as chartActions from 'store/chart/chart.actions' import { mockTestProfile1 } from '../../../tests/__mocks__/profileType.mock' import { - createMockStore, + createMockEcolyoStore, mockExpiredElec, mockExpiredGas, mockInitialEcolyoState, @@ -74,17 +73,9 @@ const mockedPartnersIssueModal = { } describe('ConsumptionView component', () => { - let store: MockStoreEnhanced< - { - ecolyo: { - global: GlobalState - chart?: ChartState - } - }, - {} - > + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useDispatchSpy.mockClear() setCurrentTimeStepSpy.mockClear() }) diff --git a/src/components/Home/ConsumptionView.tsx b/src/components/Home/ConsumptionView.tsx index e640cffc4a41660d90cbc72409ad65afc9a8b025..5d01492efad055387d8ae96f5e7b2bb0bf8d7c04 100644 --- a/src/components/Home/ConsumptionView.tsx +++ b/src/components/Home/ConsumptionView.tsx @@ -15,11 +15,11 @@ import PartnerIssueModal from 'components/PartnerIssue/PartnerIssueModal' import { useClient } from 'cozy-client' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import ProfileService from 'services/profile.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentTimeStep, setLoading } from 'store/chart/chart.actions' import { setCustomPopup, showReleaseNotes } from 'store/global/global.actions' import { openPartnersModal } from 'store/modal/modal.actions' @@ -39,7 +39,7 @@ const ConsumptionView: React.FC<ConsumptionViewProps> = ({ }: ConsumptionViewProps) => { const navigate = useNavigate() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const isMulti = fluidType !== FluidType.MULTIFLUID const { chart: { currentTimeStep, loading }, diff --git a/src/components/Home/FluidButton.spec.tsx b/src/components/Home/FluidButton.spec.tsx index 84a928dcdea7f7f5e03fc000f3bb70d59f27c00e..e58745f9c33aa4fbc16d89bc695bc3d621d939cc 100644 --- a/src/components/Home/FluidButton.spec.tsx +++ b/src/components/Home/FluidButton.spec.tsx @@ -6,8 +6,7 @@ import { Provider } from 'react-redux' import configureStore from 'redux-mock-store' import UsageEventService from 'services/usageEvent.service' import { - createMockStore, - mockInitialEcolyoState, + createMockEcolyoStore, mockInitialGlobalState, } from '../../../tests/__mocks__/store' import FluidButton from './FluidButton' @@ -28,10 +27,9 @@ jest.mock('react-router-dom', () => ({ })) describe('FluidButton component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Home/FluidButtons.spec.tsx b/src/components/Home/FluidButtons.spec.tsx index 4af5a9d40994e3e569a884f003b8290657193de9..34a90e11de944fa87e075a0642394513149b9979 100644 --- a/src/components/Home/FluidButtons.spec.tsx +++ b/src/components/Home/FluidButtons.spec.tsx @@ -2,10 +2,7 @@ import { FluidType } from 'enum/fluid.enum' import { mount } from 'enzyme' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import FluidButtons from './FluidButtons' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -24,10 +21,9 @@ jest.mock('react-router-dom', () => ({ })) describe('FluidButtons component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Hooks/useExploration.tsx b/src/components/Hooks/useExploration.tsx index d0696c7822d71c3f397c83ea5a1db3685a7100b3..0858343b897348ec9bd9b2fa2edf505721423634 100644 --- a/src/components/Hooks/useExploration.tsx +++ b/src/components/Hooks/useExploration.tsx @@ -4,13 +4,13 @@ import { ChallengeState, UserExploration } from 'models' import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import ExplorationService from 'services/exploration.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import { toggleChallengeExplorationNotification } from 'store/global/global.actions' const useExploration = (): [string, Dispatch<SetStateAction<string>>] => { const client: Client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { currentChallenge }: ChallengeState = useSelector( (state: AppStore) => state.ecolyo.challenge ) diff --git a/src/components/Hooks/useKonnectorAuth.tsx b/src/components/Hooks/useKonnectorAuth.tsx index 2feceda088b7979cff007c8b2f198db54eecf90e..2c5cfbad339da68ac1308a190808b657edadc046 100644 --- a/src/components/Hooks/useKonnectorAuth.tsx +++ b/src/components/Hooks/useKonnectorAuth.tsx @@ -10,12 +10,12 @@ import { FluidStatus, UsageEvent, } from 'models' -import { useCallback, useState } from 'react' +import { Dispatch, useCallback, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import AccountService from 'services/account.service' import ConnectionService from 'services/connection.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setLoading } from 'store/chart/chart.actions' import { updatedFluidConnection } from 'store/global/global.actions' import logApp from 'utils/logger' @@ -27,7 +27,7 @@ const useKonnectorAuth = ( ): [() => Promise<null | undefined>, () => Promise<void>, string] => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const konnectorSlug: FluidSlugType = fluidStatus.connection.konnectorConfig.slug const { sgeConnect } = useSelector((state: AppStore) => state.ecolyo.global) diff --git a/src/components/Konnector/KonnectorModal.spec.tsx b/src/components/Konnector/KonnectorModal.spec.tsx index 1a185072e8ee090c3390842bbbcd7692f25139c2..818ac1a95d4e84d1f6337c22066cc457875e785a 100644 --- a/src/components/Konnector/KonnectorModal.spec.tsx +++ b/src/components/Konnector/KonnectorModal.spec.tsx @@ -5,10 +5,7 @@ import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' import KonnectorModal from './KonnectorModal' @@ -28,9 +25,9 @@ jest.mock('react-router-dom', () => ({ })) describe('KonnectorModal component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() jest.clearAllMocks() }) const mockHandleCloseClick = jest.fn() diff --git a/src/components/Konnector/KonnectorModalFooter.spec.tsx b/src/components/Konnector/KonnectorModalFooter.spec.tsx index 3665d47b17c69dbdeea776ae8485270dc24e3d66..1a2d2dd879ad7f43a7f0afdc8562234b70182465 100644 --- a/src/components/Konnector/KonnectorModalFooter.spec.tsx +++ b/src/components/Konnector/KonnectorModalFooter.spec.tsx @@ -9,10 +9,7 @@ import React from 'react' import { Provider } from 'react-redux' import { MockStoreEnhanced } from 'redux-mock-store' import { accountsData } from '../../../tests/__mocks__/accountsData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' import KonnectorModalFooter from './KonnectorModalFooter' @@ -33,16 +30,9 @@ jest.mock('react-router-dom', () => ({ const mockClose = jest.fn() const mockDelete = jest.fn() describe('KonnectorModalFooter component', () => { - let store: MockStoreEnhanced< - { - ecolyo: { - global: GlobalState - } - }, - {} - > + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() mockDelete.mockClear() mockClose.mockClear() mockedNavigate.mockClear() diff --git a/src/components/Konnector/KonnectorViewerCard.tsx b/src/components/Konnector/KonnectorViewerCard.tsx index 1ce577ec3f9c96a60165efdc4707bb9f24781618..6a2b9e196554d3cb74c8a2e4a935a108faf6c860 100644 --- a/src/components/Konnector/KonnectorViewerCard.tsx +++ b/src/components/Konnector/KonnectorViewerCard.tsx @@ -39,7 +39,13 @@ import { UsageEvent, } from 'models' import { PartnersInfo } from 'models/partnersInfo.model' -import React, { useCallback, useEffect, useMemo, useState } from 'react' +import React, { + Dispatch, + useCallback, + useEffect, + useMemo, + useState, +} from 'react' import { useDispatch, useSelector } from 'react-redux' import AccountService from 'services/account.service' import ChallengeService from 'services/challenge.service' @@ -47,7 +53,7 @@ import DateChartService from 'services/dateChart.service' import FluidService from 'services/fluid.service' import PartnersInfoService from 'services/partnersInfo.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setChallengeConsumption } from 'store/challenge/challenge.actions' import { setSelectedDate } from 'store/chart/chart.actions' import { @@ -77,7 +83,7 @@ const KonnectorViewerCard: React.FC<KonnectorViewerCardProps> = ({ }: KonnectorViewerCardProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const fluidSlug = fluidStatus.connection.konnectorConfig.slug const fluidState = fluidStatus.status @@ -85,10 +91,9 @@ const KonnectorViewerCard: React.FC<KonnectorViewerCardProps> = ({ const account: Account | null = fluidStatus.connection.account const trigger: Trigger | null = fluidStatus.connection.trigger const { - fluidStatus: statusArray, - shouldRefreshConsent, - partnersInfo, - } = useSelector((state: AppStore) => state.ecolyo.global) + challenge: { currentChallenge }, + global: { fluidStatus: statusArray, shouldRefreshConsent, partnersInfo }, + } = useSelector((state: AppStore) => state.ecolyo) const [openModal, setOpenModal] = useState(false) const [isUpdating, setIsUpdating] = useState(false) @@ -102,9 +107,6 @@ const KonnectorViewerCard: React.FC<KonnectorViewerCardProps> = ({ [] ) const [isOutdatedData, setIsOutdatedData] = useState<number | null>(null) - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const fluidService = useMemo(() => new FluidService(client), [client]) const partnersInfoService = useMemo( () => new PartnersInfoService(client), diff --git a/src/components/Konnector/KonnectorViewerList.spec.tsx b/src/components/Konnector/KonnectorViewerList.spec.tsx index e623dfe4d4867327c2a796f06d72b94bb3d029ad..638e43f17784e764184ca06f05ccdaeb4a69afd4 100644 --- a/src/components/Konnector/KonnectorViewerList.spec.tsx +++ b/src/components/Konnector/KonnectorViewerList.spec.tsx @@ -3,8 +3,7 @@ import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { - createMockStore, - mockInitialEcolyoState, + createMockEcolyoStore, mockInitialGlobalState, } from '../../../tests/__mocks__/store' import KonnectorViewerList from './KonnectorViewerList' @@ -25,9 +24,9 @@ jest.mock('react-router-dom', () => ({ })) describe('KonnectorViewerList component', () => { - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/Onboarding/WelcomeModal.tsx b/src/components/Onboarding/WelcomeModal.tsx index b17c2fe7b323525631675c10c3603b23f3fda554..3636741e92360d3c206b92a65c280f9ed6984e9e 100644 --- a/src/components/Onboarding/WelcomeModal.tsx +++ b/src/components/Onboarding/WelcomeModal.tsx @@ -5,10 +5,11 @@ import useUserInstanceSettings from 'components/Hooks/useUserInstanceSettings' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' -import React, { useCallback } from 'react' +import React, { Dispatch, useCallback } from 'react' import { useDispatch } from 'react-redux' import EnvironmentService from 'services/environment.service' import MailService from 'services/mail.service' +import { AppActionsTypes } from 'store' import { updateProfile } from 'store/profile/profile.actions' import './welcomeModal.scss' @@ -22,7 +23,7 @@ interface WelcomeModalProps { const WelcomeModal = ({ open }: WelcomeModalProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { data: instanceSettings } = useUserInstanceSettings() const setWelcomeModalViewed = useCallback(async () => { diff --git a/src/components/Options/HelpLink/HelpLink.tsx b/src/components/Options/HelpLink/HelpLink.tsx index 7311138ae02517f63607ce95f2d93294bb061765..ee6ac458eec091d2c476caf410cfa221f7bf22e3 100644 --- a/src/components/Options/HelpLink/HelpLink.tsx +++ b/src/components/Options/HelpLink/HelpLink.tsx @@ -2,19 +2,20 @@ import Link from '@material-ui/core/Link' import QuestionMarkIcon from 'assets/icons/ico/questionMark.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React from 'react' +import React, { Dispatch } from 'react' import { useDispatch } from 'react-redux' -import { updateModalIsFeedbacksOpen } from 'store/modal/modal.actions' +import { AppActionsTypes } from 'store' +import { openFeedbackModal } from 'store/modal/modal.actions' import './HelpLink.scss' const HelpLink: React.FC = () => { const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() return ( <div className="help-root" - onClick={() => dispatch(updateModalIsFeedbacksOpen(true))} + onClick={() => dispatch(openFeedbackModal(true))} > <div className="help-content"> <div className="help-header text-16-normal-uppercase"> diff --git a/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx b/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx index b41aa5dc655eca637fbcf1106bb53a278d538a4b..72a98af3e38651d4a5183dcba9d805d6e2d2746d 100644 --- a/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx +++ b/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx @@ -26,8 +26,9 @@ import { AppStore } from 'store' import './profileTypeOptions.scss' const ProfileTypeOptions: React.FC = () => { - const profile = useSelector((state: AppStore) => state.ecolyo.profile) - const profileType = useSelector((state: AppStore) => state.ecolyo.profileType) + const { profile, profileType } = useSelector( + (state: AppStore) => state.ecolyo + ) const { t } = useI18n() const navigate = useNavigate() const [, setValidExploration] = useExploration() diff --git a/src/components/Options/ReportOptions/ReportOptions.spec.tsx b/src/components/Options/ReportOptions/ReportOptions.spec.tsx index 385447bfb9cc0fcd628010007ebe995a1b57d475..baaeff3f3d1591037497778c6148ee9c0119c277 100644 --- a/src/components/Options/ReportOptions/ReportOptions.spec.tsx +++ b/src/components/Options/ReportOptions/ReportOptions.spec.tsx @@ -7,7 +7,7 @@ import React from 'react' import { Provider } from 'react-redux' import * as profileActions from 'store/profile/profile.actions' import { - createMockStore, + createMockEcolyoStore, mockInitialEcolyoState, } from '../../../../tests/__mocks__/store' @@ -33,10 +33,9 @@ jest.mock('services/profile.service', () => { const updateProfileSpy = jest.spyOn(profileActions, 'updateProfile') describe('ReportOptions component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() updateProfileSpy.mockClear() }) @@ -63,7 +62,6 @@ describe('ReportOptions component', () => { }) it('should be rendered with sendAnalysisNotification false and toggle it to true', () => { mockInitialEcolyoState.profile.sendAnalysisNotification = false - store = createMockStore(mockInitialEcolyoState) const wrapper = mount( <Provider store={store}> @@ -81,7 +79,6 @@ describe('ReportOptions component', () => { mockInitialEcolyoState.profile.sendAnalysisNotification = false mockInitialEcolyoState.global.fluidStatus[FluidType.WATER].status = FluidState.DONE - store = createMockStore(mockInitialEcolyoState) const wrapper = mount( <Provider store={store}> <ReportOptions /> diff --git a/src/components/Options/ReportOptions/ReportOptions.tsx b/src/components/Options/ReportOptions/ReportOptions.tsx index 242cd490601b370fc48ed57060aeb89b86039eab..b311b3aa81ba36268a772f545c1e682ad8eff322 100644 --- a/src/components/Options/ReportOptions/ReportOptions.tsx +++ b/src/components/Options/ReportOptions/ReportOptions.tsx @@ -6,19 +6,21 @@ import { FluidState, FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Dataload, TimePeriod } from 'models' -import React, { useCallback, useEffect, useState } from 'react' +import React, { Dispatch, useCallback, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import ConsumptionDataManager from 'services/consumption.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateProfile } from 'store/profile/profile.actions' import './reportOptions.scss' const ReportOptions: React.FC = () => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() - const profile = useSelector((state: AppStore) => state.ecolyo.profile) - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const { + global: { fluidStatus }, + profile, + } = useSelector((state: AppStore) => state.ecolyo) const [maxDayData, setLastSemesterMaxDay] = useState<Dataload | null>(null) const updateProfileReport = async (value: boolean) => { diff --git a/src/components/Options/Unsubscribe/UnSubscribe.spec.tsx b/src/components/Options/Unsubscribe/UnSubscribe.spec.tsx index 444b03735cc6f716b5248cdb305d1e70356dc744..f1b1dc38279ff51b86f04b94e0bf360815ab831a 100644 --- a/src/components/Options/Unsubscribe/UnSubscribe.spec.tsx +++ b/src/components/Options/Unsubscribe/UnSubscribe.spec.tsx @@ -4,10 +4,7 @@ import toJson from 'enzyme-to-json' import React from 'react' import { Provider } from 'react-redux' import * as profileActions from 'store/profile/profile.actions' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../../tests/__mocks__/store' import UnSubscribe from './UnSubscribe' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -39,10 +36,9 @@ jest.mock('react-router-dom', () => ({ })) describe('UnSubscribe component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() updateProfileSpy.mockClear() }) diff --git a/src/components/Options/Unsubscribe/UnSubscribe.tsx b/src/components/Options/Unsubscribe/UnSubscribe.tsx index 19ab95cb71588e0725544d2a18e1db023455987f..8b13800328c9a8b700ea825730da73c886855e2b 100644 --- a/src/components/Options/Unsubscribe/UnSubscribe.tsx +++ b/src/components/Options/Unsubscribe/UnSubscribe.tsx @@ -5,9 +5,10 @@ import Content from 'components/Content/Content' import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React, { useState } from 'react' +import React, { Dispatch, useState } from 'react' import { useDispatch } from 'react-redux' import { useNavigate } from 'react-router-dom' +import { AppActionsTypes } from 'store' import { updateProfile } from 'store/profile/profile.actions' import './unSubscribe.scss' @@ -17,7 +18,7 @@ const UnSubscribe: React.FC = () => { setHeaderHeight(height) } const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const unSubscribe = async () => { dispatch(updateProfile({ sendAnalysisNotification: false })) diff --git a/src/components/ProfileType/ProfileTypeFinished.spec.tsx b/src/components/ProfileType/ProfileTypeFinished.spec.tsx index f151263886e5c0b2ae6cb2c206faafd190932124..9e5393094f4f30c5ef0e3ed5cb8654c2572ea8c9 100644 --- a/src/components/ProfileType/ProfileTypeFinished.spec.tsx +++ b/src/components/ProfileType/ProfileTypeFinished.spec.tsx @@ -3,10 +3,7 @@ import { mount } from 'enzyme' import React from 'react' import { Provider } from 'react-redux' import { mockProfileType } from '../../../tests/__mocks__/profileType.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import ProfileTypeFinished from './ProfileTypeFinished' const mockedNavigate = jest.fn() @@ -29,13 +26,9 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => { }) describe('ProfileTypeFinished component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - jest.clearAllMocks() - store = createMockStore(mockInitialEcolyoState) - }) - afterEach(() => { + store.clearActions() jest.clearAllMocks() }) diff --git a/src/components/ProfileType/ProfileTypeFinished.tsx b/src/components/ProfileType/ProfileTypeFinished.tsx index 0615a27c44c6690a7b0da3ec729e8bcaeb9c49c7..57d208a83342ae7e2d90b7cffeec905f1a015022 100644 --- a/src/components/ProfileType/ProfileTypeFinished.tsx +++ b/src/components/ProfileType/ProfileTypeFinished.tsx @@ -11,31 +11,28 @@ import { UserExplorationID } from 'enum/userExploration.enum' import { DateTime } from 'luxon' import { TimePeriod } from 'models' import { ProfileType } from 'models/profileType.model' -import React, { useEffect, useState } from 'react' +import React, { Dispatch, useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useLocation, useNavigate } from 'react-router-dom' import ProfileTypeService from 'services/profileType.service' import ProfileTypeEntityService from 'services/profileTypeEntity.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateProfile } from 'store/profile/profile.actions' import { newProfileTypeEntry } from 'store/profileType/profileType.actions' -interface ProfileTypeFinishedProps { - profileType: ProfileType -} - -const ProfileTypeFinished: React.FC<ProfileTypeFinishedProps> = ({ +const ProfileTypeFinished: React.FC<{ profileType: ProfileType }> = ({ profileType, -}: ProfileTypeFinishedProps) => { +}) => { const { t } = useI18n() const location = useLocation() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const client = useClient() - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) + const { + challenge: { currentChallenge }, + profile, + } = useSelector((state: AppStore) => state.ecolyo) const handleClick = () => { if (location?.pathname === '/ecogesture-form') { navigate('/ecogesture-selection') @@ -46,7 +43,6 @@ const ProfileTypeFinished: React.FC<ProfileTypeFinishedProps> = ({ const [isSaved, setIsSaved] = useState<boolean>(false) const [, setValidExploration] = useExploration() - const profile = useSelector((state: AppStore) => state.ecolyo.profile) useEffect(() => { async function checkForExistingProfileType() { diff --git a/src/components/ProfileType/ProfileTypeFormMultiChoice.spec.tsx b/src/components/ProfileType/ProfileTypeFormMultiChoice.spec.tsx index fa0cf9261f2850f80be78811727d5f873fae2f17..8b5019a070025c88702e74b651764ab955b94029 100644 --- a/src/components/ProfileType/ProfileTypeFormMultiChoice.spec.tsx +++ b/src/components/ProfileType/ProfileTypeFormMultiChoice.spec.tsx @@ -6,10 +6,7 @@ import { mockProfileType, mockProfileTypeAnswers, } from '../../../tests/__mocks__/profileType.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import ProfileTypeFormMultiChoice from './ProfileTypeFormMultiChoice' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -29,10 +26,9 @@ jest.mock('react-router-dom', () => ({ })) describe('ProfileTypeFormMultiChoice component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/ProfileType/ProfileTypeFormNumber.spec.tsx b/src/components/ProfileType/ProfileTypeFormNumber.spec.tsx index 8ddd81010f7c8cdad3d7bcab502533e582ee963b..2631a9fa3567f9464eeabe6c15dec384bd6c7d15 100644 --- a/src/components/ProfileType/ProfileTypeFormNumber.spec.tsx +++ b/src/components/ProfileType/ProfileTypeFormNumber.spec.tsx @@ -6,10 +6,7 @@ import { mockProfileType, mockProfileTypeAnswers, } from '../../../tests/__mocks__/profileType.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import ProfileTypeFormNumber from './ProfileTypeFormNumber' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -28,10 +25,9 @@ jest.mock('react-router-dom', () => ({ })) describe('ProfileTypeFormNumber component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/ProfileType/ProfileTypeFormNumberSelection.spec.tsx b/src/components/ProfileType/ProfileTypeFormNumberSelection.spec.tsx index b4182cdffe3ccd291da8d480c8edb0b61fb1aef9..e6cf7e1c3a13c3cc2a5ee9df31a53de051ee2dc7 100644 --- a/src/components/ProfileType/ProfileTypeFormNumberSelection.spec.tsx +++ b/src/components/ProfileType/ProfileTypeFormNumberSelection.spec.tsx @@ -6,10 +6,7 @@ import { mockProfileType, mockProfileTypeAnswers, } from '../../../tests/__mocks__/profileType.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import ProfileTypeFormNumberSelection from './ProfileTypeFormNumberSelection' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -28,10 +25,9 @@ jest.mock('react-router-dom', () => ({ })) describe('ProfileTypeFormNumberSelection component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/ProfileType/ProfileTypeFormSingleChoice.spec.tsx b/src/components/ProfileType/ProfileTypeFormSingleChoice.spec.tsx index 9cd981c5abf8b0e0511dc0cb3412beab17f64ef7..f8743a938df9351e4ba42963d8062b2b04a373ae 100644 --- a/src/components/ProfileType/ProfileTypeFormSingleChoice.spec.tsx +++ b/src/components/ProfileType/ProfileTypeFormSingleChoice.spec.tsx @@ -6,10 +6,7 @@ import { mockProfileType, mockProfileTypeAnswers, } from '../../../tests/__mocks__/profileType.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import ProfileTypeFormSingleChoice from './ProfileTypeFormSingleChoice' jest.mock('cozy-ui/transpiled/react/I18n', () => { @@ -28,10 +25,9 @@ jest.mock('react-router-dom', () => ({ })) describe('ProfileTypeFormSingleChoice component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/ProfileType/ProfileTypeView.spec.tsx b/src/components/ProfileType/ProfileTypeView.spec.tsx index 2018cfe89d14160993f64c8ba929b0cfaf42a835..466f3939ccff7a70a3b9523e7067a2fe0a6358a1 100644 --- a/src/components/ProfileType/ProfileTypeView.spec.tsx +++ b/src/components/ProfileType/ProfileTypeView.spec.tsx @@ -2,10 +2,7 @@ import ProfileTypeView from 'components/ProfileType/ProfileTypeView' import { mount } from 'enzyme' import React from 'react' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => { return { @@ -27,10 +24,9 @@ jest.mock('components/Header/Header', () => 'mock-header') jest.mock('components/Content/Content', () => 'mock-content') describe('ProfileTypeView component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should be rendered correctly', () => { diff --git a/src/components/ProfileType/ProfileTypeView.tsx b/src/components/ProfileType/ProfileTypeView.tsx index cfe2d0643d36ef31e5d92fba957af036c7438e80..0b255ca9c7baaa5287f894851ff3b32d5e2823d8 100644 --- a/src/components/ProfileType/ProfileTypeView.tsx +++ b/src/components/ProfileType/ProfileTypeView.tsx @@ -24,7 +24,6 @@ import { WarmingType, } from 'enum/profileType.enum' import { DateTime } from 'luxon' -import { ProfileEcogesture } from 'models/profileEcogesture.model' import { ProfileType, ProfileTypeAnswer } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' import { useSelector } from 'react-redux' @@ -33,13 +32,11 @@ import { AppStore } from 'store' import ProfileTypeFormDateSelection from './ProfileTypeFormDateSelection' const ProfileTypeView: React.FC = () => { - const profile = useSelector((state: AppStore) => state.ecolyo.profile) - const curProfileType = useSelector( - (state: AppStore) => state.ecolyo.profileType - ) - const curProfileEcogesture: ProfileEcogesture = useSelector( - (state: AppStore) => state.ecolyo.profileEcogesture - ) + const { + profile, + profileType: curProfileType, + profileEcogesture: curProfileEcogesture, + } = useSelector((state: AppStore) => state.ecolyo) const [headerHeight, setHeaderHeight] = useState<number>(0) const [profileType, setProfileType] = useState<ProfileType>({ diff --git a/src/components/Quiz/QuizBegin.tsx b/src/components/Quiz/QuizBegin.tsx index 192680150f0d1cd91d4ddd30319f9feda1cd4915..8ab9c1f630d666b358d7e94de51ec8765b9f48a6 100644 --- a/src/components/Quiz/QuizBegin.tsx +++ b/src/components/Quiz/QuizBegin.tsx @@ -6,9 +6,10 @@ import { Client, useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React from 'react' +import React, { Dispatch } from 'react' import { useDispatch } from 'react-redux' import ChallengeService from 'services/challenge.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import './quizBegin.scss' @@ -21,7 +22,7 @@ const QuizBegin: React.FC<QuizBeginProps> = ({ }: QuizBeginProps) => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const launchQuiz = async () => { const challengeService: ChallengeService = new ChallengeService(client) const userChallengeUpdated: UserChallenge = diff --git a/src/components/Quiz/QuizCustomQuestionContent.tsx b/src/components/Quiz/QuizCustomQuestionContent.tsx index a5a38de7729980d4b2ac950bf59d1ba4d0c0cbf6..f5b80fd56b71d2be0448957d72038564242ba907 100644 --- a/src/components/Quiz/QuizCustomQuestionContent.tsx +++ b/src/components/Quiz/QuizCustomQuestionContent.tsx @@ -8,11 +8,12 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { Answer, QuestionEntity, UserChallenge, UserQuiz } from 'models' -import React, { useState } from 'react' +import React, { Dispatch, useState } from 'react' import { useDispatch } from 'react-redux' import ChallengeService from 'services/challenge.service' import QuizService from 'services/quiz.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import './quizQuestion.scss' @@ -34,7 +35,7 @@ const QuizCustomQuestionContent: React.FC<QuizCustomQuestionContent> = ({ const [openModal, setOpenModal] = useState<boolean>(false) const [answerIndex, setAnswerIndex] = useState<number>(0) const client: Client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const quizService: QuizService = new QuizService(client) const challengeService: ChallengeService = new ChallengeService(client) diff --git a/src/components/Quiz/QuizFinish.tsx b/src/components/Quiz/QuizFinish.tsx index b6d49e253f2eef31bf43a8997c3d17dad7961b28..cc0274f473352cabd845a7853d5623a1fbe4f550 100644 --- a/src/components/Quiz/QuizFinish.tsx +++ b/src/components/Quiz/QuizFinish.tsx @@ -5,10 +5,11 @@ import { Client, useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { useCallback, useMemo } from 'react' +import React, { Dispatch, useCallback, useMemo } from 'react' import { useDispatch } from 'react-redux' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import './quizFinish.scss' @@ -22,7 +23,7 @@ const QuizFinish: React.FC<QuizFinishProps> = ({ const client: Client = useClient() const { t } = useI18n() const navigate = useNavigate() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const challengeService: ChallengeService = useMemo( () => new ChallengeService(client), [client] diff --git a/src/components/Quiz/QuizQuestion.spec.tsx b/src/components/Quiz/QuizQuestion.spec.tsx index a83ed32a42ca2516f2e6ede18ae322e574ace844..16a951db361c715065fcd94da472738a2d8af141 100644 --- a/src/components/Quiz/QuizQuestion.spec.tsx +++ b/src/components/Quiz/QuizQuestion.spec.tsx @@ -4,10 +4,7 @@ import { mount } from 'enzyme' import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { userChallengeData } from '../../../tests/__mocks__/userChallengeData.mock' import QuizQuestion from './QuizQuestion' @@ -47,10 +44,9 @@ jest.mock('components/Quiz/QuizQuestionContent', () => () => ( const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') describe('QuizQuestion component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useSelectorSpy.mockClear() }) diff --git a/src/components/Quiz/QuizQuestionContent.tsx b/src/components/Quiz/QuizQuestionContent.tsx index b67835140343ab066f45d45f873262048b747040..4b12b75b792bbcba8310dd932b0ac577656f8ba2 100644 --- a/src/components/Quiz/QuizQuestionContent.tsx +++ b/src/components/Quiz/QuizQuestionContent.tsx @@ -10,6 +10,7 @@ import React, { Dispatch, SetStateAction, useCallback, useState } from 'react' import { useDispatch } from 'react-redux' import ChallengeService from 'services/challenge.service' import QuizService from 'services/quiz.service' +import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.actions' import './quizQuestion.scss' @@ -35,7 +36,7 @@ const QuizQuestionContent: React.FC<QuizQuestionContent> = ({ useState<number>(questionIndexLocked) const client: Client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const quizService: QuizService = new QuizService(client) const challengeService: ChallengeService = new ChallengeService(client) diff --git a/src/components/Splash/SplashRoot.tsx b/src/components/Splash/SplashRoot.tsx index c10e94d4742f27e862553eef92914d7d26164442..097a6317e60a81b6a42da6b55005130cc899743a 100644 --- a/src/components/Splash/SplashRoot.tsx +++ b/src/components/Splash/SplashRoot.tsx @@ -33,15 +33,14 @@ import FluidService from 'services/fluid.service' import InitializationService from 'services/initialization.service' import PartnersInfoService from 'services/partnersInfo.service' import UsageEventService from 'services/usageEvent.service' +import { AppActionsTypes } from 'store' import { - ChallengeActionTypes, setChallengeConsumption, setUserChallengeList, updateUserChallengeList, } from 'store/challenge/challenge.actions' -import { ChartActionTypes, setSelectedDate } from 'store/chart/chart.actions' +import { setSelectedDate } from 'store/chart/chart.actions' import { - GlobalActionTypes, setCustomPopup, setFluidStatus, showReleaseNotes, @@ -51,19 +50,10 @@ import { toggleChallengeExplorationNotification, updateTermValidation, } from 'store/global/global.actions' -import { ModalActionTypes, openPartnersModal } from 'store/modal/modal.actions' -import { - ProfileActionTypes, - updateProfile, -} from 'store/profile/profile.actions' -import { - ProfileEcogestureActionTypes, - updateProfileEcogestureSuccess, -} from 'store/profileEcogesture/profileEcogesture.actions' -import { - ProfileTypeActionTypes, - updateProfileType, -} from 'store/profileType/profileType.actions' +import { openPartnersModal } from 'store/modal/modal.actions' +import { updateProfile } from 'store/profile/profile.actions' +import { updateProfileEcogestureSuccess } from 'store/profileEcogesture/profileEcogesture.actions' +import { updateProfileType } from 'store/profileType/profileType.actions' import logApp from 'utils/logger' import { getTodayDate } from 'utils/utils' import './splashRoot.scss' @@ -91,15 +81,7 @@ const SplashRoot = ({ fadeTimer = 1000, children }: SplashRootProps) => { const [initStepErrors, setInitStepErrors] = useState<InitStepsErrors | null>( null ) - const dispatch: Dispatch< - | ChallengeActionTypes - | ChartActionTypes - | GlobalActionTypes - | ProfileActionTypes - | ProfileEcogestureActionTypes - | ProfileTypeActionTypes - | ModalActionTypes - > = useDispatch() + const dispatch: Dispatch<AppActionsTypes> = useDispatch() /** Return current status of partner if modal has not been seen today */ const getPartnerStatus = useCallback( diff --git a/src/components/Terms/TermsView.spec.tsx b/src/components/Terms/TermsView.spec.tsx index ffcd1aaeb333c1640b0f19fad4b2b8fbfae86497..015e409851c0a385dfbec77498bde7ab86e96b1b 100644 --- a/src/components/Terms/TermsView.spec.tsx +++ b/src/components/Terms/TermsView.spec.tsx @@ -4,9 +4,8 @@ import toJson from 'enzyme-to-json' import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' -import configureStore from 'redux-mock-store' -import { globalStateData } from '../../../tests/__mocks__/globalStateData.mock' -import { profileData } from '../../../tests/__mocks__/profileData.mock' +import { default as configureStore } from 'redux-mock-store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { mockUpToDateTerm } from '../../../tests/__mocks__/termsData.mock' import TermsView from './TermsView' @@ -47,13 +46,8 @@ jest.mock('services/profile.service', () => { }) describe('TermsView component', () => { + const store = createMockEcolyoStore() it('should valid checkboxes and valid consent', () => { - const store = mockStore({ - ecolyo: { - profile: profileData, - global: globalStateData, - }, - }) mockCreateTerm.mockResolvedValueOnce(mockUpToDateTerm) const wrapper = mount( <Provider store={store}> @@ -76,12 +70,6 @@ describe('TermsView component', () => { expect(mockUseDispatch).toHaveBeenCalledTimes(3) }) it('should be rendered correctly', () => { - const store = mockStore({ - ecolyo: { - profile: profileData, - global: globalStateData, - }, - }) const component = mount( <Provider store={store}> <TermsView /> @@ -89,13 +77,7 @@ describe('TermsView component', () => { ) expect(toJson(component)).toMatchSnapshot() }) - it('shouldbe unable to valid consent', async () => { - const store = mockStore({ - ecolyo: { - profile: profileData, - global: globalStateData, - }, - }) + it('should be unable to valid consent', async () => { mockCreateTerm.mockResolvedValueOnce(mockUpToDateTerm) const wrapper = mount( <Provider store={store}> diff --git a/src/components/Terms/TermsView.tsx b/src/components/Terms/TermsView.tsx index 50aabea54f8ac5c855774608291ddd805cd3868d..51bf642c9d1c5f5b43c66c2331ed5aca5bb262cf 100644 --- a/src/components/Terms/TermsView.tsx +++ b/src/components/Terms/TermsView.tsx @@ -2,11 +2,11 @@ import { Button } from '@material-ui/core' import classNames from 'classnames' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React, { useCallback, useState } from 'react' +import React, { Dispatch, useCallback, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import TermsService from 'services/terms.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { updateTermValidation } from 'store/global/global.actions' import { decoreText } from 'utils/decoreText' import CGUModal from './CGUModal' @@ -18,7 +18,7 @@ import './termsView.scss' const TermsView: React.FC = () => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() const [GCUValidation, setGCUValidation] = useState<boolean>(false) const [dataConsentValidation, setDataConsentValidation] = diff --git a/src/components/Terms/__snapshots__/TermsView.spec.tsx.snap b/src/components/Terms/__snapshots__/TermsView.spec.tsx.snap index ac40276bd529b25d499200a7e7e78a4f356aef28..5c505a9990fa805c946808d4fc2a52a395e6a6f4 100644 --- a/src/components/Terms/__snapshots__/TermsView.spec.tsx.snap +++ b/src/components/Terms/__snapshots__/TermsView.spec.tsx.snap @@ -30,8 +30,13 @@ exports[`TermsView component should be rendered correctly 1`] = ` <h1 className="dataShare-content-title text-22-normal" > - dataShare.title1 + dataShare.title1Update </h1> + <p + className="text-14-normal" + > + dataShare.title2Update + </p> <p className="text-14-normal" > diff --git a/src/components/TimeStepSelector/TimeStepSelector.spec.tsx b/src/components/TimeStepSelector/TimeStepSelector.spec.tsx index 3903e80bccdfc267955e67bf3ab3875eae5b3476..619d07743f63c4e7236320a5ada1a099bbedbb9b 100644 --- a/src/components/TimeStepSelector/TimeStepSelector.spec.tsx +++ b/src/components/TimeStepSelector/TimeStepSelector.spec.tsx @@ -9,10 +9,7 @@ import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import UsageEventService from 'services/usageEvent.service' import * as chartActions from 'store/chart/chart.actions' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' jest.mock('cozy-ui/transpiled/react/I18n', () => { return { @@ -34,10 +31,9 @@ const setCurrentIndexSpy = jest.spyOn(chartActions, 'setCurrentIndex') const setSelectedDateSpy = jest.spyOn(chartActions, 'setSelectedDate') describe('TimeStepSelector component', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() useSelectorSpy.mockClear() useDispatchSpy.mockClear() setCurrentTimeStepSpy.mockClear() diff --git a/src/components/TimeStepSelector/TimeStepSelector.tsx b/src/components/TimeStepSelector/TimeStepSelector.tsx index 3532b3af4f500c50641f1740d460f3bcafa2fb8a..cf6c3fc9c1e6f74fbf8d4b35faedee2668e57832 100644 --- a/src/components/TimeStepSelector/TimeStepSelector.tsx +++ b/src/components/TimeStepSelector/TimeStepSelector.tsx @@ -5,11 +5,11 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { UsageEventType } from 'enum/usageEvent.enum' import { DateTime } from 'luxon' -import React from 'react' +import React, { Dispatch } from 'react' import { useDispatch, useSelector } from 'react-redux' import DateChartService from 'services/dateChart.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setCurrentTimeStep, @@ -28,7 +28,7 @@ const TimeStepSelector: React.FC<TimeStepSelectorProps> = ({ (state: AppStore) => state.ecolyo.chart ) const { t } = useI18n() - const dispatch = useDispatch() + const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const dateChartService = new DateChartService() const client = useClient() const timeStepElecArray: TimeStep[] = [ diff --git a/src/services/initialization.service.ts b/src/services/initialization.service.ts index fa41bf5e1a84297dd4ae7b5492760d6463d14f26..9e4b809185ff9f9843e6a2236dbc67c2062248fa 100644 --- a/src/services/initialization.service.ts +++ b/src/services/initialization.service.ts @@ -589,7 +589,7 @@ export default class InitializationService { ) return { monthlyAnalysisDate: actualAnalysisDate, - haveSeenLastAnalysis: profile.isFirstConnection ? true : false, + haveSeenLastAnalysis: profile.isFirstConnection, } } } catch (error) { diff --git a/src/store/challenge/challenge.actions.ts b/src/store/challenge/challenge.actions.ts index a685f415500e36444281374b20cffb3ffefaf819..03ab3e29d5de88293b56567af01eefced45b3729 100644 --- a/src/store/challenge/challenge.actions.ts +++ b/src/store/challenge/challenge.actions.ts @@ -1,4 +1,5 @@ import { Dataload, UserChallenge } from 'models' +import { defaultAction } from 'store' export const SET_USER_CHALLENGE_LIST = 'SET_USER_CHALLENGE_LIST' export const UPDATE_USER_CHALLENGE_LIST = 'UPDATE_USER_CHALLENGE_LIST' @@ -30,6 +31,7 @@ export type ChallengeActionTypes = | UpdateUserChallengeList | UnlockNextUserChallenge | SetChallengeConsumption + | typeof defaultAction export function setUserChallengeList( userChallengeList: UserChallenge[] diff --git a/src/store/challenge/challenge.reducer.spec.ts b/src/store/challenge/challenge.reducer.spec.ts index 9359a529b9d7e83c41ddc9d1e16638f574444b1e..f2ea8117f83c58af7190224ee047e35d8215f1c6 100644 --- a/src/store/challenge/challenge.reducer.spec.ts +++ b/src/store/challenge/challenge.reducer.spec.ts @@ -2,6 +2,7 @@ import { DataloadState } from 'enum/dataload.enum' import { UserChallengeState } from 'enum/userChallenge.enum' import { DateTime } from 'luxon' import { ChallengeState, Dataload, UserChallenge } from 'models' +import { defaultAction } from 'store' import { mockInitialChallengeState } from '../../../tests/__mocks__/store' import { userChallengeData, @@ -17,13 +18,12 @@ import { challengeReducer } from './challenge.reducer' describe('challenge reducer', () => { it('should return the initial state', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const result = challengeReducer(undefined as any, { type: 'default' }) - expect(result).toEqual(mockInitialChallengeState) + const state = challengeReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockInitialChallengeState) }) it('should handle SET_USER_CHALLENGE_LIST with payload', () => { - const result = challengeReducer(mockInitialChallengeState, { + const state = challengeReducer(mockInitialChallengeState, { type: SET_USER_CHALLENGE_LIST, payload: userChallengeData, }) @@ -32,14 +32,14 @@ describe('challenge reducer', () => { currentChallenge: userChallengeData[2], currentDataload: [], } - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) it('should handle SET_USER_CHALLENGE_LIST without payload', () => { - const result = challengeReducer(mockInitialChallengeState, { + const state = challengeReducer(mockInitialChallengeState, { type: SET_USER_CHALLENGE_LIST, }) - expect(result).toEqual(mockInitialChallengeState) + expect(state).toEqual(mockInitialChallengeState) }) it('should handle UPDATE_USER_CHALLENGE_LIST with payload', () => { @@ -51,7 +51,7 @@ describe('challenge reducer', () => { ...userChallengeDefault[0], state: UserChallengeState.ONGOING, } - const result = challengeReducer(updatedMockInitialChallengeState, { + const state = challengeReducer(updatedMockInitialChallengeState, { type: UPDATE_USER_CHALLENGE_LIST, payload: updatedUserChallenge, }) @@ -63,14 +63,14 @@ describe('challenge reducer', () => { currentChallenge: updatedUserChallenge, currentDataload: [], } - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) it('should handle UPDATE_USER_CHALLENGE_LIST without payload', () => { - const result = challengeReducer(mockInitialChallengeState, { + const state = challengeReducer(mockInitialChallengeState, { type: UPDATE_USER_CHALLENGE_LIST, }) - expect(result).toEqual(mockInitialChallengeState) + expect(state).toEqual(mockInitialChallengeState) }) it('should handle UNLOCK_NEXT_USER_CHALLENGE with payload', () => { @@ -86,7 +86,7 @@ describe('challenge reducer', () => { ...userChallengeDefault[1], state: UserChallengeState.UNLOCKED, } - const result = challengeReducer(updatedMockInitialChallengeState, { + const state = challengeReducer(updatedMockInitialChallengeState, { type: UNLOCK_NEXT_USER_CHALLENGE, payload: updatedUserChallenge, }) @@ -99,14 +99,14 @@ describe('challenge reducer', () => { currentChallenge: null, currentDataload: [], } - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) it('should handle UNLOCK_NEXT_USER_CHALLENGE without payload', () => { - const result = challengeReducer(mockInitialChallengeState, { + const state = challengeReducer(mockInitialChallengeState, { type: UNLOCK_NEXT_USER_CHALLENGE, }) - expect(result).toEqual(mockInitialChallengeState) + expect(state).toEqual(mockInitialChallengeState) }) it('should handle SET_CHALLENGE_CONSUMPTION with payload', () => { @@ -143,20 +143,20 @@ describe('challenge reducer', () => { currentChallenge: null, currentDataload: dataload, } - const result = challengeReducer(updatedMockInitialChallengeState, { + const state = challengeReducer(updatedMockInitialChallengeState, { type: SET_CHALLENGE_CONSUMPTION, payload: { userChallenge: updatedUserChallenge, currentDataload: dataload, }, }) - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) it('should handle SET_CHALLENGE_CONSUMPTION without payload', () => { - const result = challengeReducer(mockInitialChallengeState, { + const state = challengeReducer(mockInitialChallengeState, { type: SET_CHALLENGE_CONSUMPTION, }) - expect(result).toEqual(mockInitialChallengeState) + expect(state).toEqual(mockInitialChallengeState) }) }) diff --git a/src/store/challenge/challenge.reducer.ts b/src/store/challenge/challenge.reducer.ts index 34efada3ebc2b9bb8f2fd9c6934e26e1b89f58f5..4d85c630a4d8a864f9fcd467884f624e1cc48e34 100644 --- a/src/store/challenge/challenge.reducer.ts +++ b/src/store/challenge/challenge.reducer.ts @@ -15,95 +15,76 @@ const initialState: ChallengeState = { currentDataload: [], } -export const challengeReducer: Reducer<ChallengeState> = ( +export const challengeReducer: Reducer<ChallengeState, ChallengeActionTypes> = ( state = initialState, - action: ChallengeActionTypes -): ChallengeState => { + action +) => { + if (action.payload == undefined) return state + + const updateState = (updates: Partial<ChallengeState>): ChallengeState => ({ + ...state, + ...updates, + }) switch (action.type) { - case SET_USER_CHALLENGE_LIST: - if (action.payload !== undefined) { - const filteredCurrentChallenge = action.payload.filter( - challenge => - challenge.state === UserChallengeState.ONGOING || - challenge.state === UserChallengeState.DUEL - ) - const currentChallenge = filteredCurrentChallenge[0] - ? filteredCurrentChallenge[0] + case SET_USER_CHALLENGE_LIST: { + const filteredCurrentChallenge = action.payload.filter( + challenge => + challenge.state === UserChallengeState.ONGOING || + challenge.state === UserChallengeState.DUEL + ) + const currentChallenge = filteredCurrentChallenge[0] || null + return updateState({ + userChallengeList: action.payload, + currentChallenge: currentChallenge, + }) + } + + case UPDATE_USER_CHALLENGE_LIST: { + const id = action.payload.id + const currentChallenge = + action.payload.state === UserChallengeState.ONGOING || + action.payload.state === UserChallengeState.DUEL + ? action.payload : null - return { - ...state, - userChallengeList: action.payload, - currentChallenge: currentChallenge, + const updatedList = [...state.userChallengeList] + const findIndex = updatedList.findIndex(challenge => challenge.id === id) + updatedList[findIndex] = action.payload + return updateState({ + userChallengeList: updatedList, + currentChallenge: currentChallenge || state.currentChallenge, + }) + } + case UNLOCK_NEXT_USER_CHALLENGE: { + const id = action.payload.id + const updatedList = [...state.userChallengeList] + const findIndex = updatedList.findIndex(challenge => challenge.id === id) + updatedList[findIndex] = action.payload + if (typeof updatedList[findIndex + 1] !== 'undefined') { + updatedList[findIndex + 1] = { + ...updatedList[findIndex + 1], + state: UserChallengeState.UNLOCKED, } - } else { - return state } - case UPDATE_USER_CHALLENGE_LIST: - if (action.payload !== undefined) { - const id = action.payload.id - const currentChallenge = - action.payload.state === UserChallengeState.ONGOING || - action.payload.state === UserChallengeState.DUEL - ? action.payload - : null - const updatedList = [...state.userChallengeList] - const findIndex = updatedList.findIndex( - challenge => challenge.id === id - ) - updatedList[findIndex] = action.payload - return { - ...state, - userChallengeList: updatedList, - currentChallenge: currentChallenge - ? currentChallenge + return updateState({ + userChallengeList: updatedList, + currentChallenge: null, + }) + } + case SET_CHALLENGE_CONSUMPTION: { + const id = action.payload.userChallenge.id + const updatedList = [...state.userChallengeList] + const findIndex = updatedList.findIndex(challenge => challenge.id === id) + updatedList[findIndex] = action.payload.userChallenge + return updateState({ + userChallengeList: updatedList, + currentChallenge: + state.currentChallenge && + state.currentChallenge.id === action.payload.userChallenge.id + ? action.payload.userChallenge : state.currentChallenge, - } - } else { - return state - } - case UNLOCK_NEXT_USER_CHALLENGE: - if (action.payload !== undefined) { - const id = action.payload.id - const updatedList = [...state.userChallengeList] - const findIndex = updatedList.findIndex( - challenge => challenge.id === id - ) - updatedList[findIndex] = action.payload - if (typeof updatedList[findIndex + 1] !== 'undefined') { - updatedList[findIndex + 1] = { - ...updatedList[findIndex + 1], - state: UserChallengeState.UNLOCKED, - } - } - return { - ...state, - userChallengeList: updatedList, - currentChallenge: null, - } - } else { - return state - } - case SET_CHALLENGE_CONSUMPTION: - if (action.payload !== undefined) { - const id = action.payload.userChallenge.id - const updatedList = [...state.userChallengeList] - const findIndex = updatedList.findIndex( - challenge => challenge.id === id - ) - updatedList[findIndex] = action.payload.userChallenge - return { - ...state, - userChallengeList: updatedList, - currentChallenge: - state.currentChallenge && - state.currentChallenge.id === action.payload.userChallenge.id - ? action.payload.userChallenge - : state.currentChallenge, - currentDataload: action.payload.currentDataload, - } - } else { - return state - } + currentDataload: action.payload.currentDataload, + }) + } default: return state } diff --git a/src/store/chart/chart.actions.ts b/src/store/chart/chart.actions.ts index 67a3932c5ae391210d6615756d0a9b254f70f484..0b65793885c3501cba3f123b5823042a1978eb6c 100644 --- a/src/store/chart/chart.actions.ts +++ b/src/store/chart/chart.actions.ts @@ -1,13 +1,14 @@ import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Datachart } from 'models' +import { defaultAction } from 'store' -export const SET_CURRENT_TIMESTEP = 'SET_CURRENT_TIMESTEP' -export const SET_SELECTED_DATE = 'SET_SELECTED_DATE' -export const SET_CURRENT_INDEX = 'SET_CURRENT_INDEX' export const SET_CURRENT_DATACHART = 'SET_CURRENT_DATACHART' export const SET_CURRENT_DATACHART_INDEX = 'SET_CURRENT_DATACHART_INDEX' +export const SET_CURRENT_INDEX = 'SET_CURRENT_INDEX' +export const SET_CURRENT_TIMESTEP = 'SET_CURRENT_TIMESTEP' export const SET_LOADING = 'SET_LOADING' +export const SET_SELECTED_DATE = 'SET_SELECTED_DATE' interface SetSelectedDate { type: typeof SET_SELECTED_DATE @@ -39,29 +40,21 @@ interface SetLoading { payload?: boolean } -export type ChartActionTypes = - | SetSelectedDate - | SetCurrentTimeStep - | SetCurrentIndex - | SetCurrentDataChart - | SetCurrentDataChartIndex - | SetLoading - -export function setSelectedDate(date: DateTime): ChartActionTypes { +export function setSelectedDate(date: DateTime): SetSelectedDate { return { type: SET_SELECTED_DATE, payload: date, } } -export function setCurrentTimeStep(timeStep: TimeStep): ChartActionTypes { +export function setCurrentTimeStep(timeStep: TimeStep): SetCurrentTimeStep { return { type: SET_CURRENT_TIMESTEP, payload: timeStep, } } -export function setCurrentIndex(currentIndex: number): ChartActionTypes { +export function setCurrentIndex(currentIndex: number): SetCurrentIndex { return { type: SET_CURRENT_INDEX, payload: currentIndex, @@ -70,7 +63,7 @@ export function setCurrentIndex(currentIndex: number): ChartActionTypes { export function setCurrentDatachart( currentDatachart: Datachart -): ChartActionTypes { +): SetCurrentDataChart { return { type: SET_CURRENT_DATACHART, payload: currentDatachart, @@ -79,16 +72,25 @@ export function setCurrentDatachart( export function setCurrentDatachartIndex( currentDatachartIndex: number -): ChartActionTypes { +): SetCurrentDataChartIndex { return { type: SET_CURRENT_DATACHART_INDEX, payload: currentDatachartIndex, } } -export function setLoading(isLoading: boolean): ChartActionTypes { +export function setLoading(isLoading: boolean): SetLoading { return { type: SET_LOADING, payload: isLoading, } } + +export type ChartActionTypes = + | SetSelectedDate + | SetCurrentTimeStep + | SetCurrentIndex + | SetCurrentDataChart + | SetCurrentDataChartIndex + | SetLoading + | typeof defaultAction diff --git a/src/store/chart/chart.reducer.spec.ts b/src/store/chart/chart.reducer.spec.ts index 70b01f7e6210423d13e9714b61c3238bd14297f1..1f167acb432198679abfce62e431d36101c2e147 100644 --- a/src/store/chart/chart.reducer.spec.ts +++ b/src/store/chart/chart.reducer.spec.ts @@ -1,5 +1,6 @@ import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' +import { defaultAction } from 'store' import { graphData } from '../../../tests/__mocks__/chartData.mock' import { mockInitialChartState } from '../../../tests/__mocks__/store' import { @@ -14,122 +15,124 @@ import { chartReducer } from './chart.reducer' describe('chart reducer', () => { it('should return the initial state', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const result = chartReducer(undefined as any, { type: 'default' }) - expect(result).toEqual(mockInitialChartState) + const state = chartReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockInitialChartState) }) - it('should handle SET_SELECTED_DATE with payload', () => { - const mockDate = DateTime.fromISO('2021-01-01T00:00:00.000Z', { - zone: 'utc', - }) - const result = chartReducer(mockInitialChartState, { - type: SET_SELECTED_DATE, - payload: mockDate, - }) - expect(result).toEqual({ - ...mockInitialChartState, - selectedDate: mockDate, - }) - }) - - it('should handle SET_SELECTED_DATE without payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_SELECTED_DATE, - }) - expect(result).toEqual(mockInitialChartState) - }) - - it('should handle SET_CURRENT_TIMESTEP with payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_TIMESTEP, - payload: TimeStep.MONTH, - }) - expect(result).toEqual({ - ...mockInitialChartState, - currentTimeStep: TimeStep.MONTH, - }) - }) - - it('should handle SET_CURRENT_TIMESTEP without payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_TIMESTEP, - }) - expect(result).toEqual(mockInitialChartState) - }) - - it('should handle SET_CURRENT_INDEX with payload', () => { - const mockDate = DateTime.fromISO('2021-01-01T00:00:00.000Z', { - zone: 'utc', - }) - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_INDEX, - payload: mockDate, - }) - expect(result).toEqual({ - ...mockInitialChartState, - currentIndex: mockDate, + describe('SET_SELECTED_DATE', () => { + it('should handle SET_SELECTED_DATE with payload', () => { + const mockDate = DateTime.fromISO('2021-01-01T00:00:00.000Z', { + zone: 'utc', + }) + const state = chartReducer(mockInitialChartState, { + type: SET_SELECTED_DATE, + payload: mockDate, + }) + expect(state).toEqual({ + ...mockInitialChartState, + selectedDate: mockDate, + }) + }) + it('should handle SET_SELECTED_DATE without payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_SELECTED_DATE, + }) + expect(state).toEqual(mockInitialChartState) }) }) - it('should handle SET_CURRENT_INDEX without payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_INDEX, + describe('SET_CURRENT_TIMESTEP', () => { + it('should handle SET_CURRENT_TIMESTEP with payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_TIMESTEP, + payload: TimeStep.MONTH, + }) + expect(state).toEqual({ + ...mockInitialChartState, + currentTimeStep: TimeStep.MONTH, + }) + }) + it('should handle SET_CURRENT_TIMESTEP without payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_TIMESTEP, + }) + expect(state).toEqual(mockInitialChartState) }) - expect(result).toEqual(mockInitialChartState) }) - it('should handle SET_CURRENT_DATACHART with payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_DATACHART, - payload: graphData, - }) - expect(result).toEqual({ - ...mockInitialChartState, - currentDatachart: graphData, + describe('SET_CURRENT_INDEX', () => { + it('should handle SET_CURRENT_INDEX with payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_INDEX, + payload: 1, + }) + expect(state).toEqual({ + ...mockInitialChartState, + currentIndex: 1, + }) + }) + it('should handle SET_CURRENT_INDEX without payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_INDEX, + }) + expect(state).toEqual(mockInitialChartState) }) }) - it('should handle SET_CURRENT_DATACHART without payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_DATACHART, + describe('SET_CURRENT_DATACHART', () => { + it('should handle SET_CURRENT_DATACHART with payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_DATACHART, + payload: graphData, + }) + expect(state).toEqual({ + ...mockInitialChartState, + currentDatachart: graphData, + }) + }) + it('should handle SET_CURRENT_DATACHART without payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_DATACHART, + }) + expect(state).toEqual(mockInitialChartState) }) - expect(result).toEqual(mockInitialChartState) }) - it('should handle SET_CURRENT_DATACHART_INDEX with payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_DATACHART_INDEX, - payload: 1, - }) - expect(result).toEqual({ - ...mockInitialChartState, - currentDatachartIndex: 1, - }) - }) - - it('should handle SET_CURRENT_DATACHART_INDEX without payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_CURRENT_DATACHART_INDEX, - }) - expect(result).toEqual(mockInitialChartState) - }) - - it('should handle SET_LOADING with payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_LOADING, - payload: false, - }) - expect(result).toEqual({ - ...mockInitialChartState, - loading: false, + describe('SET_CURRENT_DATACHART_INDEX', () => { + it('should handle SET_CURRENT_DATACHART_INDEX with payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_DATACHART_INDEX, + payload: 1, + }) + expect(state).toEqual({ + ...mockInitialChartState, + currentDatachartIndex: 1, + }) + }) + it('should handle SET_CURRENT_DATACHART_INDEX without payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_CURRENT_DATACHART_INDEX, + }) + expect(state).toEqual(mockInitialChartState) }) }) - it('should handle SET_LOADING without payload', () => { - const result = chartReducer(mockInitialChartState, { - type: SET_LOADING, + describe('SET_LOADING', () => { + it('should handle SET_LOADING with payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_LOADING, + payload: false, + }) + expect(state).toEqual({ + ...mockInitialChartState, + loading: false, + }) + }) + it('should handle SET_LOADING without payload', () => { + const state = chartReducer(mockInitialChartState, { + type: SET_LOADING, + }) + expect(state).toEqual(mockInitialChartState) }) - expect(result).toEqual(mockInitialChartState) }) }) diff --git a/src/store/chart/chart.reducer.ts b/src/store/chart/chart.reducer.ts index 8b08d1097edb46aa056c1db1b314e552fe4a4848..9d79d2593a8b1830c45a3d16954b74313d4cde31 100644 --- a/src/store/chart/chart.reducer.ts +++ b/src/store/chart/chart.reducer.ts @@ -23,53 +23,36 @@ const initialState: ChartState = { loading: true, } -export const chartReducer: Reducer<ChartState> = ( +export const chartReducer: Reducer<ChartState, ChartActionTypes> = ( state = initialState, - action: ChartActionTypes -): ChartState => { + action +) => { + if (action.payload == undefined) return state + + const updateState = (updates: Partial<ChartState>): ChartState => ({ + ...state, + ...updates, + }) + switch (action.type) { case SET_SELECTED_DATE: - return action.payload != undefined - ? { - ...state, - selectedDate: action.payload, - } - : state + return updateState({ selectedDate: action.payload }) + case SET_CURRENT_TIMESTEP: - return action.payload != undefined - ? { - ...state, - currentTimeStep: action.payload, - } - : state + return updateState({ currentTimeStep: action.payload }) + case SET_CURRENT_INDEX: - return action.payload != undefined - ? { - ...state, - currentIndex: action.payload, - } - : state + return updateState({ currentIndex: action.payload }) + case SET_CURRENT_DATACHART: - return action.payload != undefined - ? { - ...state, - currentDatachart: action.payload, - } - : state + return updateState({ currentDatachart: action.payload }) + case SET_CURRENT_DATACHART_INDEX: - return action.payload != undefined - ? { - ...state, - currentDatachartIndex: action.payload, - } - : state + return updateState({ currentDatachartIndex: action.payload }) + case SET_LOADING: - return action.payload != undefined - ? { - ...state, - loading: action.payload, - } - : state + return updateState({ loading: action.payload }) + default: return state } diff --git a/src/store/global/global.action.spec.ts b/src/store/global/global.action.spec.ts index ed48220aa3becce8f61d8dfa1dff8b07a5df0b52..2a75a86c38b9fc84f2a84591df9c2d6e738ac9a7 100644 --- a/src/store/global/global.action.spec.ts +++ b/src/store/global/global.action.spec.ts @@ -4,6 +4,7 @@ import { mockInitialGlobalState } from '../../../tests/__mocks__/store' import { changeScreenType, CHANGE_SCREEN_TYPE, + GlobalActionTypes, setCustomPopup, setFluidStatus, SET_CUSTOM_POPUP, @@ -21,7 +22,7 @@ import { describe('global actions', () => { it('should create an action to change screenType', () => { const screenType = ScreenType.DESKTOP - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: CHANGE_SCREEN_TYPE, payload: screenType, } @@ -30,7 +31,7 @@ describe('global actions', () => { it('should create an action to toggle challenge exploration notification', () => { const notification = true - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION, payload: notification, } @@ -41,7 +42,7 @@ describe('global actions', () => { it('should create an action to toggle challenge action notification', () => { const notification = true - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: TOGGLE_CHALLENGE_ACTION_NOTIFICATION, payload: notification, } @@ -52,7 +53,7 @@ describe('global actions', () => { it('should create an action to toggle challenge duel notification', () => { const notification = true - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: TOGGLE_CHALLENGE_DUEL_NOTIFICATION, payload: notification, } @@ -63,7 +64,7 @@ describe('global actions', () => { it('should create an action to toggle analysis notification', () => { const notification = true - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: TOGGLE_ANALYSIS_NOTIFICATION, payload: notification, } @@ -72,7 +73,7 @@ describe('global actions', () => { it('should create an action to set fluid status', () => { const fluidStatus = mockInitialGlobalState.fluidStatus - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: SET_FLUID_STATUS, payload: fluidStatus, } @@ -81,7 +82,7 @@ describe('global actions', () => { it('should set customPopup', () => { const payload = mockCustomPopup - const expectedAction = { + const expectedAction: GlobalActionTypes = { type: SET_CUSTOM_POPUP, payload, } diff --git a/src/store/global/global.actions.ts b/src/store/global/global.actions.ts index 575d97ee5ce0f2093aa4cb93b20b29a75e71f46f..5abc17651f59e95b3e2fd815c80a18d934e6cdb6 100644 --- a/src/store/global/global.actions.ts +++ b/src/store/global/global.actions.ts @@ -5,6 +5,7 @@ import { CustomPopup } from 'models/customPopup.model' import { PartnersInfo } from 'models/partnersInfo.model' import { Notes } from 'models/releaseNotes.model' import { SgeStore } from 'models/sgeStore.model' +import { defaultAction } from 'store' export const CHANGE_SCREEN_TYPE = 'CHANGE_SCREEN_TYPE' export const SET_CUSTOM_POPUP = 'SET_CUSTOM_POPUP' @@ -33,22 +34,27 @@ interface SetPartnersInfo { payload?: PartnersInfo } -interface ToogleChallengeExplorationNotification { +interface SetPartnersInfo { + type: typeof SET_PARTNERS_INFO + payload?: PartnersInfo +} + +interface ToggleChallengeExplorationNotification { type: typeof TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION payload?: boolean } -interface ToogleChallengeActionNotification { +interface ToggleChallengeActionNotification { type: typeof TOGGLE_CHALLENGE_ACTION_NOTIFICATION payload?: boolean } -interface ToogleChallengeDuelNotification { +interface ToggleChallengeDuelNotification { type: typeof TOGGLE_CHALLENGE_DUEL_NOTIFICATION payload?: boolean } -interface ToogleAnalysisNotification { +interface ToggleAnalysisNotification { type: typeof TOGGLE_ANALYSIS_NOTIFICATION payload?: boolean } @@ -81,27 +87,12 @@ interface SetShouldRefreshConsent { type: typeof SET_SHOULD_REFRESH_CONSENT payload?: boolean } -export interface UpdateSGEConnect { +interface UpdateSGEConnect { type: typeof UPDATE_SGE_CONNECT payload?: SgeStore } -export type GlobalActionTypes = - | ChangeScreenType - | ToogleChallengeExplorationNotification - | ToogleChallengeActionNotification - | ToogleChallengeDuelNotification - | ToogleAnalysisNotification - | SetFluidStatus - | UpdatedFluidConnection - | UpdateTermValidation - | ShowReleaseNotes - | SetCustomPopup - | SetShouldRefreshConsent - | UpdateSGEConnect - | SetPartnersInfo - -export function changeScreenType(screenType: ScreenType): GlobalActionTypes { +export function changeScreenType(screenType: ScreenType): ChangeScreenType { return { type: CHANGE_SCREEN_TYPE, payload: screenType, @@ -112,7 +103,7 @@ export function showReleaseNotes( show: boolean, notes: Notes[], redirectLink?: string -): GlobalActionTypes { +): ShowReleaseNotes { return { type: SHOW_RELEASE_NOTES, payload: { show, notes, redirectLink }, @@ -120,40 +111,42 @@ export function showReleaseNotes( } export function toggleChallengeExplorationNotification( - notif: boolean -): GlobalActionTypes { + notification: boolean +): ToggleChallengeExplorationNotification { return { type: TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION, - payload: notif, + payload: notification, } } export function toggleChallengeActionNotification( - notif: boolean -): GlobalActionTypes { + notification: boolean +): ToggleChallengeActionNotification { return { type: TOGGLE_CHALLENGE_ACTION_NOTIFICATION, - payload: notif, + payload: notification, } } export function toggleChallengeDuelNotification( - notif: boolean -): GlobalActionTypes { + notification: boolean +): ToggleChallengeDuelNotification { return { type: TOGGLE_CHALLENGE_DUEL_NOTIFICATION, - payload: notif, + payload: notification, } } -export function toggleAnalysisNotification(notif: boolean): GlobalActionTypes { +export function toggleAnalysisNotification( + notification: boolean +): ToggleAnalysisNotification { return { type: TOGGLE_ANALYSIS_NOTIFICATION, - payload: notif, + payload: notification, } } -export function setFluidStatus(fluidStatus: FluidStatus[]): GlobalActionTypes { +export function setFluidStatus(fluidStatus: FluidStatus[]): SetFluidStatus { return { type: SET_FLUID_STATUS, payload: fluidStatus, @@ -162,7 +155,7 @@ export function setFluidStatus(fluidStatus: FluidStatus[]): GlobalActionTypes { export function updatedFluidConnection( fluidType: FluidType, fluidConnection: FluidConnection -): GlobalActionTypes { +): UpdatedFluidConnection { return { type: UPDATE_FLUID_CONNECTION, payload: { fluidType, fluidConnection }, @@ -171,23 +164,21 @@ export function updatedFluidConnection( export function updateTermValidation( termsStatus: TermsStatus -): GlobalActionTypes { +): UpdateTermValidation { return { type: UPDATE_TERMS_VALIDATION, payload: termsStatus, } } -export function setPartnersInfo(partnersInfo: PartnersInfo): GlobalActionTypes { +export function setPartnersInfo(partnersInfo: PartnersInfo): SetPartnersInfo { return { type: SET_PARTNERS_INFO, payload: partnersInfo, } } -export function setCustomPopup( - customPopupModal: CustomPopup -): GlobalActionTypes { +export function setCustomPopup(customPopupModal: CustomPopup): SetCustomPopup { return { type: SET_CUSTOM_POPUP, payload: customPopupModal, @@ -196,16 +187,32 @@ export function setCustomPopup( export function setShouldRefreshConsent( shouldRefreshConsent: boolean -): GlobalActionTypes { +): SetShouldRefreshConsent { return { type: SET_SHOULD_REFRESH_CONSENT, payload: shouldRefreshConsent, } } -export function updateSgeStore(sgeStore: SgeStore): GlobalActionTypes { +export function updateSgeStore(sgeStore: SgeStore): UpdateSGEConnect { return { type: UPDATE_SGE_CONNECT, payload: sgeStore, } } + +export type GlobalActionTypes = + | ChangeScreenType + | ToggleChallengeExplorationNotification + | ToggleChallengeActionNotification + | ToggleChallengeDuelNotification + | ToggleAnalysisNotification + | SetFluidStatus + | UpdatedFluidConnection + | UpdateTermValidation + | ShowReleaseNotes + | SetCustomPopup + | SetShouldRefreshConsent + | UpdateSGEConnect + | SetPartnersInfo + | typeof defaultAction diff --git a/src/store/global/global.reducer.spec.ts b/src/store/global/global.reducer.spec.ts index b645aae9ec3b6dcd7eeefa54dc9cb3c78ab40bd4..accdd07d15c231ed76387f74970504f0c71447cb 100644 --- a/src/store/global/global.reducer.spec.ts +++ b/src/store/global/global.reducer.spec.ts @@ -3,6 +3,7 @@ import { FluidSlugType } from 'enum/fluidSlug.enum' import { ScreenType } from 'enum/screen.enum' import { DateTime } from 'luxon' import { FluidStatus } from 'models' +import { defaultAction } from 'store' import { accountsData } from '../../../tests/__mocks__/accountsData.mock' import { mockCustomPopup } from '../../../tests/__mocks__/customPopup.mock' import { konnectorsData } from '../../../tests/__mocks__/konnectorsData.mock' @@ -19,112 +20,109 @@ import { } from './global.actions' import { globalReducer } from './global.reducer' -const mockDataDates: (DateTime | null)[] = [ - DateTime.local().setZone('utc', { - keepLocalTime: true, - }), - DateTime.local().setZone('utc', { - keepLocalTime: true, - }), - DateTime.local().setZone('utc', { - keepLocalTime: true, - }), -] +const nowUtc = DateTime.local().setZone('utc', { keepLocalTime: true }) +const mockDataDates = Array(3).fill(nowUtc) describe('global reducer', () => { it('should return the initial state', () => { - const result = globalReducer(undefined as any, { type: 'default' }) - expect(result).toEqual(mockInitialGlobalState) + const state = globalReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockInitialGlobalState) }) - it('should handle CHANGE_SCREEN_TYPE with payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: CHANGE_SCREEN_TYPE, - payload: ScreenType.DESKTOP, + describe('CHANGE_SCREEN_TYPE', () => { + it('should handle CHANGE_SCREEN_TYPE with payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: CHANGE_SCREEN_TYPE, + payload: ScreenType.DESKTOP, + }) + expect(state).toEqual({ + ...mockInitialGlobalState, + screenType: ScreenType.DESKTOP, + }) + }) + it('should handle CHANGE_SCREEN_TYPE without payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: CHANGE_SCREEN_TYPE, + }) + expect(state).toEqual(mockInitialGlobalState) }) - expect(result).toEqual({ - ...mockInitialGlobalState, - screenType: ScreenType.DESKTOP, - }) - }) - - it('should handle CHANGE_SCREEN_TYPE without payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: CHANGE_SCREEN_TYPE, - }) - expect(result).toEqual(mockInitialGlobalState) }) - it('should handle TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION with payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION, - payload: true, - }) - expect(result).toEqual({ - ...mockInitialGlobalState, - challengeExplorationNotification: true, + describe('TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION', () => { + it('should handle TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION with payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION, + payload: true, + }) + expect(state).toEqual({ + ...mockInitialGlobalState, + challengeExplorationNotification: true, + }) }) - }) - it('should handle TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION without payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION, + it('should handle TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION without payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION, + }) + expect(state).toEqual(mockInitialGlobalState) }) - expect(result).toEqual(mockInitialGlobalState) }) - it('should handle TOGGLE_CHALLENGE_ACTION_NOTIFICATION with payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_CHALLENGE_ACTION_NOTIFICATION, - payload: true, - }) - expect(result).toEqual({ - ...mockInitialGlobalState, - challengeActionNotification: true, + describe('TOGGLE_CHALLENGE_ACTION_NOTIFICATION', () => { + it('should handle TOGGLE_CHALLENGE_ACTION_NOTIFICATION with payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_CHALLENGE_ACTION_NOTIFICATION, + payload: true, + }) + expect(state).toEqual({ + ...mockInitialGlobalState, + challengeActionNotification: true, + }) + }) + it('should handle TOGGLE_CHALLENGE_ACTION_NOTIFICATION without payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_CHALLENGE_ACTION_NOTIFICATION, + }) + expect(state).toEqual(mockInitialGlobalState) }) }) - it('should handle TOGGLE_CHALLENGE_ACTION_NOTIFICATION without payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_CHALLENGE_ACTION_NOTIFICATION, - }) - expect(result).toEqual(mockInitialGlobalState) - }) - - it('should handle TOGGLE_CHALLENGE_DUEL_NOTIFICATION with payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_CHALLENGE_DUEL_NOTIFICATION, - payload: true, - }) - expect(result).toEqual({ - ...mockInitialGlobalState, - challengeDuelNotification: true, - }) - }) - - it('should handle TOGGLE_CHALLENGE_DUEL_NOTIFICATION without payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_CHALLENGE_DUEL_NOTIFICATION, - }) - expect(result).toEqual(mockInitialGlobalState) - }) - - it('should handle TOGGLE_ANALYSIS_NOTIFICATION with payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_ANALYSIS_NOTIFICATION, - payload: true, - }) - expect(result).toEqual({ - ...mockInitialGlobalState, - analysisNotification: true, + describe('TOGGLE_CHALLENGE_DUEL_NOTIFICATION', () => { + it('should handle TOGGLE_CHALLENGE_DUEL_NOTIFICATION with payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_CHALLENGE_DUEL_NOTIFICATION, + payload: true, + }) + expect(state).toEqual({ + ...mockInitialGlobalState, + challengeDuelNotification: true, + }) + }) + it('should handle TOGGLE_CHALLENGE_DUEL_NOTIFICATION without payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_CHALLENGE_DUEL_NOTIFICATION, + }) + expect(state).toEqual(mockInitialGlobalState) }) }) - it('should handle TOGGLE_ANALYSIS_NOTIFICATION without payload', () => { - const result = globalReducer(mockInitialGlobalState, { - type: TOGGLE_ANALYSIS_NOTIFICATION, + describe('TOGGLE_ANALYSIS_NOTIFICATION', () => { + it('should handle TOGGLE_ANALYSIS_NOTIFICATION with payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_ANALYSIS_NOTIFICATION, + payload: true, + }) + expect(state).toEqual({ + ...mockInitialGlobalState, + analysisNotification: true, + }) + }) + it('should handle TOGGLE_ANALYSIS_NOTIFICATION without payload', () => { + const state = globalReducer(mockInitialGlobalState, { + type: TOGGLE_ANALYSIS_NOTIFICATION, + }) + expect(state).toEqual(mockInitialGlobalState) }) - expect(result).toEqual(mockInitialGlobalState) }) it('should handle SET_FLUID_STATUS with payload', () => { @@ -197,11 +195,11 @@ describe('global reducer', () => { }, }, ] - const result = globalReducer(mockInitialGlobalState, { + const state = globalReducer(mockInitialGlobalState, { type: SET_FLUID_STATUS, payload: fluidStatus, }) - expect(result).toEqual({ + expect(state).toEqual({ ...mockInitialGlobalState, fluidStatus: fluidStatus, fluidTypes: [FluidType.ELECTRICITY, FluidType.WATER], @@ -209,14 +207,14 @@ describe('global reducer', () => { }) it('should handle SET_FLUID_STATUS without payload', () => { - const result = globalReducer(mockInitialGlobalState, { + const state = globalReducer(mockInitialGlobalState, { type: SET_FLUID_STATUS, }) - expect(result).toEqual(mockInitialGlobalState) + expect(state).toEqual(mockInitialGlobalState) }) it('should handle SET_CUSTOM_POPUP with payload', () => { - const result = { + const state = { ...mockInitialGlobalState, customPopupModal: mockCustomPopup, } @@ -225,6 +223,6 @@ describe('global reducer', () => { type: SET_CUSTOM_POPUP, payload: mockCustomPopup, }).customPopupModal - ).toBe(result.customPopupModal) + ).toBe(state.customPopupModal) }) }) diff --git a/src/store/global/global.reducer.ts b/src/store/global/global.reducer.ts index 8abedaec8353adbc9095304edf9ce4e032d3c518..39beff291511099d4c5da0ab6bdcc18576fed8c2 100644 --- a/src/store/global/global.reducer.ts +++ b/src/store/global/global.reducer.ts @@ -1,3 +1,4 @@ +/* eslint-disable camelcase */ import { FluidState, FluidType } from 'enum/fluid.enum' import { FluidSlugType } from 'enum/fluidSlug.enum' import { ScreenType } from 'enum/screen.enum' @@ -152,110 +153,68 @@ const getFluidTypesFromStatus = (fluidStatus: FluidStatus[]): FluidType[] => { return fluidTypes.sort() } -export const globalReducer: Reducer<GlobalState> = ( +export const globalReducer: Reducer<GlobalState, GlobalActionTypes> = ( state = initialState, - action: GlobalActionTypes -): GlobalState => { + action +) => { + if (action.payload == undefined) return state + + const updateState = (updates: Partial<GlobalState>): GlobalState => ({ + ...state, + ...updates, + }) + switch (action.type) { case CHANGE_SCREEN_TYPE: - return action.payload != undefined - ? { - ...state, - screenType: action.payload, - } - : state + return updateState({ screenType: action.payload }) + case TOGGLE_CHALLENGE_EXPLORATION_NOTIFICATION: - return action.payload != undefined - ? { - ...state, - challengeExplorationNotification: action.payload, - } - : state + return updateState({ challengeExplorationNotification: action.payload }) + case TOGGLE_CHALLENGE_ACTION_NOTIFICATION: - return action.payload != undefined - ? { - ...state, - challengeActionNotification: action.payload, - } - : state + return updateState({ challengeActionNotification: action.payload }) + case TOGGLE_CHALLENGE_DUEL_NOTIFICATION: - return action.payload != undefined - ? { - ...state, - challengeDuelNotification: action.payload, - } - : state + return updateState({ challengeDuelNotification: action.payload }) + case TOGGLE_ANALYSIS_NOTIFICATION: - return action.payload != undefined - ? { - ...state, - analysisNotification: action.payload, - } - : state + return updateState({ analysisNotification: action.payload }) + case SET_FLUID_STATUS: - return action.payload != undefined - ? { - ...state, - fluidStatus: action.payload, - fluidTypes: getFluidTypesFromStatus(action.payload), - } - : state + return updateState({ + fluidStatus: action.payload, + fluidTypes: getFluidTypesFromStatus(action.payload), + }) + case UPDATE_TERMS_VALIDATION: - return action.payload != undefined - ? { - ...state, - termsStatus: action.payload, - } - : state + return updateState({ termsStatus: action.payload }) + case SHOW_RELEASE_NOTES: - return action.payload != undefined - ? { - ...state, - releaseNotes: action.payload, - } - : state + return updateState({ releaseNotes: action.payload }) + case SET_PARTNERS_INFO: - return action.payload != undefined - ? { - ...state, - partnersInfo: action.payload, - } - : state + return updateState({ partnersInfo: action.payload }) + case SET_CUSTOM_POPUP: - return { - ...state, - customPopupModal: action.payload, - } + return updateState({ customPopupModal: action.payload }) + case SET_SHOULD_REFRESH_CONSENT: - return action.payload != undefined - ? { - ...state, - shouldRefreshConsent: action.payload, - } - : state + return updateState({ shouldRefreshConsent: action.payload }) + case UPDATE_FLUID_CONNECTION: - if (action.payload !== undefined) { - const updatedFluidStatus = [...state.fluidStatus] - const fluidType: FluidType = action.payload.fluidType - const findIndex = state.fluidStatus.findIndex( - fluid => fluid.fluidType === fluidType - ) - updatedFluidStatus[findIndex].connection = - action.payload.fluidConnection - return { - ...state, - fluidStatus: updatedFluidStatus, - } - } else { - return state + const updatedFluidStatus = [...state.fluidStatus] + const fluidType: FluidType = action.payload.fluidType + const findIndex = state.fluidStatus.findIndex( + fluid => fluid.fluidType === fluidType + ) + updatedFluidStatus[findIndex].connection = action.payload.fluidConnection + return { + ...state, + fluidStatus: updatedFluidStatus, } case UPDATE_SGE_CONNECT: - if (action.payload != undefined) - return { - ...state, - sgeConnect: action.payload, - } - return state + return updateState({ sgeConnect: action.payload }) + default: return state } diff --git a/src/store/index.ts b/src/store/index.ts index 0b17fa1f0a0d9b968b763a1fb5fd3071db83a108..42611fc1fa84555572335a6a4d16893a273c4280 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -20,30 +20,39 @@ import { composeWithDevTools } from 'redux-devtools-extension' import thunkMiddleware from 'redux-thunk' import { globalReducer } from 'store/global/global.reducer' import { modalReducer } from 'store/modal/modal.reducer' +import { ChallengeActionTypes } from './challenge/challenge.actions' import { challengeReducer } from './challenge/challenge.reducer' +import { ChartActionTypes } from './chart/chart.actions' import { chartReducer } from './chart/chart.reducer' +import { GlobalActionTypes } from './global/global.actions' +import { ModalActionTypes } from './modal/modal.actions' +import { ProfileActionTypes } from './profile/profile.actions' import { profileReducer } from './profile/profile.reducer' +import { ProfileEcogestureActionTypes } from './profileEcogesture/profileEcogesture.actions' import { profileEcogestureReducer } from './profileEcogesture/profileEcogesture.reducer' +import { ProfileTypeActionTypes } from './profileType/profileType.actions' import { profileTypeReducer } from './profileType/profileType.reducer' export interface EcolyoState { + challenge: ChallengeState + chart: ChartState global: GlobalState + modal: ModalState profile: Profile - profileType: ProfileType profileEcogesture: ProfileEcogesture - chart: ChartState - modal: ModalState - challenge: ChallengeState + profileType: ProfileType } -export const ecolyoReducer = combineReducers({ +export const defaultAction = { type: null, payload: undefined } + +const ecolyoReducer = combineReducers({ + challenge: challengeReducer, + chart: chartReducer, global: globalReducer, + modal: modalReducer, profile: profileReducer, - profileType: profileTypeReducer, profileEcogesture: profileEcogestureReducer, - chart: chartReducer, - modal: modalReducer, - challenge: challengeReducer, + profileType: profileTypeReducer, }) export interface AppStore { @@ -51,16 +60,22 @@ export interface AppStore { cozy: unknown } +export type AppActionsTypes = + | ChallengeActionTypes + | ChartActionTypes + | GlobalActionTypes + | ModalActionTypes + | ProfileActionTypes + | ProfileEcogestureActionTypes + | ProfileTypeActionTypes + const sentryReduxEnhancer = Sentry.createReduxEnhancer({}) -const configureStore = ( - client: Client, - persistedState: any -): Store<AppStore> => { +const configureStore = (client: Client, persistedState: any) => { const middlewares = [thunkMiddleware.withExtraArgument({ client })] const composeEnhancers = composeWithDevTools({ trace: true }) || compose - const store: Store<AppStore> = createStore( + const store: Store<AppStore, AppActionsTypes> = createStore( combineReducers({ ecolyo: ecolyoReducer, cozy: client.reducer(), diff --git a/src/store/modal/modal.action.spec.ts b/src/store/modal/modal.action.spec.ts index 2d5ab156c903db2a5152f53b29efa6fc621fd9d4..7a4fec68aed008ecb60f8e6eef099d032f6ac48c 100644 --- a/src/store/modal/modal.action.spec.ts +++ b/src/store/modal/modal.action.spec.ts @@ -1,15 +1,12 @@ -import { - updateModalIsFeedbacksOpen, - UPDATE_MODAL_ISFEEDBACKSOPEN, -} from './modal.actions' +import { openFeedbackModal, OPEN_FEEDBACK_MODAL } from './modal.actions' describe('modal actions', () => { it('should create an action to update isFeedbacksOpen', () => { const isOpen = true const expectedAction = { - type: UPDATE_MODAL_ISFEEDBACKSOPEN, + type: OPEN_FEEDBACK_MODAL, payload: isOpen, } - expect(updateModalIsFeedbacksOpen(isOpen)).toEqual(expectedAction) + expect(openFeedbackModal(isOpen)).toEqual(expectedAction) }) }) diff --git a/src/store/modal/modal.actions.ts b/src/store/modal/modal.actions.ts index 8ece8265e28c2b80163354f41e17325d0edb5ae6..fe1ea172b7b15172883d3ff6294aa38d60a69547 100644 --- a/src/store/modal/modal.actions.ts +++ b/src/store/modal/modal.actions.ts @@ -1,37 +1,39 @@ -export const UPDATE_MODAL_ISFEEDBACKSOPEN = 'UPDATE_MODAL_ISFEEDBACKSOPEN' -export const OPEN_PARTNERS_MODAL = 'SET_PARTNERS_ISSUE' +import { defaultAction } from 'store' -interface UpdateModalFeedbacks { - type: typeof UPDATE_MODAL_ISFEEDBACKSOPEN +export const OPEN_PARTNERS_MODAL = 'OPEN_PARTNERS_ISSUE' +export const OPEN_FEEDBACK_MODAL = 'OPEN_FEEDBACK_MODAL' + +interface OpenFeedbackModal { + type: typeof OPEN_FEEDBACK_MODAL payload?: boolean } interface OpenPartnersModal { type: typeof OPEN_PARTNERS_MODAL payload?: { - enedis: boolean egl: boolean + enedis: boolean grdf: boolean } } export type ModalActionTypes = - | UpdateModalFeedbacks + | OpenFeedbackModal | OpenPartnersModal - | { type: null } + | typeof defaultAction -export function updateModalIsFeedbacksOpen(isOpen: boolean): ModalActionTypes { +export function openFeedbackModal(isOpen: boolean): OpenFeedbackModal { return { - type: UPDATE_MODAL_ISFEEDBACKSOPEN, + type: OPEN_FEEDBACK_MODAL, payload: isOpen, } } export function openPartnersModal(openPartnersModal: { - enedis: boolean egl: boolean + enedis: boolean grdf: boolean -}): ModalActionTypes { +}): OpenPartnersModal { return { type: OPEN_PARTNERS_MODAL, payload: openPartnersModal, diff --git a/src/store/modal/modal.reducer.spec.ts b/src/store/modal/modal.reducer.spec.ts index ce4ca149e325dfb7ffd4e0ba4268af4fcf35bd65..b52662c6fd8e473eafc2b65911080e6408289f0d 100644 --- a/src/store/modal/modal.reducer.spec.ts +++ b/src/store/modal/modal.reducer.spec.ts @@ -1,36 +1,31 @@ import { ModalState } from 'models' +import { defaultAction } from 'store' import { mockInitialModalState } from '../../../tests/__mocks__/store' -import { - OPEN_PARTNERS_MODAL, - UPDATE_MODAL_ISFEEDBACKSOPEN, -} from './modal.actions' +import { OPEN_FEEDBACK_MODAL, OPEN_PARTNERS_MODAL } from './modal.actions' import { modalReducer } from './modal.reducer' describe('modal reducer', () => { it('should return the initial state', () => { - const result = modalReducer(undefined, { - type: null, - }) - expect(result).toEqual(mockInitialModalState) + const state = modalReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockInitialModalState) }) - describe('FeedbackOpen', () => { - it('should handle UPDATE_MODAL_ISFEEDBACKSOPEN with payload', () => { - const result = modalReducer(mockInitialModalState, { - type: UPDATE_MODAL_ISFEEDBACKSOPEN, + describe('Feedback Modal', () => { + it('should handle UPDATE_FEEDBACK_MODAL with payload', () => { + const state = modalReducer(mockInitialModalState, { + type: OPEN_FEEDBACK_MODAL, payload: true, }) - expect(result).toEqual({ + expect(state).toEqual({ ...mockInitialModalState, isFeedbacksOpen: true, }) }) - - it('should handle UPDATE_MODAL_ISFEEDBACKSOPEN without payload', () => { - const result = modalReducer(mockInitialModalState, { - type: UPDATE_MODAL_ISFEEDBACKSOPEN, + it('should handle UPDATE_FEEDBACK_MODAL without payload', () => { + const state = modalReducer(mockInitialModalState, { + type: OPEN_FEEDBACK_MODAL, }) - expect(result).toEqual(mockInitialModalState) + expect(state).toEqual(mockInitialModalState) }) }) @@ -41,9 +36,7 @@ describe('modal reducer', () => { grdf: true, } it('should have all partners to false by default', () => { - const result = modalReducer(mockInitialModalState, { - type: null, - }) + const state = modalReducer(mockInitialModalState, { ...defaultAction }) const expectedResult: ModalState = { ...mockInitialModalState, partnersIssueModal: { @@ -52,12 +45,12 @@ describe('modal reducer', () => { grdf: false, }, } - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) it('should handle OPEN_PARTNERS_MODAL to set all partners to true', () => { - const result = modalReducer(mockInitialModalState, { + const state = modalReducer(mockInitialModalState, { type: OPEN_PARTNERS_MODAL, - payload: { egl: true, enedis: true, grdf: true }, + payload: { ...partnersModalAllTrue }, }) const expectedResult: ModalState = { ...mockInitialModalState, @@ -65,10 +58,10 @@ describe('modal reducer', () => { ...partnersModalAllTrue, }, } - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) it('should handle OPEN_PARTNERS_MODAL to set some partners to false', () => { - const result = modalReducer( + const state = modalReducer( { ...mockInitialModalState, partnersIssueModal: { @@ -88,7 +81,7 @@ describe('modal reducer', () => { grdf: false, }, } - expect(result).toEqual(expectedResult) + expect(state).toEqual(expectedResult) }) }) }) diff --git a/src/store/modal/modal.reducer.ts b/src/store/modal/modal.reducer.ts index 9a4052a2707e675357c19ffb614fcc13aa8f9613..10b2a2715e0bc90697838ddeaf5c96ffba415521 100644 --- a/src/store/modal/modal.reducer.ts +++ b/src/store/modal/modal.reducer.ts @@ -2,8 +2,8 @@ import { ModalState } from 'models' import { Reducer } from 'redux' import { ModalActionTypes, + OPEN_FEEDBACK_MODAL, OPEN_PARTNERS_MODAL, - UPDATE_MODAL_ISFEEDBACKSOPEN, } from 'store/modal/modal.actions' const initialState: ModalState = { @@ -19,21 +19,20 @@ export const modalReducer: Reducer<ModalState, ModalActionTypes> = ( state = initialState, action ) => { + if (action.payload == undefined) return state + + const updateState = (updates: Partial<ModalState>): ModalState => ({ + ...state, + ...updates, + }) + switch (action.type) { - case UPDATE_MODAL_ISFEEDBACKSOPEN: - const isOpen = - action.payload != undefined ? action.payload : state.isFeedbacksOpen - return { - ...state, - isFeedbacksOpen: isOpen, - } + case OPEN_FEEDBACK_MODAL: + return updateState({ isFeedbacksOpen: action.payload }) + case OPEN_PARTNERS_MODAL: - return action.payload != undefined - ? { - ...state, - partnersIssueModal: action.payload, - } - : state + return updateState({ partnersIssueModal: action.payload }) + default: return state } diff --git a/src/store/profile/profile.action.spec.ts b/src/store/profile/profile.action.spec.ts index a9d3d73f8fd23a6e0ce8fa0a215e83c937a3df04..bd942e0879fd04363c8bc7c29039108e41ff3589 100644 --- a/src/store/profile/profile.action.spec.ts +++ b/src/store/profile/profile.action.spec.ts @@ -1,8 +1,5 @@ import { profileData } from '../../../tests/__mocks__/profileData.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { updateProfile, UPDATE_PROFILE } from './profile.actions' const mockUpdateProfile = jest.fn() @@ -15,10 +12,9 @@ jest.mock('services/profile.service', () => { }) describe('profile actions', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should create an UPDATE_PROFILE action when profile is updated', async () => { mockUpdateProfile.mockResolvedValueOnce(profileData) diff --git a/src/store/profile/profile.actions.ts b/src/store/profile/profile.actions.ts index c589a65c5620091ecd17cf3797b82d0cfcb63f8b..4d3808f88bd9ad846956f91f837cfc8b9b34e595 100644 --- a/src/store/profile/profile.actions.ts +++ b/src/store/profile/profile.actions.ts @@ -2,34 +2,32 @@ import { Client } from 'cozy-client' import { Profile } from 'models' import { Dispatch } from 'react' import ProfileService from 'services/profile.service' -import { AppStore } from 'store' +import { AppStore, defaultAction } from 'store' export const UPDATE_PROFILE = 'UPDATE_PROFILE' -export const SET_FIRST_CONNECTION = 'SET_FIRST_CONNECTION' export interface UpdateProfile { type: typeof UPDATE_PROFILE payload?: Profile } -export type ProfileActionTypes = UpdateProfile +export type ProfileActionTypes = UpdateProfile | typeof defaultAction -export function updateProfileSuccess(updatedProfile: Profile): UpdateProfile { +function updateProfileSuccess(updatedProfile: Profile): UpdateProfile { return { type: UPDATE_PROFILE, payload: updatedProfile, } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function updateProfile(upd: Partial<Profile>): any { +export function updateProfile(updates: Partial<Profile>): any { return async ( dispatch: Dispatch<UpdateProfile>, getState: () => AppStore, { client }: { client: Client } ) => { const profileService = new ProfileService(client) - const updatedProfile = await profileService.updateProfile(upd) + const updatedProfile = await profileService.updateProfile(updates) if (updatedProfile) { dispatch(updateProfileSuccess(updatedProfile)) } diff --git a/src/store/profile/profile.reducer.spec.ts b/src/store/profile/profile.reducer.spec.ts index b1764154b9433d461d6d649641ace3f36e9154d0..95c22aaef918c56d97060f0a2d8191982e6314d0 100644 --- a/src/store/profile/profile.reducer.spec.ts +++ b/src/store/profile/profile.reducer.spec.ts @@ -1,3 +1,4 @@ +import { defaultAction } from 'store' import { profileData } from '../../../tests/__mocks__/profileData.mock' import { mockInitialProfileState } from '../../../tests/__mocks__/store' import { UPDATE_PROFILE } from './profile.actions' @@ -5,23 +6,22 @@ import { profileReducer } from './profile.reducer' describe('profile reducer', () => { it('should return the initial state', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const result = profileReducer(undefined as any, { type: 'default' }) - expect(result).toEqual(mockInitialProfileState) + const state = profileReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockInitialProfileState) }) it('should handle UPDATE_PROFILE with payload', () => { - const result = profileReducer(mockInitialProfileState, { + const state = profileReducer(mockInitialProfileState, { type: UPDATE_PROFILE, payload: profileData, }) - expect(result).toEqual(profileData) + expect(state).toEqual(profileData) }) it('should handle UPDATE_PROFILE without payload', () => { - const result = profileReducer(mockInitialProfileState, { + const state = profileReducer(mockInitialProfileState, { type: UPDATE_PROFILE, }) - expect(result).toEqual(mockInitialProfileState) + expect(state).toEqual(mockInitialProfileState) }) }) diff --git a/src/store/profile/profile.reducer.ts b/src/store/profile/profile.reducer.ts index 5c3d9433d75c9b740904fe7f2b972d421b497386..498a098cf83fe3e47c0914f67ea51f53f82a60e3 100644 --- a/src/store/profile/profile.reducer.ts +++ b/src/store/profile/profile.reducer.ts @@ -36,10 +36,10 @@ const initialState: Profile = { activateHalfHourDate: DateTime.fromISO('0000-01-01T00:00:00.000Z'), } -export const profileReducer: Reducer<Profile> = ( +export const profileReducer: Reducer<Profile, ProfileActionTypes> = ( state = initialState, - action: ProfileActionTypes -): Profile => { + action +) => { switch (action.type) { case UPDATE_PROFILE: return { diff --git a/src/store/profileEcogesture/profileEcogesture.action.spec.ts b/src/store/profileEcogesture/profileEcogesture.action.spec.ts index 3047ecd4f42e64c8eb6be1c827184382562fb148..ad0f42b7948f74982e2040eb6e39b49b863760bd 100644 --- a/src/store/profileEcogesture/profileEcogesture.action.spec.ts +++ b/src/store/profileEcogesture/profileEcogesture.action.spec.ts @@ -1,11 +1,8 @@ import { mockProfileEcogesture } from '../../../tests/__mocks__/profileEcogesture.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { updateProfileEcogesture, - UPDATE_PROFILEECOGESTURE, + UPDATE_PROFILE_ECOGESTURE, } from './profileEcogesture.actions' const mockUpdateProfileEcogesture = jest.fn() @@ -20,16 +17,15 @@ jest.mock('services/profileEcogesture.service', () => { }) describe('profileEcogesture actions', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) - it('should create an UPDATE_PROFILEECOGESTURE action when ecogestureProfile is updated', async () => { + it('should create an UPDATE_PROFILE_ECOGESTURE action when ecogestureProfile is updated', async () => { mockUpdateProfileEcogesture.mockResolvedValueOnce(mockProfileEcogesture) const expectedActions = [ { - type: UPDATE_PROFILEECOGESTURE, + type: UPDATE_PROFILE_ECOGESTURE, payload: mockProfileEcogesture, }, ] diff --git a/src/store/profileEcogesture/profileEcogesture.actions.ts b/src/store/profileEcogesture/profileEcogesture.actions.ts index 8ffa09f17af88b424984f57a4daaafae76850dc2..77140546584eca81839145ed7e8571534cf4c82c 100644 --- a/src/store/profileEcogesture/profileEcogesture.actions.ts +++ b/src/store/profileEcogesture/profileEcogesture.actions.ts @@ -3,36 +3,40 @@ import { PROFILEECOGESTURE_DOCTYPE } from 'doctypes/com-grandlyon-ecolyo-profile import { ProfileEcogesture } from 'models/profileEcogesture.model' import { Dispatch } from 'react' import ProfileEcogestureService from 'services/profileEcogesture.service' -import { AppStore } from 'store' +import { AppStore, defaultAction } from 'store' -export const UPDATE_PROFILEECOGESTURE = 'UPDATE_PROFILEECOGESTURE' -export const CREATE_NEW_PROFILEECOGESTURE = 'CREATE_NEW_PROFILEECOGESTURE' +// TODO never used ? +export const CREATE_NEW_PROFILE_ECOGESTURE = 'CREATE_NEW_PROFILE_ECOGESTURE' +export const UPDATE_PROFILE_ECOGESTURE = 'UPDATE_PROFILE_ECOGESTURE' export interface UpdateProfileEcogesture { - type: typeof UPDATE_PROFILEECOGESTURE + type: typeof UPDATE_PROFILE_ECOGESTURE payload?: ProfileEcogesture } +// TODO never used ? export interface CreateNewProfileEcogesture { - type: typeof CREATE_NEW_PROFILEECOGESTURE + type: typeof CREATE_NEW_PROFILE_ECOGESTURE payload?: ProfileEcogesture } export type ProfileEcogestureActionTypes = | UpdateProfileEcogesture | CreateNewProfileEcogesture + | typeof defaultAction export function updateProfileEcogestureSuccess( updatedProfileEcogesture: ProfileEcogesture ): UpdateProfileEcogesture { return { - type: UPDATE_PROFILEECOGESTURE, + type: UPDATE_PROFILE_ECOGESTURE, payload: updatedProfileEcogesture, } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function updateProfileEcogesture(upd: Partial<ProfileEcogesture>): any { +export function updateProfileEcogesture( + updates: Partial<ProfileEcogesture> +): any { return async ( dispatch: Dispatch<UpdateProfileEcogesture>, getState: () => AppStore, @@ -40,7 +44,7 @@ export function updateProfileEcogesture(upd: Partial<ProfileEcogesture>): any { ) => { const profileEcogestureService = new ProfileEcogestureService(client) const updatedProfileEcogesture = - await profileEcogestureService.updateProfileEcogesture(upd) + await profileEcogestureService.updateProfileEcogesture(updates) if (updatedProfileEcogesture) { dispatch(updateProfileEcogestureSuccess(updatedProfileEcogesture)) } @@ -48,8 +52,7 @@ export function updateProfileEcogesture(upd: Partial<ProfileEcogesture>): any { } export function newProfileEcogestureEntry( - upd: Partial<ProfileEcogesture> - // eslint-disable-next-line @typescript-eslint/no-explicit-any + updates: Partial<ProfileEcogesture> ): any { return async ( dispatch: Dispatch<UpdateProfileEcogesture>, @@ -58,7 +61,7 @@ export function newProfileEcogestureEntry( ) => { const { data: newProfileEcogesture } = await client.create( PROFILEECOGESTURE_DOCTYPE, - upd + updates ) if (newProfileEcogesture) { dispatch(updateProfileEcogestureSuccess(newProfileEcogesture)) diff --git a/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts b/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts index 8980936c054ac964582ffc91de534c94a6c10b77..1158a9881f3f659e21808483c764c1a324095e8a 100644 --- a/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts +++ b/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts @@ -1,31 +1,29 @@ +import { defaultAction } from 'store' import { mockProfileEcogesture, mockProfileEcogestureUpdated, } from '../../../tests/__mocks__/profileEcogesture.mock' -import { UPDATE_PROFILEECOGESTURE } from './profileEcogesture.actions' +import { UPDATE_PROFILE_ECOGESTURE } from './profileEcogesture.actions' import { profileEcogestureReducer } from './profileEcogesture.reducer' describe('profileEcogesture reducer', () => { it('should return the initial state', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const result = profileEcogestureReducer(undefined as any, { - type: 'default', - }) - expect(result).toEqual(mockProfileEcogesture) + const state = profileEcogestureReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockProfileEcogesture) }) - it('should handle UPDATE_PROFILEECOGESTURE with payload', () => { - const result = profileEcogestureReducer(mockProfileEcogesture, { - type: UPDATE_PROFILEECOGESTURE, + it('should handle UPDATE_PROFILE_ECOGESTURE with payload', () => { + const state = profileEcogestureReducer(mockProfileEcogesture, { + type: UPDATE_PROFILE_ECOGESTURE, payload: mockProfileEcogestureUpdated, }) - expect(result).toEqual(mockProfileEcogestureUpdated) + expect(state).toEqual(mockProfileEcogestureUpdated) }) - it('should handle UPDATE_PROFILEECOGESTURE without payload', () => { - const result = profileEcogestureReducer(mockProfileEcogesture, { - type: UPDATE_PROFILEECOGESTURE, + it('should handle UPDATE_PROFILE_ECOGESTURE without payload', () => { + const state = profileEcogestureReducer(mockProfileEcogesture, { + type: UPDATE_PROFILE_ECOGESTURE, }) - expect(result).toEqual(mockProfileEcogesture) + expect(state).toEqual(mockProfileEcogesture) }) }) diff --git a/src/store/profileEcogesture/profileEcogesture.reducer.ts b/src/store/profileEcogesture/profileEcogesture.reducer.ts index d9ea84e23c6b4186e056fd005d70accc82809381..511c813a06fd8b23eb1a58185a1343762274da53 100644 --- a/src/store/profileEcogesture/profileEcogesture.reducer.ts +++ b/src/store/profileEcogesture/profileEcogesture.reducer.ts @@ -2,9 +2,9 @@ import { IndividualOrCollective, WarmingType } from 'enum/profileType.enum' import { ProfileEcogesture } from 'models/profileEcogesture.model' import { Reducer } from 'redux' import { - CREATE_NEW_PROFILEECOGESTURE, + CREATE_NEW_PROFILE_ECOGESTURE, ProfileEcogestureActionTypes, - UPDATE_PROFILEECOGESTURE, + UPDATE_PROFILE_ECOGESTURE, } from './profileEcogesture.actions' const initialState: ProfileEcogesture = { @@ -14,13 +14,15 @@ const initialState: ProfileEcogesture = { equipments: [], } -export const profileEcogestureReducer: Reducer<ProfileEcogesture> = ( - state = initialState, - action: ProfileEcogestureActionTypes -): ProfileEcogesture => { +export const profileEcogestureReducer: Reducer< + ProfileEcogesture, + ProfileEcogestureActionTypes +> = (state = initialState, action) => { + if (action.payload == undefined) return state + switch (action.type) { - case UPDATE_PROFILEECOGESTURE: - case CREATE_NEW_PROFILEECOGESTURE: + case UPDATE_PROFILE_ECOGESTURE: + case CREATE_NEW_PROFILE_ECOGESTURE: return { ...state, ...action.payload, diff --git a/src/store/profileType/profileType.actions.spec.ts b/src/store/profileType/profileType.actions.spec.ts index 3e0cebf6d2996fc42e411f6dca901cde7e71e795..dec9b8345c6ab2e56ecb080238b010d15bb12069 100644 --- a/src/store/profileType/profileType.actions.spec.ts +++ b/src/store/profileType/profileType.actions.spec.ts @@ -1,8 +1,5 @@ import { profileTypeData } from '../../../tests/__mocks__/profileType.mock' -import { - createMockStore, - mockInitialEcolyoState, -} from '../../../tests/__mocks__/store' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { updateProfileType, UPDATE_PROFILETYPE } from './profileType.actions' const mockUpdateProfileType = jest.fn() @@ -15,10 +12,9 @@ jest.mock('services/profileTypeEntity.service', () => { }) describe('profileType actions', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let store: any + const store = createMockEcolyoStore() beforeEach(() => { - store = createMockStore(mockInitialEcolyoState) + store.clearActions() }) it('should create an UPDATE_PROFILETYPE action when profileType is updated', async () => { mockUpdateProfileType.mockResolvedValueOnce(profileTypeData) diff --git a/src/store/profileType/profileType.actions.ts b/src/store/profileType/profileType.actions.ts index 9939d9acf35e8bf414a5a5409bbff905037e611b..25c43810920ec723e4a7adeb3ea7d6b6c053cc7b 100644 --- a/src/store/profileType/profileType.actions.ts +++ b/src/store/profileType/profileType.actions.ts @@ -3,7 +3,7 @@ import { PROFILETYPE_DOCTYPE } from 'doctypes' import { ProfileType } from 'models' import { Dispatch } from 'react' import ProfileTypeEntityService from 'services/profileTypeEntity.service' -import { AppStore } from 'store' +import { AppStore, defaultAction } from 'store' export const UPDATE_PROFILETYPE = 'UPDATE_PROFILETYPE' export const CREATE_NEW_PROFILETYPE = 'CREATE_NEW_PROFILETYPE' @@ -18,7 +18,10 @@ export interface CreateNewProfileType { payload?: ProfileType } -export type ProfileTypeActionTypes = UpdateProfileType | CreateNewProfileType +export type ProfileTypeActionTypes = + | UpdateProfileType + | CreateNewProfileType + | typeof defaultAction export function updateProfileTypeSuccess( updatedProfileType: ProfileType @@ -29,16 +32,15 @@ export function updateProfileTypeSuccess( } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function updateProfileType(upd: Partial<ProfileType>): any { +export function updateProfileType(updates: Partial<ProfileType>): any { return async ( dispatch: Dispatch<UpdateProfileType>, getState: () => AppStore, { client }: { client: Client } - ) => { + ): Promise<void> => { const profileTypeEntityService = new ProfileTypeEntityService(client) const updatedProfileType = await profileTypeEntityService.updateProfileType( - upd + updates ) if (updatedProfileType) { dispatch(updateProfileTypeSuccess(updatedProfileType)) @@ -46,8 +48,7 @@ export function updateProfileType(upd: Partial<ProfileType>): any { } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function newProfileTypeEntry(upd: Partial<ProfileType>): any { +export function newProfileTypeEntry(updates: Partial<ProfileType>): any { return async ( dispatch: Dispatch<UpdateProfileType>, getState: () => AppStore, @@ -55,7 +56,7 @@ export function newProfileTypeEntry(upd: Partial<ProfileType>): any { ) => { const { data: newProfileType } = await client.create( PROFILETYPE_DOCTYPE, - upd + updates ) if (newProfileType) { dispatch(updateProfileTypeSuccess(newProfileType)) diff --git a/src/store/profileType/profileType.reducer.spec.ts b/src/store/profileType/profileType.reducer.spec.ts index 8c92d82a0a7f35421ecc209b599b6d5c4079ffc0..7704a227a54f9cfa5f719fa517a8524234b41600 100644 --- a/src/store/profileType/profileType.reducer.spec.ts +++ b/src/store/profileType/profileType.reducer.spec.ts @@ -1,3 +1,4 @@ +import { defaultAction } from 'store' import { profileTypeData } from '../../../tests/__mocks__/profileType.mock' import { mockInitialProfileTypeState } from '../../../tests/__mocks__/store' import { UPDATE_PROFILETYPE } from './profileType.actions' @@ -5,22 +6,22 @@ import { profileTypeReducer } from './profileType.reducer' describe('profile reducer', () => { it('should return the initial state', () => { - const result = profileTypeReducer(undefined as any, { type: 'default' }) - expect(result).toEqual(mockInitialProfileTypeState) + const state = profileTypeReducer(undefined, { ...defaultAction }) + expect(state).toEqual(mockInitialProfileTypeState) }) it('should handle UPDATE_PROFILETYPE with payload', () => { - const result = profileTypeReducer(mockInitialProfileTypeState, { + const state = profileTypeReducer(mockInitialProfileTypeState, { type: UPDATE_PROFILETYPE, payload: profileTypeData, }) - expect(result).toEqual(profileTypeData) + expect(state).toEqual(profileTypeData) }) it('should handle UPDATE_PROFILETYPE without payload', () => { - const result = profileTypeReducer(mockInitialProfileTypeState, { + const state = profileTypeReducer(mockInitialProfileTypeState, { type: UPDATE_PROFILETYPE, }) - expect(result).toEqual(mockInitialProfileTypeState) + expect(state).toEqual(mockInitialProfileTypeState) }) }) diff --git a/src/store/profileType/profileType.reducer.ts b/src/store/profileType/profileType.reducer.ts index 2cce9c4a7a8f977f52e4570e15079b49a5ce350f..6dbc015b193ab6f42cc01de3370510b193a0a646 100644 --- a/src/store/profileType/profileType.reducer.ts +++ b/src/store/profileType/profileType.reducer.ts @@ -44,10 +44,10 @@ const initialState: ProfileType = { equipments: [], } -export const profileTypeReducer: Reducer<ProfileType> = ( - state = initialState, - action: ProfileTypeActionTypes -): ProfileType => { +export const profileTypeReducer: Reducer< + ProfileType, + ProfileTypeActionTypes +> = (state = initialState, action) => { switch (action.type) { case UPDATE_PROFILETYPE: case CREATE_NEW_PROFILETYPE: diff --git a/src/targets/browser/index.tsx b/src/targets/browser/index.tsx index eb5836f4578cd219bcb3568be388fe65e718b80e..89a2aa750e98e8eb59aba0db902a5f3ee1ebc686 100644 --- a/src/targets/browser/index.tsx +++ b/src/targets/browser/index.tsx @@ -49,7 +49,7 @@ const setupApp = memoize(() => { }) const persistedState: any = {} - const store: any = configureStore(client, persistedState) + const store = configureStore(client, persistedState) const envService = new EnvironmentService() const isLocal = envService.isLocal() const development = envService.isDev() diff --git a/tests/__mocks__/store.ts b/tests/__mocks__/store.ts index abcba7ea2ff91dc213d64c285e7fd759ad841552..f523b0bfd3a81169cf045e597f636b0413d9c59b 100644 --- a/tests/__mocks__/store.ts +++ b/tests/__mocks__/store.ts @@ -25,11 +25,13 @@ import { Profile, ProfileType, } from 'models' +import { ProfileEcogesture } from 'models/profileEcogesture.model' import configureStore from 'redux-mock-store' import thunkMiddleware from 'redux-thunk' -import { EcolyoState } from 'store' +import { AppActionsTypes, EcolyoState } from 'store' import mockClient from './client' import { mockProfileEcogesture } from './profileEcogesture.mock' + export const mockInitialGlobalState: GlobalState = { screenType: ScreenType.MOBILE, challengeExplorationNotification: false, @@ -292,7 +294,7 @@ export const mockInitialChallengeState: ChallengeState = { currentDataload: [], } -export const mockInitialEcolyoState = { +export const mockInitialEcolyoState: EcolyoState = { global: mockInitialGlobalState, profile: mockInitialProfileState, profileType: mockInitialProfileTypeState, @@ -303,16 +305,35 @@ export const mockInitialEcolyoState = { } const middlewares = [thunkMiddleware.withExtraArgument({ mockClient })] -const mockStore = configureStore<{ ecolyo: { global: GlobalState } }>( - middlewares -) +const mockStore = configureStore< + { + ecolyo: { + challenge: ChallengeState + chart: ChartState + global: GlobalState + modal: ModalState + profile: Profile + profileEcogesture: ProfileEcogesture + profileType: ProfileType + } + cozy: unknown + }, + AppActionsTypes +>(middlewares) const mockedStore = mockStore({ ecolyo: mockInitialEcolyoState, + cozy: {}, }) -export const createMockStore = (initialState: EcolyoState) => { +/** + * Create a mocked Ecolyo store with the default mockInitialEcolyoState + */ +export const createMockEcolyoStore = ( + initialState: EcolyoState = mockInitialEcolyoState +) => { return mockStore({ ecolyo: initialState, + cozy: {}, }) }