Skip to content

Commit

Permalink
Add a nonce option and Render testing
Browse files Browse the repository at this point in the history
Fix for #393, allows passing a nonce through the new `RenderOptions` API added in #451.
  • Loading branch information
Nick Craver committed Apr 4, 2020
1 parent 75acbc4 commit 065abca
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/MiniProfiler.Shared/Internal/Render.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static string Includes(
var sb = StringBuilderCache.Get();
var options = profiler.Options;

sb.Append("<script async=\"async\" id=\"mini-profiler\" src=\"");
sb.Append("<script async id=\"mini-profiler\" src=\"");
sb.Append(path);
sb.Append("includes.min.js?v=");
sb.Append(options.VersionHash);
Expand Down Expand Up @@ -82,6 +82,10 @@ public static string Includes(
{
sb.Append(" data-start-hidden=\"true\"");
}
if (renderOptions?.Nonce.HasValue() ?? false)
{
sb.Append(" nonce=\"").Append(renderOptions.Nonce).Append("\"");
}

sb.Append(" data-max-traces=\"");
sb.Append((renderOptions?.MaxTracesToShow ?? options.PopupMaxTracesToShow).ToString(CultureInfo.InvariantCulture));
Expand Down
6 changes: 6 additions & 0 deletions src/MiniProfiler.Shared/RenderOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,11 @@ public class RenderOptions
/// Defaults to <see cref="MiniProfilerBaseOptions.ColorScheme"/>.
/// </summary>
public ColorScheme? ColorScheme { get; set; }

/// <summary>
/// A one-time-use nonce to render in the script tag.
/// </summary>
/// <remarks>https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script</remarks>
public string Nonce { get; set; }
}
}
108 changes: 108 additions & 0 deletions tests/MiniProfiler.Tests/RenderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using StackExchange.Profiling.Internal;
using Xunit;
using Xunit.Abstractions;

namespace StackExchange.Profiling.Tests
{
public class RenderTests : BaseTest
{
public RenderTests(ITestOutputHelper output) : base(output) { }

[Fact]
public void DefaultRender()
{
var profiler = GetBasicProfiler();
var renderOptions = new RenderOptions();
var result = Render.Includes(profiler, "/", true, renderOptions, new List<Guid>() { profiler.Id });
Output.WriteLine("Result: " + result);

Assert.NotNull(result);
Assert.Contains("id=\"mini-profiler\"", result);

var expected = $@"<script async id=""mini-profiler"" src=""/includes.min.js?v={Options.VersionHash}"" data-version=""{Options.VersionHash}"" data-path=""/"" data-current-id=""{profiler.Id}"" data-ids=""{profiler.Id}"" data-position=""Left"""" data-scheme=""Light"" data-authorized=""true"" data-max-traces=""15"" data-toggle-shortcut=""Alt+P"" data-trivial-milliseconds=""2.0"" data-ignored-duplicate-execute-types=""Open,OpenAsync,Close,CloseAsync""></script>";
Assert.Equal(expected, result);
}

[Fact]
public void OptionsSet()
{
var profiler = GetBasicProfiler();
var renderOptions = new RenderOptions()
{
ColorScheme = ColorScheme.Auto,
MaxTracesToShow = 12,
Nonce = "myNonce",
PopupToggleKeyboardShortcut = "Alt+Q",
Position = RenderPosition.Right,
ShowControls = true,
ShowTimeWithChildren = true,
ShowTrivial = true,
StartHidden = true,
TrivialDurationThresholdMilliseconds = 23
};
var result = Render.Includes(profiler, "/", true, renderOptions, new List<Guid>() { profiler.Id });
Output.WriteLine("Result: " + result);

Assert.NotNull(result);
Assert.Contains("id=\"mini-profiler\"", result);

var expected = $@"<script async id=""mini-profiler"" src=""/includes.min.js?v={Options.VersionHash}"" data-version=""{Options.VersionHash}"" data-path=""/"" data-current-id=""{profiler.Id}"" data-ids=""{profiler.Id}"" data-position=""Right"""" data-scheme=""Auto"" data-authorized=""true"" data-trivial=""true"" data-children=""true"" data-controls=""true"" data-start-hidden=""true"" nonce=""myNonce"" data-max-traces=""12"" data-toggle-shortcut=""Alt+Q"" data-trivial-milliseconds=""23"" data-ignored-duplicate-execute-types=""Open,OpenAsync,Close,CloseAsync""></script>";
Assert.Equal(expected, result);
}

[Theory]
[InlineData(null, @"data-scheme=""Light""")]
[InlineData(ColorScheme.Auto, @"data-scheme=""Auto""")]
[InlineData(ColorScheme.Dark, @"data-scheme=""Dark""")]
[InlineData(ColorScheme.Light, @"data-scheme=""Light""")]
public void ColorSchemes(ColorScheme? scheme, string expected)
{
var profiler = GetBasicProfiler();
var renderOptions = new RenderOptions() { ColorScheme = scheme };

var result = Render.Includes(profiler, " / ", true, renderOptions);
Output.WriteLine("Result: " + result);

Assert.NotNull(result);
Assert.Contains(expected, result);
}

[Theory]
[InlineData(null, @"data-position=""Left""")]
[InlineData(RenderPosition.BottomLeft, @"data-position=""BottomLeft""")]
[InlineData(RenderPosition.BottomRight, @"data-position=""BottomRight""")]
[InlineData(RenderPosition.Left, @"data-position=""Left""")]
[InlineData(RenderPosition.Right, @"data-position=""Right""")]
public void Positions(RenderPosition? position, string expected)
{
var profiler = GetBasicProfiler();
var renderOptions = new RenderOptions() { Position = position };

var result = Render.Includes(profiler, " / ", true, renderOptions);
Output.WriteLine("Result: " + result);

Assert.NotNull(result);
Assert.Contains(expected, result);
}

[Fact]
public void Nonce()
{
var profiler = GetBasicProfiler();
var renderOptions = new RenderOptions();

// Default
var result = Render.Includes(profiler, "/", true, renderOptions);
Output.WriteLine("Result: " + result);
Assert.DoesNotContain("nonce", result);

// With nonce
var nonce = Guid.NewGuid().ToString();
renderOptions.Nonce = nonce;
result = Render.Includes(profiler, "/", true, renderOptions);
Assert.Contains($@"nonce=""{nonce}""", result);
}
}
}

0 comments on commit 065abca

Please sign in to comment.