mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Injectable DOMProperty configs, and add back ID attribute
https://github.com/facebook/react/pull/141
This commit is contained in:
committed by
Paul O’Shannessy
parent
d50148591b
commit
32423a83fc
@@ -22,6 +22,9 @@ var ReactDOM = require('ReactDOM');
|
||||
var ReactDOMForm = require('ReactDOMForm');
|
||||
var ReactDOMTextarea = require('ReactDOMTextarea');
|
||||
|
||||
var DefaultDOMPropertyConfig = require('DefaultDOMPropertyConfig');
|
||||
var DOMProperty = require('DOMProperty');
|
||||
|
||||
var DefaultEventPluginOrder = require('DefaultEventPluginOrder');
|
||||
var EnterLeaveEventPlugin = require('EnterLeaveEventPlugin');
|
||||
var ChangeEventPlugin = require('ChangeEventPlugin');
|
||||
@@ -37,7 +40,7 @@ function inject() {
|
||||
EventPluginHub.injection.injectInstanceHandle(ReactInstanceHandles);
|
||||
|
||||
/**
|
||||
* Two important event plugins included by default (without having to require
|
||||
* Some important event plugins included by default (without having to require
|
||||
* them).
|
||||
*/
|
||||
EventPluginHub.injection.injectEventPluginsByName({
|
||||
@@ -46,17 +49,13 @@ function inject() {
|
||||
'ChangeEventPlugin': ChangeEventPlugin
|
||||
});
|
||||
|
||||
/**
|
||||
* This is a bit of a hack. We need to override the <form> element to be a
|
||||
* composite component because IE8 does not bubble or capture submit to the
|
||||
* top level. In order to make this work with our dependency graph we need to
|
||||
* inject it here.
|
||||
*/
|
||||
ReactDOM.injection.injectComponentClasses({
|
||||
form: ReactDOMForm,
|
||||
// TODO: Inject `ReactDOMInput`.
|
||||
textarea: ReactDOMTextarea
|
||||
});
|
||||
|
||||
DOMProperty.injection.injectDOMPropertyConfig(DefaultDOMPropertyConfig);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -193,6 +193,9 @@ describe('ReactNativeComponent', function() {
|
||||
beforeEach(function() {
|
||||
require('mock-modules').dumpCache();
|
||||
|
||||
var ReactDefaultInjection = require('ReactDefaultInjection');
|
||||
ReactDefaultInjection.inject();
|
||||
|
||||
var mixInto = require('mixInto');
|
||||
var ReactNativeComponent = require('ReactNativeComponent');
|
||||
|
||||
@@ -217,7 +220,7 @@ describe('ReactNativeComponent', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle className", function() {
|
||||
it("should generate the correct markup with className", function() {
|
||||
expect(genMarkup({ className: 'a' })).toHaveAttribute('class', 'a');
|
||||
expect(genMarkup({ className: 'a b' })).toHaveAttribute('class', 'a b');
|
||||
expect(genMarkup({ className: '' })).toHaveAttribute('class', '');
|
||||
|
||||
+110
-165
@@ -23,6 +23,101 @@
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
var DOMPropertyInjection = {
|
||||
/**
|
||||
* Mapping from normalized, camelcased property names to a configuration that
|
||||
* specifies how the associated DOM property should be accessed or rendered.
|
||||
*/
|
||||
MUST_USE_ATTRIBUTE: 0x1,
|
||||
MUST_USE_PROPERTY: 0x2,
|
||||
HAS_BOOLEAN_VALUE: 0x4,
|
||||
HAS_SIDE_EFFECTS: 0x8,
|
||||
|
||||
/**
|
||||
* Inject some specialized knowledge about the DOM. This takes a config object
|
||||
* with the following properties:
|
||||
*
|
||||
* isCustomAttribute: function that given an attribute name will return true
|
||||
* if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
|
||||
* attributes where it's impossible to enumerate all of the possible
|
||||
* attribute names,
|
||||
*
|
||||
* Properties: object mapping DOM property name to one of the
|
||||
* DOMPropertyInjection constants or null. If your attribute isn't in here,
|
||||
* it won't get written to the DOM.
|
||||
*
|
||||
* DOMAttributeNames: object mapping React attribute name to the DOM
|
||||
* attribute name. Attribute names not specified use the **lowercase**
|
||||
* normalized name.
|
||||
*
|
||||
* DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.
|
||||
* Property names not specified use the normalized name.
|
||||
*
|
||||
* DOMMutationMethods: Properties that require special mutation methods. If
|
||||
* `value` is undefined, the mutation method should unset the property.
|
||||
*
|
||||
* @param {object} domPropertyConfig the config as described above.
|
||||
*/
|
||||
injectDOMPropertyConfig: function(domPropertyConfig) {
|
||||
var Properties = domPropertyConfig.Properties || {};
|
||||
var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};
|
||||
var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};
|
||||
var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};
|
||||
|
||||
if (domPropertyConfig.isCustomAttribute) {
|
||||
DOMProperty._isCustomAttributeFunctions.push(
|
||||
domPropertyConfig.isCustomAttribute
|
||||
);
|
||||
}
|
||||
|
||||
for (var propName in Properties) {
|
||||
invariant(
|
||||
!DOMProperty.isStandardName[propName],
|
||||
'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' +
|
||||
'\'%s\' which has already been injected. You may be accidentally ' +
|
||||
'injecting the same DOM property config twice, or you may be ' +
|
||||
'injecting two configs that have conflicting property names.',
|
||||
propName
|
||||
);
|
||||
|
||||
DOMProperty.isStandardName[propName] = true;
|
||||
|
||||
DOMProperty.getAttributeName[propName] =
|
||||
DOMAttributeNames[propName] || propName.toLowerCase();
|
||||
|
||||
DOMProperty.getPropertyName[propName] =
|
||||
DOMPropertyNames[propName] || propName;
|
||||
|
||||
var mutationMethod = DOMMutationMethods[propName];
|
||||
if (mutationMethod) {
|
||||
DOMProperty.getMutationMethod[propName] = mutationMethod;
|
||||
}
|
||||
|
||||
var propConfig = Properties[propName];
|
||||
DOMProperty.mustUseAttribute[propName] =
|
||||
propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE;
|
||||
DOMProperty.mustUseProperty[propName] =
|
||||
propConfig & DOMPropertyInjection.MUST_USE_PROPERTY;
|
||||
DOMProperty.hasBooleanValue[propName] =
|
||||
propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE;
|
||||
DOMProperty.hasSideEffects[propName] =
|
||||
propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS;
|
||||
|
||||
invariant(
|
||||
!DOMProperty.mustUseAttribute[propName] ||
|
||||
!DOMProperty.mustUseProperty[propName],
|
||||
'DOMProperty: Cannot use require using both attribute and property: %s',
|
||||
propName
|
||||
);
|
||||
invariant(
|
||||
DOMProperty.mustUseProperty[propName] ||
|
||||
!DOMProperty.hasSideEffects[propName],
|
||||
'DOMProperty: Properties that have side effects must use property: %s',
|
||||
propName
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
var defaultValueCache = {};
|
||||
|
||||
/**
|
||||
@@ -94,13 +189,22 @@ var DOMProperty = {
|
||||
*/
|
||||
hasSideEffects: {},
|
||||
|
||||
/**
|
||||
* All of the isCustomAttribute() functions that have been injected.
|
||||
*/
|
||||
_isCustomAttributeFunctions: [],
|
||||
|
||||
/**
|
||||
* Checks whether a property name is a custom attribute.
|
||||
* @method
|
||||
*/
|
||||
isCustomAttribute: RegExp.prototype.test.bind(
|
||||
/^(data|aria)-[a-z_][a-z\d_.\-]*$/
|
||||
),
|
||||
isCustomAttribute: function(attributeName) {
|
||||
return DOMProperty._isCustomAttributeFunctions.some(
|
||||
function(isCustomAttributeFn) {
|
||||
return isCustomAttributeFn.call(null, attributeName);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the default property value for a DOM property (i.e., not an
|
||||
@@ -121,168 +225,9 @@ var DOMProperty = {
|
||||
nodeDefaults[prop] = testElement[prop];
|
||||
}
|
||||
return nodeDefaults[prop];
|
||||
}
|
||||
},
|
||||
|
||||
injection: DOMPropertyInjection
|
||||
};
|
||||
|
||||
/**
|
||||
* Mapping from normalized, camelcased property names to a configuration that
|
||||
* specifies how the associated DOM property should be accessed or rendered.
|
||||
*/
|
||||
var MustUseAttribute = 0x1;
|
||||
var MustUseProperty = 0x2;
|
||||
var HasBooleanValue = 0x4;
|
||||
var HasSideEffects = 0x8;
|
||||
|
||||
var Properties = {
|
||||
/**
|
||||
* Standard Properties
|
||||
*/
|
||||
accept: null,
|
||||
action: null,
|
||||
ajaxify: MustUseAttribute,
|
||||
allowFullScreen: MustUseAttribute | HasBooleanValue,
|
||||
alt: null,
|
||||
autoComplete: null,
|
||||
autoplay: HasBooleanValue,
|
||||
cellPadding: null,
|
||||
cellSpacing: null,
|
||||
checked: MustUseProperty | HasBooleanValue,
|
||||
className: MustUseProperty,
|
||||
colSpan: null,
|
||||
contentEditable: null,
|
||||
controls: MustUseProperty | HasBooleanValue,
|
||||
data: null, // For `<object />` acts as `src`.
|
||||
dir: null,
|
||||
disabled: MustUseProperty | HasBooleanValue,
|
||||
draggable: null,
|
||||
enctype: null,
|
||||
height: MustUseAttribute,
|
||||
href: null,
|
||||
htmlFor: null,
|
||||
max: null,
|
||||
method: null,
|
||||
min: null,
|
||||
multiple: MustUseProperty | HasBooleanValue,
|
||||
name: null,
|
||||
poster: null,
|
||||
preload: null,
|
||||
placeholder: null,
|
||||
rel: null,
|
||||
required: HasBooleanValue,
|
||||
role: MustUseAttribute,
|
||||
scrollLeft: MustUseProperty,
|
||||
scrollTop: MustUseProperty,
|
||||
selected: MustUseProperty | HasBooleanValue,
|
||||
spellCheck: null,
|
||||
src: null,
|
||||
step: null,
|
||||
style: null,
|
||||
tabIndex: null,
|
||||
target: null,
|
||||
title: null,
|
||||
type: null,
|
||||
value: MustUseProperty | HasSideEffects,
|
||||
width: MustUseAttribute,
|
||||
wmode: MustUseAttribute,
|
||||
/**
|
||||
* SVG Properties
|
||||
*/
|
||||
cx: MustUseProperty,
|
||||
cy: MustUseProperty,
|
||||
d: MustUseProperty,
|
||||
fill: MustUseProperty,
|
||||
fx: MustUseProperty,
|
||||
fy: MustUseProperty,
|
||||
points: MustUseProperty,
|
||||
r: MustUseProperty,
|
||||
stroke: MustUseProperty,
|
||||
strokeLinecap: MustUseProperty,
|
||||
strokeWidth: MustUseProperty,
|
||||
transform: MustUseProperty,
|
||||
x: MustUseProperty,
|
||||
x1: MustUseProperty,
|
||||
x2: MustUseProperty,
|
||||
version: MustUseProperty,
|
||||
viewBox: MustUseProperty,
|
||||
y: MustUseProperty,
|
||||
y1: MustUseProperty,
|
||||
y2: MustUseProperty,
|
||||
spreadMethod: MustUseProperty,
|
||||
offset: MustUseProperty,
|
||||
stopColor: MustUseProperty,
|
||||
stopOpacity: MustUseProperty,
|
||||
gradientUnits: MustUseProperty,
|
||||
gradientTransform: MustUseProperty
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute names not specified use the **lowercase** normalized name.
|
||||
*/
|
||||
var DOMAttributeNames = {
|
||||
className: 'class',
|
||||
htmlFor: 'for',
|
||||
strokeLinecap: 'stroke-linecap',
|
||||
strokeWidth: 'stroke-width',
|
||||
stopColor: 'stop-color',
|
||||
stopOpacity: 'stop-opacity'
|
||||
};
|
||||
|
||||
/**
|
||||
* Property names not specified use the normalized name.
|
||||
*/
|
||||
var DOMPropertyNames = {
|
||||
autoComplete: 'autocomplete',
|
||||
spellCheck: 'spellcheck'
|
||||
};
|
||||
|
||||
/**
|
||||
* Properties that require special mutation methods. If `value` is undefined,
|
||||
* the mutation method should unset the property.
|
||||
*/
|
||||
var DOMMutationMethods = {
|
||||
/**
|
||||
* Setting `className` to null may cause it to be set to the string "null".
|
||||
*
|
||||
* @param {DOMElement} node
|
||||
* @param {*} value
|
||||
*/
|
||||
className: function(node, value) {
|
||||
node.className = value || '';
|
||||
}
|
||||
};
|
||||
|
||||
for (var propName in Properties) {
|
||||
DOMProperty.isStandardName[propName] = true;
|
||||
|
||||
DOMProperty.getAttributeName[propName] =
|
||||
DOMAttributeNames[propName] || propName.toLowerCase();
|
||||
|
||||
DOMProperty.getPropertyName[propName] =
|
||||
DOMPropertyNames[propName] || propName;
|
||||
|
||||
var mutationMethod = DOMMutationMethods[propName];
|
||||
if (mutationMethod) {
|
||||
DOMProperty.getMutationMethod[propName] = mutationMethod;
|
||||
}
|
||||
|
||||
var propConfig = Properties[propName];
|
||||
DOMProperty.mustUseAttribute[propName] = propConfig & MustUseAttribute;
|
||||
DOMProperty.mustUseProperty[propName] = propConfig & MustUseProperty;
|
||||
DOMProperty.hasBooleanValue[propName] = propConfig & HasBooleanValue;
|
||||
DOMProperty.hasSideEffects[propName] = propConfig & HasSideEffects;
|
||||
|
||||
invariant(
|
||||
!DOMProperty.mustUseAttribute[propName] ||
|
||||
!DOMProperty.mustUseProperty[propName],
|
||||
'DOMProperty: Cannot use require using both attribute and property: %s',
|
||||
propName
|
||||
);
|
||||
invariant(
|
||||
DOMProperty.mustUseProperty[propName] ||
|
||||
!DOMProperty.hasSideEffects[propName],
|
||||
'DOMProperty: Properties that have side effects must use property: %s',
|
||||
propName
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = DOMProperty;
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Copyright 2013 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @providesModule DefaultDOMPropertyConfig
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var DOMProperty = require('DOMProperty');
|
||||
|
||||
var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE;
|
||||
var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
|
||||
var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
|
||||
var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS;
|
||||
|
||||
var DefaultDOMPropertyConfig = {
|
||||
isCustomAttribute: RegExp.prototype.test.bind(
|
||||
/^(data|aria)-[a-z_][a-z\d_.\-]*$/
|
||||
),
|
||||
Properties: {
|
||||
/**
|
||||
* Standard Properties
|
||||
*/
|
||||
accept: null,
|
||||
action: null,
|
||||
ajaxify: MUST_USE_ATTRIBUTE,
|
||||
allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
|
||||
alt: null,
|
||||
autoComplete: null,
|
||||
autoplay: HAS_BOOLEAN_VALUE,
|
||||
cellPadding: null,
|
||||
cellSpacing: null,
|
||||
checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
|
||||
className: MUST_USE_PROPERTY,
|
||||
colSpan: null,
|
||||
contentEditable: null,
|
||||
controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
|
||||
data: null, // For `<object />` acts as `src`.
|
||||
dir: null,
|
||||
disabled: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
|
||||
draggable: null,
|
||||
enctype: null,
|
||||
height: MUST_USE_ATTRIBUTE,
|
||||
href: null,
|
||||
htmlFor: null,
|
||||
id: MUST_USE_PROPERTY,
|
||||
max: null,
|
||||
method: null,
|
||||
min: null,
|
||||
multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
|
||||
name: null,
|
||||
poster: null,
|
||||
preload: null,
|
||||
placeholder: null,
|
||||
rel: null,
|
||||
required: HAS_BOOLEAN_VALUE,
|
||||
role: MUST_USE_ATTRIBUTE,
|
||||
scrollLeft: MUST_USE_PROPERTY,
|
||||
scrollTop: MUST_USE_PROPERTY,
|
||||
selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
|
||||
spellCheck: null,
|
||||
src: null,
|
||||
step: null,
|
||||
style: null,
|
||||
tabIndex: null,
|
||||
target: null,
|
||||
title: null,
|
||||
type: null,
|
||||
value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
|
||||
width: MUST_USE_ATTRIBUTE,
|
||||
wmode: MUST_USE_ATTRIBUTE,
|
||||
/**
|
||||
* SVG Properties
|
||||
*/
|
||||
cx: MUST_USE_PROPERTY,
|
||||
cy: MUST_USE_PROPERTY,
|
||||
d: MUST_USE_PROPERTY,
|
||||
fill: MUST_USE_PROPERTY,
|
||||
fx: MUST_USE_PROPERTY,
|
||||
fy: MUST_USE_PROPERTY,
|
||||
points: MUST_USE_PROPERTY,
|
||||
r: MUST_USE_PROPERTY,
|
||||
stroke: MUST_USE_PROPERTY,
|
||||
strokeLinecap: MUST_USE_PROPERTY,
|
||||
strokeWidth: MUST_USE_PROPERTY,
|
||||
transform: MUST_USE_PROPERTY,
|
||||
x: MUST_USE_PROPERTY,
|
||||
x1: MUST_USE_PROPERTY,
|
||||
x2: MUST_USE_PROPERTY,
|
||||
version: MUST_USE_PROPERTY,
|
||||
viewBox: MUST_USE_PROPERTY,
|
||||
y: MUST_USE_PROPERTY,
|
||||
y1: MUST_USE_PROPERTY,
|
||||
y2: MUST_USE_PROPERTY,
|
||||
spreadMethod: MUST_USE_PROPERTY,
|
||||
offset: MUST_USE_PROPERTY,
|
||||
stopColor: MUST_USE_PROPERTY,
|
||||
stopOpacity: MUST_USE_PROPERTY,
|
||||
gradientUnits: MUST_USE_PROPERTY,
|
||||
gradientTransform: MUST_USE_PROPERTY
|
||||
},
|
||||
DOMAttributeNames: {
|
||||
className: 'class',
|
||||
htmlFor: 'for',
|
||||
strokeLinecap: 'stroke-linecap',
|
||||
strokeWidth: 'stroke-width',
|
||||
stopColor: 'stop-color',
|
||||
stopOpacity: 'stop-opacity'
|
||||
},
|
||||
DOMPropertyNames: {
|
||||
autoComplete: 'autocomplete',
|
||||
spellCheck: 'spellcheck'
|
||||
},
|
||||
DOMMutationMethods: {
|
||||
/**
|
||||
* Setting `className` to null may cause it to be set to the string "null".
|
||||
*
|
||||
* @param {DOMElement} node
|
||||
* @param {*} value
|
||||
*/
|
||||
className: function(node, value) {
|
||||
node.className = value || '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = DefaultDOMPropertyConfig;
|
||||
@@ -21,10 +21,15 @@
|
||||
|
||||
describe('DOMPropertyOperations', function() {
|
||||
var DOMPropertyOperations;
|
||||
var DOMProperty;
|
||||
|
||||
beforeEach(function() {
|
||||
require('mock-modules').dumpCache();
|
||||
var ReactDefaultInjection = require('ReactDefaultInjection');
|
||||
ReactDefaultInjection.inject();
|
||||
|
||||
DOMPropertyOperations = require('DOMPropertyOperations');
|
||||
DOMProperty = require('DOMProperty');
|
||||
});
|
||||
|
||||
describe('createMarkupForProperty', function() {
|
||||
@@ -46,6 +51,13 @@ describe('DOMPropertyOperations', function() {
|
||||
)).toBe('');
|
||||
});
|
||||
|
||||
it('should work with the id attribute', function() {
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'id',
|
||||
'simple'
|
||||
)).toBe('id="simple"');
|
||||
});
|
||||
|
||||
it('should create markup for boolean properties', function() {
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'checked',
|
||||
@@ -126,4 +138,57 @@ describe('DOMPropertyOperations', function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('injectDOMPropertyConfig', function() {
|
||||
it('should support custom attributes', function() {
|
||||
// foobar does not exist yet
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'foobar',
|
||||
'simple'
|
||||
)).toBe(null);
|
||||
|
||||
// foo-* does not exist yet
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'foo-xyz',
|
||||
'simple'
|
||||
)).toBe(null);
|
||||
|
||||
// inject foobar DOM property
|
||||
DOMProperty.injection.injectDOMPropertyConfig({
|
||||
isCustomAttribute: function(name) {
|
||||
return name.indexOf('foo-') === 0;
|
||||
},
|
||||
Properties: {foobar: null}
|
||||
});
|
||||
|
||||
// Ensure old attributes still work
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'name',
|
||||
'simple'
|
||||
)).toBe('name="simple"');
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'data-name',
|
||||
'simple'
|
||||
)).toBe('data-name="simple"');
|
||||
|
||||
// foobar should work
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'foobar',
|
||||
'simple'
|
||||
)).toBe('foobar="simple"');
|
||||
|
||||
// foo-* should work
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'foo-xyz',
|
||||
'simple'
|
||||
)).toBe('foo-xyz="simple"');
|
||||
|
||||
// It should complain about double injections.
|
||||
expect(function() {
|
||||
DOMProperty.injection.injectDOMPropertyConfig(
|
||||
{Properties: {foobar: null}}
|
||||
);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,23 +26,42 @@ describe('AnalyticsEventPlugin', function() {
|
||||
var EventPluginHub;
|
||||
var EventPluginRegistry;
|
||||
var React;
|
||||
var ReactDefaultInjection;
|
||||
var ReactEventEmitter;
|
||||
var ReactEventTopLevelCallback;
|
||||
var ReactTestUtils;
|
||||
|
||||
var DefaultEventPluginOrder;
|
||||
var EnterLeaveEventPlugin;
|
||||
var ChangeEventPlugin;
|
||||
var ReactInstanceHandles;
|
||||
var SimpleEventPlugin;
|
||||
|
||||
beforeEach(function() {
|
||||
AnalyticsEventPluginFactory = require('AnalyticsEventPluginFactory');
|
||||
EventPluginHub = require('EventPluginHub');
|
||||
EventPluginRegistry = require('EventPluginRegistry');
|
||||
React = require('React');
|
||||
ReactDefaultInjection = require('ReactDefaultInjection');
|
||||
ReactEventEmitter = require('ReactEventEmitter');
|
||||
ReactEventTopLevelCallback = require('ReactEventTopLevelCallback');
|
||||
ReactTestUtils = require('ReactTestUtils');
|
||||
|
||||
EventPluginRegistry._resetEventPlugins();
|
||||
ReactDefaultInjection.inject();
|
||||
|
||||
// Re-inject default events system after resetting.
|
||||
DefaultEventPluginOrder = require('DefaultEventPluginOrder');
|
||||
EnterLeaveEventPlugin = require('EnterLeaveEventPlugin');
|
||||
ChangeEventPlugin = require('ChangeEventPlugin');
|
||||
ReactInstanceHandles = require('ReactInstanceHandles');
|
||||
SimpleEventPlugin = require('SimpleEventPlugin');
|
||||
|
||||
EventPluginHub.injection.injectEventPluginOrder(DefaultEventPluginOrder);
|
||||
EventPluginHub.injection.injectInstanceHandle(ReactInstanceHandles);
|
||||
|
||||
EventPluginHub.injection.injectEventPluginsByName({
|
||||
'SimpleEventPlugin': SimpleEventPlugin,
|
||||
'EnterLeaveEventPlugin': EnterLeaveEventPlugin,
|
||||
'ChangeEventPlugin': ChangeEventPlugin
|
||||
});
|
||||
|
||||
ReactEventEmitter.ensureListening(false, ReactEventTopLevelCallback);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user