Update README.md with additional SonarCloud badges and improve CI workflow for coverage reporting
ci / build-backend (push) Successful in 2m34s
ci / build-frontend (push) Successful in 41s
ci / tests (push) Successful in 2m55s
ci / sonar (push) Successful in 5m21s

Enhanced the README.md file by adding new SonarCloud badges for coverage, bugs, code smells, security rating, and maintainability rating. Updated the CI workflow to remove coverage collection from the test step, as it is now handled by SonarCloud, streamlining the process and ensuring accurate badge representation.
This commit is contained in:
Leonid Pershin
2026-07-27 03:19:18 +03:00
parent 464355434b
commit 790d01b587
22 changed files with 2891 additions and 99 deletions
@@ -0,0 +1,128 @@
using TeleWave.Application.Streaming.ListPublicChannels;
using TeleWave.Application.Tests.Support;
using TeleWave.Domain.Broadcast;
using TeleWave.Domain.Library;
using TeleWave.Domain.Media;
using Xunit;
namespace TeleWave.Application.Tests.Streaming;
/// <summary>
/// Витрина зрителя: только включённые каналы, порядок по номеру и обложка того, что идёт прямо
/// сейчас. Выключенный канал не должен просачиваться в публичную выдачу.
/// </summary>
public class ListPublicChannelsTests
{
private static readonly DateTimeOffset T0 = new(2026, 1, 1, 0, 0, 0, TimeSpan.Zero);
[Fact]
public async Task List_ReturnsEnabledChannelsOrderedByNumber()
{
var fixture = new TestDb();
var numbered = Channel.Create("Второй", "two", T0);
numbered.UpdateTimeSettings(
2,
Channel.DefaultUtcOffsetMinutes,
Channel.DefaultDayStartTime
);
var first = Channel.Create("Первый", "one", T0);
first.UpdateTimeSettings(1, Channel.DefaultUtcOffsetMinutes, Channel.DefaultDayStartTime);
var unnumbered = Channel.Create("Аврора", "aurora", T0);
var disabled = Channel.Create("Выключенный", "off", T0);
foreach (var channel in new[] { numbered, first, unnumbered })
channel.UpdateSettings(channel.Name, isEnabled: true, bumpersEnabled: false, null);
disabled.UpdateSettings("Выключенный", isEnabled: false, bumpersEnabled: false, null);
await using (var seed = fixture.New())
{
seed.Channels.AddRange(numbered, first, unnumbered, disabled);
await seed.SaveChangesAsync(CancellationToken.None);
}
await using var db = fixture.New();
var channels = await new ListPublicChannelsQueryHandler(db).Handle(
new ListPublicChannelsQuery(),
CancellationToken.None
);
// Ненумерованный уходит в конец: на телевизоре порядок задаёт номер.
Assert.Equal(
new[] { "Первый", "Второй", "Аврора" },
channels.Select(c => c.Name).ToArray()
);
Assert.Null(channels[^1].Number);
Assert.All(channels, c => Assert.Null(c.CurrentShowId));
}
[Fact]
public async Task List_AddsCurrentProgramCover()
{
var fixture = new TestDb();
var channel = Channel.Create("Первый", "one", T0);
channel.UpdateSettings("Первый", isEnabled: true, bumpersEnabled: false, null);
var logoId = Guid.NewGuid();
channel.UpdateViewerSettings(logoId, LogoCorner.TopRight, 0.5, showClock: true, 0.3);
var show = Show.Create("Сейчас в эфире", ShowKind.Series);
show.SetPosterImage(Guid.NewGuid());
var asset = MediaAsset.Register("now.mkv", ".mkv", MediaSource.Upload);
var now = DateTimeOffset.UtcNow;
var current = ScheduleEntry.Program(
channel.Id,
asset.Id,
now.AddMinutes(-5),
now.AddMinutes(25),
show.Id,
0
);
// Прошедшая запись того же канала не должна перебить текущую.
var past = ScheduleEntry.Program(
channel.Id,
asset.Id,
now.AddHours(-2),
now.AddHours(-1),
Guid.NewGuid(),
0
);
await using (var seed = fixture.New())
{
seed.Channels.Add(channel);
seed.Shows.Add(show);
seed.MediaAssets.Add(asset);
seed.ScheduleEntries.AddRange(current, past);
await seed.SaveChangesAsync(CancellationToken.None);
}
await using var db = fixture.New();
var channels = await new ListPublicChannelsQueryHandler(db).Handle(
new ListPublicChannelsQuery(),
CancellationToken.None
);
var dto = Assert.Single(channels);
Assert.Equal(show.Id, dto.CurrentShowId);
Assert.Equal("Сейчас в эфире", dto.CurrentShowName);
Assert.Equal(show.PosterImageId, dto.CurrentShowPosterImageId);
Assert.Equal(logoId, dto.LogoImageId);
Assert.Equal(LogoCorner.TopRight, dto.LogoCorner);
Assert.Equal(0.5, dto.LogoOpacity);
Assert.True(dto.ShowClock);
Assert.Equal(0.3, dto.AnalogFilterStrength);
}
[Fact]
public async Task List_WithoutEnabledChannels_ReturnsEmpty()
{
var fixture = new TestDb();
await using var db = fixture.New();
var channels = await new ListPublicChannelsQueryHandler(db).Handle(
new ListPublicChannelsQuery(),
CancellationToken.None
);
Assert.Empty(channels);
}
}