react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / core / __tests__ / ReactInstanceHandles-test.js
81155 views/**1* Copyright 2013-2014, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @emails react-core9*/1011"use strict";1213var React = require('React');14var ReactTestUtils = require('ReactTestUtils');15var ReactMount = require('ReactMount');1617/**18* Ensure that all callbacks are invoked, passing this unique argument.19*/20var ARG = {arg: true};21var ARG2 = {arg2: true};2223var ChildComponent = React.createClass({24render: function() {25return (26<div ref="DIV">27<div ref="DIV_1" />28<div ref="DIV_2" />29</div>30);31}32});3334var ParentComponent = React.createClass({35render: function() {36return (37<div ref="P">38<div ref="P_P1">39<ChildComponent ref="P_P1_C1" />40<ChildComponent ref="P_P1_C2" />41</div>42<div ref="P_OneOff" />43</div>44);45}46});4748function renderParentIntoDocument() {49return ReactTestUtils.renderIntoDocument(<ParentComponent />);50}5152describe('ReactInstanceHandles', function() {53var ReactInstanceHandles;5455var aggregatedArgs;56function argAggregator(id, isUp, arg) {57aggregatedArgs.push({58id: id,59isUp: isUp,60arg: arg61});62}6364beforeEach(function() {65ReactInstanceHandles = require('ReactInstanceHandles');66aggregatedArgs = [];67});6869describe('isRenderedByReact', function() {70it('should not crash on text nodes', function() {71expect(function() {72ReactMount.isRenderedByReact(document.createTextNode('yolo'));73}).not.toThrow();74});75});7677describe('findComponentRoot', function() {78it('should find the correct node with prefix sibling IDs', function() {79var parentNode = document.createElement('div');80var childNodeA = document.createElement('div');81var childNodeB = document.createElement('div');82parentNode.appendChild(childNodeA);83parentNode.appendChild(childNodeB);8485ReactMount.setID(parentNode, '.0');86ReactMount.setID(childNodeA, '.0.0');87ReactMount.setID(childNodeB, '.0.0:1');8889expect(90ReactMount.findComponentRoot(91parentNode,92ReactMount.getID(childNodeB)93)94).toBe(childNodeB);95});9697it('should work around unidentified nodes', function() {98var parentNode = document.createElement('div');99var childNodeA = document.createElement('div');100var childNodeB = document.createElement('div');101parentNode.appendChild(childNodeA);102parentNode.appendChild(childNodeB);103104ReactMount.setID(parentNode, '.0');105// No ID on `childNodeA`.106ReactMount.setID(childNodeB, '.0.0:1');107108expect(109ReactMount.findComponentRoot(110parentNode,111ReactMount.getID(childNodeB)112)113).toBe(childNodeB);114});115116it('should throw if a rendered element cannot be found', function() {117var parentNode = document.createElement('table');118var childNodeA = document.createElement('tbody');119var childNodeB = document.createElement('tr');120parentNode.appendChild(childNodeA);121childNodeA.appendChild(childNodeB);122123ReactMount.setID(parentNode, '.0');124// No ID on `childNodeA`, it was "rendered by the browser".125ReactMount.setID(childNodeB, '.0.1:0');126127expect(ReactMount.findComponentRoot(128parentNode,129ReactMount.getID(childNodeB)130)).toBe(childNodeB);131132expect(function() {133ReactMount.findComponentRoot(134parentNode,135ReactMount.getID(childNodeB) + ":junk"136);137}).toThrow(138'Invariant Violation: findComponentRoot(..., .0.1:0:junk): ' +139'Unable to find element. This probably means the DOM was ' +140'unexpectedly mutated (e.g., by the browser), usually due to ' +141'forgetting a <tbody> when using tables, nesting tags ' +142'like <form>, <p>, or <a>, or using non-SVG elements in an <svg> ' +143'parent. ' +144'Try inspecting the child nodes of the element with React ID `.0`.'145);146});147});148149describe('getReactRootIDFromNodeID', function() {150it('should support strings', function() {151var test = '.s_0_1.0..1';152var expected = '.s_0_1';153var actual = ReactInstanceHandles.getReactRootIDFromNodeID(test);154expect(actual).toEqual(expected);155});156});157158describe('getReactRootIDFromNodeID', function() {159it('should return null for invalid IDs', function() {160var getReactRootIDFromNodeID = (161ReactInstanceHandles.getReactRootIDFromNodeID162);163164expect(getReactRootIDFromNodeID(null)).toEqual(null);165expect(getReactRootIDFromNodeID('.')).toEqual(null);166expect(getReactRootIDFromNodeID('#')).toEqual(null);167});168});169170describe('traverseTwoPhase', function() {171it("should not traverse when traversing outside DOM", function() {172var targetID = '';173var expectedAggregation = [];174ReactInstanceHandles.traverseTwoPhase(targetID, argAggregator, ARG);175expect(aggregatedArgs).toEqual(expectedAggregation);176});177178it("should traverse two phase across component boundary", function() {179var parent = renderParentIntoDocument();180var targetID = parent.refs.P_P1_C1.refs.DIV_1._rootNodeID;181var expectedAggregation = [182{id: parent.refs.P._rootNodeID, isUp: false, arg: ARG},183{id: parent.refs.P_P1._rootNodeID, isUp: false, arg: ARG},184{id: parent.refs.P_P1_C1.refs.DIV._rootNodeID, isUp: false, arg: ARG},185{id: parent.refs.P_P1_C1.refs.DIV_1._rootNodeID, isUp: false, arg: ARG},186187{id: parent.refs.P_P1_C1.refs.DIV_1._rootNodeID, isUp: true, arg: ARG},188{id: parent.refs.P_P1_C1.refs.DIV._rootNodeID, isUp: true, arg: ARG},189{id: parent.refs.P_P1._rootNodeID, isUp: true, arg: ARG},190{id: parent.refs.P._rootNodeID, isUp: true, arg: ARG}191];192ReactInstanceHandles.traverseTwoPhase(targetID, argAggregator, ARG);193expect(aggregatedArgs).toEqual(expectedAggregation);194});195196it("should traverse two phase at shallowest node", function() {197var parent = renderParentIntoDocument();198var targetID = parent.refs.P._rootNodeID;199var expectedAggregation = [200{id: parent.refs.P._rootNodeID, isUp: false, arg: ARG},201{id: parent.refs.P._rootNodeID, isUp: true, arg: ARG}202];203ReactInstanceHandles.traverseTwoPhase(targetID, argAggregator, ARG);204expect(aggregatedArgs).toEqual(expectedAggregation);205});206});207208describe('traverseEnterLeave', function() {209it("should not traverse when enter/leaving outside DOM", function() {210var targetID = '';211var expectedAggregation = [];212ReactInstanceHandles.traverseEnterLeave(213targetID, targetID, argAggregator, ARG, ARG2214);215expect(aggregatedArgs).toEqual(expectedAggregation);216});217218it("should not traverse if enter/leave the same node", function() {219var parent = renderParentIntoDocument();220var leaveID = parent.refs.P_P1_C1.refs.DIV_1._rootNodeID;221var enterID = parent.refs.P_P1_C1.refs.DIV_1._rootNodeID;222var expectedAggregation = [];223ReactInstanceHandles.traverseEnterLeave(224leaveID, enterID, argAggregator, ARG, ARG2225);226expect(aggregatedArgs).toEqual(expectedAggregation);227});228229it("should traverse enter/leave to sibling - avoids parent", function() {230var parent = renderParentIntoDocument();231var leaveID = parent.refs.P_P1_C1.refs.DIV_1._rootNodeID;232var enterID = parent.refs.P_P1_C1.refs.DIV_2._rootNodeID;233var expectedAggregation = [234{id: parent.refs.P_P1_C1.refs.DIV_1._rootNodeID, isUp: true, arg: ARG},235// enter/leave shouldn't fire antyhing on the parent236{id: parent.refs.P_P1_C1.refs.DIV_2._rootNodeID, isUp: false, arg: ARG2}237];238ReactInstanceHandles.traverseEnterLeave(239leaveID, enterID, argAggregator, ARG, ARG2240);241expect(aggregatedArgs).toEqual(expectedAggregation);242});243244it("should traverse enter/leave to parent - avoids parent", function() {245var parent = renderParentIntoDocument();246var leaveID = parent.refs.P_P1_C1.refs.DIV_1._rootNodeID;247var enterID = parent.refs.P_P1_C1.refs.DIV._rootNodeID;248var expectedAggregation = [249{id: parent.refs.P_P1_C1.refs.DIV_1._rootNodeID, isUp: true, arg: ARG}250];251ReactInstanceHandles.traverseEnterLeave(252leaveID, enterID, argAggregator, ARG, ARG2253);254expect(aggregatedArgs).toEqual(expectedAggregation);255});256257it("should enter from the window", function() {258var parent = renderParentIntoDocument();259var leaveID = ''; // From the window or outside of the React sandbox.260var enterID = parent.refs.P_P1_C1.refs.DIV._rootNodeID;261var expectedAggregation = [262{id: parent.refs.P._rootNodeID, isUp: false, arg: ARG2},263{id: parent.refs.P_P1._rootNodeID, isUp: false, arg: ARG2},264{id: parent.refs.P_P1_C1.refs.DIV._rootNodeID, isUp: false, arg: ARG2}265];266ReactInstanceHandles.traverseEnterLeave(267leaveID, enterID, argAggregator, ARG, ARG2268);269expect(aggregatedArgs).toEqual(expectedAggregation);270});271272it("should enter from the window to the shallowest", function() {273var parent = renderParentIntoDocument();274var leaveID = ''; // From the window or outside of the React sandbox.275var enterID = parent.refs.P._rootNodeID;276var expectedAggregation = [277{id: parent.refs.P._rootNodeID, isUp: false, arg: ARG2}278];279ReactInstanceHandles.traverseEnterLeave(280leaveID, enterID, argAggregator, ARG, ARG2281);282expect(aggregatedArgs).toEqual(expectedAggregation);283});284285it("should leave to the window", function() {286var parent = renderParentIntoDocument();287var enterID = ''; // From the window or outside of the React sandbox.288var leaveID = parent.refs.P_P1_C1.refs.DIV._rootNodeID;289var expectedAggregation = [290{id: parent.refs.P_P1_C1.refs.DIV._rootNodeID, isUp: true, arg: ARG},291{id: parent.refs.P_P1._rootNodeID, isUp: true, arg: ARG},292{id: parent.refs.P._rootNodeID, isUp: true, arg: ARG}293];294ReactInstanceHandles.traverseEnterLeave(295leaveID, enterID, argAggregator, ARG, ARG2296);297expect(aggregatedArgs).toEqual(expectedAggregation);298});299300it("should leave to the window from the shallowest", function() {301var parent = renderParentIntoDocument();302var enterID = ''; // From the window or outside of the React sandbox.303var leaveID = parent.refs.P_P1_C1.refs.DIV._rootNodeID;304var expectedAggregation = [305{id: parent.refs.P_P1_C1.refs.DIV._rootNodeID, isUp: true, arg: ARG},306{id: parent.refs.P_P1._rootNodeID, isUp: true, arg: ARG},307{id: parent.refs.P._rootNodeID, isUp: true, arg: ARG}308];309ReactInstanceHandles.traverseEnterLeave(310leaveID, enterID, argAggregator, ARG, ARG2311);312expect(aggregatedArgs).toEqual(expectedAggregation);313});314});315316describe('getNextDescendantID', function() {317it("should return next descendent from window", function() {318var parent = renderParentIntoDocument();319expect(320ReactInstanceHandles._getNextDescendantID(321'',322parent.refs.P_P1._rootNodeID323)324).toBe(parent.refs.P._rootNodeID);325});326327it("should return window for next descendent towards window", function() {328expect(ReactInstanceHandles._getNextDescendantID('', '')).toBe('');329});330331it("should return self for next descendent towards self", function() {332var parent = renderParentIntoDocument();333expect(334ReactInstanceHandles._getNextDescendantID(335parent.refs.P_P1._rootNodeID,336parent.refs.P_P1._rootNodeID337)338).toBe(parent.refs.P_P1._rootNodeID);339});340});341342describe('getFirstCommonAncestorID', function() {343it("should determine the first common ancestor correctly", function() {344var parent = renderParentIntoDocument();345var ancestors = [346// Common ancestor from window to deep element is ''.347{ one: {_rootNodeID: ''},348two: parent.refs.P_P1_C1.refs.DIV_1,349com: {_rootNodeID: ''}350},351// Same as previous - reversed direction.352{ one: parent.refs.P_P1_C1.refs.DIV_1,353two: {_rootNodeID: ''},354com: {_rootNodeID: ''}355},356// Common ancestor from window to shallow id is ''.357{ one: parent.refs.P,358two: {_rootNodeID: ''},359com: {_rootNodeID: ''}360},361// Common ancestor with self is self.362{ one: parent.refs.P_P1_C1.refs.DIV_1,363two: parent.refs.P_P1_C1.refs.DIV_1,364com: parent.refs.P_P1_C1.refs.DIV_1365},366// Common ancestor with self is self - even if topmost DOM.367{ one: parent.refs.P, two: parent.refs.P, com: parent.refs.P },368// Siblings369{370one: parent.refs.P_P1_C1.refs.DIV_1,371two: parent.refs.P_P1_C1.refs.DIV_2,372com: parent.refs.P_P1_C1.refs.DIV373},374// Common ancestor with parent is the parent.375{376one: parent.refs.P_P1_C1.refs.DIV_1,377two: parent.refs.P_P1_C1.refs.DIV,378com: parent.refs.P_P1_C1.refs.DIV379},380// Common ancestor with grandparent is the grandparent.381{382one: parent.refs.P_P1_C1.refs.DIV_1,383two: parent.refs.P_P1_C1,384com: parent.refs.P_P1_C1385},386// Grantparent across subcomponent boundaries.387{388one: parent.refs.P_P1_C1.refs.DIV_1,389two: parent.refs.P_P1_C2.refs.DIV_1,390com: parent.refs.P_P1391},392// Something deep with something one-off.393{394one: parent.refs.P_P1_C1.refs.DIV_1,395two: parent.refs.P_OneOff,396com: parent.refs.P397}398];399var i;400for (i = 0; i < ancestors.length; i++) {401var plan = ancestors[i];402var firstCommon = ReactInstanceHandles._getFirstCommonAncestorID(403plan.one._rootNodeID,404plan.two._rootNodeID405);406expect(firstCommon).toBe(plan.com._rootNodeID);407}408});409});410411});412413414