fix: preserve compatibility query in plugin embeds
This commit is contained in:
parent
eea9a3e410
commit
1a8fbaebb6
@ -80,6 +80,49 @@ public class PluginDetailsUITests(ITestOutputHelper output) : PageTest
|
||||
Assert.True(detailsBox.Y < reviewsBox.Y, "Metadata should stay above reviews in embedded details.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PluginDetails_EmbedSelection_PreservesCompatibilityQuery()
|
||||
{
|
||||
await using var tester = new PlaywrightTester(_log);
|
||||
tester.Server.ReuseDatabase = false;
|
||||
await tester.StartAsync();
|
||||
|
||||
var ownerId = await tester.Server.CreateFakeUserAsync("embed-selection-owner@x.com", confirmEmail: true, githubVerified: true);
|
||||
const string firstSlug = "embed-select-a";
|
||||
const string secondSlug = "embed-select-b";
|
||||
await tester.Server.CreateAndBuildPluginAsync(ownerId, firstSlug);
|
||||
await tester.Server.CreateAndBuildPluginAsync(ownerId, secondSlug);
|
||||
|
||||
var detailsUrl = new Uri(tester.ServerUri!, $"/public/plugins/{firstSlug}?embed=1&btcpayVersion=2.3.6&includePreRelease=true");
|
||||
await tester.Page!.SetContentAsync($"""
|
||||
<iframe id="details" src="{detailsUrl}"></iframe>
|
||||
""");
|
||||
|
||||
await tester.Page.WaitForFunctionAsync("""
|
||||
() => document.querySelector('#details')?.contentWindow?.document?.querySelector('[data-embed-page="details"]')
|
||||
""");
|
||||
|
||||
await tester.Page.EvaluateAsync($$"""
|
||||
() => document.querySelector('#details').contentWindow.postMessage({
|
||||
type: 'btcpay:host-context',
|
||||
selectedSlug: '{{secondSlug}}'
|
||||
}, window.location.origin)
|
||||
""");
|
||||
|
||||
var finalUrlHandle = await tester.Page.WaitForFunctionAsync($$"""
|
||||
() => {
|
||||
const href = document.querySelector('#details')?.contentWindow?.location?.href || '';
|
||||
return href.includes('/public/plugins/{{secondSlug}}') ? href : false;
|
||||
}
|
||||
""");
|
||||
var finalUrl = await finalUrlHandle.JsonValueAsync<string>();
|
||||
|
||||
Assert.Contains($"/public/plugins/{secondSlug}", finalUrl);
|
||||
Assert.Contains("embed=1", finalUrl);
|
||||
Assert.Contains("btcpayVersion=2.3.6", finalUrl);
|
||||
Assert.Contains("includePreRelease=true", finalUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PluginDetails_Reviews_Flow_Works()
|
||||
{
|
||||
|
||||
@ -17,6 +17,45 @@ public class PublicDirectoryUITests(ITestOutputHelper output) : PageTest
|
||||
{
|
||||
private readonly XUnitLogger _log = new("PublicDirectoryUITests", output);
|
||||
|
||||
[Fact]
|
||||
public async Task PublicDirectory_EmbedLinks_PreserveCompatibilityQuery()
|
||||
{
|
||||
await using var tester = new PlaywrightTester(_log);
|
||||
tester.Server.ReuseDatabase = false;
|
||||
await tester.StartAsync();
|
||||
await using var conn = await tester.Server.GetService<DBConnectionFactory>().Open();
|
||||
|
||||
var ownerId = await tester.Server.CreateFakeUserAsync(confirmEmail: true, githubVerified: true);
|
||||
const string pluginSlug = "public-directory-embed-query";
|
||||
var fullBuildId = await tester.Server.CreateAndBuildPluginAsync(ownerId, pluginSlug);
|
||||
|
||||
var manifestInfoJson = await conn.QuerySingleAsync<string>(
|
||||
"SELECT manifest_info FROM builds WHERE plugin_slug = @PluginSlug AND id = @BuildId",
|
||||
new { PluginSlug = pluginSlug, fullBuildId.BuildId });
|
||||
var manifest = PluginManifest.Parse(manifestInfoJson);
|
||||
await conn.SetVersionBuild(fullBuildId, manifest.Version, manifest.BTCPayMinVersion, manifest.BTCPayMaxVersion, false);
|
||||
await conn.SetPluginSettings(pluginSlug, null, PluginVisibilityEnum.Listed);
|
||||
|
||||
await tester.GoToUrl("/public/plugins?embed=1&btcpayVersion=2.3.6-rc2&includePreRelease=true&sort=rating");
|
||||
await tester.AssertNoError();
|
||||
|
||||
await Expect(tester.Page!.Locator("form input[name='btcpayVersion']")).ToHaveValueAsync("2.3.6-rc2");
|
||||
await Expect(tester.Page.Locator("form input[name='includePreRelease']")).ToHaveValueAsync("true");
|
||||
|
||||
var detailsHref = await tester.Page.Locator($"a[data-plugin-slug='{pluginSlug}']").GetAttributeAsync("href");
|
||||
Assert.NotNull(detailsHref);
|
||||
Assert.Contains($"/public/plugins/{pluginSlug}", detailsHref);
|
||||
Assert.Contains("embed=1", detailsHref);
|
||||
Assert.Contains("btcpayVersion=2.3.6-rc2", detailsHref);
|
||||
Assert.Contains("includePreRelease=true", detailsHref);
|
||||
|
||||
var alphaSortHref = await tester.Page.Locator("a.dropdown-item[href*='sort=alpha']").GetAttributeAsync("href");
|
||||
Assert.NotNull(alphaSortHref);
|
||||
Assert.Contains("embed=1", alphaSortHref);
|
||||
Assert.Contains("btcpayVersion=2.3.6-rc2", alphaSortHref);
|
||||
Assert.Contains("includePreRelease=true", alphaSortHref);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PublicDirectory_RespectsPluginVisibility()
|
||||
{
|
||||
|
||||
@ -210,8 +210,8 @@ public class HomeController(
|
||||
[HttpGet("public/plugins")]
|
||||
[EnableRateLimiting(Policies.PublicApiRateLimit)]
|
||||
public async Task<IActionResult> AllPlugins(
|
||||
[ModelBinder(typeof(PluginVersionModelBinder))]
|
||||
PluginVersion? btcpayVersion = null, string? searchPluginName = null, string sort = "smart")
|
||||
[ModelBinder(typeof(BtcPayHostVersionModelBinder))]
|
||||
PluginVersion? btcpayVersion = null, bool includePreRelease = false, string? searchPluginName = null, string sort = "smart")
|
||||
{
|
||||
searchPluginName = searchPluginName.StripControlCharacters();
|
||||
|
||||
@ -285,7 +285,7 @@ public class HomeController(
|
||||
new
|
||||
{
|
||||
btcpayVersion = btcpayVersion?.VersionParts,
|
||||
includePreRelease = false,
|
||||
includePreRelease,
|
||||
searchPattern = $"%{searchPluginName}%",
|
||||
hasSearchTerm = !string.IsNullOrWhiteSpace(searchPluginName)
|
||||
});
|
||||
|
||||
@ -11,6 +11,10 @@
|
||||
|
||||
var currentSearch = Context.Request.Query["searchPluginName"].ToString();
|
||||
var currentSort = (string?)Context.Request.Query["sort"] ?? "smart";
|
||||
var currentBtcpayVersion = Context.Request.Query["btcpayVersion"].ToString();
|
||||
var currentIncludePreRelease = Context.Request.Query["includePreRelease"].ToString();
|
||||
var btcpayVersionRoute = string.IsNullOrEmpty(currentBtcpayVersion) ? null : currentBtcpayVersion;
|
||||
var includePreReleaseRoute = string.IsNullOrEmpty(currentIncludePreRelease) ? null : currentIncludePreRelease;
|
||||
if (string.IsNullOrEmpty(currentSort)) currentSort = "smart";
|
||||
|
||||
var sortLabel = currentSort switch
|
||||
@ -55,6 +59,14 @@
|
||||
{
|
||||
<input type="hidden" name="embed" value="1" />
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(currentBtcpayVersion))
|
||||
{
|
||||
<input type="hidden" name="btcpayVersion" value="@currentBtcpayVersion" />
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(currentIncludePreRelease))
|
||||
{
|
||||
<input type="hidden" name="includePreRelease" value="@currentIncludePreRelease" />
|
||||
}
|
||||
|
||||
<input type="text"
|
||||
name="searchPluginName"
|
||||
@ -75,6 +87,8 @@
|
||||
<a class="dropdown-item @(currentSort == "smart" ? "active" : "")"
|
||||
asp-action="AllPlugins"
|
||||
asp-route-searchPluginName="@currentSearch"
|
||||
asp-route-btcpayVersion="@btcpayVersionRoute"
|
||||
asp-route-includePreRelease="@includePreReleaseRoute"
|
||||
asp-route-embed="@embedRoute"
|
||||
asp-route-sort="smart">
|
||||
Relevance
|
||||
@ -82,6 +96,8 @@
|
||||
<a class="dropdown-item @(currentSort == "rating" ? "active" : "")"
|
||||
asp-action="AllPlugins"
|
||||
asp-route-searchPluginName="@currentSearch"
|
||||
asp-route-btcpayVersion="@btcpayVersionRoute"
|
||||
asp-route-includePreRelease="@includePreReleaseRoute"
|
||||
asp-route-embed="@embedRoute"
|
||||
asp-route-sort="rating">
|
||||
Highest rated
|
||||
@ -89,6 +105,8 @@
|
||||
<a class="dropdown-item @(currentSort == "recent" ? "active" : "")"
|
||||
asp-action="AllPlugins"
|
||||
asp-route-searchPluginName="@currentSearch"
|
||||
asp-route-btcpayVersion="@btcpayVersionRoute"
|
||||
asp-route-includePreRelease="@includePreReleaseRoute"
|
||||
asp-route-embed="@embedRoute"
|
||||
asp-route-sort="recent">
|
||||
Most recent
|
||||
@ -96,6 +114,8 @@
|
||||
<a class="dropdown-item @(currentSort == "alpha" ? "active" : "")"
|
||||
asp-action="AllPlugins"
|
||||
asp-route-searchPluginName="@currentSearch"
|
||||
asp-route-btcpayVersion="@btcpayVersionRoute"
|
||||
asp-route-includePreRelease="@includePreReleaseRoute"
|
||||
asp-route-embed="@embedRoute"
|
||||
asp-route-sort="alpha">
|
||||
Alphabetical
|
||||
@ -132,6 +152,8 @@
|
||||
<h3 style="margin-top: 0; margin-bottom: 5px;">
|
||||
<a asp-action="GetPluginDetails"
|
||||
asp-route-embed="@embedRoute"
|
||||
asp-route-btcpayVersion="@btcpayVersionRoute"
|
||||
asp-route-includePreRelease="@includePreReleaseRoute"
|
||||
data-plugin-slug="@plugin.ProjectSlug"
|
||||
data-plugin-identifier="@plugin.ManifestInfo?["Identifier"]?.ToString()"
|
||||
asp-route-pluginSlug="@plugin.ProjectSlug">@plugin.PluginTitle</a>
|
||||
|
||||
@ -134,6 +134,13 @@
|
||||
|
||||
function buildDetailsUrl(slug) {
|
||||
const url = new URL("/public/plugins/" + encodeURIComponent(slug), window.location.origin);
|
||||
const currentUrl = new URL(window.location.href);
|
||||
["btcpayVersion", "includePreRelease"].forEach(function (param) {
|
||||
const value = currentUrl.searchParams.get(param);
|
||||
if (value) {
|
||||
url.searchParams.set(param, value);
|
||||
}
|
||||
});
|
||||
url.searchParams.set("embed", "1");
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user