Retry chat bulk actions after stale menu URL
This commit is contained in:
@@ -805,7 +805,8 @@ public sealed class ChatsController(
|
|||||||
|
|
||||||
private static bool IsChatOpenFailure(string? error)
|
private static bool IsChatOpenFailure(string? error)
|
||||||
{
|
{
|
||||||
return error?.Contains("not found or did not open", StringComparison.OrdinalIgnoreCase) == true;
|
return error?.Contains("not found or did not open", StringComparison.OrdinalIgnoreCase) == true ||
|
||||||
|
error?.Contains("menu was not opened", StringComparison.OrdinalIgnoreCase) == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<Chat>> LoadChatsWithAttachmentsAsync(IReadOnlyCollection<Guid> chatIds, CancellationToken cancellationToken)
|
private async Task<List<Chat>> LoadChatsWithAttachmentsAsync(IReadOnlyCollection<Guid> chatIds, CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -682,6 +682,45 @@ public sealed class ApiSmokeTests : IDisposable
|
|||||||
Assert.DoesNotContain(chats!, x => x.Id == chat.Id);
|
Assert.DoesNotContain(chats!, x => x.Id == chat.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task BulkDeleteRefreshesStaleChatUrlAfterMenuOpenFailure()
|
||||||
|
{
|
||||||
|
const string externalId = "stale-menu-url-chat";
|
||||||
|
const string staleUrl = "https://max.test/chat/wrong-chat";
|
||||||
|
var bridge = new ResolvingDeleteMaxBridgeClient(staleUrl);
|
||||||
|
using var factory = _factory.WithWebHostBuilder(builder =>
|
||||||
|
{
|
||||||
|
builder.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.RemoveAll<IMaxBridgeClient>();
|
||||||
|
services.AddSingleton<IMaxBridgeClient>(bridge);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
using var client = factory.CreateClient();
|
||||||
|
await LoginAsync(client);
|
||||||
|
|
||||||
|
var chat = await CreateDirectChatAsync(client, externalId, "Stale Menu Url");
|
||||||
|
await using (var scope = factory.Services.CreateAsyncScope())
|
||||||
|
{
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<QMaxDbContext>();
|
||||||
|
var stored = await db.Chats.SingleAsync(x => x.Id == chat.Id);
|
||||||
|
stored.WebUrl = staleUrl;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await client.PostAsJsonAsync(
|
||||||
|
"/api/chats/delete",
|
||||||
|
new ChatBulkActionRequest([chat.Id]),
|
||||||
|
JsonOptions);
|
||||||
|
await AssertStatusAsync(HttpStatusCode.NoContent, response);
|
||||||
|
|
||||||
|
Assert.Equal(externalId, bridge.ResolvedExternalId);
|
||||||
|
Assert.Equal([staleUrl, $"https://max.test/chat/{externalId}"], bridge.DeleteChatUrls);
|
||||||
|
|
||||||
|
var chats = await client.GetFromJsonAsync<ChatDto[]>("/api/chats", JsonOptions);
|
||||||
|
Assert.DoesNotContain(chats!, x => x.Id == chat.Id);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task FailedMaxTextSendMarksLocalMessageFailed()
|
public async Task FailedMaxTextSendMarksLocalMessageFailed()
|
||||||
{
|
{
|
||||||
@@ -1457,8 +1496,16 @@ public sealed class ApiSmokeTests : IDisposable
|
|||||||
|
|
||||||
private sealed class ResolvingDeleteMaxBridgeClient : IMaxBridgeClient
|
private sealed class ResolvingDeleteMaxBridgeClient : IMaxBridgeClient
|
||||||
{
|
{
|
||||||
|
private readonly string? _staleUrlToReject;
|
||||||
|
|
||||||
|
public ResolvingDeleteMaxBridgeClient(string? staleUrlToReject = null)
|
||||||
|
{
|
||||||
|
_staleUrlToReject = staleUrlToReject;
|
||||||
|
}
|
||||||
|
|
||||||
public string? ResolvedExternalId { get; private set; }
|
public string? ResolvedExternalId { get; private set; }
|
||||||
public string? DeleteChatUrl { get; private set; }
|
public string? DeleteChatUrl { get; private set; }
|
||||||
|
public List<string?> DeleteChatUrls { get; } = [];
|
||||||
|
|
||||||
public Task<MaxBridgeStatus> GetStatusAsync(CancellationToken cancellationToken)
|
public Task<MaxBridgeStatus> GetStatusAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@@ -1508,7 +1555,13 @@ public sealed class ApiSmokeTests : IDisposable
|
|||||||
|
|
||||||
public Task<MaxActionResult> DeleteChatAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
|
public Task<MaxActionResult> DeleteChatAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
DeleteChatUrls.Add(chatUrl);
|
||||||
DeleteChatUrl = chatUrl;
|
DeleteChatUrl = chatUrl;
|
||||||
|
if (string.Equals(chatUrl, _staleUrlToReject, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return Task.FromResult(new MaxActionResult(false, "MAX chat menu was not opened."));
|
||||||
|
}
|
||||||
|
|
||||||
return Task.FromResult(string.IsNullOrWhiteSpace(chatUrl)
|
return Task.FromResult(string.IsNullOrWhiteSpace(chatUrl)
|
||||||
? new MaxActionResult(false, "MAX chat was not found or did not open.")
|
? new MaxActionResult(false, "MAX chat was not found or did not open.")
|
||||||
: new MaxActionResult(true, null));
|
: new MaxActionResult(true, null));
|
||||||
|
|||||||
Reference in New Issue
Block a user