From 47de20cea86babec29c6c16c82a1bdb39f3a5123 Mon Sep 17 00:00:00 2001 From: Eve Essex Date: Sat, 12 Aug 2017 18:41:27 -0400 Subject: [PATCH] testing --- .../sections/image_collection/index.coffee | 2 +- .../content2/section_container/index.coffee | 2 - .../section_container/test/index.coffee | 2 +- .../content2/section_list/index.coffee | 29 ++-- .../content2/section_list/test/index.coffee | 10 +- .../content2/sections/header/index.coffee | 6 +- .../content2/sections/header/index.styl | 4 +- .../sections/header/test/index.coffee | 2 +- .../sections/image_collection/index.coffee | 5 +- .../content2/sections/text/index.coffee | 2 +- .../content2/sections/text/test/index.coffee | 2 +- .../components/input_paragraph.coffee | 105 ------------ .../{edit_nav.coffee => nav.coffee} | 2 +- .../rich_text2/components/paragraph.coffee | 19 ++- .../rich_text2/test/input_paragraph.coffee | 95 ----------- .../test/{edit_nav.coffee => nav.coffee} | 26 +-- .../rich_text2/test/paragraph.coffee | 153 ++++++++++++++++++ 17 files changed, 212 insertions(+), 254 deletions(-) delete mode 100644 client/components/rich_text2/components/input_paragraph.coffee rename client/components/rich_text2/components/{edit_nav.coffee => nav.coffee} (98%) delete mode 100644 client/components/rich_text2/test/input_paragraph.coffee rename client/components/rich_text2/test/{edit_nav.coffee => nav.coffee} (89%) create mode 100644 client/components/rich_text2/test/paragraph.coffee diff --git a/client/apps/edit/components/content/sections/image_collection/index.coffee b/client/apps/edit/components/content/sections/image_collection/index.coffee index e37515b63..767be3ebf 100644 --- a/client/apps/edit/components/content/sections/image_collection/index.coffee +++ b/client/apps/edit/components/content/sections/image_collection/index.coffee @@ -12,7 +12,7 @@ DragContainer = React.createFactory require '../../../../../../components/drag_d { div, section, ul, li } = React.DOM components = require('@artsy/reaction-force/dist/components/publishing/index').default -ImageSetPreview = React.createFactory components.ImagesetPreviewClassic +ImageSetPreview = React.createFactory components.ImageSetPreviewClassic module.exports = React.createClass displayName: 'SectionImageCollection' diff --git a/client/apps/edit/components/content2/section_container/index.coffee b/client/apps/edit/components/content2/section_container/index.coffee index 2b4aa2342..3c58eb786 100644 --- a/client/apps/edit/components/content2/section_container/index.coffee +++ b/client/apps/edit/components/content2/section_container/index.coffee @@ -11,7 +11,6 @@ Video = React.createFactory require '../../content/sections/video/index.coffee' Slideshow = React.createFactory require '../../content/sections/slideshow/index.coffee' Embed = React.createFactory require '../../content/sections/embed/index.coffee' Fullscreen = React.createFactory require '../../content/sections/fullscreen/index.coffee' -Callout = React.createFactory require '../../content/sections/callout/index.coffee' ImageCollection = React.createFactory require '../sections/image_collection/index.coffee' Image = React.createFactory require '../../content/sections/image/index.coffee' { div, nav, button } = React.DOM @@ -69,7 +68,6 @@ module.exports = React.createClass when 'slideshow' then Slideshow when 'embed' then Embed when 'fullscreen' then Fullscreen - when 'callout' then Callout when 'image_set' then ImageCollection when 'image_collection' then ImageCollection when 'image' then Image diff --git a/client/apps/edit/components/content2/section_container/test/index.coffee b/client/apps/edit/components/content2/section_container/test/index.coffee index cd3673433..73469ba09 100644 --- a/client/apps/edit/components/content2/section_container/test/index.coffee +++ b/client/apps/edit/components/content2/section_container/test/index.coffee @@ -38,7 +38,7 @@ describe 'SectionContainer', -> dragOver: 4 article: new Article } - @SectionContainer.__set__ 'SectionText', -> + @SectionContainer.__set__ 'Text', -> @component = ReactDOM.render React.createElement(@SectionContainer, @props ), $("
")[0], => setTimeout => @component.setState = sinon.stub() diff --git a/client/apps/edit/components/content2/section_list/index.coffee b/client/apps/edit/components/content2/section_list/index.coffee index 5e40e8b6a..e90bb9a27 100644 --- a/client/apps/edit/components/content2/section_list/index.coffee +++ b/client/apps/edit/components/content2/section_list/index.coffee @@ -59,20 +59,21 @@ module.exports = React.createClass article: @props.article }, @props.sections.map (section, i) => - [ - SectionContainer { - sections: @props.sections - section: section - index: i - editing: @state.editingIndex is i - ref: 'section' + i - key: section.cid - channel: @props.channel - onSetEditing: @onSetEditing - article: @props.article - } - SectionTool { sections: @props.sections, index: i, key: i } - ] + unless section.get('type') is 'callout' + [ + SectionContainer { + sections: @props.sections + section: section + index: i + editing: @state.editingIndex is i + ref: 'section' + i + key: section.cid + channel: @props.channel + onSetEditing: @onSetEditing + article: @props.article + } + SectionTool { sections: @props.sections, index: i, key: i } + ] if @props.channel.isEditorial() div { className: 'edit-sections__postscript' diff --git a/client/apps/edit/components/content2/section_list/test/index.coffee b/client/apps/edit/components/content2/section_list/test/index.coffee index 3174a9010..43ecb7e57 100644 --- a/client/apps/edit/components/content2/section_list/test/index.coffee +++ b/client/apps/edit/components/content2/section_list/test/index.coffee @@ -20,18 +20,18 @@ describe 'SectionList', -> global.HTMLElement = () => {} @SectionList = benv.require resolve(__dirname, '../index') DragContainer = benv.require resolve(__dirname, '../../../../../../components/drag_drop/index') - RichTextParagraph = benv.require resolve( - __dirname, '../../../../../../components/rich_text/components/input_paragraph.coffee' + Paragraph = benv.require resolve( + __dirname, '../../../../../../components/rich_text2/components/paragraph.coffee' ) @SectionList.__set__ 'SectionTool', @SectionTool = sinon.stub() @SectionContainer = benv.requireWithJadeify( resolve(__dirname, '../../section_container/index'), ['icons'] ) - @SectionContainer.__set__ 'SectionText', text = sinon.stub() - @SectionContainer.__set__ 'SectionImageCollection', image_collection = sinon.stub() + @SectionContainer.__set__ 'Text', text = sinon.stub() + @SectionContainer.__set__ 'ImageCollection', image_collection = sinon.stub() @SectionList.__set__ 'SectionContainer', React.createFactory @SectionContainer @SectionList.__set__ 'DragContainer', React.createFactory DragContainer - @SectionList.__set__ 'RichTextParagraph', React.createFactory RichTextParagraph + @SectionList.__set__ 'Paragraph', React.createFactory Paragraph @props = { article: new Backbone.Model {layout: 'feature'} sections: @sections = new Sections [ diff --git a/client/apps/edit/components/content2/sections/header/index.coffee b/client/apps/edit/components/content2/sections/header/index.coffee index 0df2452ac..39b27d58e 100644 --- a/client/apps/edit/components/content2/sections/header/index.coffee +++ b/client/apps/edit/components/content2/sections/header/index.coffee @@ -23,11 +23,11 @@ module.exports = React.createClass className: 'edit-header__lead-paragraph' }, Paragraph { - html: @props.article.get('lead_paragraph') or '' + html: @props.article.get('lead_paragraph') onChange: @setLeadParagraph placeholder: 'Lead Paragraph (optional)' type: 'lead_paragraph' - linked: true + linked: false linebreaks: false layout: @props.article.get('layout') } @@ -63,5 +63,5 @@ module.exports = React.createClass @props.article.get('author').name p { className: 'date' }, @props.article.getPublishDate() - if layout is 'standard' and @props.article.get('lead_paragraph').length + if layout is 'standard' and @props.article.get('lead_paragraph')?.length @renderLeadParagraph() diff --git a/client/apps/edit/components/content2/sections/header/index.styl b/client/apps/edit/components/content2/sections/header/index.styl index 652a30121..f51c4cc95 100644 --- a/client/apps/edit/components/content2/sections/header/index.styl +++ b/client/apps/edit/components/content2/sections/header/index.styl @@ -2,6 +2,7 @@ padding-top 60px .public-DraftEditorPlaceholder-root position absolute + top 1em color gray-dark-color &__title position relative @@ -82,5 +83,4 @@ garamond l-body max-width classic-body-width margin 20px auto 0 auto - .public-DraftEditorPlaceholder-root - color gray-dark-color + diff --git a/client/apps/edit/components/content2/sections/header/test/index.coffee b/client/apps/edit/components/content2/sections/header/test/index.coffee index be72c2c91..21bcbf062 100644 --- a/client/apps/edit/components/content2/sections/header/test/index.coffee +++ b/client/apps/edit/components/content2/sections/header/test/index.coffee @@ -112,7 +112,7 @@ describe 'SectionHeader: Standard', -> benv.expose $: benv.require 'jquery' global.HTMLElement = () => {} SectionHeader = benv.require resolve(__dirname, '../index.coffee') - Paragraph = benv.require resolve(__dirname, '../../../../../../../components/rich_text2/components/input_paragraph.coffee') + Paragraph = benv.require resolve(__dirname, '../../../../../../../components/rich_text2/components/paragraph.coffee') SectionHeader.__set__ 'Paragraph', React.createFactory Paragraph @article = new Article _.extend fixtures().articles, layout: 'standard' diff --git a/client/apps/edit/components/content2/sections/image_collection/index.coffee b/client/apps/edit/components/content2/sections/image_collection/index.coffee index 67f6ba7e1..3103904c7 100644 --- a/client/apps/edit/components/content2/sections/image_collection/index.coffee +++ b/client/apps/edit/components/content2/sections/image_collection/index.coffee @@ -10,9 +10,8 @@ Controls = React.createFactory require './components/controls.coffee' DragContainer = React.createFactory require '../../../../../../components/drag_drop/index.coffee' { fillWidth } = require '../../../../../../components/fill_width/index.coffee' { div, section, ul, li } = React.DOM - components = require('@artsy/reaction-force/dist/components/publishing/index').default -ImagesetPreviewClassic = React.createFactory components.ImagesetPreviewClassic +ImageSetPreviewClassic = React.createFactory components.ImageSetPreviewClassic module.exports = React.createClass displayName: 'SectionImageCollection' @@ -115,7 +114,7 @@ module.exports = React.createClass }, if hasImages if !@props.editing and @props.section.get('type') is 'image_set' - ImagesetPreviewClassic { + ImageSetPreviewClassic { images: images } else diff --git a/client/apps/edit/components/content2/sections/text/index.coffee b/client/apps/edit/components/content2/sections/text/index.coffee index cbd21541a..ccccf84fe 100644 --- a/client/apps/edit/components/content2/sections/text/index.coffee +++ b/client/apps/edit/components/content2/sections/text/index.coffee @@ -5,7 +5,7 @@ sd = require('sharify').data window.process = {env: {NODE_ENV: sd.NODE_ENV}} components = require('@artsy/reaction-force/dist/components/publishing/index').default Config = require './draft_config.coffee' -Nav = React.createFactory require '../../../../../../components/rich_text2/components/edit_nav.coffee' +Nav = React.createFactory require '../../../../../../components/rich_text2/components/nav.coffee' InputUrl = React.createFactory require '../../../../../../components/rich_text2/components/input_url.coffee' Text = React.createFactory components.Text Utils = require '../../../../../../components/rich_text2/utils/index.coffee' diff --git a/client/apps/edit/components/content2/sections/text/test/index.coffee b/client/apps/edit/components/content2/sections/text/test/index.coffee index 1c513c9d4..76d54b954 100644 --- a/client/apps/edit/components/content2/sections/text/test/index.coffee +++ b/client/apps/edit/components/content2/sections/text/test/index.coffee @@ -39,7 +39,7 @@ describe 'Section Text', -> resolve(__dirname, '../../../../../../../components/rich_text2/components/input_url'), ['icons'] ) Nav = benv.requireWithJadeify( - resolve(__dirname, '../../../../../../../components/rich_text2/components/edit_nav'), ['icons'] + resolve(__dirname, '../../../../../../../components/rich_text2/components/nav'), ['icons'] ) @SectionText.__set__ 'InputUrl', React.createFactory InputUrl @SectionText.__set__ 'Nav', React.createFactory Nav diff --git a/client/components/rich_text2/components/input_paragraph.coffee b/client/components/rich_text2/components/input_paragraph.coffee deleted file mode 100644 index c861ba333..000000000 --- a/client/components/rich_text2/components/input_paragraph.coffee +++ /dev/null @@ -1,105 +0,0 @@ -# A basic paragraph component including bold and italic by default - -# RichTextParagraph { -# text *required -# onChange *required -# placeholder -# styleMap: ['italic', 'underline'] #overrides default styles -# } - -React = require 'react' -sd = require('sharify').data -window.process = {env: {NODE_ENV: sd.NODE_ENV}} -{ ContentState, - Editor, - EditorState, - RichUtils, - Modifier } = require 'draft-js' -{ convertToHTML, convertFromHTML } = require 'draft-convert' -{ div } = React.DOM -editor = (props) -> React.createElement Editor, props - -module.exports = React.createClass - displayName: 'RichTextParagraph' - - getInitialState: -> - editorState: EditorState.createEmpty() - focus: false - styleMap: @props.styleMap or ['bold', 'italic'] - - componentDidMount: -> - if $(@props.text).text().length - blocksFromHTML = @convertFromHTML(@props.text) - @setState - html: @props.text - editorState: EditorState.createWithContent(blocksFromHTML) - - onChange: (editorState) -> - html = @convertToHtml editorState - @setState editorState: editorState, html: html - @props.onChange(html) - - focus: -> - @setState focus: true - @refs.editor.focus() - - onBlur: -> - @setState focus: false - - convertFromHTML: (html) -> - blocksFromHTML = convertFromHTML({})(html) - return blocksFromHTML - - convertToHtml: (editorState) -> - html = convertToHTML({})(editorState.getCurrentContent()) - html = html.replace(/ /g, '  ') - return html - - onPaste: (text, html) -> - { editorState } = @state - unless html - html = '
' + text + '
' - blocksFromHTML = @convertFromHTML(html) - convertedHtml = blocksFromHTML.getBlocksAsArray().map (contentBlock) => - unstyled = @stripPastedStyles contentBlock - unless unstyled.getType() is 'unstyled' - unstyled = unstyled.set('type', 'unstyled') - return unstyled - blockMap = ContentState.createFromBlockArray(convertedHtml, blocksFromHTML.entityMap).blockMap - newState = Modifier.replaceWithFragment(editorState.getCurrentContent(), editorState.getSelection(), blockMap) - this.onChange(EditorState.push(editorState, newState, 'insert-fragment')) - return true - - stripPastedStyles: (contentBlock) -> - styleMap = @state.styleMap.map (style) -> - return style.toUpperCase() - characterList = contentBlock.getCharacterList().map (character) -> - if character.get('style') not in styleMap - character.set('style', character.get('style').clear()) - unstyled = contentBlock.set('characterList', characterList) - return unstyled - - handleKeyCommand: (e) -> - if e in @state.styleMap - newState = RichUtils.handleKeyCommand @state.editorState, e - if newState - @onChange newState - return true - return false - - render: -> - div { className: 'rich-text--paragraph' }, - div { - className: 'rich-text--paragraph__input' - onClick: @focus - onBlur: @onBlur - }, - editor { - ref: 'editor' - placeholder: @props.placeholder - editorState: @state.editorState - spellCheck: true - onChange: @onChange - handlePastedText: @onPaste - handleKeyCommand: @handleKeyCommand - } diff --git a/client/components/rich_text2/components/edit_nav.coffee b/client/components/rich_text2/components/nav.coffee similarity index 98% rename from client/components/rich_text2/components/edit_nav.coffee rename to client/components/rich_text2/components/nav.coffee index 9f5be29a5..4bf35eed7 100644 --- a/client/components/rich_text2/components/edit_nav.coffee +++ b/client/components/rich_text2/components/nav.coffee @@ -4,7 +4,7 @@ _ = require 'underscore' icons = -> require('../utils/icons.jade') arguments... module.exports = React.createClass - displayName: 'EditNav' + displayName: 'RichTextNav' onToggle: (e) -> e.preventDefault() diff --git a/client/components/rich_text2/components/paragraph.coffee b/client/components/rich_text2/components/paragraph.coffee index b6a3ad655..ad32135b8 100644 --- a/client/components/rich_text2/components/paragraph.coffee +++ b/client/components/rich_text2/components/paragraph.coffee @@ -30,7 +30,7 @@ Utils = require '../utils/index.coffee' { div, a } = React.DOM editor = (props) -> React.createElement Editor, props components = require('@artsy/reaction-force/dist/components/publishing/index').default -Nav = React.createFactory require './edit_nav.coffee' +Nav = React.createFactory require './nav.coffee' InputUrl = React.createFactory require './input_url.coffee' Text = React.createFactory components.Text @@ -46,6 +46,7 @@ module.exports = React.createClass showNav: false urlValue: '' selectionTarget: null + linebreaks: @props.linebreaks or true componentDidMount: -> if $(@props.html).text().length @@ -71,7 +72,9 @@ module.exports = React.createClass @refs.editor.focus() onBlur: -> - @setState focus: false + @setState + focus: false + showNav: false convertFromHTML: (html) -> blocksFromHTML = convertFromHTML({ @@ -103,7 +106,7 @@ module.exports = React.createClass return Array.from(available) handleKeyCommand: (e) -> - return 'handled' if @props.linebreaks is false and e is 'split-block' + return 'handled' if @state.linebreaks is false and e is 'split-block' if e is 'link-prompt' @promptForLink() if @hasLinks() return 'handled' @@ -122,7 +125,10 @@ module.exports = React.createClass { editorState } = @state unless html html = '
' + text + '
' + html = Utils.standardizeSpacing html html = Utils.stripGoogleStyles html + unless @state.linebreaks + html = html.replace(/<\/p>

/g, '') blocksFromHTML = @convertFromHTML html convertedHtml = blocksFromHTML.getBlocksAsArray().map (contentBlock) => unstyled = Utils.stripCharacterStyles contentBlock, true @@ -135,7 +141,8 @@ module.exports = React.createClass editorState.getSelection() blockMap ) - @onChange EditorState.push(editorState, newState, 'insert-fragment') + newState = EditorState.push(editorState, newState, 'insert-fragment') + @onChange newState return true promptForLink: (e) -> @@ -206,7 +213,7 @@ module.exports = React.createClass checkSelection: -> if !window.getSelection().isCollapsed location = Utils.getSelectionLocation $(ReactDOM.findDOMNode(@refs.editor)).offset() - selectionTargetL = Config.inlineStyles(@props.type).length * 50 + selectionTargetL = Config.inlineStyles(@props.type).length * 25 selectionTargetL = selectionTargetL + 50 if @hasLinks() @setState showNav: true, selectionTarget: Utils.stickyControlsBox(location, -43, selectionTargetL) else @@ -221,7 +228,7 @@ module.exports = React.createClass Nav { styles: Config.inlineStyles(@props.type) toggleStyle: @toggleInlineStyle - promptForLink: @promptForLink + promptForLink: @promptForLink if @hasLinks() position: @state.selectionTarget } div { diff --git a/client/components/rich_text2/test/input_paragraph.coffee b/client/components/rich_text2/test/input_paragraph.coffee deleted file mode 100644 index 8e3ddc580..000000000 --- a/client/components/rich_text2/test/input_paragraph.coffee +++ /dev/null @@ -1,95 +0,0 @@ -benv = require 'benv' -{ resolve } = require 'path' -sinon = require 'sinon' - -describe 'RichTextParagraph', -> - - beforeEach (done) -> - benv.setup => - benv.expose - $: benv.require 'jquery' - React: require 'react' - ReactDOM: require 'react-dom' - ReactTestUtils: require 'react-addons-test-utils' - ReactDOMServer: require 'react-dom/server' - Draft: require 'draft-js' - window.jQuery = $ - @r = - find: ReactTestUtils.findRenderedDOMComponentWithClass - simulate: ReactTestUtils.Simulate - @d = - EditorState: Draft.EditorState - global.HTMLElement = () => {} - global.HTMLAnchorElement = () => {} - @RichTextParagraph = benv.require resolve __dirname, '../components/input_paragraph' - @props = { - text: '

Here is the lead paragraph for this article.

' - placeholder: 'Lead paragraph (optional)' - onChange: sinon.stub() - } - @rendered = ReactDOMServer.renderToString React.createElement(@RichTextParagraph, @props) - - @component = ReactDOM.render React.createElement(@RichTextParagraph, @props), (@$el = $ "
")[0], => setTimeout => - @component.state.editorState.getSelection().isCollapsed = sinon.stub().returns false - selection = @component.state.editorState.getSelection() - newSelection = selection.merge({ - anchorKey: @component.state.editorState.getCurrentContent().getFirstBlock().key - anchorOffset: 0 - focusKey: @component.state.editorState.getCurrentContent().getFirstBlock().key - focusOffset: 7 - }) - newEditorState = @d.EditorState.acceptSelection(@component.state.editorState, newSelection) - @component.onChange newEditorState - done() - - afterEach -> - benv.teardown() - - it 'Shows a placeholder if provided and empty', -> - $(@rendered).text().should.eql 'Lead paragraph (optional)' - - it 'Renders an existing lead paragraph', -> - $(ReactDOM.findDOMNode(@component)).text().should.eql 'Here is the lead paragraph for this article.' - @component.state.html.should.eql '

Here is  the lead paragraph for  this article.

' - - it 'Can toggle bold styles by default', -> - @component.handleKeyCommand('bold') - @component.state.html.should.eql '

Here is  the lead paragraph for  this article.

' - - it 'Can toggle italic styles by default', -> - @component.handleKeyCommand('italic') - @component.state.html.should.eql '

Here is  the lead paragraph for  this article.

' - - it 'Ignores unsuppored styles', -> - @component.handleKeyCommand('underline') - @component.state.html.should.eql '

Here is  the lead paragraph for  this article.

' - - it 'Can override default styles via props.styleMap', -> - @props.styleMap = ['bold'] - @props.text = '

Here is the a paragraph for this article.

' - component = ReactDOM.render React.createElement(@RichTextParagraph, @props), (@$el = $ "
")[0] - component.state.editorState.getSelection().isCollapsed = sinon.stub().returns false - selection = component.state.editorState.getSelection() - newSelection = selection.merge({ - anchorKey: component.state.editorState.getCurrentContent().getFirstBlock().key - anchorOffset: 0 - focusKey: component.state.editorState.getCurrentContent().getFirstBlock().key - focusOffset: 7 - }) - newEditorState = @d.EditorState.acceptSelection(component.state.editorState, newSelection) - component.onChange newEditorState - - component.handleKeyCommand('italic') - component.state.html.should.eql '

Here is the a paragraph for this article.

' - - component.handleKeyCommand('bold') - component.state.html.should.eql '

Here is the a paragraph for this article.

' - - it 'Strips unsuported html out of pasted text', -> - @component.onPaste 'Available at: Espacio Valverde Galleries Sector, Booth 9F01', '

Available at: Espacio Valverde • Galleries Sector, Booth 9F01

' - @component.state.html.should.eql '

Available at: Espacio Valverde • Galleries Sector, Booth 9F01  the lead paragraph for  this article.

' - - it 'Sends converted html to parent onChange', -> - @component.onChange @component.state.editorState - @component.props.onChange.called.should.eql true - @component.props.onChange.args[0][0].should.eql '

Here is  the lead paragraph for  this article.

' diff --git a/client/components/rich_text2/test/edit_nav.coffee b/client/components/rich_text2/test/nav.coffee similarity index 89% rename from client/components/rich_text2/test/edit_nav.coffee rename to client/components/rich_text2/test/nav.coffee index 4913d34e9..0766c8b79 100644 --- a/client/components/rich_text2/test/edit_nav.coffee +++ b/client/components/rich_text2/test/nav.coffee @@ -13,14 +13,14 @@ r = { blockTypes, inlineStyles } = require '../../../apps/edit/components/content2/sections/text/draft_config.coffee' -describe 'RichText: EditNav', -> +describe 'RichText: Nav', -> describe 'Classic: partner', -> beforeEach (done) -> benv.setup => benv.expose $: benv.require 'jquery' - @EditNav = benv.requireWithJadeify( - resolve(__dirname, '../components/edit_nav'), ['icons'] + @Nav = benv.requireWithJadeify( + resolve(__dirname, '../components/nav'), ['icons'] ) @props = { hasFeatures: false @@ -32,7 +32,7 @@ describe 'RichText: EditNav', -> makePlainText: @makePlainText = sinon.stub() position: { top: 20, left: 20 } } - @component = ReactDOM.render React.createElement(@EditNav, @props), (@$el = $ "
")[0], => setTimeout => + @component = ReactDOM.render React.createElement(@Nav, @props), (@$el = $ "
")[0], => setTimeout => done() afterEach -> @@ -81,8 +81,8 @@ describe 'RichText: EditNav', -> beforeEach (done) -> benv.setup => benv.expose $: benv.require 'jquery' - @EditNav = benv.requireWithJadeify( - resolve(__dirname, '../components/edit_nav'), ['icons'] + @Nav = benv.requireWithJadeify( + resolve(__dirname, '../components/nav'), ['icons'] ) @props = { hasFeatures: true @@ -94,7 +94,7 @@ describe 'RichText: EditNav', -> makePlainText: @makePlainText = sinon.stub() position: { top: 20, left: 20 } } - @component = ReactDOM.render React.createElement(@EditNav, @props), (@$el = $ "
")[0], => setTimeout => + @component = ReactDOM.render React.createElement(@Nav, @props), (@$el = $ "
")[0], => setTimeout => done() afterEach -> @@ -128,8 +128,8 @@ describe 'RichText: EditNav', -> beforeEach (done) -> benv.setup => benv.expose $: benv.require 'jquery' - @EditNav = benv.requireWithJadeify( - resolve(__dirname, '../components/edit_nav'), ['icons'] + @Nav = benv.requireWithJadeify( + resolve(__dirname, '../components/nav'), ['icons'] ) @props = { hasFeatures: true @@ -141,7 +141,7 @@ describe 'RichText: EditNav', -> makePlainText: @makePlainText = sinon.stub() position: { top: 20, left: 20 } } - @component = ReactDOM.render React.createElement(@EditNav, @props), (@$el = $ "
")[0], => setTimeout => + @component = ReactDOM.render React.createElement(@Nav, @props), (@$el = $ "
")[0], => setTimeout => done() afterEach -> @@ -176,8 +176,8 @@ describe 'RichText: EditNav', -> beforeEach (done) -> benv.setup => benv.expose $: benv.require 'jquery' - @EditNav = benv.requireWithJadeify( - resolve(__dirname, '../components/edit_nav'), ['icons'] + @Nav = benv.requireWithJadeify( + resolve(__dirname, '../components/nav'), ['icons'] ) @props = { hasFeatures: true @@ -189,7 +189,7 @@ describe 'RichText: EditNav', -> makePlainText: @makePlainText = sinon.stub() position: { top: 20, left: 20 } } - @component = ReactDOM.render React.createElement(@EditNav, @props), (@$el = $ "
")[0], => setTimeout => + @component = ReactDOM.render React.createElement(@Nav, @props), (@$el = $ "
")[0], => setTimeout => done() afterEach -> diff --git a/client/components/rich_text2/test/paragraph.coffee b/client/components/rich_text2/test/paragraph.coffee new file mode 100644 index 000000000..a804de9a5 --- /dev/null +++ b/client/components/rich_text2/test/paragraph.coffee @@ -0,0 +1,153 @@ +benv = require 'benv' +{ resolve } = require 'path' +sinon = require 'sinon' +React = require 'react' +ReactDOM = require 'react-dom' +ReactTestUtils = require 'react-addons-test-utils' +ReactDOMServer = require 'react-dom/server' +Draft = require 'draft-js' +{ EditorState, Modifier } = require 'draft-js' + +r = + find: ReactTestUtils.findRenderedDOMComponentWithClass + simulate: ReactTestUtils.Simulate + +describe 'Paragraph', -> + + beforeEach (done) -> + benv.setup => + benv.expose + $: benv.require 'jquery' + window.jQuery = $ + global.Node = () => {} + global.HTMLElement = () => {} + global.HTMLAnchorElement = () => {} + window.getSelection = sinon.stub().returns( + isCollapsed: false + getRangeAt: sinon.stub().returns( + getClientRects: sinon.stub.returns([{ + bottom: 170 + height: 25 + left: 425 + right: 525 + top: 145 + width: 95 + }]) + ) + ) + @Paragraph = benv.require resolve __dirname, '../components/paragraph' + @Paragraph.__set__ 'Modifier', Modifier + @Paragraph.__set__ 'EditorState', EditorState + @Utils = benv.require resolve __dirname, '../utils' + @Paragraph.__set__ 'Utils', @Utils + Config = require '../utils/config.coffee' + @Paragraph.__set__ 'Config', Config + Nav = benv.requireWithJadeify( + resolve(__dirname, '../components/nav'), ['icons'] + ) + @Paragraph.__set__ 'Nav', React.createFactory Nav + InputUrl = benv.requireWithJadeify( + resolve(__dirname, '../components/input_url'), ['icons'] + ) + @Paragraph.__set__ 'InputUrl', React.createFactory InputUrl + @Paragraph.__set__ 'Utils.stickyControlsBox', sinon.stub().returns {top: 20, left: 40} + @Paragraph.__set__ 'Utils.getSelectionLocation', sinon.stub().returns({top: 40, left: 20}) + @Paragraph.__set__ 'Utils.stripGoogleStyles', @stripGoogleStyles = sinon.stub().returns('

hello

here again.

') + @leadParagraph = '

Here is the lead paragraph for this article.

' + @postscript = '

Illustration by Tomi Um.

' + @props = { + html: @postscript + placeholder: 'Postscript (optional)' + onChange: sinon.stub() + linked: true + } + @component = ReactDOM.render React.createElement(@Paragraph, @props), (@$el = $ "
")[0], => setTimeout => + @component.stickyControlsBox = sinon.stub().returns {top: 20, left: 40} + @component.state.editorState.getSelection().isCollapsed = sinon.stub().returns false + selection = @component.state.editorState.getSelection() + newSelection = selection.merge({ + anchorKey: @component.state.editorState.getCurrentContent().getFirstBlock().key + anchorOffset: 0 + focusKey: @component.state.editorState.getCurrentContent().getFirstBlock().key + focusOffset: 12 + }) + newEditorState = EditorState.acceptSelection(@component.state.editorState, newSelection) + @component.onChange newEditorState + done() + + afterEach -> + benv.teardown() + + describe 'Render', -> + + it 'Shows a placeholder if provided and empty', -> + component = ReactDOMServer.renderToString React.createElement(@Paragraph, @props) + $(component).text().should.containEql 'Postscript (optional)' + + it 'Renders existing html', -> + $(ReactDOM.findDOMNode(@component)).text().should.containEql 'Illustration by Tomi Um.' + + it 'Renders existing link entities', -> + $(ReactDOM.findDOMNode(@component)).html().should.containEql '' + + describe 'Key commands', -> + + it 'Can toggle bold styles', -> + @component.setState = sinon.stub() + @component.handleKeyCommand('bold') + @component.setState.args[0][0].html.should.containEql 'Illustration' + + it 'Can toggle italic styles', -> + @component.setState = sinon.stub() + @component.handleKeyCommand('italic') + @component.setState.args[0][0].html.should.containEql 'Illustration' + + it 'Can toggle a link prompt', -> + @component.setState = sinon.stub() + @component.handleKeyCommand('link-prompt') + @component.setState.args[0][0].selectionTarget.should.eql { top: 20, left: 40 } + @component.setState.args[0][0].showUrlInput.should.eql true + + describe '#hasLinks', -> + + it 'returns true if props.linked', -> + component = ReactDOM.render React.createElement(@Paragraph, @props), (@$el = $ "
")[0], => + haslinks = component.hasLinks() + haslinks.should.eql true + + it 'returns true if type is postscript', -> + @props.type = 'postscript' + @props.linked = null + component = ReactDOM.render React.createElement(@Paragraph, @props), (@$el = $ "
")[0], => + haslinks = component.hasLinks() + haslinks.should.eql true + + it 'returns true if type is caption', -> + @props.type = 'caption' + @props.linked = null + component = ReactDOM.render React.createElement(@Paragraph, @props), (@$el = $ "
")[0], => + haslinks = component.hasLinks() + haslinks.should.eql true + + describe 'Links', -> + + it '#confirmLink can save a link as html', -> + @component.confirmLink('http://artsy.net') + (@component.state.html.match(/
+ + it 'calls stripGoogleStyles', -> + @component.onChange = sinon.stub() + @component.onPaste('hello here again.', '

hello

here again.

') + @stripGoogleStyles.called.should.eql true + + xit 'strips linebreaks if linebreaks is false', -> + @component.setState linebreaks: false + + + it 'calls standardizeSpacing', -> + @Utils.standardizeSpacing = sinon.stub() + @component.onChange = sinon.stub() + @component.onPaste('hello here again.', '

hello

here again.

') + @Utils.standardizeSpacing.called.should.eql true