mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-24 00:52:23 -04:00
Shakeout Testing Part 1 (#1052)
* Have language from epubs populate metadata * series detail needs to reload the underlying volumes when scan event comes in, not just metadata. * Added Id to chapter detail modal (for debugging) * Implement IDisposable on applicable Unit Tests * Removed unused using statements * Fixed a bug where images would flash like crazy during a scan because the code to refresh the underlying image wasn't checking the entity type or Id. * When filtering rating, only apply the filter to your account. * Removed Disposable on tests
This commit is contained in:
parent
1f8f6f6fac
commit
2b0d47d15e
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Order;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions.TestingHelpers;
|
||||
@ -10,15 +11,11 @@ using API.DTOs.Reader;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Services;
|
||||
using API.Services.Tasks;
|
||||
using API.SignalR;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetVips;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
@ -26,10 +23,7 @@ namespace API.Tests.Services;
|
||||
|
||||
public class BookmarkServiceTests
|
||||
{
|
||||
private readonly ILogger<CleanupService> _logger = Substitute.For<ILogger<CleanupService>>();
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IHubContext<MessageHub> _messageHub = Substitute.For<IHubContext<MessageHub>>();
|
||||
|
||||
private readonly DbConnection _connection;
|
||||
private readonly DataContext _context;
|
||||
|
||||
@ -63,8 +57,6 @@ public class BookmarkServiceTests
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void Dispose() => _connection.Dispose();
|
||||
|
||||
private async Task<bool> SeedDb()
|
||||
{
|
||||
await _context.Database.MigrateAsync();
|
||||
|
@ -61,8 +61,6 @@ public class CleanupServiceTests
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void Dispose() => _connection.Dispose();
|
||||
|
||||
private async Task<bool> SeedDb()
|
||||
{
|
||||
await _context.Database.MigrateAsync();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.IO.Abstractions.TestingHelpers;
|
||||
using System.Linq;
|
||||
@ -95,8 +96,6 @@ public class ParseScannedFilesTests
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void Dispose() => _connection.Dispose();
|
||||
|
||||
private async Task<bool> SeedDb()
|
||||
{
|
||||
await _context.Database.MigrateAsync();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.IO.Abstractions.TestingHelpers;
|
||||
using System.Linq;
|
||||
@ -10,10 +11,8 @@ using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Helpers;
|
||||
using API.Services;
|
||||
using API.SignalR;
|
||||
using API.Tests.Helpers;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
@ -25,9 +24,8 @@ namespace API.Tests.Services;
|
||||
|
||||
public class ReaderServiceTests
|
||||
{
|
||||
private readonly ILogger<CacheService> _logger = Substitute.For<ILogger<CacheService>>();
|
||||
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IHubContext<MessageHub> _messageHub = Substitute.For<IHubContext<MessageHub>>();
|
||||
|
||||
private readonly DbConnection _connection;
|
||||
private readonly DataContext _context;
|
||||
@ -61,8 +59,6 @@ public class ReaderServiceTests
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void Dispose() => _connection.Dispose();
|
||||
|
||||
private async Task<bool> SeedDb()
|
||||
{
|
||||
await _context.Database.MigrateAsync();
|
||||
@ -902,6 +898,81 @@ public class ReaderServiceTests
|
||||
Assert.Equal(-1, prevChapter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetPrevChapterIdAsync_ShouldFindNoPrevChapterFromVolumeWithZeroChapter()
|
||||
{
|
||||
await ResetDB();
|
||||
|
||||
_context.Series.Add(new Series()
|
||||
{
|
||||
Name = "Test",
|
||||
Library = new Library() {
|
||||
Name = "Test LIb",
|
||||
Type = LibraryType.Manga,
|
||||
},
|
||||
Volumes = new List<Volume>()
|
||||
{
|
||||
EntityFactory.CreateVolume("1", new List<Chapter>()
|
||||
{
|
||||
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
_context.AppUser.Add(new AppUser()
|
||||
{
|
||||
UserName = "majora2007"
|
||||
});
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var readerService = new ReaderService(_unitOfWork, Substitute.For<ILogger<ReaderService>>());
|
||||
|
||||
|
||||
var prevChapter = await readerService.GetPrevChapterIdAsync(1, 1, 1, 1);
|
||||
Assert.Equal(-1, prevChapter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetPrevChapterIdAsync_ShouldFindNoPrevChapterFromVolumeWithZeroChapterAndHasNormalChapters()
|
||||
{
|
||||
await ResetDB();
|
||||
|
||||
_context.Series.Add(new Series()
|
||||
{
|
||||
Name = "Test",
|
||||
Library = new Library() {
|
||||
Name = "Test LIb",
|
||||
Type = LibraryType.Manga,
|
||||
},
|
||||
Volumes = new List<Volume>()
|
||||
{
|
||||
EntityFactory.CreateVolume("0", new List<Chapter>()
|
||||
{
|
||||
EntityFactory.CreateChapter("1", false, new List<MangaFile>()),
|
||||
EntityFactory.CreateChapter("2", false, new List<MangaFile>()),
|
||||
}),
|
||||
EntityFactory.CreateVolume("1", new List<Chapter>()
|
||||
{
|
||||
EntityFactory.CreateChapter("0", false, new List<MangaFile>()),
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
_context.AppUser.Add(new AppUser()
|
||||
{
|
||||
UserName = "majora2007"
|
||||
});
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var readerService = new ReaderService(_unitOfWork, Substitute.For<ILogger<ReaderService>>());
|
||||
|
||||
|
||||
var prevChapter = await readerService.GetPrevChapterIdAsync(1, 1, 1, 1);
|
||||
Assert.Equal(-1, prevChapter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetPrevChapterIdAsync_ShouldFindNoPrevChapterFromChapter()
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace API.Constants
|
||||
{
|
||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
using API.DTOs;
|
||||
using API.DTOs.Reader;
|
||||
using API.Entities.Enums;
|
||||
using API.Extensions;
|
||||
|
@ -156,7 +156,7 @@ namespace API.Controllers
|
||||
{
|
||||
tag.CoverImageLocked = false;
|
||||
tag.CoverImage = string.Empty;
|
||||
await _messageHub.Clients.All.SendAsync(SignalREvents.CoverUpdate, MessageFactory.CoverUpdateEvent(tag.Id, "collection"));
|
||||
await _messageHub.Clients.All.SendAsync(SignalREvents.CoverUpdate, MessageFactory.CoverUpdateEvent(tag.Id, "collectionTag"));
|
||||
_unitOfWork.CollectionTagRepository.Update(tag);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ using API.Data.Repositories;
|
||||
using API.DTOs;
|
||||
using API.DTOs.Reader;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Extensions;
|
||||
using API.Services;
|
||||
using API.Services.Tasks;
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs.Stats;
|
||||
using API.DTOs.Update;
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace API.DTOs.Account;
|
||||
namespace API.DTOs.Account;
|
||||
|
||||
public class MigrateUserEmailDto
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
using API.DTOs.CollectionTags;
|
||||
using API.DTOs.Metadata;
|
||||
using API.DTOs.ReadingLists;
|
||||
using API.Entities;
|
||||
|
||||
namespace API.DTOs.Search;
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -636,7 +636,7 @@ public class SeriesRepository : ISeriesRepository
|
||||
&& (!hasPeopleFilter || s.Metadata.People.Any(p => allPeopleIds.Contains(p.Id)))
|
||||
&& (!hasCollectionTagFilter ||
|
||||
s.Metadata.CollectionTags.Any(t => filter.CollectionTags.Contains(t.Id)))
|
||||
&& (!hasRatingFilter || s.Ratings.Any(r => r.Rating >= filter.Rating))
|
||||
&& (!hasRatingFilter || s.Ratings.Any(r => r.Rating >= filter.Rating && r.AppUserId == userId))
|
||||
&& (!hasProgressFilter || seriesIds.Contains(s.Id))
|
||||
&& (!hasAgeRating || filter.AgeRating.Contains(s.Metadata.AgeRating))
|
||||
&& (!hasTagsFilter || s.Metadata.Tags.Any(t => filter.Tags.Contains(t.Id)))
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Linq;
|
||||
using API.DTOs;
|
||||
using API.DTOs.CollectionTags;
|
||||
using API.DTOs.Email;
|
||||
using API.DTOs.Metadata;
|
||||
using API.DTOs.Reader;
|
||||
using API.DTOs.ReadingLists;
|
||||
|
@ -388,6 +388,7 @@ namespace API.Services
|
||||
Year = !string.IsNullOrEmpty(publicationDate) ? DateTime.Parse(publicationDate).Year : 0,
|
||||
Title = epubBook.Title,
|
||||
Genre = string.Join(",", epubBook.Schema.Package.Metadata.Subjects.Select(s => s.ToLower().Trim())),
|
||||
LanguageISO = epubBook.Schema.Package.Metadata.Languages.FirstOrDefault() ?? string.Empty
|
||||
|
||||
};
|
||||
// Parse tags not exposed via Library
|
||||
|
@ -4,7 +4,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
using API.Data.Repositories;
|
||||
using API.DTOs.Reader;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
@ -7,7 +6,6 @@ using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using API.Comparators;
|
||||
using API.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
@ -6,7 +6,6 @@ using System.Threading.Tasks;
|
||||
using API.Comparators;
|
||||
using API.Data;
|
||||
using API.Data.Repositories;
|
||||
using API.Data.Scanner;
|
||||
using API.Entities;
|
||||
using API.Extensions;
|
||||
using API.Helpers;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using API.DTOs.Update;
|
||||
|
||||
namespace API.SignalR
|
||||
|
@ -3,5 +3,5 @@
|
||||
*/
|
||||
export interface CoverUpdateEvent {
|
||||
id: number;
|
||||
entityType: 'series' | 'chapter' | 'volume' | 'collection';
|
||||
entityType: 'series' | 'chapter' | 'volume' | 'collectionTag';
|
||||
}
|
@ -4,7 +4,11 @@
|
||||
|
||||
|
||||
<!-- Arc Information -->
|
||||
|
||||
<div class="row no-gutters">
|
||||
<div class="col">
|
||||
Id: {{chapter.id}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutters">
|
||||
<div class="col">
|
||||
|
@ -203,10 +203,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
||||
} else if (event.event === EVENTS.ScanSeries) {
|
||||
const seriesCoverUpdatedEvent = event.payload as ScanSeriesEvent;
|
||||
if (seriesCoverUpdatedEvent.seriesId === this.series.id) {
|
||||
this.seriesService.getMetadata(this.series.id).pipe(take(1)).subscribe(metadata => {
|
||||
this.seriesMetadata = metadata;
|
||||
this.createHTML();
|
||||
});
|
||||
this.loadSeries(seriesId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { CoverUpdateEvent } from 'src/app/_models/events/cover-update-event';
|
||||
import { ImageService } from 'src/app/_services/image.service';
|
||||
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
|
||||
|
||||
@ -46,7 +47,13 @@ export class ImageComponent implements OnChanges, OnDestroy {
|
||||
constructor(public imageService: ImageService, private renderer: Renderer2, private hubService: MessageHubService) {
|
||||
this.hubService.messages$.pipe(takeUntil(this.onDestroy)).subscribe(res => {
|
||||
if (res.event === EVENTS.CoverUpdate) {
|
||||
this.imageUrl = this.imageService.randomize(this.imageUrl);
|
||||
const updateEvent = res.payload as CoverUpdateEvent;
|
||||
if (this.imageUrl === undefined || this.imageUrl === null || this.imageUrl === '') return;
|
||||
|
||||
const tokens = this.imageUrl.split(updateEvent.entityType + 'Id=');
|
||||
if (tokens.length > 1 && tokens[1] === (updateEvent.id + '')) {
|
||||
this.imageUrl = this.imageService.randomize(this.imageUrl);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user