630 lines
22 KiB
C#
630 lines
22 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using GameList.Tests.Support;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace GameList.Tests;
|
|
|
|
public class SuggestionTests
|
|
{
|
|
[Fact]
|
|
public async Task Player_cannot_exceed_five_suggestions()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("suggestor");
|
|
|
|
for (var i = 0; i < 5; i++)
|
|
{
|
|
var resp = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = $"Game {i}",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
resp.EnsureSuccessStatusCode();
|
|
}
|
|
|
|
var sixth = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "Overflow",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
Assert.Equal(HttpStatusCode.BadRequest, sixth.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Rejects_invalid_image_extension_and_player_counts()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("validate");
|
|
|
|
var badExt = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "BadImg",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = "http://example.com/file.txt",
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, badExt.StatusCode);
|
|
|
|
var badPlayers = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "BadPlayers",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = 4,
|
|
MaxPlayers = 2
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, badPlayers.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Joker_allows_single_extra_suggestion_and_unfinalizes_votes()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var player = factory.CreateClientWithCookies();
|
|
await player.RegisterAsync("joker");
|
|
var other = factory.CreateClientWithCookies();
|
|
await other.RegisterAsync("other");
|
|
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var p = await db.Players.FirstAsync();
|
|
p.HasJoker = true;
|
|
p.CurrentPhase = Domain.Phase.Vote;
|
|
var o = await db.Players.SingleAsync(x => x.Username == "other");
|
|
o.VotesFinal = true;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var suggestion = await player.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "JokerGame",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
suggestion.EnsureSuccessStatusCode();
|
|
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var p = await db.Players.FirstAsync();
|
|
Assert.False(p.HasJoker);
|
|
Assert.False(p.VotesFinal);
|
|
var o = await db.Players.SingleAsync(x => x.Username == "other");
|
|
Assert.False(o.VotesFinal);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Admin_can_update_during_vote_phase()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var admin = factory.CreateClientWithCookies();
|
|
await admin.RegisterAsync("admin", admin: true);
|
|
|
|
var player = factory.CreateClientWithCookies();
|
|
await player.RegisterAsync("author");
|
|
var id = await player.CreateSuggestionAsync("OldName");
|
|
await player.PostAsJsonAsync("/api/me/phase/next", new { });
|
|
|
|
var update = await admin.PutAsJsonAsync($"/api/suggestions/{id}", new
|
|
{
|
|
Name = "NewName",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
update.EnsureSuccessStatusCode();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Phase_gate_blocks_player_update_in_vote_phase()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var player = factory.CreateClientWithCookies();
|
|
await player.RegisterAsync("phase");
|
|
var id = await player.CreateSuggestionAsync("Lock");
|
|
await player.PostAsJsonAsync("/api/me/phase/next", new { });
|
|
|
|
var update = await player.PutAsJsonAsync($"/api/suggestions/{id}", new
|
|
{
|
|
Name = "Blocked",
|
|
Genre = "NewGenre",
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
update.EnsureSuccessStatusCode();
|
|
|
|
var loaded = await factory.WithDbContextAsync(async db => await db.Suggestions.FindAsync(id));
|
|
Assert.Equal("Lock", loaded!.Name); // title locked
|
|
Assert.Equal("NewGenre", loaded.Genre); // other fields still editable in vote
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Player_cannot_edit_suggestion_in_results_phase()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var player = factory.CreateClientWithCookies();
|
|
await player.RegisterAsync("results");
|
|
var id = await player.CreateSuggestionAsync("Frozen");
|
|
|
|
// Move everyone to Results
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var state = await db.AppState.FirstAsync();
|
|
state.ResultsOpen = true;
|
|
var p = await db.Players.FirstAsync();
|
|
p.CurrentPhase = Domain.Phase.Results;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var update = await player.PutAsJsonAsync($"/api/suggestions/{id}", new
|
|
{
|
|
Name = "ShouldFail",
|
|
Genre = "Nope",
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
Assert.Equal(HttpStatusCode.BadRequest, update.StatusCode);
|
|
|
|
var loaded = await factory.WithDbContextAsync(async db => await db.Suggestions.FindAsync(id));
|
|
Assert.Equal("Frozen", loaded!.Name);
|
|
Assert.Equal("Coop", loaded.Genre);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Player_cannot_edit_other_players_suggestion()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var owner = factory.CreateClientWithCookies();
|
|
await owner.RegisterAsync("owner");
|
|
var other = factory.CreateClientWithCookies();
|
|
await other.RegisterAsync("intruder");
|
|
|
|
var id = await owner.CreateSuggestionAsync("Protected");
|
|
|
|
var update = await other.PutAsJsonAsync($"/api/suggestions/{id}", new
|
|
{
|
|
Name = "Hacked",
|
|
Genre = "Bad",
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
Assert.Equal(HttpStatusCode.Unauthorized, update.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Joker_allows_unlimited_extra_suggestions_when_granted_multiple_times()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("sixth");
|
|
|
|
// Seed 5 suggestions in Suggest phase
|
|
for (var i = 0; i < 5; i++)
|
|
{
|
|
var resp = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = $"Game{i}",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
resp.EnsureSuccessStatusCode();
|
|
}
|
|
|
|
// Move to Vote and grant joker
|
|
await client.PostAsJsonAsync("/api/me/phase/next", new { });
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var p = await db.Players.FirstAsync();
|
|
p.HasJoker = true;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var sixth = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "JokerExtra",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
sixth.EnsureSuccessStatusCode();
|
|
|
|
// Grant another joker and add a seventh suggestion
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var p = await db.Players.FirstAsync();
|
|
p.HasJoker = true;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var seventh = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "TooMany",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
seventh.EnsureSuccessStatusCode();
|
|
|
|
// No joker left; further suggestions should be blocked
|
|
var eighth = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "BlockedNow",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
Assert.Equal(HttpStatusCode.BadRequest, eighth.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Unreachable_screenshot_url_is_rejected()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
factory.HttpHandler.SetResponder(_ => new HttpResponseMessage(HttpStatusCode.BadRequest));
|
|
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("imgtester");
|
|
|
|
var response = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "Needs image",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = "http://example.com/image.png",
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Get_all_requires_vote_phase()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("viewer");
|
|
|
|
var resp = await client.GetAsync("/api/suggestions/all");
|
|
Assert.Equal(HttpStatusCode.BadRequest, resp.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Mine_returns_ordered_list()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("mine");
|
|
|
|
var secondId = await client.CreateSuggestionAsync("Second");
|
|
var thirdId = await client.CreateSuggestionAsync("Third");
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var second = await db.Suggestions.FindAsync(secondId);
|
|
var third = await db.Suggestions.FindAsync(thirdId);
|
|
second!.CreatedAt = DateTimeOffset.UtcNow.AddMinutes(-1);
|
|
third!.CreatedAt = DateTimeOffset.UtcNow;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var mine = await client.GetFromJsonAsync<List<JsonElement>>("/api/suggestions/mine");
|
|
Assert.Equal("Second", mine![0].GetProperty("name").GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_requires_suggest_phase_and_display_name()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("phasegate");
|
|
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var p = await db.Players.FirstAsync();
|
|
p.CurrentPhase = Domain.Phase.Vote;
|
|
p.DisplayName = null;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var badPhase = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "Nope",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, badPhase.StatusCode);
|
|
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var p = await db.Players.FirstAsync();
|
|
p.CurrentPhase = Domain.Phase.Suggest;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
var noDisplay = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "NoDisplay",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, noDisplay.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Rejects_invalid_urls_name_length_and_player_counts()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("validate2");
|
|
|
|
var badGame = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "Bad",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = "ftp://bad",
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, badGame.StatusCode);
|
|
|
|
var badYoutube = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "BadYt",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = "file://bad",
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, badYoutube.StatusCode);
|
|
|
|
var longName = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = new string('x', 101),
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = (int?)null,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, longName.StatusCode);
|
|
|
|
var minOnly = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "MinOnly",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = 2,
|
|
MaxPlayers = (int?)null
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, minOnly.StatusCode);
|
|
|
|
var maxTooHigh = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "MaxHigh",
|
|
Genre = (string?)null,
|
|
Description = (string?)null,
|
|
ScreenshotUrl = (string?)null,
|
|
YoutubeUrl = (string?)null,
|
|
GameUrl = (string?)null,
|
|
MinPlayers = 2,
|
|
MaxPlayers = 40
|
|
});
|
|
Assert.Equal(HttpStatusCode.BadRequest, maxTooHigh.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Trims_and_truncates_optional_fields()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("trim");
|
|
|
|
var longGenre = new string('g', 60);
|
|
var longDesc = new string('d', 600);
|
|
var resp = await client.PostAsJsonAsync("/api/suggestions", new
|
|
{
|
|
Name = "Trim",
|
|
Genre = $" {longGenre} ",
|
|
Description = $" {longDesc} ",
|
|
ScreenshotUrl = "http://example.com/img.png",
|
|
YoutubeUrl = "http://example.com/y",
|
|
GameUrl = "http://example.com/g",
|
|
MinPlayers = 1,
|
|
MaxPlayers = 4
|
|
});
|
|
resp.EnsureSuccessStatusCode();
|
|
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var s = await db.Suggestions.AsNoTracking().FirstAsync();
|
|
Assert.Equal(50, s.Genre!.Length);
|
|
Assert.Equal(500, s.Description!.Length);
|
|
Assert.Equal("http://example.com/img.png", s.ScreenshotUrl);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Mine_excludes_other_players()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var a = factory.CreateClientWithCookies();
|
|
await a.RegisterAsync("alice");
|
|
var b = factory.CreateClientWithCookies();
|
|
await b.RegisterAsync("bob");
|
|
|
|
await a.CreateSuggestionAsync("AliceGame");
|
|
await b.CreateSuggestionAsync("BobGame");
|
|
|
|
var mine = await a.GetFromJsonAsync<List<JsonElement>>("/api/suggestions/mine");
|
|
Assert.NotNull(mine);
|
|
Assert.Single(mine);
|
|
Assert.Equal("AliceGame", mine[0].GetProperty("name").GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task All_returns_link_metadata_and_ordering()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var client = factory.CreateClientWithCookies();
|
|
await client.RegisterAsync("owner");
|
|
|
|
var id1 = await client.CreateSuggestionAsync("Alpha");
|
|
var id2 = await client.CreateSuggestionAsync("Beta");
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var alpha = await db.Suggestions.FindAsync(id1);
|
|
var beta = await db.Suggestions.FindAsync(id2);
|
|
alpha!.CreatedAt = DateTimeOffset.UtcNow.AddMinutes(-1);
|
|
beta!.CreatedAt = DateTimeOffset.UtcNow;
|
|
beta!.ParentSuggestionId = id1;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
await client.PostAsJsonAsync("/api/me/phase/next", new { }); // to Vote
|
|
|
|
var all = await client.GetFromJsonAsync<List<JsonElement>>("/api/suggestions/all");
|
|
Assert.Equal(2, all!.Count);
|
|
var first = all[0];
|
|
Assert.Equal("Alpha", first.GetProperty("name").GetString());
|
|
var second = all[1];
|
|
var linkedIds = second.GetProperty("linkedIds").EnumerateArray().Select(x => x.GetInt32()).ToList();
|
|
Assert.Contains(id1, linkedIds);
|
|
var linkedTitles = second.GetProperty("linkedTitles").EnumerateArray().Select(x => x.GetString()).ToList();
|
|
Assert.Contains("Alpha", linkedTitles);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Delete_respects_phase_and_clears_links_and_votes()
|
|
{
|
|
await using var factory = new TestWebApplicationFactory();
|
|
var owner = factory.CreateClientWithCookies();
|
|
await owner.RegisterAsync("deleter");
|
|
var other = factory.CreateClientWithCookies();
|
|
await other.RegisterAsync("voter");
|
|
|
|
var id = await owner.CreateSuggestionAsync("DeleteMe");
|
|
var child = await owner.CreateSuggestionAsync("Child");
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
var c = await db.Suggestions.FindAsync(child);
|
|
c!.ParentSuggestionId = id;
|
|
await db.SaveChangesAsync();
|
|
});
|
|
|
|
await owner.PostAsJsonAsync("/api/me/phase/next", new { }); // Vote
|
|
await other.CreateSuggestionAsync("Other vote seed");
|
|
await other.PostAsJsonAsync("/api/me/phase/next", new { });
|
|
await other.PostAsJsonAsync("/api/votes", new
|
|
{
|
|
SuggestionId = id,
|
|
Score = 5
|
|
});
|
|
|
|
var blocked = await owner.DeleteAsync($"/api/suggestions/{id}");
|
|
Assert.Equal(HttpStatusCode.BadRequest, blocked.StatusCode);
|
|
|
|
var admin = factory.CreateClientWithCookies();
|
|
await admin.RegisterAsync("admin", admin: true);
|
|
var delete = await admin.DeleteAsync($"/api/suggestions/{id}");
|
|
delete.EnsureSuccessStatusCode();
|
|
|
|
await factory.WithDbContextAsync(async db =>
|
|
{
|
|
Assert.False(await db.Suggestions.AnyAsync(s => s.Id == id));
|
|
var childEntity = await db.Suggestions.FindAsync(child);
|
|
Assert.Null(childEntity!.ParentSuggestionId);
|
|
Assert.False(db.Votes.Any(v => v.SuggestionId == id));
|
|
});
|
|
}
|
|
}
|