diff --git a/src/React.Core/AssemblyRegistration.cs b/src/React.Core/AssemblyRegistration.cs index 2b7c40a91..fafe79e33 100644 --- a/src/React.Core/AssemblyRegistration.cs +++ b/src/React.Core/AssemblyRegistration.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014-Present, Facebook, Inc. * All rights reserved. * @@ -37,6 +37,7 @@ public void Register(TinyIoCContainer container) container.Register().AsPerRequestSingleton(); container.Register((c, o) => JsEngineSwitcher.Instance); container.Register().AsSingleton(); + container.Register().AsSingleton(); container.Register().AsPerRequestSingleton(); } diff --git a/src/React.Core/GuidExtensions.cs b/src/React.Core/GuidExtensions.cs deleted file mode 100644 index 18a7dace9..000000000 --- a/src/React.Core/GuidExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2016-Present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System; - -namespace React -{ - /// - /// Extension methods relating to GUIDs. - /// - public static class GuidExtensions - { - /// - /// Returns a short identifier for this GUID. - /// - /// The unique identifier. - /// A short version of the unique identifier - public static string ToShortGuid(this Guid guid) - { - return Convert.ToBase64String(guid.ToByteArray()) - .Replace("/", string.Empty) - .Replace("+", string.Empty) - .TrimEnd('='); - } - } -} diff --git a/tests/React.Tests/Core/GuidExtensionsTests.cs b/src/React.Core/IReactIdGenerator.cs similarity index 54% rename from tests/React.Tests/Core/GuidExtensionsTests.cs rename to src/React.Core/IReactIdGenerator.cs index 53429c24f..6e2dbfb9f 100644 --- a/tests/React.Tests/Core/GuidExtensionsTests.cs +++ b/src/React.Core/IReactIdGenerator.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2016-Present, Facebook, Inc. * All rights reserved. * @@ -7,18 +7,14 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -using System; -using Xunit; - -namespace React.Tests.Core +namespace React { - public class GuidExtensionsTests + public interface IReactIdGenerator { - [Fact] - public void ToShortGuid() - { - var guid = Guid.Parse("c027191d-3785-485d-9fd7-5e0b376bd547"); - Assert.Equal("HRknwIU3XUif114LN2vVRw", guid.ToShortGuid()); - } + /// + /// Returns a short react identifier starts with "react_". + /// + /// + string Generate(); } } diff --git a/src/React.Core/ReactComponent.cs b/src/React.Core/ReactComponent.cs index 012100403..ca2f61a82 100644 --- a/src/React.Core/ReactComponent.cs +++ b/src/React.Core/ReactComponent.cs @@ -94,15 +94,16 @@ public object Props /// /// The environment. /// Site-wide configuration. + /// React Id generator. /// Name of the component. /// The ID of the container DIV for this component - public ReactComponent(IReactEnvironment environment, IReactSiteConfiguration configuration, string componentName, string containerId) + public ReactComponent(IReactEnvironment environment, IReactSiteConfiguration configuration, IReactIdGenerator reactIdGenerator, string componentName, string containerId) { EnsureComponentNameValid(componentName); _environment = environment; _configuration = configuration; ComponentName = componentName; - ContainerId = string.IsNullOrEmpty(containerId) ? GenerateId() : containerId; + ContainerId = string.IsNullOrEmpty(containerId) ? reactIdGenerator.Generate() : containerId; ContainerTag = "div"; } @@ -229,14 +230,5 @@ internal static void EnsureComponentNameValid(string componentName) )); } } - - /// - /// Generates a unique identifier for this component, if one was not passed in. - /// - /// - private static string GenerateId() - { - return "react_" + Guid.NewGuid().ToShortGuid(); - } } } diff --git a/src/React.Core/ReactEnvironment.cs b/src/React.Core/ReactEnvironment.cs index ced8e1e95..edecc5e9d 100644 --- a/src/React.Core/ReactEnvironment.cs +++ b/src/React.Core/ReactEnvironment.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014-Present, Facebook, Inc. * All rights reserved. * @@ -55,6 +55,10 @@ public class ReactEnvironment : IReactEnvironment, IDisposable /// Hash algorithm for file-based cache /// protected readonly IFileCacheHash _fileCacheHash; + /// + /// React Id generator + /// + private readonly IReactIdGenerator _reactIdGenerator; /// /// JSX Transformer instance for this environment @@ -120,12 +124,14 @@ public static IReactEnvironment GetCurrentOrThrow /// The cache to use for JSX compilation /// File system wrapper /// Hash algorithm for file-based cache + /// React ID generator public ReactEnvironment( IJavaScriptEngineFactory engineFactory, IReactSiteConfiguration config, ICache cache, IFileSystem fileSystem, - IFileCacheHash fileCacheHash + IFileCacheHash fileCacheHash, + IReactIdGenerator reactIdGenerator ) { _engineFactory = engineFactory; @@ -133,6 +139,7 @@ IFileCacheHash fileCacheHash _cache = cache; _fileSystem = fileSystem; _fileCacheHash = fileCacheHash; + _reactIdGenerator = reactIdGenerator; _babelTransformer = new Lazy(() => new Babel(this, _cache, _fileSystem, _fileCacheHash, _config) ); @@ -294,7 +301,7 @@ public virtual IReactComponent CreateComponent(string componentName, T props, EnsureUserScriptsLoaded(); } - var component = new ReactComponent(this, _config, componentName, containerId) + var component = new ReactComponent(this, _config, _reactIdGenerator, componentName, containerId) { Props = props, ServerOnly = serverOnly diff --git a/src/React.Core/ReactIdGenerator.cs b/src/React.Core/ReactIdGenerator.cs new file mode 100644 index 000000000..a61647b7e --- /dev/null +++ b/src/React.Core/ReactIdGenerator.cs @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016-Present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +using System; +using System.Threading; + +namespace React +{ + /// + /// React ID generator. + /// + public class ReactIdGenerator : IReactIdGenerator + { + private static readonly string _encode32Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; + + private static long _random = DateTime.UtcNow.Ticks; + + private static readonly char[] reactPrefix = "react_".ToCharArray(); + + /// + /// "react_".Length = 6 + 13 random symbols + /// + private const int reactIdLength = 19; + + [ThreadStatic] + private static char[] _chars; + + /// + /// Returns a short react identifier starts with "react_". + /// + /// + public string Generate() + { + var chars = _chars; + if (chars == null) + { + _chars = chars = new char[reactIdLength]; + Array.Copy(reactPrefix, 0, chars, 0, reactPrefix.Length); + } + + var id = Interlocked.Increment(ref _random); + + // from 6 because "react_".Length == 6, _encode32Chars.Length == 32 (base32), + // base32 characters are 5 bits in length and from long (64 bits) we can get 13 symbols + chars[6] = _encode32Chars[(int)(id >> 60) & 31]; + chars[7] = _encode32Chars[(int)(id >> 55) & 31]; + chars[8] = _encode32Chars[(int)(id >> 50) & 31]; + chars[9] = _encode32Chars[(int)(id >> 45) & 31]; + chars[10] = _encode32Chars[(int)(id >> 40) & 31]; + chars[11] = _encode32Chars[(int)(id >> 35) & 31]; + chars[12] = _encode32Chars[(int)(id >> 30) & 31]; + chars[13] = _encode32Chars[(int)(id >> 25) & 31]; + chars[14] = _encode32Chars[(int)(id >> 20) & 31]; + chars[15] = _encode32Chars[(int)(id >> 15) & 31]; + chars[16] = _encode32Chars[(int)(id >> 10) & 31]; + chars[17] = _encode32Chars[(int)(id >> 5) & 31]; + chars[18] = _encode32Chars[(int)id & 31]; + + return new string(chars, 0, reactIdLength); + } + } +} diff --git a/src/React.Router/ReactEnvironmentExtensions.cs b/src/React.Router/ReactEnvironmentExtensions.cs index 3137538cd..fb66b3021 100644 --- a/src/React.Router/ReactEnvironmentExtensions.cs +++ b/src/React.Router/ReactEnvironmentExtensions.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014-Present, Facebook, Inc. * All rights reserved. * @@ -35,11 +35,10 @@ public static ReactRouterComponent CreateRouterComponent( bool clientOnly = false ) { - var config = AssemblyRegistration.Container.Resolve(); - var component = new ReactRouterComponent( - env, - config, + env, + AssemblyRegistration.Container.Resolve(), + AssemblyRegistration.Container.Resolve(), componentName, containerId, path diff --git a/src/React.Router/ReactRouterComponent.cs b/src/React.Router/ReactRouterComponent.cs index 02dce30ca..993ac2953 100644 --- a/src/React.Router/ReactRouterComponent.cs +++ b/src/React.Router/ReactRouterComponent.cs @@ -26,16 +26,18 @@ public class ReactRouterComponent : ReactComponent /// /// The environment. /// Site-wide configuration. + /// React Id generator. /// Name of the component. /// The ID of the container DIV for this component /// F.x. from Request.Path. Used by React Static Router to determine context and routing. public ReactRouterComponent( IReactEnvironment environment, IReactSiteConfiguration configuration, + IReactIdGenerator reactIdGenerator, string componentName, string containerId, string path - ) : base(environment, configuration, componentName, containerId) + ) : base(environment, configuration, reactIdGenerator, componentName, containerId) { _path = path; } diff --git a/tests/React.Tests/Core/ReactComponentTest.cs b/tests/React.Tests/Core/ReactComponentTest.cs index 94f26678b..735436b54 100644 --- a/tests/React.Tests/Core/ReactComponentTest.cs +++ b/tests/React.Tests/Core/ReactComponentTest.cs @@ -24,7 +24,9 @@ public void RenderHtmlShouldThrowExceptionIfComponentDoesNotExist() environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(false); var config = new Mock(); config.Setup(x => x.UseServerSideRendering).Returns(true); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container"); + var reactIdGenerator = new Mock(); + + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container"); Assert.Throws(() => { @@ -39,8 +41,9 @@ public void RenderHtmlShouldCallRenderComponent() environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true); var config = new Mock(); config.Setup(x => x.UseServerSideRendering).Returns(true); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" } }; @@ -58,8 +61,9 @@ public void RenderHtmlShouldWrapComponentInDiv() .Returns("[HTML]"); var config = new Mock(); config.Setup(x => x.UseServerSideRendering).Returns(true); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" } }; @@ -76,8 +80,9 @@ public void RenderHtmlShouldNotRenderComponentHtml() environment.Setup(x => x.Execute(@"React.renderToString(React.createElement(Foo, {""hello"":""World""}))")) .Returns("[HTML]"); var config = new Mock(); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" } }; @@ -94,8 +99,9 @@ public void RenderHtmlShouldNotRenderClientSideAttributes() environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true); var config = new Mock(); config.Setup(x => x.UseServerSideRendering).Returns(true); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" } }; @@ -113,8 +119,9 @@ public void RenderHtmlShouldWrapComponentInCustomElement() environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true); environment.Setup(x => x.Execute(@"ReactDOMServer.renderToString(React.createElement(Foo, {""hello"":""World""}))")) .Returns("[HTML]"); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" }, ContainerTag = "span" @@ -133,8 +140,9 @@ public void RenderHtmlShouldNotRenderComponentWhenContainerOnly() environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true); environment.Setup(x => x.Execute(@"ReactDOMServer.renderToString(React.createElement(Foo, {""hello"":""World""}))")) .Returns("[HTML]"); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" }, ContainerTag = "span" @@ -153,8 +161,9 @@ public void RenderHtmlShouldNotWrapComponentWhenServerSideOnly() environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true); environment.Setup(x => x.Execute(@"ReactDOMServer.renderToStaticMarkup(React.createElement(Foo, {""hello"":""World""}))")) .Returns("[HTML]"); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" }, }; @@ -173,7 +182,9 @@ public void RenderHtmlShouldAddClassToElement() environment.Setup(x => x.Execute(@"ReactDOMServer.renderToString(React.createElement(Foo, {""hello"":""World""}))")) .Returns("[HTML]"); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var reactIdGenerator = new Mock(); + + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" }, ContainerClass="test-class" @@ -188,8 +199,9 @@ public void RenderJavaScriptShouldCallRenderComponent() { var environment = new Mock(); var config = new Mock(); + var reactIdGenerator = new Mock(); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" } }; @@ -228,9 +240,11 @@ public void GeneratesContainerIdIfNotProvided() { var environment = new Mock(); var config = new Mock(); + var reactIdGenerator = new Mock(); + reactIdGenerator.Setup(x => x.Generate()).Returns("customReactId"); - var component = new ReactComponent(environment.Object, config.Object, "Foo", null); - Assert.StartsWith("react_", component.ContainerId); + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", null); + Assert.Equal("customReactId", component.ContainerId); } [Fact] @@ -245,7 +259,9 @@ public void ExceptionThrownIsHandled() config.Setup(x => x.UseServerSideRendering).Returns(true); config.Setup(x => x.ExceptionHandler).Returns(() => throw new ReactServerRenderingException("test")); - var component = new ReactComponent(environment.Object, config.Object, "Foo", "container") + var reactIdGenerator = new Mock(); + + var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container") { Props = new { hello = "World" } }; diff --git a/tests/React.Tests/Core/ReactEnvironmentTest.cs b/tests/React.Tests/Core/ReactEnvironmentTest.cs index 47fceeb51..d70ad433a 100644 --- a/tests/React.Tests/Core/ReactEnvironmentTest.cs +++ b/tests/React.Tests/Core/ReactEnvironmentTest.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014-Present, Facebook, Inc. * All rights reserved. * @@ -82,30 +82,18 @@ public void ExecuteWithBabelShouldThrowIfBabelDisabled() }); } - [Fact] - public void GeneratesContainerIdIfNotProvided() - { - var mocks = new Mocks(); - var environment = mocks.CreateReactEnvironment(); - mocks.Config.Setup(x => x.Scripts).Returns(new List()); - - var component1 = environment.CreateComponent("ComponentName", new { }); - var component2 = environment.CreateComponent("ComponentName", new { }); - Assert.StartsWith("react_", component1.ContainerId); - Assert.StartsWith("react_", component2.ContainerId); - } - [Fact] public void UsesProvidedContainerId() { var mocks = new Mocks(); var environment = mocks.CreateReactEnvironment(); mocks.Config.Setup(x => x.Scripts).Returns(new List()); + mocks.ReactIdGenerator.Setup(x => x.Generate()).Returns("react_customId"); var component1 = environment.CreateComponent("ComponentName", new { }, "foo"); var component2 = environment.CreateComponent("ComponentName", new { }); Assert.Equal("foo", component1.ContainerId); - Assert.StartsWith("react_", component2.ContainerId); + Assert.Equal("react_customId", component2.ContainerId); } [Fact] @@ -156,6 +144,7 @@ public class Mocks public Mock Cache { get; private set; } public Mock FileSystem { get; private set; } public Mock FileCacheHash { get; private set; } + public Mock ReactIdGenerator { get; private set; } public Mocks() { Engine = new Mock(); @@ -164,6 +153,7 @@ public Mocks() Cache = new Mock(); FileSystem = new Mock(); FileCacheHash = new Mock(); + ReactIdGenerator = new Mock(); EngineFactory.Setup(x => x.GetEngine()).Returns(Engine.Object); EngineFactory.Setup(x => x.GetEngineForCurrentThread()).Returns(Engine.Object); @@ -177,7 +167,8 @@ public ReactEnvironment CreateReactEnvironment() Config.Object, Cache.Object, FileSystem.Object, - FileCacheHash.Object + FileCacheHash.Object, + ReactIdGenerator.Object ); } diff --git a/tests/React.Tests/Core/ReactIdGeneratorTests.cs b/tests/React.Tests/Core/ReactIdGeneratorTests.cs new file mode 100644 index 000000000..c8466b432 --- /dev/null +++ b/tests/React.Tests/Core/ReactIdGeneratorTests.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-Present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +using System; +using Xunit; + +namespace React.Tests.Core +{ + public class ReactIdGeneratorTests + { + [Fact] + public void GuidShouldHaveFixedRange() + { + var generator = new ReactIdGenerator(); + + var shortGuid = generator.Generate(); + + Assert.Equal(19, shortGuid.Length); + } + + [Fact] + public void ShouldStartsWithReact() + { + var generator = new ReactIdGenerator(); + + var shortGuid = generator.Generate(); + + Assert.StartsWith("react_", shortGuid); + } + + [Fact] + public void TwoGuidsShouldNotEqual() + { + var generator = new ReactIdGenerator(); + + var shortGuid1 = generator.Generate(); + var shortGuid2 = generator.Generate(); + + Assert.NotEqual(shortGuid1, shortGuid2); + } + } +} diff --git a/tests/React.Tests/Router/HtmlHelperExtensionsTest.cs b/tests/React.Tests/Router/HtmlHelperExtensionsTest.cs index 7f1100cbd..3bac03c38 100644 --- a/tests/React.Tests/Router/HtmlHelperExtensionsTest.cs +++ b/tests/React.Tests/Router/HtmlHelperExtensionsTest.cs @@ -46,6 +46,13 @@ private Mock ConfigureMockConfiguration() return config; } + private Mock ConfigureReactIdGenerator() + { + var reactIdGenerator = new Mock(); + AssemblyRegistration.Container.Register(reactIdGenerator.Object); + return reactIdGenerator; + } + /// /// Mock an html helper with a mocked response object. /// Used when testing for server response modification. @@ -76,18 +83,22 @@ class ReactRouterMocks public Mock config; public Mock environment; public Mock component; + public Mock reactIdGenerator; public ReactRouterMocks( Mock conf, - Mock env + Mock env, + Mock idGenerator ) { config = conf; environment = env; + reactIdGenerator = idGenerator; component = new Mock( environment.Object, config.Object, + reactIdGenerator.Object, "ComponentName", "", "/" @@ -110,7 +121,8 @@ public void EngineIsReturnedToPoolAfterRender() { var config = ConfigureMockConfiguration(); var environment = ConfigureMockEnvironment(); - var routerMocks = new ReactRouterMocks(config, environment); + var reactIdGenerator = ConfigureReactIdGenerator(); + var routerMocks = new ReactRouterMocks(config, environment, reactIdGenerator); var htmlHelperMock = new HtmlHelperMocks(); environment.Verify(x => x.ReturnEngineToPool(), Times.Never); @@ -133,7 +145,8 @@ public void ReactWithClientOnlyTrueShouldCallRenderHtmlWithTrue() var htmlHelperMock = new HtmlHelperMocks(); var environment = ConfigureMockEnvironment(); - var routerMocks = new ReactRouterMocks(config, environment); + var reactIdGenerator = ConfigureReactIdGenerator(); + var routerMocks = new ReactRouterMocks(config, environment, reactIdGenerator); var result = HtmlHelperExtensions.ReactRouter( htmlHelper: htmlHelperMock.htmlHelper.Object, @@ -154,7 +167,8 @@ public void ReactWithServerOnlyTrueShouldCallRenderHtmlWithTrue() var htmlHelperMock = new HtmlHelperMocks(); var environment = ConfigureMockEnvironment(); - var routerMocks = new ReactRouterMocks(config, environment); + var reactIdGenerator = ConfigureReactIdGenerator(); + var routerMocks = new ReactRouterMocks(config, environment, reactIdGenerator); var result = HtmlHelperExtensions.ReactRouter( htmlHelper: htmlHelperMock.htmlHelper.Object, @@ -173,6 +187,7 @@ public void ShouldModifyStatusCode() { var mocks = ConfigureMockReactEnvironment(); ConfigureMockConfiguration(); + ConfigureReactIdGenerator(); mocks.Engine.Setup(x => x.Evaluate("JSON.stringify(context);")) .Returns("{ status: 200 }"); @@ -193,6 +208,7 @@ public void ShouldRunCustomContextHandler() { var mocks = ConfigureMockReactEnvironment(); ConfigureMockConfiguration(); + ConfigureReactIdGenerator(); mocks.Engine.Setup(x => x.Evaluate("JSON.stringify(context);")) .Returns("{ status: 200 }"); @@ -214,6 +230,7 @@ public void ShouldRedirectPermanent() { var mocks = ConfigureMockReactEnvironment(); ConfigureMockConfiguration(); + ConfigureReactIdGenerator(); mocks.Engine.Setup(x => x.Evaluate("JSON.stringify(context);")) .Returns(@"{ status: 301, url: ""/foo"" }"); @@ -234,6 +251,7 @@ public void ShouldRedirectWithJustUrl() { var mocks = ConfigureMockReactEnvironment(); ConfigureMockConfiguration(); + ConfigureReactIdGenerator(); mocks.Engine.Setup(x => x.Evaluate("JSON.stringify(context);")) .Returns(@"{ url: ""/foo"" }"); @@ -254,6 +272,7 @@ public void ShouldFailRedirectWithNoUrl() { var mocks = ConfigureMockReactEnvironment(); ConfigureMockConfiguration(); + ConfigureReactIdGenerator(); mocks.Engine.Setup(x => x.Evaluate("JSON.stringify(context);")) .Returns("{ status: 301 }"); diff --git a/tests/React.Tests/Router/ReactEnvironmentExtensionsTest.cs b/tests/React.Tests/Router/ReactEnvironmentExtensionsTest.cs index 98a486311..3e379303c 100644 --- a/tests/React.Tests/Router/ReactEnvironmentExtensionsTest.cs +++ b/tests/React.Tests/Router/ReactEnvironmentExtensionsTest.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014-Present, Facebook, Inc. * All rights reserved. * @@ -24,6 +24,8 @@ public void EnvironmentShouldGetCalledClientOnly() AssemblyRegistration.Container.Register(environment.Object); var config = new Mock(); AssemblyRegistration.Container.Register(config.Object); + var reactIdGenerator = new Mock(); + AssemblyRegistration.Container.Register(reactIdGenerator.Object); var component = ReactEnvironmentExtensions.CreateRouterComponent( environment.Object, diff --git a/tests/React.Tests/Router/ReactRouterComponentTest.cs b/tests/React.Tests/Router/ReactRouterComponentTest.cs index 731b26341..0fa9a1209 100644 --- a/tests/React.Tests/Router/ReactRouterComponentTest.cs +++ b/tests/React.Tests/Router/ReactRouterComponentTest.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014-Present, Facebook, Inc. * All rights reserved. * @@ -22,8 +22,9 @@ public void RenderJavaScriptShouldNotIncludeContextOrPath() { var environment = new Mock(); var config = new Mock(); + var reactIdGenerator = new Mock(); - var component = new ReactRouterComponent(environment.Object, config.Object, "Foo", "container", "/bar") + var component = new ReactRouterComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container", "/bar") { Props = new { hello = "World" } };