diff --git a/front/.eslintrc.json b/front/.eslintrc.json index 8ef48ad9..b4c7bd54 100644 --- a/front/.eslintrc.json +++ b/front/.eslintrc.json @@ -1,6 +1,6 @@ { "env": { - "browser": false, + "browser": true, "es6": true, "mocha": false, "node": true @@ -15,32 +15,8 @@ "sourceType": "module" }, "rules": { - "arrow-spacing": "error", - "brace-style": "error", - "comma-dangle": ["error", "always-multiline"], - "comma-spacing": ["error", { "before": false, "after": true }], - "indent": ["error", 2], - "keyword-spacing": ["error"], - "line-comment-position": ["error", { "position": "above" }], - "max-len": [ - "error", - { - "ignoreStrings": true, - "ignoreRegExpLiterals": true, - "ignoreUrls": true, - "ignoreTemplateLiterals": true, - "code": 80 - } - ], - "multiline-comment-style": ["error", "starred-block"], - "object-curly-spacing": ["error", "always"], - "quotes": ["error", "double"], - "react/jsx-curly-spacing": ["error", { "when": "always" }], - "react/prop-types": "off", - "semi": ["error", "always"], - "sort-imports": "error", - "sort-keys": "error", - "spaced-comment": ["error", "always"] + "no-unused-vars": ["error", { "argsIgnorePattern": "_" }], + "react/prop-types": "off" }, "settings": { "react": { diff --git a/front/src/Component/App.js b/front/src/Component/App.js index 36176bcc..ab60fcd6 100644 --- a/front/src/Component/App.js +++ b/front/src/Component/App.js @@ -22,7 +22,7 @@ const App = ({ be able to insert images or youtube videos.

- I'm doing my best to have tweet insertion fixed asap. Happy testing ! + I`‘m doing my best to have tweet insertion fixed asap. Happy testing !

diff --git a/front/src/Component/Container/MediaPicker/MediaPicker.js b/front/src/Component/Container/MediaPicker/MediaPicker.js index 2e860cce..f6bba2aa 100644 --- a/front/src/Component/Container/MediaPicker/MediaPicker.js +++ b/front/src/Component/Container/MediaPicker/MediaPicker.js @@ -11,8 +11,8 @@ import { searchVideos } from '../../../Redux/State/MediaPicker/VideoPicker' import MediaPicker from '../../View/MediaPicker/MediaPicker' import { componentWillUnmount } from 'react-functional-lifecycle' -// mapStateToProps :: (State, Props) -> Props -const mapStateToProps = (state, ownProps) => ({ +// mapStateToProps :: State -> Props +const mapStateToProps = state => ({ isOpened: state.MediaPicker.Display.opened, isFetchingImages: state.MediaPicker.ImagePicker.isFetching, isFetchingVideos: state.MediaPicker.VideoPicker.isFetching, diff --git a/front/src/Component/View/MediaPicker/MediaPicker.js b/front/src/Component/View/MediaPicker/MediaPicker.js index fdd0ffe2..a82433b7 100644 --- a/front/src/Component/View/MediaPicker/MediaPicker.js +++ b/front/src/Component/View/MediaPicker/MediaPicker.js @@ -14,7 +14,6 @@ const MediaPicker = ({ searchImages, searchVideos, openImagePicker, - openVideoPicker, }) =>
diff --git a/front/src/Epic/BrightcovePlayer.js b/front/src/Epic/BrightcovePlayer.js index 077477bc..1769e66a 100644 --- a/front/src/Epic/BrightcovePlayer.js +++ b/front/src/Epic/BrightcovePlayer.js @@ -48,7 +48,7 @@ export const renderVideoEpic = (action$, state$, { window }) => map(compose(getVideoElement, prop('id'))), filter(complement(isNil)), withLatestFrom(state$), - filter(([ video, state ]) => state.BrightcovePlayer[`enPlayerReady`]), + filter(([ _, state ]) => state.BrightcovePlayer[`enPlayerReady`]), // brightcove SDK is loaded from the loadPlayerEpic above filter(() => !isNil(window['bc'])), map(([ video ]) => ({ diff --git a/front/src/Epic/MediaPicker/ImagePicker.spec.js b/front/src/Epic/MediaPicker/ImagePicker.spec.js index 12af523d..fc2a5c10 100644 --- a/front/src/Epic/MediaPicker/ImagePicker.spec.js +++ b/front/src/Epic/MediaPicker/ImagePicker.spec.js @@ -9,7 +9,6 @@ import { PICK_IMAGE_WITH_CREDITS, RECEIVED_IMAGES, } from '../../Redux/State/MediaPicker/ImagePicker' -import { OPEN_IMAGE_PICKER } from '../../Redux/State/MediaPicker/MediaPicker' import { searchImagesEpic, changePageEpic, @@ -43,15 +42,13 @@ const dependencies = { describe('Epic :: MediaPicker :: ImagePicker :: searchImagesEpic', () => { const fetchImages$ = of(fetchImages()); - it('dispatches receivedImages', done => { - searchImagesEpic(fetchImages$, null, dependencies) + it('dispatches receivedImages', async () => { + const action = await searchImagesEpic(fetchImages$, null, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(RECEIVED_IMAGES); - expect(action.images).toEqual(transformedImages); - done(); - }) - .catch(error => { console.error(error); done(); }); + ; + + expect(action.type).toEqual(RECEIVED_IMAGES); + expect(action.images).toEqual(transformedImages); }, 1000); }); @@ -68,26 +65,22 @@ describe('Epic :: MediaPicker :: ImagePicker :: changePageEpic', () => { }); // @TODO rewrite this using rxjs TestScheduler - it('dispatches receivedImages (after scrollLeft action)', done => { - changePageEpic(scrollLeft$, state$, dependencies) + it('dispatches receivedImages (after scrollLeft action)', async () => { + const action = await changePageEpic(scrollLeft$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(RECEIVED_IMAGES); - expect(action.images).toEqual(transformedImages); - done(); - }) - .catch(error => { console.error(error); done(); }); + ; + + expect(action.type).toEqual(RECEIVED_IMAGES); + expect(action.images).toEqual(transformedImages); }, 1000); - it('dispatches receivedImages (after scrollRight action)', done => { - changePageEpic(scrollRight$, state$, dependencies) + it('dispatches receivedImages (after scrollRight action)', async () => { + const action = await changePageEpic(scrollRight$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(RECEIVED_IMAGES); - expect(action.images).toEqual(transformedImages); - done(); - }) - .catch(error => { console.error(error); done(); }); + ; + + expect(action.type).toEqual(RECEIVED_IMAGES); + expect(action.images).toEqual(transformedImages); }, 1000); }); @@ -103,27 +96,23 @@ describe('Epic :: MediaPicker :: ImagePicker :: ensurePickedImageHasCreditsEpic' }, }) - it('dispatches pickImageWithCredits when image has credits', done => { + it('dispatches pickImageWithCredits when image has credits', async () => { const pickImage$ = of(pickImage(1)); - ensurePickedImageHasCreditsEpic(pickImage$, state$) + const action = await ensurePickedImageHasCreditsEpic(pickImage$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(PICK_IMAGE_WITH_CREDITS); - done(); - }) - .catch(error => { console.error(error); done(); }); + ; + + expect(action.type).toEqual(PICK_IMAGE_WITH_CREDITS); }, 1000); - it('dispatches error when picked image has no credit', done => { + it('dispatches error when picked image has no credit', async() => { const pickImage$ = of(pickImage(2)); - ensurePickedImageHasCreditsEpic(pickImage$, state$) + const action = await ensurePickedImageHasCreditsEpic(pickImage$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(ERROR); - done(); - }) - .catch(error => { console.error(error); done(); }); + ; + + expect(action.type).toEqual(ERROR); }, 1000); }); diff --git a/front/src/Epic/MediaPicker/MediaPicker.spec.js b/front/src/Epic/MediaPicker/MediaPicker.spec.js index d625f19c..39862b3d 100644 --- a/front/src/Epic/MediaPicker/MediaPicker.spec.js +++ b/front/src/Epic/MediaPicker/MediaPicker.spec.js @@ -15,7 +15,7 @@ describe('Epic :: ArticleEditor :: closeMediaPickerEpic', () => { expect(actual).toEqual(expected); }); - testScheduler.run(({ hot, cold, expectObservable }) => { + testScheduler.run(({ hot, expectObservable }) => { const action$ = hot('ab-ef-gh-ij', { a: open(), b: pickImageWithCredits(), diff --git a/front/src/Epic/MediaPicker/VideoPicker.js b/front/src/Epic/MediaPicker/VideoPicker.js index f69c48e9..bf08bcd1 100644 --- a/front/src/Epic/MediaPicker/VideoPicker.js +++ b/front/src/Epic/MediaPicker/VideoPicker.js @@ -18,7 +18,7 @@ export const fetchVideosEpic = (action$, state$, { fetchApi }) => action$.pipe( ofType(FETCH_VIDEOS), withLatestFrom(state$), - mergeMap(([ action, state ]) => fetchApi(join('', [ + mergeMap(([ _, state ]) => fetchApi(join('', [ `${process.env.REACT_APP_MOCK_SERVER_API_URL}/videos`, `?q=${state.MediaPicker.VideoPicker.searchString}`, `&page=${state.MediaPicker.VideoPicker.page}`, diff --git a/front/src/Epic/MediaPicker/VideoPicker.spec.js b/front/src/Epic/MediaPicker/VideoPicker.spec.js index 47614f55..d282f665 100644 --- a/front/src/Epic/MediaPicker/VideoPicker.spec.js +++ b/front/src/Epic/MediaPicker/VideoPicker.spec.js @@ -15,7 +15,7 @@ import { } from '../../Redux/State/MediaPicker/VideoPicker' describe('Epic :: MediaPicker :: VideoPicker :: fetchVideosEpic', () => { - it('dispatches videosReceived', done => { + it('dispatches videosReceived', async () => { const fetchVideos$ = of(fetchVideos()); const state$ = new StateObservable(new Subject(), { MediaPicker: { @@ -30,14 +30,11 @@ describe('Epic :: MediaPicker :: VideoPicker :: fetchVideosEpic', () => { fetchApi: () => new Promise(resolve => resolve({})), }; - fetchVideosEpic(fetchVideos$, state$, dependencies) + const action = await fetchVideosEpic(fetchVideos$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(VIDEOS_RECEIVED) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(VIDEOS_RECEIVED); }, 1000); }); @@ -47,7 +44,7 @@ describe('Epic :: MediaPicker :: VideoPicker :: searchVideosEpic', () => { expect(actual).toEqual(expected); }); - testScheduler.run(({ hot, cold, expectObservable }) => { + testScheduler.run(({ hot, expectObservable }) => { const action$ = hot('a-b----c', { a: scrollLeft(), b: scrollRight(), diff --git a/front/src/Epic/TextEditor/InsertTweet.spec.js b/front/src/Epic/TextEditor/InsertTweet.spec.js index c13d1a2b..83e23672 100644 --- a/front/src/Epic/TextEditor/InsertTweet.spec.js +++ b/front/src/Epic/TextEditor/InsertTweet.spec.js @@ -28,34 +28,28 @@ describe('Epic :: TextEditor :: InsertTweet :: fetchEmbedTweetEpic', () => { const insertTweet$ = of(insertTweet()); const state$ = new StateObservable(new Subject(), {}); - it('dispatches embedTweetFetched action', done => { + it('dispatches embedTweetFetched action', async () => { const dependencies = { fetchApi: () => Promise.resolve({ body: {}}), }; - fetchEmbedTweetEpic(insertTweet$, state$, dependencies) + const action = await fetchEmbedTweetEpic(insertTweet$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(EMBED_TWEET_FETCHED) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(EMBED_TWEET_FETCHED); }, 1000); - it('dispatches error action', done => { + it('dispatches error action', async () => { const dependencies = { fetchApi: () => Promise.reject('fail !'), }; - fetchEmbedTweetEpic(insertTweet$, state$, dependencies) + const action = await fetchEmbedTweetEpic(insertTweet$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(ERROR) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(ERROR); }, 1000); }); @@ -70,53 +64,44 @@ describe('Epic :: TextEditor :: InsertTweet :: insertTweetEpic', () => { }, }); - it('dispatches tweetInserted action', done => { + it('dispatches tweetInserted action', async () => { const embedTweetFetched$ = of(embedTweetFetched( 'editor-name', '

test

', 'https://twitter.com/realDonaldTrump/status/1083756525196320773' )); - insertTweetEpic(embedTweetFetched$, state$) + const action = await insertTweetEpic(embedTweetFetched$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(TWEET_INSERTED) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(TWEET_INSERTED); }, 1000); - it('dispatches error action', done => { + it('dispatches error action', async () => { const embedTweetFetched$ = of(embedTweetFetched( 'wrong-editor-name', 'badly formatted html string', 'wrong url', )); - insertTweetEpic(embedTweetFetched$, state$) + const action = await insertTweetEpic(embedTweetFetched$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(ERROR) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(ERROR); }, 1000); }); describe('Epic :: TextEditor :: InsertTweet', () => { - it('dispatches renderTweet action', done => { + it('dispatches renderTweet action', async () => { const tweetInserted$ = of(tweetInserted('editor-name', '1', 'zxylog', '

')); const state$ = new StateObservable(new Subject(), {}); - renderInsertedTweetEpic(tweetInserted$, state$) + const action = await renderInsertedTweetEpic(tweetInserted$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(RENDER_TWEET) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(RENDER_TWEET); }, 1000); }); diff --git a/front/src/Epic/TextEditor/InsertYoutubeVideo.spec.js b/front/src/Epic/TextEditor/InsertYoutubeVideo.spec.js index 5b2e0a03..58dfffa1 100644 --- a/front/src/Epic/TextEditor/InsertYoutubeVideo.spec.js +++ b/front/src/Epic/TextEditor/InsertYoutubeVideo.spec.js @@ -30,40 +30,28 @@ beforeEach(() => { }); describe('Epic :: TextEditor :: InsertYoutubeVideo', () => { - it('validate a youtube url : success', done => { - validateYoutubeUrl('https://www.youtube.com/watch?v=jadxTFqyhRM') - .then(url => { - expect(url).toEqual( - 'https://www.youtube.com/embed/jadxTFqyhRM' - ) + it('validate a youtube url : success', async () => { + const url = await validateYoutubeUrl('https://www.youtube.com/watch?v=jadxTFqyhRM'); - done() - }) - .catch(err => { console.error(err); done() }); + expect(url).toEqual( + 'https://www.youtube.com/embed/jadxTFqyhRM' + ); }, 1000); - it('validate a youtube url : failure (wrong base url)', done => { - validateYoutubeUrl('https://www.youtube.com/watch?v=jadx') - .catch(error => { - expect(error).toEqual( - 'The provided URL is not a valid youtube video.' - ) - - done() - }) - .catch(err => { console.error(err); done() }); + it('validate a youtube url : failure (wrong base url)', async () => { + await expect( + validateYoutubeUrl('https://www.youtube.com/watch?v=jadx') + ).rejects.toBe( + 'The provided URL is not a valid youtube video.' + ); }, 1000); - it('validate a youtube url : failure (wrong id)', done => { - validateYoutubeUrl('https://www.knplabs.com') - .catch(error => { - expect(error).toEqual( - 'The provided URL is not a valid youtube video.' - ) - - done() - }) - .catch(err => { console.error(err); done() }); + it('validate a youtube url : failure (wrong id)', async () => { + await expect( + validateYoutubeUrl('https://www.knplabs.com') + ).rejects.toBe( + 'The provided URL is not a valid youtube video.' + ); }, 1000); }); @@ -78,34 +66,28 @@ describe('Epic :: TextEditor :: InsertYoutubeVideo :: insertYoutubeVideoEpic', ( }, }); - it('dispatches youtubeVideoInserted', done => { + it('dispatches youtubeVideoInserted', async () => { const insertYoutubeVideo$ = of( insertYoutubeVideo('editor-name', 'https://www.youtube.com/watch?v=O9mxrurGTqo') ); - insertYoutubeVideoEpic(insertYoutubeVideo$, state$) + const action = await insertYoutubeVideoEpic(insertYoutubeVideo$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(YOUTUBE_VIDEO_INSERTED) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(YOUTUBE_VIDEO_INSERTED); }, 1000); - it('dispatches error', done => { + it('dispatches error', async () => { const insertYoutubeVideo$ = of( insertYoutubeVideo('editor-name', 'https://www.msn.com') ); - insertYoutubeVideoEpic(insertYoutubeVideo$, state$) + const action = await insertYoutubeVideoEpic(insertYoutubeVideo$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(ERROR) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(ERROR); }, 1000); }); @@ -115,7 +97,7 @@ describe('Epic :: TextEditor :: InsertYoutubeVideo :: closeInsertYoutubeVideoEpi expect(actual).toEqual(expected); }); - testScheduler.run(({ hot, cold, expectObservable }) => { + testScheduler.run(({ hot, expectObservable }) => { const action$ = hot('a-b-c', { a: youtubeVideoInserted('editor-name'), b: openInsertTweet('editor-name'), diff --git a/front/src/Epic/TextEditor/TextEditor.js b/front/src/Epic/TextEditor/TextEditor.js index f1ab2c8c..4dd4b335 100644 --- a/front/src/Epic/TextEditor/TextEditor.js +++ b/front/src/Epic/TextEditor/TextEditor.js @@ -173,10 +173,10 @@ export const createLinkEpic = (action$, state$, { window }) => action, state.TextEditor.TextToolbox[action.editorName].range, ]), - tap(([ action, range ]) => recoverSelection(window)(range)), + tap(([ _, range ]) => recoverSelection(window)(range)), // then we can apply the mutation - tap(([ action, range ]) => document.execCommand('createLink', false, action.options.href)), - map(([ action, range ]) => closeLinkCreator(action.editorName)), + tap(([ action ]) => document.execCommand('createLink', false, action.options.href)), + map(([ action ]) => closeLinkCreator(action.editorName)), logObservableError(), ) @@ -245,8 +245,8 @@ const isInParent = parentTagName => pipe( range.endContainer.parentNode.closest(parentTagName), ], allPass([ - ([ startNode, endNode ]) => !isNil(startNode), - ([ startNode, endNode ]) => !isNil(endNode), + ([ startNode ]) => !isNil(startNode), + ([ _, endNode ]) => !isNil(endNode), ([ startNode, endNode ]) => equals(startNode, endNode), ]) ) diff --git a/front/src/Epic/TextEditor/TextEditor.spec.js b/front/src/Epic/TextEditor/TextEditor.spec.js index 8403f95d..ee2ad8eb 100644 --- a/front/src/Epic/TextEditor/TextEditor.spec.js +++ b/front/src/Epic/TextEditor/TextEditor.spec.js @@ -65,15 +65,12 @@ describe('Epic :: TextEditor :: TextEditor :: saveRangeEpic', () => { const openLinkCreator$ = of(openLinkCreator('editor-name')); const state$ = new StateObservable(new Subject(), {}); - it('dispatches saveRange', done => { - saveRangeEpic(openLinkCreator$, state$, dependencies) + it('dispatches saveRange', async () => { + const action = await saveRangeEpic(openLinkCreator$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(SAVE_RANGE) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(SAVE_RANGE); }, 1000); }); @@ -86,56 +83,46 @@ describe('Epic :: TextEditor :: TextEditor :: createLinkEpic', () => { }, }); -it('dispatches closeLinkCreator', done => { +it('dispatches closeLinkCreator', async () => { const mutate$ = of(mutate('editor-name')('LINK', { href: ''})); - createLinkEpic(mutate$, state$, dependencies) + const action = await createLinkEpic(mutate$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(CLOSE_LINK_CREATOR) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(CLOSE_LINK_CREATOR); }, 1000); - it('reject others mutations', done => { + it('reject others mutations', async () => { const rejectMutate$ = of(mutate('editorName')('BOLD')); - createLinkEpic(rejectMutate$, state$, dependencies) + const action = await createLinkEpic(rejectMutate$, state$, dependencies) .toPromise(Promise) - .then(result => { - expect(result).toEqual(undefined) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action).toEqual(undefined); }, 1000); }); describe('Epic :: TextEditor :: TextEditor :: refreshTextToolboxStateEpic', () => { - it('dispatches refreshButtonsState', done => { + it('dispatches refreshButtonsState', async () => { const showTextToolbox$ = of(showTextToolbox('editor-name', 10)); const mutate$ = of(mutate('editor-name')('LINK')); - Promise.all([ + const [a1, a2] = await Promise.all([ refreshTextToolboxStateEpic(showTextToolbox$, null, dependencies) .toPromise(Promise), refreshTextToolboxStateEpic(mutate$, null, dependencies) .toPromise(Promise), - ]) - .then(([a1, a2]) => { - expect(a1.type).toEqual(REFRESH_BUTTONS_STATE) - expect(a2.type).toEqual(REFRESH_BUTTONS_STATE) - - done() - }) - .catch(err => { console.error(err); done() }); + ]); + + expect(a1.type).toEqual(REFRESH_BUTTONS_STATE); + expect(a2.type).toEqual(REFRESH_BUTTONS_STATE); }, 1000); }); describe('Epic :: TextEditor :: TextEditor :: pickImageEpic', () => { - it('dispatches insertImage', done => { + it('dispatches insertImage', async () => { const pickImageWithCredits$ = of( pickImageWithCredits(1, 'TEXT_EDITOR', { editorName: 'editor-name'}) ); @@ -147,19 +134,16 @@ describe('Epic :: TextEditor :: TextEditor :: pickImageEpic', () => { }, }); - pickImageEpic(pickImageWithCredits$, state$) + const action = await pickImageEpic(pickImageWithCredits$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(INSERT_IMAGE) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(INSERT_IMAGE); }, 1000); }); describe('Epic :: TextEditor :: TextEditor :: insertImageEpic', () => { - it('dispatches imageInserted', done => { + it('dispatches imageInserted', async () => { const imageMock = { href: 'http://imagelibmock.org/test.png', legend: 'merkel'}; const insertImage$ = of(insertImage('editor-name', imageMock)); const state$ = new StateObservable(new Subject, { @@ -172,22 +156,20 @@ describe('Epic :: TextEditor :: TextEditor :: insertImageEpic', () => { }, }); - insertImageEpic(insertImage$, state$) + const action = await insertImageEpic(insertImage$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(IMAGE_INSERTED) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(IMAGE_INSERTED); }, 1000); }); describe('Epic :: TextEditor :: TextEditor :: pickVideoEpic', () => { - it('dispatches insertVideo', done => { + it('dispatches insertVideo', async () => { const pickVideo$ = of( pickVideo("slkdhlskdg", 'TEXT_EDITOR', { editorName: 'editor-name' }) ); + const state$ = new StateObservable(new Subject(), { MediaPicker: { VideoPicker: { @@ -198,19 +180,16 @@ describe('Epic :: TextEditor :: TextEditor :: pickVideoEpic', () => { }, }); - pickVideoEpic(pickVideo$, state$) + const action = await pickVideoEpic(pickVideo$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(INSERT_VIDEO) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(INSERT_VIDEO); }, 1000); }); describe('Epic :: TextEditor :: TextEditor :: insertVideoEpic', () => { - it('dispatches videoInserted', done => { + it('dispatches videoInserted', async () => { const videoMock = { id: "9329875", name: "test" }; const insertVideo$ = of(insertVideo('editor-name', videoMock)); const state$ = new StateObservable(new Subject(), { @@ -223,13 +202,10 @@ describe('Epic :: TextEditor :: TextEditor :: insertVideoEpic', () => { }, }); - insertVideoEpic(insertVideo$, state$) + const action = await insertVideoEpic(insertVideo$, state$) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(VIDEO_INSERTED) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(VIDEO_INSERTED); }, 1000); }); diff --git a/front/src/Epic/TextEditor/ToolBoxes.spec.js b/front/src/Epic/TextEditor/ToolBoxes.spec.js index 993f80c8..571bc513 100644 --- a/front/src/Epic/TextEditor/ToolBoxes.spec.js +++ b/front/src/Epic/TextEditor/ToolBoxes.spec.js @@ -53,32 +53,26 @@ describe('Epic :: TextEditor :: ToolBoxes :: showTextToolboxEpic', () => { const selectText$ = of(selectText('editor-name')); const state$ = new StateObservable(new Subject(), {}); - it('dispatches showTextToolbox', done => { - showTextToolboxEpic(selectText$, state$, dependencies) + it('dispatches showTextToolbox', async () => { + const action = await showTextToolboxEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(SHOW_TEXT_TOOLBOX) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(SHOW_TEXT_TOOLBOX); }, 1000); - it('dont dispatches showTextToolbox (empty selection)', done => { + it('dont dispatches showTextToolbox (empty selection)', async () => { const dependencies = { window: { getSelection: () => ({ type: 'Char'}) } }; - showTextToolboxEpic(selectText$, state$, dependencies) + const action = await showTextToolboxEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(result => { - expect(result).toEqual(undefined) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action).toEqual(undefined); }, 1000); }); @@ -94,32 +88,26 @@ describe('Epic :: TextEditor :: ToolBoxes :: hideAllTextToolboxesEpic', () => { }, }); - it('dispatches hideTextToolbox', done => { + it('dispatches hideTextToolbox', async () => { const dependencies = { window: { getSelection: () => ({ type: 'Char'}) } }; - hideAllTextToolboxesEpic(selectText$, state$, dependencies) + const action = await hideAllTextToolboxesEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(HIDE_TEXT_TOOLBOX) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(HIDE_TEXT_TOOLBOX); }, 1000); - it('dont dispatches hideTextToolbox (not empty selection)', done => { - hideAllTextToolboxesEpic(selectText$, state$, dependencies) + it('dont dispatches hideTextToolbox (not empty selection)', async () => { + const action = await hideAllTextToolboxesEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(result => { - expect(result).toEqual(undefined) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action).toEqual(undefined); }, 1000); }); @@ -127,7 +115,7 @@ describe('Epic :: TextEditor :: ToolBoxes :: showParagraphToolboxEpic', () => { const selectText$ = of(selectText('editor-name')); const state$ = new StateObservable(new Subject(), {}); - it('dispatches showParagraphToolbox', done => { + it('dispatches showParagraphToolbox', async () => { const dependencies = { window: { getSelection: () => ({ @@ -139,17 +127,14 @@ describe('Epic :: TextEditor :: ToolBoxes :: showParagraphToolboxEpic', () => { }, }; - showParagraphToolboxEpic(selectText$, state$, dependencies) + const action = await showParagraphToolboxEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(action => { - expect(action.type).toEqual(SHOW_PARAGRAPH_TOOLBOX) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action.type).toEqual(SHOW_PARAGRAPH_TOOLBOX); }, 1000); - it('does not dispatch showParagraphToolbox (not empty paragraph)', done => { + it('does not dispatch showParagraphToolbox (not empty paragraph)', async () => { const dependencies = { window: { getSelection: () => ({ @@ -161,17 +146,14 @@ describe('Epic :: TextEditor :: ToolBoxes :: showParagraphToolboxEpic', () => { }, }; - showParagraphToolboxEpic(selectText$, state$, dependencies) + const action = await showParagraphToolboxEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(result => { - expect(result).toEqual(undefined) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action).toEqual(undefined); }, 1000); - it('does not dispatch showParagraphToolbox (not in a paragraph)', done => { + it('does not dispatch showParagraphToolbox (not in a paragraph)', async () => { const dependencies = { window: { getSelection: () => ({ @@ -183,14 +165,11 @@ describe('Epic :: TextEditor :: ToolBoxes :: showParagraphToolboxEpic', () => { }, }; - showParagraphToolboxEpic(selectText$, state$, dependencies) + const action = await showParagraphToolboxEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(result => { - expect(result).toEqual(undefined) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action).toEqual(undefined); }, 1000); }); @@ -198,7 +177,7 @@ describe('Epic :: TextEditor :: ToolBoxes :: hideAllParagraphToolboxesEpic', () const state$ = new StateObservable(new Subject(), {}); const selectText$ = of(selectText('editor-name')); - it('dispatches hideParagraphToolbox', done => { + it('dispatches hideParagraphToolbox', async () => { const tweetInserted$ = of(tweetInserted('editor-name')); const imageInseretd$ = of(imageInserted('editor-name')); const videoInserted$ = of(videoInserted('editor-name')) @@ -213,7 +192,7 @@ describe('Epic :: TextEditor :: ToolBoxes :: hideAllParagraphToolboxesEpic', () }, }; - Promise.all([ + const [a1, a2, a3, a4] = await Promise.all([ hideAllParagraphToolboxesEpic(selectText$, state$, dependencies) .toPromise(Promise), hideAllParagraphToolboxesEpic(tweetInserted$, state$, dependencies) @@ -222,19 +201,15 @@ describe('Epic :: TextEditor :: ToolBoxes :: hideAllParagraphToolboxesEpic', () .toPromise(Promise), hideAllParagraphToolboxesEpic(videoInserted$, state$, dependencies) .toPromise(Promise), - ]) - .then(([a1, a2, a3, a4]) => { - expect(a1.type).toEqual(HIDE_PARAGRAPH_TOOLBOX) - expect(a2.type).toEqual(HIDE_PARAGRAPH_TOOLBOX) - expect(a3.type).toEqual(HIDE_PARAGRAPH_TOOLBOX) - expect(a4.type).toEqual(HIDE_PARAGRAPH_TOOLBOX) + ]); - done() - }) - .catch(err => { console.error(err); done() }); + expect(a1.type).toEqual(HIDE_PARAGRAPH_TOOLBOX); + expect(a2.type).toEqual(HIDE_PARAGRAPH_TOOLBOX); + expect(a3.type).toEqual(HIDE_PARAGRAPH_TOOLBOX); + expect(a4.type).toEqual(HIDE_PARAGRAPH_TOOLBOX); }, 1000); - it('does not dispatch hideParagraphToolbox (empty paragraph)', done => { + it('does not dispatch hideParagraphToolbox (empty paragraph)', async () => { const dependencies = { window: { getSelection: () => ({ @@ -246,13 +221,10 @@ describe('Epic :: TextEditor :: ToolBoxes :: hideAllParagraphToolboxesEpic', () }, }; - hideAllParagraphToolboxesEpic(selectText$, state$, dependencies) + const action = await hideAllParagraphToolboxesEpic(selectText$, state$, dependencies) .toPromise(Promise) - .then(result => { - expect(result).toEqual(undefined) + ; - done() - }) - .catch(err => { console.error(err); done() }); + expect(action).toEqual(undefined); }, 1000); }); diff --git a/front/src/Parser/HtmlToBackend.js b/front/src/Parser/HtmlToBackend.js deleted file mode 100644 index 930c8fcf..00000000 --- a/front/src/Parser/HtmlToBackend.js +++ /dev/null @@ -1,49 +0,0 @@ -import { pipe, tap } from 'ramda' - -// createWrapper :: String -> Element -const createWrapper = body => pipe( - tap(e => e.innerHTML = body) -)(document.createElement('div')) - -// createOriginalTweetElement :: Element, Object -> Element -const createOriginalTweetElement = (tweetElement, originalHtmlMarkups) => pipe( - tap(wrapper => wrapper.innerHTML = originalHtmlMarkups[tweetElement.dataset.tweetId]), - wrapper => wrapper.firstChild, -)(document.createElement('div')) - -// sanitizeTweet :: Element, Object -> Void -const sanitizeTweet = (tweetElement, originalHtmlMarkups) => tweetElement - .parentNode - .replaceChild( - createOriginalTweetElement(tweetElement, originalHtmlMarkups), - tweetElement - ) - -// sanitizeTweets :: State.Tweet.renderedTweets -> Element -> Element -// Reverts rendered tweets to their embed markup. -const sanitizeTweets = renderedTweets => pipe( - tap(wrapper => Array - .from(wrapper.getElementsByClassName('knp-rendered-tweet')) - .reverse() - .map(tweetElement => sanitizeTweet(tweetElement, renderedTweets)) - ) -) - -// sanitizeVideo :: Element -> Element -const sanitizeVideo = videoElement => videoElement.innerHTML = '' - -// sanitizeBrightcoveVideos :: Node -> String -const sanitizeBrightcoveVideos = pipe( - tap(wrapper => Array - .from(wrapper.getElementsByClassName('knp-rendered-video')) - .map(sanitizeVideo) - ) -) - -// sanitizeContentBody :: Object -> String -> String -export const sanitizeContentBody = renderedTweets => pipe( - createWrapper, - sanitizeTweets(renderedTweets), - sanitizeBrightcoveVideos(renderedVideos), - wrapper => wrapper.innerHTML, -) diff --git a/front/src/Parser/HtmlToComponents.js b/front/src/Parser/HtmlToComponents.js index 9143cdaa..59877435 100644 --- a/front/src/Parser/HtmlToComponents.js +++ b/front/src/Parser/HtmlToComponents.js @@ -22,7 +22,7 @@ import parseUrl from 'url-parse' // toArray :: [Node] -> [Object] const toArray = nodes => Object .values(nodes) - .reduce((dest, node, i) => append(node, dest), []) + .reduce((dest, node) => append(node, dest), []) // isHeading :: Node -> Boolean const isHeading = node => range(2, 7).map(x => `H${x}`).includes(node.tagName) diff --git a/front/src/Redux/State/TextEditor/TextToolbox.spec.js b/front/src/Redux/State/TextEditor/TextToolbox.spec.js index 68356ea0..15bf9742 100644 --- a/front/src/Redux/State/TextEditor/TextToolbox.spec.js +++ b/front/src/Redux/State/TextEditor/TextToolbox.spec.js @@ -2,7 +2,6 @@ import { clear, closeLinkCreator, default as reducer, - hide, initialize, openLinkCreator, refreshButtonsState, diff --git a/front/src/Redux/State/index.js b/front/src/Redux/State/index.js index bd0c539e..b6c97d04 100644 --- a/front/src/Redux/State/index.js +++ b/front/src/Redux/State/index.js @@ -7,16 +7,12 @@ import Tweet from './Tweet' // debug :: ((State, Action *) -> State) -> State -> Action * -> State export const debug = reducer => (state = reducer(), action = {}) => pipe( - tap(() => console.log(':: DEBUG ::')), tap(({ type }) => console.log(`Action :: ${type || 'NONE'}`)), - tap(({ type, ...payload }) => console.log('Payload ::', payload)), + tap(({ _, ...payload }) => console.log('Payload ::', payload)), tap(() => console.log('InitialState ::', state)), - tap(() => console.time('Reducer :: Timer :')), action => reducer(state, action), tap(newState => console.log('NewState ::', newState)), - tap(() => console.timeEnd('Reducer :: Timer :')), - tap(() => console.log(':: END DEBUG ::')), - tap(() => console.log('')), + tap(() => console.log("")), )(action) // State :: (State, Action *) -> State