From e788bb8899eb15479431a77f46e576d6887c5e6b Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Wed, 27 Apr 2016 22:32:26 +0200 Subject: [PATCH 01/11] Framework: Upgrade to React 15.1.0, plus two peer dependencies For React 15 compatibility: * qrcode.react 0.6.1 Changelog: https://github.com/zpao/qrcode.react/blob/master/CHANGELOG.md#061---2016-04-13 * react-tap-event-plugin 1.0.0 --- npm-shrinkwrap.json | 89 +++++++++++++++++++++++++-------------------- package.json | 20 +++++----- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 30e995c7e8a70a..5b69cd9a01e1bd 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -460,9 +460,6 @@ "balanced-match": { "version": "0.4.1" }, - "base62": { - "version": "0.1.1" - }, "Base64": { "version": "0.2.1" }, @@ -534,7 +531,7 @@ "version": "1.0.5" }, "brace-expansion": { - "version": "1.1.4" + "version": "1.1.5" }, "braces": { "version": "1.8.5" @@ -1090,9 +1087,6 @@ "entities": { "version": "1.0.0" }, - "envify": { - "version": "3.4.0" - }, "enzyme": { "version": "2.2.0" }, @@ -1703,15 +1697,6 @@ }, "commander": { "version": "2.9.0" - }, - "core-js": { - "version": "1.2.6" - }, - "fbjs": { - "version": "0.8.3" - }, - "react": { - "version": "15.1.0" } } }, @@ -2023,17 +2008,6 @@ "jstimezonedetect": { "version": "1.0.5" }, - "jstransform": { - "version": "10.1.0", - "dependencies": { - "esprima-fb": { - "version": "13001.1001.0-dev-harmony-fb" - }, - "source-map": { - "version": "0.1.31" - } - } - }, "jstransformer": { "version": "0.0.3" }, @@ -2717,6 +2691,9 @@ "pinkie-promise": { "version": "2.0.1" }, + "pkg-conf": { + "version": "1.1.3" + }, "postcss": { "version": "5.0.21", "dependencies": { @@ -2780,7 +2757,7 @@ "version": "0.0.0" }, "qrcode.react": { - "version": "0.5.2" + "version": "0.6.1" }, "qs": { "version": "4.0.0" @@ -2804,33 +2781,33 @@ "version": "2.1.6" }, "react": { - "version": "0.14.3", + "version": "15.1.0", "dependencies": { "core-js": { "version": "1.2.6" }, "fbjs": { - "version": "0.3.2" + "version": "0.8.3" } } }, "react-addons-create-fragment": { - "version": "0.14.3" + "version": "15.1.0" }, "react-addons-css-transition-group": { - "version": "0.14.3" + "version": "15.1.0" }, "react-addons-linked-state-mixin": { - "version": "0.14.3" + "version": "15.1.0" }, "react-addons-shallow-compare": { - "version": "0.14.3" + "version": "15.1.0" }, "react-addons-test-utils": { - "version": "0.14.3" + "version": "15.1.0" }, "react-addons-update": { - "version": "0.14.3" + "version": "15.1.0" }, "react-click-outside": { "version": "2.1.0" @@ -2839,7 +2816,7 @@ "version": "1.3.2" }, "react-dom": { - "version": "0.14.3" + "version": "15.1.0" }, "react-helmet": { "version": "2.2.0", @@ -2884,7 +2861,7 @@ } }, "react-tap-event-plugin": { - "version": "0.2.1", + "version": "1.0.0", "dependencies": { "core-js": { "version": "1.2.6" @@ -3033,6 +3010,9 @@ } } }, + "require-main-filename": { + "version": "1.0.1" + }, "requireindex": { "version": "1.1.0" }, @@ -3108,10 +3088,22 @@ "version": "1.11.1" }, "sass-graph": { - "version": "2.1.1", + "version": "2.1.2", "dependencies": { + "camelcase": { + "version": "3.0.0" + }, + "cliui": { + "version": "3.2.0" + }, "glob": { - "version": "6.0.4" + "version": "7.0.3" + }, + "window-size": { + "version": "0.2.0" + }, + "yargs": { + "version": "4.7.1" } } }, @@ -3178,6 +3170,9 @@ } } }, + "set-blocking": { + "version": "1.0.0" + }, "sha.js": { "version": "2.2.6" }, @@ -3463,6 +3458,9 @@ "swap-case": { "version": "1.1.2" }, + "symbol": { + "version": "0.2.3" + }, "symbol-tree": { "version": "3.1.4" }, @@ -3746,6 +3744,9 @@ "wpcom-xhr-request": { "version": "0.5.0" }, + "wrap-ansi": { + "version": "2.0.0" + }, "wrappy": { "version": "1.0.2" }, @@ -3790,6 +3791,14 @@ }, "yargs": { "version": "3.10.0" + }, + "yargs-parser": { + "version": "2.4.0", + "dependencies": { + "camelcase": { + "version": "2.1.1" + } + } } } } \ No newline at end of file diff --git a/package.json b/package.json index 90294a65a7d04c..daa5e535ddf3fb 100644 --- a/package.json +++ b/package.json @@ -84,22 +84,22 @@ "photon": "2.0.0", "postcss-cli": "2.5.1", "q": "1.0.1", - "qrcode.react": "0.5.2", + "qrcode.react": "0.6.1", "qs": "4.0.0", - "react": "0.14.3", - "react-addons-create-fragment": "0.14.3", - "react-addons-css-transition-group": "0.14.3", - "react-addons-linked-state-mixin": "0.14.3", - "react-addons-shallow-compare": "0.14.3", - "react-addons-update": "0.14.3", + "react": "15.1.0", + "react-addons-create-fragment": "15.1.0", + "react-addons-css-transition-group": "15.1.0", + "react-addons-linked-state-mixin": "15.1.0", + "react-addons-shallow-compare": "15.1.0", + "react-addons-update": "15.1.0", "react-click-outside": "2.1.0", "react-day-picker": "1.3.2", - "react-dom": "0.14.3", + "react-dom": "15.1.0", "react-helmet": "2.2.0", "react-masonry-component": "4.0.4", "react-pure-render": "1.0.2", "react-redux": "4.4.5", - "react-tap-event-plugin": "0.2.1", + "react-tap-event-plugin": "1.0.0", "react-virtualized": "7.2.0", "redux": "3.0.4", "redux-thunk": "1.0.0", @@ -163,7 +163,7 @@ "mocha-junit-reporter": "1.9.1", "mockery": "1.4.0", "nock": "2.17.0", - "react-addons-test-utils": "0.14.3", + "react-addons-test-utils": "15.1.0", "react-hot-loader": "1.3.0", "sinon": "1.12.2", "sinon-chai": "2.7.0", From 83d6d460b298aff1f0ab47618110cb39374befaf Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Wed, 27 Apr 2016 23:08:11 +0200 Subject: [PATCH 02/11] s/fill-rule/fillRule --- client/layout/masterbar/logged-out.jsx | 2 +- client/my-sites/site-settings/delete-site/index.jsx | 2 +- client/my-sites/site-settings/start-over/index.jsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/layout/masterbar/logged-out.jsx b/client/layout/masterbar/logged-out.jsx index 2dc7eaf79de74f..6ae098a2525d37 100644 --- a/client/layout/masterbar/logged-out.jsx +++ b/client/layout/masterbar/logged-out.jsx @@ -16,7 +16,7 @@ import config from 'config'; const MasterbarLoggedOut = ( { title, translate } ) => ( - + { title } diff --git a/client/my-sites/site-settings/delete-site/index.jsx b/client/my-sites/site-settings/delete-site/index.jsx index b1668f3c23f1b1..a379ccd416a74f 100644 --- a/client/my-sites/site-settings/delete-site/index.jsx +++ b/client/my-sites/site-settings/delete-site/index.jsx @@ -107,7 +107,7 @@ module.exports = React.createClass( { - { strings.exportContent }.ZIP + { strings.exportContent }.ZIP { strings.exportContentFirst }

{ diff --git a/client/my-sites/site-settings/start-over/index.jsx b/client/my-sites/site-settings/start-over/index.jsx index e04d6646015380..d85b733fe83f02 100644 --- a/client/my-sites/site-settings/start-over/index.jsx +++ b/client/my-sites/site-settings/start-over/index.jsx @@ -49,7 +49,7 @@ module.exports = React.createClass( { - { strings.startOver } + { strings.startOver } { strings.startOver }

{ From 093835adc96a224dc7a4225f5689982ab80d98ad Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Thu, 12 May 2016 16:30:51 +0200 Subject: [PATCH 03/11] TokenField test: Fix for React 15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests relied on React text elements being wrapped in ``s. The React team considers this behavior an implementation detail and thus [removed](https://facebook.github.io/react/blog/2016/04/07/react-v15.html#no-more-extra-ltspangts) it with React 15, replacing them with comments inserted around text nodes. Text nodes, however, obviously don’t have `innerHtml()`, so we need to use `textContent()` instead, dropping all checks that relied on HTML being returned. Also, when checking for suggested matches, e.g. when entering `’t’`, we were previously checking for `[ '', ’t’, 'he‘ ]`. Since there is no text node inserted for the empty string parts, we need to change checks like these to `[ '', ’t’, 'he‘ ]` instead. Note that this can also be considered an implementation detaill that doesn’t affect functionality — the `TokenField` will continue to suggest the right things, as empty strings weren’t displayed or styled before anyway. --- client/components/token-field/test/index.jsx | 31 ++++++++------ .../token-field/test/lib/fixtures.js | 42 +++++++++---------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/client/components/token-field/test/index.jsx b/client/components/token-field/test/index.jsx index 5b44d175809a7a..3625359ca7c1be 100644 --- a/client/components/token-field/test/index.jsx +++ b/client/components/token-field/test/index.jsx @@ -2,6 +2,7 @@ * External dependencies */ import map from 'lodash/map'; +import filter from 'lodash/filter'; import { expect } from 'chai'; import React from 'react'; import { test } from 'sinon'; @@ -76,13 +77,19 @@ describe( 'TokenField', function() { return getNodeInnerHtml( node ); } - // This suggestion is part of a partial match; return the three + // This suggestion is part of a partial match; return up to three // sections of the suggestion (before match, match, and after // match) const div = document.createElement( 'div' ); div.innerHTML = node.find( 'span' ).html(); - return map( div.firstChild.childNodes, childNode => childNode.innerHTML ); + return map( + filter( + div.firstChild.childNodes, + childNode => childNode.nodeType !== window.Node.COMMENT_NODE + ), + childNode => childNode.textContent + ); } function getSelectedSuggestion() { @@ -203,23 +210,23 @@ describe( 'TokenField', function() { expect( getSuggestionsHTML() ).to.deep.equal( fixtures.matchingSuggestions.t ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'he' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); sendKeyDown( keyCodes.downArrow ); // 'to' - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'o' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); const hoverSuggestion = tokenFieldNode.find( '.token-field__suggestion' ).at( 5 ); // 'it' - expect( getSuggestionNodeHTML( hoverSuggestion ) ).to.deep.equal( [ 'i', 't', '' ] ); + expect( getSuggestionNodeHTML( hoverSuggestion ) ).to.deep.equal( [ 'i', 't' ] ); // before sending a hover event, we need to wait for // SuggestionList#_scrollingIntoView to become false this.clock.tick( 100 ); hoverSuggestion.simulate( 'mouseEnter' ); - expect( getSelectedSuggestion() ).to.deep.equal( [ 'i', 't', '' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 'i', 't' ] ); sendKeyDown( keyCodes.upArrow ); expect( getSelectedSuggestion() ).to.deep.equal( [ 'wi', 't', 'h' ] ); sendKeyDown( keyCodes.upArrow ); - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'his' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'his' ] ); hoverSuggestion.simulate( 'click' ); expect( getSelectedSuggestion() ).to.equal( null ); expect( getTokensHTML() ).to.deep.equal( [ 'foo', 'bar', 'it' ] ); @@ -329,7 +336,7 @@ describe( 'TokenField', function() { testOnBlur( 't', // initialText true, // selectSuggestion - [ '', 't', 'o' ], // expectedSuggestion + [ 't', 'o' ], // expectedSuggestion [ 'foo', 'bar', 'to' ], // expectedTokens this.clock ); @@ -396,9 +403,9 @@ describe( 'TokenField', function() { setText( 't' ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'he' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); sendKeyDown( keyCodes.downArrow ); // 'to' - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'o' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); sendKeyDown( keyCodes.tab ); expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'to' ] ); expect( getSelectedSuggestion() ).to.equal( null ); @@ -408,9 +415,9 @@ describe( 'TokenField', function() { setText( 't' ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'he' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); sendKeyDown( keyCodes.downArrow ); // 'to' - expect( getSelectedSuggestion() ).to.deep.equal( [ '', 't', 'o' ] ); + expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); sendKeyDown( keyCodes.enter ); expect( wrapper.state( 'tokens' ) ).to.deep.equal( [ 'foo', 'bar', 'to' ] ); expect( getSelectedSuggestion() ).to.equal( null ); diff --git a/client/components/token-field/test/lib/fixtures.js b/client/components/token-field/test/lib/fixtures.js index f964e22a333cb8..4a8841b995cc6a 100644 --- a/client/components/token-field/test/lib/fixtures.js +++ b/client/components/token-field/test/lib/fixtures.js @@ -11,39 +11,39 @@ module.exports = { textUnescaped: [ '<3', 'Stuff & Things', 'Tags & Stuff', 'Tags & Stuff 2' ], htmlUnescaped: [ '<3', 'Stuff & Things', 'Tags & Stuff', 'Tags & Stuff 2' ], matchAmpersandUnescaped: [ - [ 'Stuff ', '&', ' Things' ], - [ 'Tags ', '&', ' Stuff' ], - [ 'Tags ', '&', ' Stuff 2' ] + [ 'Stuff ', '&', ' Things' ], + [ 'Tags ', '&', ' Stuff' ], + [ 'Tags ', '&', ' Stuff 2' ] ], matchAmpersandSequence: [ - [ 'Tag', 's &', ' Stuff' ], - [ 'Tag', 's &', ' Stuff 2' ] + [ 'Tag', 's &', ' Stuff' ], + [ 'Tag', 's &', ' Stuff 2' ] ], matchAmpersandEscaped: [] }, matchingSuggestions: { 't': [ - [ '', 't', 'he' ], - [ '', 't', 'o' ], - [ '', 't', 'hat' ], - [ '', 't', 'his' ], + [ 't', 'he' ], + [ 't', 'o' ], + [ 't', 'hat' ], + [ 't', 'his' ], [ 'wi', 't', 'h' ], - [ 'i', 't', '' ], - [ 'no', 't', '' ], - [ 'a', 't', '' ] + [ 'i', 't' ], + [ 'no', 't' ], + [ 'a', 't' ] ], 's': [ - [ '', 's', 'nake' ], - [ '', 's', 'ound' ], - [ 'i', 's', '' ], - [ 'thi', 's', '' ], - [ 'a', 's', '' ], - [ 'wa', 's', '' ], - [ 'pipe', 's', ''] + [ 's', 'nake' ], + [ 's', 'ound' ], + [ 'i', 's' ], + [ 'thi', 's' ], + [ 'a', 's' ], + [ 'wa', 's' ], + [ 'pipe', 's'] ], 'at': [ - [ '', 'at', '' ], - [ 'th', 'at', '' ] + [ 'at' ], + [ 'th', 'at' ] ] } }; From 6cbed2a4fe8d38d9c6faf97252493e4577150ddb Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Thu, 12 May 2016 16:38:56 +0200 Subject: [PATCH 04/11] TokenField test: Placate ESLint --- client/components/token-field/test/lib/fixtures.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/components/token-field/test/lib/fixtures.js b/client/components/token-field/test/lib/fixtures.js index 4a8841b995cc6a..a5b6e8917151c3 100644 --- a/client/components/token-field/test/lib/fixtures.js +++ b/client/components/token-field/test/lib/fixtures.js @@ -22,7 +22,7 @@ module.exports = { matchAmpersandEscaped: [] }, matchingSuggestions: { - 't': [ + t: [ [ 't', 'he' ], [ 't', 'o' ], [ 't', 'hat' ], @@ -32,7 +32,7 @@ module.exports = { [ 'no', 't' ], [ 'a', 't' ] ], - 's': [ + s: [ [ 's', 'nake' ], [ 's', 'ound' ], [ 'i', 's' ], @@ -41,7 +41,7 @@ module.exports = { [ 'wa', 's' ], [ 'pipe', 's'] ], - 'at': [ + at: [ [ 'at' ], [ 'th', 'at' ] ] From 2b57477a25fb07b5edd10d32c41a467ff95d1419 Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Thu, 12 May 2016 16:41:29 +0200 Subject: [PATCH 05/11] TokenField test: Rename getSuggestions(Node)HTML to getSuggestions(Node)Text Since it's really text now that those functions return. --- client/components/token-field/test/index.jsx | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/client/components/token-field/test/index.jsx b/client/components/token-field/test/index.jsx index 3625359ca7c1be..4a70725cd469cb 100644 --- a/client/components/token-field/test/index.jsx +++ b/client/components/token-field/test/index.jsx @@ -66,13 +66,13 @@ describe( 'TokenField', function() { return textNodes.map( getNodeInnerHtml ); } - function getSuggestionsHTML( selector ) { + function getSuggestionsText( selector ) { const suggestionNodes = tokenFieldNode.find( selector || '.token-field__suggestion' ); - return suggestionNodes.map( getSuggestionNodeHTML ); + return suggestionNodes.map( getSuggestionNodeText ); } - function getSuggestionNodeHTML( node ) { + function getSuggestionNodeText( node ) { if ( ! node.find( 'span' ).length ) { return getNodeInnerHtml( node ); } @@ -93,7 +93,7 @@ describe( 'TokenField', function() { } function getSelectedSuggestion() { - var selectedSuggestions = getSuggestionsHTML( '.token-field__suggestion.is-selected' ); + var selectedSuggestions = getSuggestionsText( '.token-field__suggestion.is-selected' ); return selectedSuggestions[ 0 ] || null; } @@ -142,38 +142,38 @@ describe( 'TokenField', function() { describe( 'suggestions', function() { it( 'should render default suggestions', function() { // limited by maxSuggestions (default 100 so doesn't matter here) - expect( getSuggestionsHTML() ).to.deep.equal( wrapper.state( 'tokenSuggestions' ) ); + expect( getSuggestionsText() ).to.deep.equal( wrapper.state( 'tokenSuggestions' ) ); } ); it( 'should remove already added tags from suggestions', function() { wrapper.setState( { tokens: Object.freeze( [ 'of', 'and' ] ) } ); - expect( getSuggestionsHTML() ).to.not.include.members( getTokensHTML() ); + expect( getSuggestionsText() ).to.not.include.members( getTokensHTML() ); } ); it( 'should suggest partial matches', function() { setText( 't' ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.matchingSuggestions.t ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.t ); } ); it( 'suggestions that begin with match are boosted', function() { setText( 's' ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.matchingSuggestions.s ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.s ); } ); it( 'should display suggestions with escaped special characters properly', function() { wrapper.setState( { tokenSuggestions: fixtures.specialSuggestions.textEscaped } ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.specialSuggestions.htmlEscaped ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.htmlEscaped ); } ); it( 'should display suggestions with special characters properly', function() { wrapper.setState( { tokenSuggestions: fixtures.specialSuggestions.textUnescaped } ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.specialSuggestions.htmlUnescaped ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.htmlUnescaped ); } ); it( 'should match against the unescaped values of suggestions with special characters', function() { @@ -181,7 +181,7 @@ describe( 'TokenField', function() { wrapper.setState( { tokenSuggestions: fixtures.specialSuggestions.textUnescaped } ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.specialSuggestions.matchAmpersandUnescaped ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.matchAmpersandUnescaped ); } ); it( 'should match against the unescaped values of suggestions with special characters (including spaces)', function() { @@ -189,7 +189,7 @@ describe( 'TokenField', function() { wrapper.setState( { tokenSuggestions: fixtures.specialSuggestions.textUnescaped } ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.specialSuggestions.matchAmpersandSequence ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.matchAmpersandSequence ); } ); it( 'should not match against the escaped values of suggestions with special characters', function() { @@ -197,17 +197,17 @@ describe( 'TokenField', function() { wrapper.setState( { tokenSuggestions: fixtures.specialSuggestions.textUnescaped } ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.specialSuggestions.matchAmpersandEscaped ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.specialSuggestions.matchAmpersandEscaped ); } ); it( 'should match suggestions even with trailing spaces', function() { setText( ' at ' ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.matchingSuggestions.at ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.at ); } ); it( 'should manage the selected suggestion based on both keyboard and mouse events', test( function() { setText( 't' ); - expect( getSuggestionsHTML() ).to.deep.equal( fixtures.matchingSuggestions.t ); + expect( getSuggestionsText() ).to.deep.equal( fixtures.matchingSuggestions.t ); expect( getSelectedSuggestion() ).to.equal( null ); sendKeyDown( keyCodes.downArrow ); // 'the' expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'he' ] ); @@ -215,7 +215,7 @@ describe( 'TokenField', function() { expect( getSelectedSuggestion() ).to.deep.equal( [ 't', 'o' ] ); const hoverSuggestion = tokenFieldNode.find( '.token-field__suggestion' ).at( 5 ); // 'it' - expect( getSuggestionNodeHTML( hoverSuggestion ) ).to.deep.equal( [ 'i', 't' ] ); + expect( getSuggestionNodeText( hoverSuggestion ) ).to.deep.equal( [ 'i', 't' ] ); // before sending a hover event, we need to wait for // SuggestionList#_scrollingIntoView to become false From 9c159680852f66581317047d6cb59c5d009a3243 Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Thu, 12 May 2016 16:47:05 +0200 Subject: [PATCH 06/11] TrackInputChanges test: Update expected error message to match React 15 --- client/components/track-input-changes/test/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/components/track-input-changes/test/index.jsx b/client/components/track-input-changes/test/index.jsx index 092a7e58cba203..9a816b6853b8e1 100644 --- a/client/components/track-input-changes/test/index.jsx +++ b/client/components/track-input-changes/test/index.jsx @@ -3,7 +3,7 @@ */ import ReactDom from 'react-dom'; import React from 'react'; -import TestUtils from 'react-addons-test-utils' +import TestUtils from 'react-addons-test-utils'; import { expect } from 'chai'; import sinon from 'sinon'; import useFakeDom from 'test/helpers/use-fake-dom'; @@ -120,6 +120,6 @@ describe( 'TrackInputChanges#onNewValue', function() { /> , container - ) ).to.throw( 'Invariant Violation' ); + ) ).to.throw( 'onlyChild must be passed a children with exactly one child.' ); } ); } ); From c2101acf7338e497e083cc4bfa0aa5e6cf7a7b5f Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Tue, 24 May 2016 00:10:11 +0200 Subject: [PATCH 07/11] Wrap text nodes in span elements for styling Up to React 15, React text elements were being wrapped in ``s. The React team considered this behavior an implementation detail and thus [removed](https://facebook.github.io/react/blog/2016/04/07/react-v15.html#no-more-extra-ltspangts) it with React 15, replacing them with comments inserted around text nodes. However, some of our styling relied on those spans. This commit seeks to re-add those `span`s manually, or adapt the styling where applicable. Essentially, I looked for SASS selectors like `span {` or `span,` and searched for the corresponding React code. --- client/components/accordion/docs/example.jsx | 2 +- .../components/bulk-select/docs/example.jsx | 2 +- .../components/forms/multi-checkbox/README.md | 4 +-- .../components/forms/multi-checkbox/index.jsx | 4 +-- .../global-notices/docs/example.jsx | 2 +- client/components/notice/index.jsx | 12 ++++++--- client/components/section-header/index.jsx | 2 +- .../plugins/contact-form/dialog/field.jsx | 2 +- .../reader-subscriptions/index.jsx | 4 +-- .../cancel-private-registration/index.jsx | 4 +-- .../security-2fa-backup-codes-list/index.jsx | 2 +- .../category-selector/add-category.jsx | 2 +- .../my-sites/menus/menu-item-drop-target.jsx | 1 - client/my-sites/menus/menu-name.jsx | 12 ++++----- client/my-sites/menus/menu.jsx | 10 +++---- .../my-sites/post-selector/docs/example.jsx | 2 +- client/my-sites/posts/post.jsx | 2 +- .../my-sites/site-settings/form-writing.jsx | 2 +- .../stats/stats-module/placeholder.scss | 2 +- .../checkout/privacy-protection-example.jsx | 2 +- .../email/add-google-apps-card.jsx | 26 ++++++++++--------- .../post-editor/editor-discussion/index.jsx | 2 +- .../editor-sharing/publicize-connection.jsx | 2 +- .../editor-sharing/publicize-options.jsx | 4 +-- .../editor-sharing/sharing-like-options.jsx | 4 +-- .../post-editor/editor-visibility/index.jsx | 16 +++++++----- client/reader/share/index.jsx | 4 +-- 27 files changed, 71 insertions(+), 62 deletions(-) diff --git a/client/components/accordion/docs/example.jsx b/client/components/accordion/docs/example.jsx index 130a01f123d10b..eaf91f5b7fb36c 100644 --- a/client/components/accordion/docs/example.jsx +++ b/client/components/accordion/docs/example.jsx @@ -41,7 +41,7 @@ module.exports = React.createClass( { checked={ this.state.showSubtitles } onChange={ this._toggleShowSubtitles } /> - Show subtitles + Show subtitles diff --git a/client/components/bulk-select/docs/example.jsx b/client/components/bulk-select/docs/example.jsx index 8cf948f48d84ed..04686b0cb6e669 100644 --- a/client/components/bulk-select/docs/example.jsx +++ b/client/components/bulk-select/docs/example.jsx @@ -44,7 +44,7 @@ module.exports = React.createClass( { return ( ); } ); diff --git a/client/components/forms/multi-checkbox/README.md b/client/components/forms/multi-checkbox/README.md index 8347ee6c598ab4..03f30135758fa1 100644 --- a/client/components/forms/multi-checkbox/README.md +++ b/client/components/forms/multi-checkbox/README.md @@ -20,8 +20,8 @@ This code snippet will generate the following output: ```html

- - + +
``` diff --git a/client/components/forms/multi-checkbox/index.jsx b/client/components/forms/multi-checkbox/index.jsx index 788b4c6e3bd1c3..e338251b65edc4 100644 --- a/client/components/forms/multi-checkbox/index.jsx +++ b/client/components/forms/multi-checkbox/index.jsx @@ -54,7 +54,7 @@ var MultiCheckbox = module.exports = React.createClass({ return ( ); }, this ); @@ -63,4 +63,4 @@ var MultiCheckbox = module.exports = React.createClass({ render: function() { return
{ this.getCheckboxElements() }
; } -}); +} ); diff --git a/client/components/global-notices/docs/example.jsx b/client/components/global-notices/docs/example.jsx index a02f42e3fb7005..505c68a0853b0f 100644 --- a/client/components/global-notices/docs/example.jsx +++ b/client/components/global-notices/docs/example.jsx @@ -50,7 +50,7 @@ class GlobalNotices extends Component { - Use global application state + Use global application state diff --git a/client/components/notice/index.jsx b/client/components/notice/index.jsx index 040611cff1bca1..7bb11c23eb8deb 100644 --- a/client/components/notice/index.jsx +++ b/client/components/notice/index.jsx @@ -51,15 +51,21 @@ export default React.createClass( { }, renderChildren() { - let content; + let content, text; if ( typeof this.props.children === 'string' ) { - return { this.props.children }; + return { this.props.children }; } if ( this.props.text ) { + if ( typeof this.props.text === 'string' ) { + text = { this.props.text }; + } else { + text = this.props.text; + } + content = [ this.props.children ]; - content.unshift( { this.props.text } ); + content.unshift( { text } ); } else { content = { this.props.children }; } diff --git a/client/components/section-header/index.jsx b/client/components/section-header/index.jsx index 14918b6815a4d3..05143d51b044a1 100644 --- a/client/components/section-header/index.jsx +++ b/client/components/section-header/index.jsx @@ -29,7 +29,7 @@ export default React.createClass( { return (
- { this.props.label } + { this.props.label } { 'number' === typeof this.props.count && diff --git a/client/components/tinymce/plugins/contact-form/dialog/field.jsx b/client/components/tinymce/plugins/contact-form/dialog/field.jsx index 1a56a737d7d4b5..002ad8dc920aa8 100644 --- a/client/components/tinymce/plugins/contact-form/dialog/field.jsx +++ b/client/components/tinymce/plugins/contact-form/dialog/field.jsx @@ -106,7 +106,7 @@ export default React.createClass( { this.props.onUpdate( { required: ! this.props.required } ) } /> - { this.translate( 'Required' ) } + { this.translate( 'Required' ) } diff --git a/client/me/notification-settings/reader-subscriptions/index.jsx b/client/me/notification-settings/reader-subscriptions/index.jsx index 7eaeaf8aeb7100..56817b72bce590 100644 --- a/client/me/notification-settings/reader-subscriptions/index.jsx +++ b/client/me/notification-settings/reader-subscriptions/index.jsx @@ -89,7 +89,7 @@ module.exports = React.createClass( { id="subscription_delivery_jabber_default" name="subscription_delivery_jabber_default" onClick={ this.recordCheckboxEvent( 'Notification Delivery by Jabber' ) } /> - { this.translate( 'Default delivery via Jabber instant message' ) } + { this.translate( 'Default delivery via Jabber instant message' ) } @@ -158,7 +158,7 @@ module.exports = React.createClass( { id="subscription_delivery_email_blocked" name="subscription_delivery_email_blocked" onClick={ this.recordCheckboxEvent( 'Block All Notification Emails' ) }/> - { this.translate( 'Block all email updates from blogs you’re following on WordPress.com' ) } + { this.translate( 'Block all email updates from blogs you’re following on WordPress.com' ) } diff --git a/client/me/purchases/cancel-private-registration/index.jsx b/client/me/purchases/cancel-private-registration/index.jsx index 6c5e6a7b16e4e7..9476049de0419f 100644 --- a/client/me/purchases/cancel-private-registration/index.jsx +++ b/client/me/purchases/cancel-private-registration/index.jsx @@ -186,10 +186,10 @@ const CancelPrivateRegistration = React.createClass( { { notice }
- { descriptionText } + { descriptionText }
- { warningText } + { warningText }
{ button } diff --git a/client/me/security-2fa-backup-codes-list/index.jsx b/client/me/security-2fa-backup-codes-list/index.jsx index 8c4c65dbb77232..5ee00e9f5e4131 100644 --- a/client/me/security-2fa-backup-codes-list/index.jsx +++ b/client/me/security-2fa-backup-codes-list/index.jsx @@ -201,7 +201,7 @@ module.exports = React.createClass( { defaultChecked={ this.state.userAgrees } onChange={ this.onUserAgreesChange } /> - { this.translate( 'I have printed or saved these codes', { context: 'The codes are the backup codes for Two-Step Authentication.' } ) } + { this.translate( 'I have printed or saved these codes', { context: 'The codes are the backup codes for Two-Step Authentication.' } ) } - { this.translate( 'Top level category', { context: 'Categories: New category being created is top level i.e. has no parent' } ) } + { this.translate( 'Top level category', { context: 'Categories: New category being created is top level i.e. has no parent' } ) } - { this.state.value } + { this.state.value } ); @@ -73,9 +73,9 @@ var MenuName = React.createClass({ return menuEditable; } -}); +} ); -var TemporaryInput = React.createClass({ +var TemporaryInput = React.createClass( { getInitialState: function() { return { @@ -88,7 +88,7 @@ var TemporaryInput = React.createClass({ node.focus(); try { node.setSelectionRange( 0, 999 ); - } catch (e) { + } catch ( e ) { debug( 'setSelectionRange failed' ); } }, @@ -119,6 +119,6 @@ var TemporaryInput = React.createClass({ value={ this.state.value } /> ); } -}); +} ); module.exports = MenuName; diff --git a/client/my-sites/menus/menu.jsx b/client/my-sites/menus/menu.jsx index 0c536f0a40a6ed..e19682db8aef32 100644 --- a/client/my-sites/menus/menu.jsx +++ b/client/my-sites/menus/menu.jsx @@ -13,7 +13,7 @@ var protectForm = require( 'lib/mixins/protect-form' ), classNames = require( 'classnames' ), MenuName = require( './menu-name' ), MenuItemList = require( './menu-item-list' ), - MenuDeleteButton = require ( './menu-delete-button' ), + MenuDeleteButton = require( './menu-delete-button' ), MenuSaveButton = require( './menus-save-button' ), MenuRevertButton = require( './menus-revert-button' ), analytics = require( 'lib/analytics' ); @@ -71,7 +71,6 @@ var Menu = React.createClass( { moveOp = this.getMoveOperation( x, y, item ); if ( moveOp && ! this.operationsEqual( moveOp, this.previousOp ) ) { - // prevent drop of item into its own subtree if ( menuData.isAncestor( this.draggedItem, item ) ) { return; @@ -203,10 +202,11 @@ var Menu = React.createClass( { }, renderAddTip: function() { - return ! this.getEditItem() ? -
+ return ! this.getEditItem() + ?
{ this.translate( 'Add new item' ) } -
: null; +
+ : null; }, updateTitleEditing: function( editing ) { diff --git a/client/my-sites/post-selector/docs/example.jsx b/client/my-sites/post-selector/docs/example.jsx index 5b68e23aa69158..2645d5ef7bb279 100644 --- a/client/my-sites/post-selector/docs/example.jsx +++ b/client/my-sites/post-selector/docs/example.jsx @@ -35,7 +35,7 @@ const PostSelectorExample = React.createClass( { type="checkbox" checked={ this.state.showTypeLabels } onChange={ () => this.setState( { showTypeLabels: ! this.state.showTypeLabels } ) } /> - Show Type Labels + Show Type Labels { this.props.sites.initialized && ( { item } ); + return (
  • { item }
  • ); }, this ); return (
      { footerMetaItems }
    ); diff --git a/client/my-sites/site-settings/form-writing.jsx b/client/my-sites/site-settings/form-writing.jsx index 24a72da200a0a6..878467a5992f88 100644 --- a/client/my-sites/site-settings/form-writing.jsx +++ b/client/my-sites/site-settings/form-writing.jsx @@ -176,7 +176,7 @@ const SiteSettingsFormWriting = React.createClass( { onClick={ this.recordEvent.bind( this, 'Clicked Press This Button' ) } onDragStart={ this.recordEvent.bind( this, 'Dragged Press This Button' ) }> - { this.translate( 'Press This', { context: 'name of browser bookmarklet tool' } ) } + { this.translate( 'Press This', { context: 'name of browser bookmarklet tool' } ) }

    diff --git a/client/my-sites/stats/stats-module/placeholder.scss b/client/my-sites/stats/stats-module/placeholder.scss index e54d466107f337..01b906e4ecc3de 100644 --- a/client/my-sites/stats/stats-module/placeholder.scss +++ b/client/my-sites/stats/stats-module/placeholder.scss @@ -63,7 +63,7 @@ // Make text invisible .module-content-list-header .label, .module-content-list-header .value, - .module-header-title span, + .module-header-title, ul.module-content-tabs li:hover .label, ul.module-content-tabs li.module-tab.is-selected:hover .label { color: $transparent; diff --git a/client/my-sites/upgrades/checkout/privacy-protection-example.jsx b/client/my-sites/upgrades/checkout/privacy-protection-example.jsx index 23198b32e1d487..8d324ca7a6a21f 100644 --- a/client/my-sites/upgrades/checkout/privacy-protection-example.jsx +++ b/client/my-sites/upgrades/checkout/privacy-protection-example.jsx @@ -80,7 +80,7 @@ module.exports = React.createClass( { } return ( -

    { lines }

    +

    { lines.map( l => { l } ) }

    ); } } ); diff --git a/client/my-sites/upgrades/domain-management/email/add-google-apps-card.jsx b/client/my-sites/upgrades/domain-management/email/add-google-apps-card.jsx index f77447b9f7ae28..622dfc822d7364 100644 --- a/client/my-sites/upgrades/domain-management/email/add-google-apps-card.jsx +++ b/client/my-sites/upgrades/domain-management/email/add-google-apps-card.jsx @@ -48,19 +48,21 @@ const AddGoogleAppsCard = React.createClass( {

    - { - this.translate( - '{{strong}}%(price)s{{/strong}} per user / month', - { - components: { - strong: - }, - args: { - price: price + + { + this.translate( + '{{strong}}%(price)s{{/strong}} per user / month', + { + components: { + strong: + }, + args: { + price: price + } } - } - ) - } + ) + } +

    | diff --git a/client/post-editor/editor-discussion/index.jsx b/client/post-editor/editor-discussion/index.jsx index f45e1e612984f5..af1166607265ce 100644 --- a/client/post-editor/editor-discussion/index.jsx +++ b/client/post-editor/editor-discussion/index.jsx @@ -102,7 +102,7 @@ export default React.createClass( { checked={ statusToBoolean( discussion.ping_status ) } disabled={ ! this.props.post } onChange={ this.onChange } /> - { this.translate( 'Allow Pingbacks & Trackbacks' ) } + { this.translate( 'Allow Pingbacks & Trackbacks' ) } ); diff --git a/client/post-editor/editor-sharing/publicize-connection.jsx b/client/post-editor/editor-sharing/publicize-connection.jsx index 74c8effa4c8e6f..250be9d3db7898 100644 --- a/client/post-editor/editor-sharing/publicize-connection.jsx +++ b/client/post-editor/editor-sharing/publicize-connection.jsx @@ -99,7 +99,7 @@ export default React.createClass( { checked={ ! this.isConnectionSkipped() } disabled={ this.isDisabled() } onChange={ this.onChange } /> - { connection && connection.external_display } + { connection && connection.external_display } { this.renderBrokenConnection() }
    diff --git a/client/post-editor/editor-sharing/publicize-options.jsx b/client/post-editor/editor-sharing/publicize-options.jsx index d1ab347634ccce..22e28b3c35fb6d 100644 --- a/client/post-editor/editor-sharing/publicize-options.jsx +++ b/client/post-editor/editor-sharing/publicize-options.jsx @@ -181,7 +181,7 @@ module.exports = React.createClass( { if ( this.props.site && this.props.site.options.publicize_permanently_disabled ) { return (
    -

    { this.translate( 'Publicize is disabled on this site.' ) }

    +

    { this.translate( 'Publicize is disabled on this site.' ) }

    ); } @@ -189,7 +189,7 @@ module.exports = React.createClass( { if ( this.props.site && this.props.site.jetpack && ! this.props.site.isModuleActive( 'publicize' ) ) { return (
    -

    { this.translate( 'Enable the Publicize module to automatically share new posts to social networks.' ) }

    +

    { this.translate( 'Enable the Publicize module to automatically share new posts to social networks.' ) }