# This tests the basic Contenteditable component. For various modules of # the contenteditable (such as selection, tooltip, quoting, etc) see the # related test files. # _ = require "underscore" fs = require 'fs' React = require "react/addons" ReactTestUtils = React.addons.TestUtils ContenteditableComponent = require "../lib/contenteditable-component", describe "ContenteditableComponent", -> beforeEach -> @onChange = jasmine.createSpy('onChange') html = 'Test HTML' @component = ReactTestUtils.renderIntoDocument( ) @editableNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithAttr(@component, 'contentEditable')) describe "render", -> it 'should render into the document', -> expect(ReactTestUtils.isCompositeComponentWithType @component, ContenteditableComponent).toBe true it "should include a content-editable div", -> expect(@editableNode).toBeDefined() describe "when the html is changed", -> beforeEach -> @changedHtmlWithoutQuote = 'Changed NEW 1 HTML
' @performEdit = (newHTML, component = @component) => @editableNode.innerHTML = newHTML ReactTestUtils.Simulate.input(@editableNode, {target: {value: newHTML}}) it "should fire `props.onChange`", -> @performEdit('Test New HTML') expect(@onChange).toHaveBeenCalled() # One day we may make this more efficient. For now we aggressively # re-render because of the manual cursor positioning. it "should fire if the html is the same", -> expect(@onChange.callCount).toBe(0) @performEdit(@changedHtmlWithoutQuote) expect(@onChange.callCount).toBe(1) @performEdit(@changedHtmlWithoutQuote) expect(@onChange.callCount).toBe(2) describe "pasting", -> beforeEach -> describe "when a file item is present", -> beforeEach -> @mockEvent = preventDefault: jasmine.createSpy('preventDefault') clipboardData: items: [{ kind: 'file' type: 'image/png' getAsFile: -> new Blob(['12341352312411'], {type : 'image/png'}) }] it "should save the image to a temporary file and call `onFilePaste`", -> onPaste = jasmine.createSpy('onPaste') @component = ReactTestUtils.renderIntoDocument( ) @editableNode = React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithAttr(@component, 'contentEditable')) runs -> ReactTestUtils.Simulate.paste(@editableNode, @mockEvent) waitsFor -> onPaste.callCount > 0 runs -> path = require('path') file = onPaste.mostRecentCall.args[0] expect(path.basename(file)).toEqual('Pasted File.png') contents = fs.readFileSync(file) expect(contents.toString()).toEqual('12341352312411') describe "when html and plain text parts are present", -> beforeEach -> @mockEvent = preventDefault: jasmine.createSpy('preventDefault') clipboardData: getData: -> return 'This is text' if 'text/html' return 'This is plain text' if 'text/plain' return null items: [{ kind: 'string' type: 'text/html' getAsString: -> 'This is text' },{ kind: 'string' type: 'text/plain' getAsString: -> 'This is plain text' }] it "should sanitize the HTML string and call insertHTML", -> spyOn(document, 'execCommand') spyOn(@component, '_sanitizeInput').andCallThrough() runs -> ReactTestUtils.Simulate.paste(@editableNode, @mockEvent) waitsFor -> document.execCommand.callCount > 0 runs -> expect(@component._sanitizeInput).toHaveBeenCalledWith('This is text', 'text/html') [command, a, html] = document.execCommand.mostRecentCall.args expect(command).toEqual('insertHTML') expect(html).toEqual('This is text') describe "when html and plain text parts are present", -> beforeEach -> @mockEvent = preventDefault: jasmine.createSpy('preventDefault') clipboardData: getData: -> return 'This is plain text' if 'text/plain' return null items: [{ kind: 'string' type: 'text/plain' getAsString: -> 'This is plain text' }] it "should sanitize the plain text string and call insertHTML", -> spyOn(document, 'execCommand') spyOn(@component, '_sanitizeInput').andCallThrough() runs -> ReactTestUtils.Simulate.paste(@editableNode, @mockEvent) waitsFor -> document.execCommand.callCount > 0 runs -> expect(@component._sanitizeInput).toHaveBeenCalledWith('This is plain text', 'text/html') [command, a, html] = document.execCommand.mostRecentCall.args expect(command).toEqual('insertHTML') expect(html).toEqual('This is plain text') describe "sanitization", -> tests = [ { in: "" sanitizedAsHTML: "" sanitizedAsPlain: "" }, { in: "Hello World" sanitizedAsHTML: "Hello World" sanitizedAsPlain: "Hello World" }, { in: " Hello World" # Should collapse to 1 space when rendered sanitizedAsHTML: " Hello World" # Preserving 2 spaces sanitizedAsPlain: "  Hello  World" }, { in: " Hello World" sanitizedAsHTML: " Hello World" # Preserving 3 spaces sanitizedAsPlain: "   Hello   World" }, { in: " Hello World" sanitizedAsHTML: " Hello World" # Preserving 4 spaces sanitizedAsPlain: "    Hello    World" }, { in: "Hello\nWorld" sanitizedAsHTML: "Hello
World" # Convert newline to br sanitizedAsPlain: "Hello
World" }, { in: "Hello\rWorld" sanitizedAsHTML: "Hello
World" # Convert carriage return to br sanitizedAsPlain: "Hello
World" }, { in: "Hello\n\n\nWorld" # Never have more than 2 br's in a row sanitizedAsHTML: "Hello

World" # Convert multiple newlines to same number of brs sanitizedAsPlain: "Hello


World" }, { in: " Foo Bar
Baz
" # Strip bad tags sanitizedAsHTML: " Foo Bar Baz" # HTML encode tags for literal display sanitizedAsPlain: "<style>Yo</style> Foo Bar <div>Baz</div>" }, { in: " Yo < script>Boo! < / script >" # Strip non white-list tags and encode malformed ones. sanitizedAsHTML: " Yo < script>Boo! < / script >" # HTML encode tags for literal display sanitizedAsPlain: "<script>Bah</script> Yo < script>Boo! < / script >" }, { in: """ """ # Strip non white-list tags and encode malformed ones. sanitizedAsHTML: "" # HTML encode tags for literal display sanitizedAsPlain: "<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="1265.21">
<style type="text/css">
li.li1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
ul.ul1 {list-style-type: disc}
</style>
</head>
<body>
<ul class="ul1">
<li class="li1"><b>Packet pickup: </b>I'll pick up my packet at some point on Saturday at Fort Mason. Let me know if you'd like me to get yours. I'll need a photo of your ID and your confirmation number. Also, shirt color preference, I believe. Gray or black? Can't remember...</li>
</ul>
</body>
</html>" } ] it "sanitizes plain text properly", -> for test in tests expect(@component._sanitizeInput(test.in, "text/plain")).toBe test.sanitizedAsPlain it "sanitizes html text properly", -> for test in tests expect(@component._sanitizeInput(test.in, "text/html")).toBe test.sanitizedAsHTML