From dcfbfd33b26b5ad67eb9fb5fdec5e193b90cecac Mon Sep 17 00:00:00 2001 From: Alexandre Cordeiro Date: Thu, 7 Dec 2017 20:15:00 -0200 Subject: [PATCH 1/2] (WIP) Use only public API for getNodeForCharacterOffset test (#11299) --- .../getNodeForCharacterOffset-test.js | 112 +++++++++--------- 1 file changed, 54 insertions(+), 58 deletions(-) diff --git a/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js b/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js index 6df208437f073..efa67dc780b24 100644 --- a/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js +++ b/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js @@ -9,74 +9,70 @@ 'use strict'; -// TODO: can we express this test with only public API? -var getNodeForCharacterOffset = require('../getNodeForCharacterOffset').default; +describe('getNodeForCharacterOffset', () => { + var React; + var ReactDOM; -// Create node from HTML string -function createNode(html) { - var node = (getTestDocument() || document).createElement('div'); - node.innerHTML = html; - return node; -} + beforeEach(() => { + React = require('react'); + ReactDOM = require('react-dom'); + }); -function getTestDocument(markup) { - var doc = document.implementation.createHTMLDocument(''); - doc.open(); - doc.write( - markup || - 'test doc', - ); - doc.close(); - return doc; -} + it('should re-render an input with the same selection', done => { + const container = document.createElement('div'); + let node, component; + document.body.appendChild(container); -// Check getNodeForCharacterOffset return value matches expected result. -function expectNodeOffset(result, textContent, nodeOffset) { - expect(result.node.textContent).toBe(textContent); - expect(result.offset).toBe(nodeOffset); -} + class InputComponent extends React.Component { + constructor(props) { + super(props); -describe('getNodeForCharacterOffset', () => { - it('should handle siblings', () => { - var node = createNode('123456789'); + this.state = { + oneFirst: true, + oneValue: 'foo', + twoValue: 'foo', + }; + } - expectNodeOffset(getNodeForCharacterOffset(node, 0), '123', 0); - expectNodeOffset(getNodeForCharacterOffset(node, 4), '456', 1); - }); + componentWillMount() { + component = this; + } - it('should handle trailing chars', () => { - var node = createNode('123456789'); + handleChange(e) { + this.setState({value: e.target.value}); + } - expectNodeOffset(getNodeForCharacterOffset(node, 3), '123', 3); - expectNodeOffset(getNodeForCharacterOffset(node, 9), '789', 3); - }); + renderForms() { + if (this.state.oneFirst) { + return [ + (node = e)} + readOnly={true} + />, + , + ]; + } else { + return [ + , + , + ]; + } + } - it('should handle trees', () => { - var node = createNode( - '' + - '1' + - '' + - '' + - '2' + - '' + - '' + - '' + - '' + - '3' + - '45' + - '' + - '', - ); + render() { + return
{this.renderForms()}
; + } + } - expectNodeOffset(getNodeForCharacterOffset(node, 3), '3', 1); - expectNodeOffset(getNodeForCharacterOffset(node, 5), '45', 2); - expect(getNodeForCharacterOffset(node, 10)).toBeUndefined(); - }); + ReactDOM.render(, container); - it('should handle non-existent offset', () => { - var node = createNode('123'); + node.focus(); + node.setSelectionRange(0, 1); - expect(getNodeForCharacterOffset(node, -1)).toBeUndefined(); - expect(getNodeForCharacterOffset(node, 4)).toBeUndefined(); + component.setState({oneFirst: false}, () => { + done(); + }); }); }); From 7469f0390325c36439b064fb37a343ffdc51216f Mon Sep 17 00:00:00 2001 From: Alexandre Cordeiro Date: Tue, 19 Dec 2017 20:09:59 -0200 Subject: [PATCH 2/2] (WIP) Improve getNodeForCharacterOffset test to exercise it via public API --- .../getNodeForCharacterOffset-test.js | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js b/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js index efa67dc780b24..6e662d264dfb5 100644 --- a/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js +++ b/packages/react-dom/src/client/__tests__/getNodeForCharacterOffset-test.js @@ -69,10 +69,48 @@ describe('getNodeForCharacterOffset', () => { ReactDOM.render(, container); node.focus(); - node.setSelectionRange(0, 1); + node.setSelectionRange(1, 1); - component.setState({oneFirst: false}, () => { - done(); + const inputDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'selectionStart'); + + delete HTMLInputElement.prototype.selectionStart; + + let startMarkerNode, startMarkerOffset; + let endMarkerNode, endMarkerOffset; + + // These aren't implemented by jsdom yet, so let's re-implement them + // to test the markers created by getNodeForCharacterOffset + + window.getSelection = () => ({ + removeAllRanges: function() { + return true; + }, + addRange: function(range) {}, + extend: function(endNode, endOffset) { + endMarkerNode = endNode; + endMarkerOffset = endOffset; + }, }); + + document.createRange = () => ({ + setStart: function(startNode, startOffset) { + startMarkerNode = startNode; + startMarkerOffset = startOffset; + }, + setEnd: function(endNode, endOffset) { + endMarkerNode = endNode; + endMarkerOffset = endOffset; + }, + }); + + try { + component.setState({oneFirst: false}, () => { + console.log(startMarkerNode, startMarkerOffset); + console.log(endMarkerNode, endMarkerOffset); + done(); + }); + } finally { + Object.defineProperty(HTMLInputElement.prototype, 'selectionStart', inputDescriptor); + } }); });