Skip to content

Commit

Permalink
Update tests; add GitHub Action
Browse files Browse the repository at this point in the history
  • Loading branch information
martijn committed Jun 21, 2024
1 parent 7a0f93c commit 71ac934
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 62 deletions.
22 changes: 21 additions & 1 deletion .github/workflows/fly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,31 @@ name: Deploy to fly.io

on:
push:
branches: [ "main" ]
branches: ["main"]
pull_request:
branches: ["main"]

jobs:
unittest:
name: Unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal

deploy:
name: Deploy
if: github.event_name == 'push'
needs: unittest
runs-on: ubuntu-latest
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
Expand Down
22 changes: 22 additions & 0 deletions PointingParty.Client.Tests/GameContextTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;

namespace PointingParty.Client.Tests;

public class GameContextTests
{
[Fact]
public void CreateGame_Returns_GameAggregate()
{
var sut = new GameContext(
Substitute.For<ILogger<GameContext>>(),
Substitute.For<NavigationManager>()
);

var agg = sut.CreateGame("Game", "Player");

Assert.Equal(sut.Game, agg);
Assert.Equal("Game", agg.State.GameId);
Assert.Equal("Player", sut.PlayerName);
}
}
12 changes: 6 additions & 6 deletions PointingParty.Client.Tests/GameStateExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public void Calculates_Average()
{
var state = new GameState(
string.Empty,
new Dictionary<string, Vote>()
new Dictionary<string, Vote>
{
{ "a", 1 },
{ "b", 2 }
Expand All @@ -19,7 +19,7 @@ public void Calculates_Average()

Assert.Equal(1.5, state.AverageVote());
}

[Theory]
[InlineData(VoteStatus.Pending)]
[InlineData(VoteStatus.Coffee)]
Expand All @@ -28,7 +28,7 @@ public void Ignores_Non_Voters(VoteStatus vote)
{
var state = new GameState(
string.Empty,
new Dictionary<string, Vote>()
new Dictionary<string, Vote>
{
{ "a", 1 },
{ "b", 2 },
Expand All @@ -47,13 +47,13 @@ public void Returns_Default_When_Nobody_Voted(VoteStatus vote)
{
var state = new GameState(
string.Empty,
new Dictionary<string, Vote>()
new Dictionary<string, Vote>
{
{ "a", vote },
{ "b", vote},
{ "b", vote }
}.ToImmutableDictionary(),
true);

Assert.Equal(default, state.AverageVote());
}
}
Original file line number Diff line number Diff line change
@@ -1,75 +1,73 @@
@using PointingParty.Domain.Events
@inherits TestContext
using AngleSharp.Dom;
using PointingParty.Domain;
using PointingParty.Domain.Events;

@code {
private readonly ITestOutputHelper _testOutputHelper;
private readonly GameAggregate _game;
private readonly IGameContext _gameContext;
namespace PointingParty.Client.Tests;

public class GameUiTests : BunitContext
{
private const string PlayerName = "Player";
private const string GameId = "TestGame";
private readonly GameAggregate _game;
private readonly IGameContext _gameContext;

public GameUiTests(ITestOutputHelper testOutputHelper)
public GameUiTests()
{
_testOutputHelper = testOutputHelper;
_game = new GameAggregate(GameId, PlayerName);
_gameContext = Substitute.For<IGameContext>();
_gameContext.Game = _game;

JSInterop.Mode = JSRuntimeMode.Loose;
}

[Fact]
public void Renders_PlayerName()
{
_gameContext.PlayerName.Returns(PlayerName);
var cut = Render(@<GameUi GameContext="@_gameContext"/>);

var cut = Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));
cut.Find("h3").TextContent.MarkupMatches($"Your vote, {PlayerName}:");
}

[Fact]
public void Publishes_PlayerJoined_Event()
{
Render(@<GameUi GameContext="@_gameContext"/>);
Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));

Assert.Collection(_game.EventsToPublish, e => Assert.IsType<PlayerJoinedGame>(e));
_gameContext.Received(1).PublishEvents();
}

[Fact]
public void Publishes_Vote_Event()
{
var cut = Render(@<GameUi GameContext="@_gameContext"/>);
var cut = Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));

_gameContext.ClearReceivedCalls();
_game.EventsToPublish.Clear();

cut.FindComponent<VoteButton>().Find("button").Click();

Assert.Collection(_game.EventsToPublish, e =>
{
Assert.IsType<VoteCast>(e);
Assert.Equal(((VoteCast)e).Vote, 1);
});

_gameContext.Received(1).PublishEvents();
}

[Fact]
public void Publishes_VotesShown_Event()
{
var cut = Render(@<GameUi GameContext="@_gameContext"/>);
var cut = Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));

_gameContext.ClearReceivedCalls();
_game.EventsToPublish.Clear();

cut.FindComponent<FatButton>().Find("button").Click();

Assert.Collection(_game.EventsToPublish, e =>
{
Assert.IsType<VotesShown>(e);
});
Assert.Collection(_game.EventsToPublish, e => { Assert.IsType<VotesShown>(e); });

_gameContext.Received(1).PublishEvents();
}
Expand All @@ -79,15 +77,15 @@ public void Shows_Players_Alphabetized()
{
_game.Handle(new PlayerJoinedGame(GameId, "Player Two"));
_game.Handle(new PlayerJoinedGame(GameId, "Player Three"));

var cut = Render(@<GameUi GameContext="@_gameContext"/>);

var results = cut.FindAll(@"table[data-testid=""results""] tbody tr td:first-child");
var cut = Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));

var results = cut.FindAll("""table[data-testid="results"] tbody tr td:first-child""");

Assert.Collection(results,
e => { Assert.Equal(e.GetInnerText(), PlayerName); },
e => { Assert.Equal(e.GetInnerText(), "Player Three"); },
e => { Assert.Equal(e.GetInnerText(), "Player Two"); }
e => { Assert.Equal(PlayerName, e.GetInnerText()); },
e => { Assert.Equal("Player Three", e.GetInnerText()); },
e => { Assert.Equal("Player Two", e.GetInnerText()); }
);
}

Expand All @@ -96,21 +94,21 @@ public void Hides_Votes_By_Default()
{
_game.Handle(new PlayerJoinedGame(GameId, "Player Two"));
_game.Handle(new VoteCast(GameId, "Player Two", 8));
var cut = Render(@<GameUi GameContext="@_gameContext"/>);
var results = cut.Find(@"[data-testid=""vote-for-Player Two""]");
Assert.Equal(results.GetInnerText(), "Voted!");

var cut = Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));
var results = cut.Find("""[data-testid="vote-for-Player Two"]""");
Assert.Equal("Voted!", results.GetInnerText());
}

[Fact]
public void Shows_Votes_After_VotesShown_Event()
{
_game.Handle(new PlayerJoinedGame(GameId, "Player Two"));
_game.Handle(new VoteCast(GameId, "Player Two", 8));
_game.Handle(new VotesShown(GameId));

var cut = Render(@<GameUi GameContext="@_gameContext"/>);
var results = cut.Find(@"[data-testid=""vote-for-Player Two""]");
Assert.Equal(results.GetInnerText(), "8");
var cut = Render<GameUi>(parameters => parameters.Add(p => p.GameContext, _gameContext));
var results = cut.Find("""[data-testid="vote-for-Player Two"]""");
Assert.Equal("8", results.GetInnerText());
}
}
}
2 changes: 2 additions & 0 deletions PointingParty.Client.Tests/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
global using Bunit;
global using NSubstitute;
global using Xunit;
78 changes: 78 additions & 0 deletions PointingParty.Client.Tests/Pages/GameTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using Bunit.TestDoubles;
using Microsoft.Extensions.DependencyInjection;
using PointingParty.Client.Pages;
using PointingParty.Domain;

namespace PointingParty.Client.Tests.Pages;

public class GameTests : BunitContext
{
private readonly IGameContext _gameContext;

public GameTests()
{
_gameContext = Substitute.For<IGameContext>();
Services.AddTransient<IGameContext>(_ => _gameContext);
ComponentFactories.AddStub<GameUi>();
}

[Fact]
public void WhenSubmittingForm_CreatesGame()
{
var cut = Render<Game>(parameters =>
parameters.Add(p => p.GameId, "Game"));

var nameInput = cut.Find("""input[placeholder="Player Name"]""");
nameInput.Change("Player");

cut.Find("button").Click();

_gameContext.Received(1).CreateGame("Game", "Player");
_gameContext.Received(1).Initialize(Arg.Any<Action>());
}

[Fact]
public void WithGame_RendersGameUi()
{
_gameContext.Game.Returns(new GameAggregate());

var cut = Render<Game>(parameters =>
parameters.Add(p => p.GameId, "Game"));

Assert.NotNull(cut.FindComponent<Stub<GameUi>>());
}

[Fact]
public void WithGame_RendersTitle()
{
_gameContext.Game.Returns(new GameAggregate());

var cut = Render<Game>(parameters =>
parameters.Add(p => p.GameId, "Game"));

var h2 = cut.Find("h2");

Assert.Equal("Pointing Party: Game", h2.TextContent);
}

[Fact]
public void WithPlayerName_CreatesGame_And_UpdatesUrl()
{
_gameContext.Game.Returns(new GameAggregate());
var navMan = Services.GetRequiredService<BunitNavigationManager>();

navMan.NavigateTo("/Game/Game?PlayerName=Player");

Render<Game>(parameters => { parameters.Add(p => p.GameId, "Game"); });

Assert.Equal("http://localhost/Game/Game", navMan.Uri);

_gameContext.Received(1).CreateGame("Game", "Player");
_gameContext.Received(1).Initialize(Arg.Any<Action>());
}

protected override void Dispose(bool disposing)
{
// Override BunitContext.Dispose to avoid calling sync Dispose on the Services
}
}
16 changes: 12 additions & 4 deletions PointingParty.Client.Tests/PointingParty.Client.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="bunit" Version="2.0.24-preview" />
<PackageReference Include="bunit" Version="2.0.24-preview"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="NSubstitute" Version="5.1.0"/>
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.8.1"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand All @@ -25,7 +29,11 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\PointingParty.Client\PointingParty.Client.csproj" />
<ProjectReference Include="..\PointingParty.Client\PointingParty.Client.csproj"/>
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="GameUiTests.cs"/>
</ItemGroup>

</Project>
12 changes: 0 additions & 12 deletions PointingParty.Client.Tests/_Imports.razor

This file was deleted.

Loading

0 comments on commit 71ac934

Please sign in to comment.