-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix 404 during project reset test (#740)
* Remove race-condition window in ResetProject * Remove race-condition window in FinishReset * Faster SendReceiveAfterProjectReset test Now that we've removed the race condition in ResetProject, we no longer need to wait for the hgweb refresh interval in the middle of the SendReceiveAfterProjectReset tests. (We still do need to wait for it at the start of the test, after project creation). * Delete invalid reset-project zip file contents If the zip file uploaded during the reset project step had no .hg directory anywhere inside it, we want to delete it entirely before presenting the error message to the user. Otherwise we might leave quite large amounts of useless data lying around in the repos volume. * Add project reset 404 integration test * Proper temp folder, restore metadata after reset * Fix primary-key error on FlexProjectMetadata * Address review comments * simplify moving folders around for reset, introduce helper method to get a temp repo path * Use ShouldAllBe for better error messages * Keep test repo zip in Git instead of downloading it This saves seeral seconds of test setup time. * Move TusDotNetClient reference to correct location This allows the project to build when MercurialVersion is set to 6. * write tests for the integration fixture * Make user typeahead safer for Playwright tests The user typeahead had two debounces, one in the input and one in the typeahead store. The debounce in the input was causing Playwright tests to fail because they were filling in the input and expecting the form to be valid immediately, but it wasn't valid until the debounce triggered. The debounce on the input now serves no purpose; removing it. * Make email-handling more robust in Playwright tests Many times the Playwright code gets to the email page before the email has actually shown up. So we need to make it wait for up to 10 seconds, refreshing the email list periodically (because mailDev, at least, doesn't auto-refresh: you have to click the refresh button). * Just use template repo from orig location, no copy * Nicer way to set TemplateRepoZip * Simply use relative path for TemplateRepoZip * Check email subjects and bump playwright timeout * Fix IntegrationFixtureTests --------- Co-authored-by: Tim Haasdyk <[email protected]> Co-authored-by: Kevin Hahn <[email protected]>
- Loading branch information
1 parent
e1b2f7d
commit ec3b763
Showing
20 changed files
with
346 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using Shouldly; | ||
using Testing.Fixtures; | ||
using static Testing.Services.Utils; | ||
|
||
namespace Testing.ApiTests; | ||
|
||
// Issue: https://github.com/sillsdev/languageforge-lexbox/issues/728 | ||
// Sadly, this does not reproduce the 404, but I still think it's a decent test | ||
[Trait("Category", "Integration")] | ||
public class ResetPojectRaceCondition : IClassFixture<IntegrationFixture> | ||
{ | ||
|
||
private readonly IntegrationFixture _fixture; | ||
private readonly ApiTestBase _adminApiTester; | ||
|
||
public ResetPojectRaceCondition(IntegrationFixture fixture) | ||
{ | ||
_fixture = fixture; | ||
_adminApiTester = _fixture.AdminApiTester; | ||
} | ||
|
||
[Fact] | ||
public async Task SimultaneousResetsDontResultIn404s() | ||
{ | ||
// Create projects on server | ||
var config1 = GetNewProjectConfig(); | ||
var config2 = GetNewProjectConfig(); | ||
var config3 = GetNewProjectConfig(); | ||
|
||
await using var project1 = await RegisterProjectInLexBox(config1, _adminApiTester); | ||
await using var project2 = await RegisterProjectInLexBox(config2, _adminApiTester); | ||
await using var project3 = await RegisterProjectInLexBox(config3, _adminApiTester); | ||
|
||
var lastCommitBefore1 = await _adminApiTester.GetProjectLastCommit(config1.Code); | ||
var lastCommitBefore2 = await _adminApiTester.GetProjectLastCommit(config2.Code); | ||
var lastCommitBefore3 = await _adminApiTester.GetProjectLastCommit(config3.Code); | ||
|
||
lastCommitBefore1.ShouldBeNullOrWhiteSpace(); | ||
lastCommitBefore2.ShouldBeNullOrWhiteSpace(); | ||
lastCommitBefore3.ShouldBeNullOrWhiteSpace(); | ||
|
||
// Reset and fill projects on server | ||
var newLastCommits = await Task.WhenAll( | ||
DoFullProjectResetAndVerifyLastCommit(config1.Code), | ||
DoFullProjectResetAndVerifyLastCommit(config2.Code), | ||
DoFullProjectResetAndVerifyLastCommit(config3.Code) | ||
); | ||
|
||
newLastCommits[0].ShouldNotBeNullOrWhiteSpace(); | ||
newLastCommits[0].ShouldBe(newLastCommits[1]); | ||
newLastCommits[0].ShouldBe(newLastCommits[2]); | ||
|
||
// we need a short delay between resets or we'll get naming collisions on the backups of the reset projects | ||
await Task.Delay(1000); | ||
|
||
// Reset and fill projects on server | ||
var templateRepoLastCommit = newLastCommits[0]; | ||
newLastCommits = await Task.WhenAll( | ||
DoFullProjectResetAndVerifyLastCommit(config1.Code, templateRepoLastCommit), | ||
DoFullProjectResetAndVerifyLastCommit(config2.Code, templateRepoLastCommit), | ||
DoFullProjectResetAndVerifyLastCommit(config3.Code, templateRepoLastCommit) | ||
); | ||
} | ||
|
||
private async Task<string?> DoFullProjectResetAndVerifyLastCommit(string projectCode, string? expectedLastCommit = null) | ||
{ | ||
await _adminApiTester.StartLexboxProjectReset(projectCode); | ||
var lastCommitBefore = await _adminApiTester.GetProjectLastCommit(projectCode); | ||
lastCommitBefore.ShouldBeNullOrWhiteSpace(); | ||
await _fixture.FinishLexboxProjectResetWithTemplateRepo(projectCode); | ||
var lastCommit = await _adminApiTester.GetProjectLastCommit(projectCode); | ||
if (expectedLastCommit is not null) lastCommit.ShouldBe(expectedLastCommit); | ||
else lastCommit.ShouldNotBeNullOrWhiteSpace(); | ||
return lastCommit; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
using System.IO.Compression; | ||
using System.Net; | ||
using System.Reflection; | ||
using System.Runtime.CompilerServices; | ||
using LexCore.Utils; | ||
using Shouldly; | ||
using Testing.ApiTests; | ||
using Testing.Services; | ||
using TusDotNetClient; | ||
using static Testing.Services.Constants; | ||
|
||
namespace Testing.Fixtures; | ||
|
||
public class IntegrationFixture : IAsyncLifetime | ||
{ | ||
private static readonly string _templateRepoName = "test-template-repo.zip"; | ||
public FileInfo TemplateRepoZip { get; } = new(_templateRepoName); | ||
public DirectoryInfo TemplateRepo { get; } = new(Path.Join(BasePath, "_template-repo_")); | ||
public ApiTestBase AdminApiTester { get; private set; } = new(); | ||
private string AdminJwt = string.Empty; | ||
|
||
public async Task InitializeAsync(ApiTestBase apiTester) | ||
{ | ||
AdminApiTester = apiTester; | ||
await InitializeAsync(); | ||
} | ||
|
||
public async Task InitializeAsync() | ||
{ | ||
DeletePreviousTestFiles(); | ||
Directory.CreateDirectory(BasePath); | ||
InitTemplateRepo(); | ||
AdminJwt = await AdminApiTester.LoginAs(AdminAuth.Username, AdminAuth.Password); | ||
} | ||
|
||
public Task DisposeAsync() | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
|
||
private static void DeletePreviousTestFiles() | ||
{ | ||
if (Directory.Exists(BasePath)) Directory.Delete(BasePath, true); | ||
} | ||
|
||
private void InitTemplateRepo() | ||
{ | ||
using var stream = TemplateRepoZip.OpenRead(); | ||
ZipFile.ExtractToDirectory(stream, TemplateRepo.FullName); | ||
} | ||
|
||
public ProjectConfig InitLocalFlexProjectWithRepo(HgProtocol? protocol = null, [CallerMemberName] string projectName = "") | ||
{ | ||
var projectConfig = Utils.GetNewProjectConfig(protocol, projectName); | ||
InitLocalFlexProjectWithRepo(projectConfig); | ||
return projectConfig; | ||
} | ||
|
||
public void InitLocalFlexProjectWithRepo(ProjectPath projectPath) | ||
{ | ||
var projectDir = Directory.CreateDirectory(projectPath.Dir); | ||
FileUtils.CopyFilesRecursively(TemplateRepo, projectDir); | ||
File.Move(Path.Join(projectPath.Dir, "kevin-test-01.fwdata"), projectPath.FwDataFile); | ||
Directory.EnumerateFiles(projectPath.Dir).ShouldContain(projectPath.FwDataFile); | ||
} | ||
|
||
public async Task FinishLexboxProjectResetWithTemplateRepo(string projectCode) | ||
{ | ||
await FinishLexboxProjectResetWithRepo(projectCode, TemplateRepoZip); | ||
} | ||
|
||
public async Task FinishLexboxProjectResetWithRepo(string projectCode, FileInfo repo) | ||
{ | ||
var client = new TusClient(); | ||
client.AdditionalHeaders.Add("Cookie", $".LexBoxAuth={AdminJwt}"); | ||
var fileUrl = await client.CreateAsync($"{AdminApiTester.BaseUrl}/api/project/upload-zip/{projectCode}", repo.Length, [("filetype", "application/zip")]); | ||
var responses = await client.UploadAsync(fileUrl, repo, chunkSize: 20); | ||
responses.ShouldAllBe(r => r.StatusCode.ToString() == nameof(HttpStatusCode.NoContent)); | ||
} | ||
} |
Oops, something went wrong.