From 55a4cadf2a7931702fe1ce1c23ae4dd26bc41b68 Mon Sep 17 00:00:00 2001 From: Ahmad Abdolsaheb Date: Mon, 4 Nov 2019 16:50:14 +0300 Subject: [PATCH] fix: clean failed challenges (#37526) --- .../Header/components/universalNav.css | 3 + client/src/redux/failed-updates-epic.js | 16 ++++- client/src/redux/failed-updates-epic.test.js | 62 +++++++++++++++++++ client/utils/challengeTypes.js | 1 + 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 client/src/redux/failed-updates-epic.test.js diff --git a/client/src/components/Header/components/universalNav.css b/client/src/components/Header/components/universalNav.css index bd054c35d8..5957f126be 100644 --- a/client/src/components/Header/components/universalNav.css +++ b/client/src/components/Header/components/universalNav.css @@ -19,6 +19,9 @@ .universal-nav a { text-decoration: none; +} + +.universal-nav .universal-nav-right a { font-family: 'Roboto Mono', monospace; } diff --git a/client/src/redux/failed-updates-epic.js b/client/src/redux/failed-updates-epic.js index 33fa0bd3c2..64b7270f03 100644 --- a/client/src/redux/failed-updates-epic.js +++ b/client/src/redux/failed-updates-epic.js @@ -19,6 +19,7 @@ import { } from './'; import postUpdate$ from '../templates/Challenges/utils/postUpdate$'; import { isGoodXHRStatus } from '../templates/Challenges/utils'; +import { backEndProject } from '../../utils/challengeTypes'; const key = 'fcc-failed-updates'; @@ -26,6 +27,10 @@ function delay(time = 0, fn) { return setTimeout(fn, time); } +// check if backenEndProjects have a solution +const isSubmitable = failure => + failure.payload.challengeType !== backEndProject || failure.payload.solution; + function failedUpdateEpic(action$, state$) { const storeUpdates = action$.pipe( ofType(types.updateFailed), @@ -45,7 +50,16 @@ function failedUpdateEpic(action$, state$) { filter(() => store.get(key)), filter(() => isOnlineSelector(state$.value)), tap(() => { - const failures = store.get(key) || []; + let failures = store.get(key) || []; + + let submitableFailures = failures.filter(isSubmitable); + + // delete unsubmitable failed challenges + if (submitableFailures.length !== failures.length) { + store.set(key, submitableFailures); + failures = submitableFailures; + } + let delayTime = 100; const batch = failures.map((update, i) => { // we stagger the updates here so we don't hammer the server diff --git a/client/src/redux/failed-updates-epic.test.js b/client/src/redux/failed-updates-epic.test.js new file mode 100644 index 0000000000..2fa6c6c16b --- /dev/null +++ b/client/src/redux/failed-updates-epic.test.js @@ -0,0 +1,62 @@ +/* global expect */ + +import { Subject } from 'rxjs'; +import { ActionsObservable, StateObservable } from 'redux-observable'; +import failedUpdatesEpic from './failed-updates-epic'; +import { types } from './'; +import store from 'store'; + +const key = 'fcc-failed-updates'; + +describe('failed-updates-epic', () => { + it('should remove falty backend challenges from localStorage', async () => { + store.set(key, failedSubmitions); + + const action$ = ActionsObservable.of({ + type: types.updateComplete + }); + const state$ = new StateObservable(new Subject(), initialState); + const epic$ = failedUpdatesEpic(action$, state$); + + await epic$.toPromise(); + + expect(store.get(key)).toEqual(submitableChallenges); + }); +}); + +const initialState = { + app: { + isOnline: true, + appUsername: 'developmentuser' + } +}; + +const failedSubmitions = [ + { + endpoint: '/project-completed', + id: 'b1507944-7310-479f-bb59-ccafac488592', + payload: { id: '587d8249367417b2b2512c41', challengeType: 4 } + }, + { + endpoint: '/project-completed', + id: 'b1507944-7310-479f-bb59-ccafac488593', + payload: { + id: '587d8249367417b2b2512c42', + challengeType: 4, + solution: 'http://freecodecamp.org/', + githubLink: 'https://github.com/' + } + }, + { + endpoint: '/project-completed', + id: 'b1507944-7310-479f-bb59-ccafac488594', + payload: { + id: '587d8249367417b2b2512c43', + challengeType: 4, + solution: 'http://freecodecamp.org/', + githubLink: 'https://github.com/' + } + } +]; + +const submitableChallenges = failedSubmitions.slice(1); diff --git a/client/utils/challengeTypes.js b/client/utils/challengeTypes.js index 4ffcf472fa..35635fb451 100644 --- a/client/utils/challengeTypes.js +++ b/client/utils/challengeTypes.js @@ -13,6 +13,7 @@ const invalid = 9; // individual exports exports.backend = backend; exports.frontEndProject = frontEndProject; +exports.backEndProject = backEndProject; exports.challengeTypes = { html,