removed fp6 from shop
All checks were successful
Deploy / build-deploy (push) Successful in 5m35s

This commit is contained in:
Jorijn van der Graaf 2026-09-05 18:38:39 +02:00
commit 25805a093a
20 changed files with 788 additions and 805 deletions

View file

@ -12,8 +12,10 @@ No permission is granted to copy, modify, distribute, or create derivative works
// (the timezone price hint); everything else ships none at all.
import std;
import Catcrafts.Shared;
import Catcrafts.E2eHarness;
using namespace Catcrafts;
using namespace Catcrafts::E2e;
namespace {
@ -53,10 +55,14 @@ int main(int argc, char** argv) {
// Placeholders are dev-only markers; one reaching production is a content
// bug (an imprint that says PLACEHOLDER once shipped exactly that way).
for (std::string_view pg : { "/legal/privacy", "/legal/terms", "/legal/imprint",
"/shop/fp6-pmos", "/shop/fp6plus-pmos", "/financials" }) {
"/financials" }) {
srv.BodyLacks(std::string(pg), "PLACEHOLDER",
std::format("{} ships no placeholder markers", pg));
}
for (const Product& pr : Content::Products()) {
srv.BodyLacks("/shop/" + pr.slug, "PLACEHOLDER",
std::format("/shop/{} ships no placeholder markers", pr.slug));
}
// Shop pages are the one exception to script-free: they carry exactly ONE
// EXECUTABLE inline script — the timezone price hint, whose tag is the
@ -65,8 +71,15 @@ int main(int argc, char** argv) {
// rule. Pin the shape hard: inline only (no src=, so nothing external can
// ever ride in under this exception), no network APIs, and the page must
// remain complete without it — both prices in the markup regardless.
for (std::string_view pg : { "/shop", "/shop/fp6-pmos", "/shop/fp6plus-pmos" }) {
const std::string body = srv.Body(std::string(pg));
// The pages under the rule: the shop index and every PRICED product page.
// The donation page has no price to convert and ships no script at all
// (ShouldSellTheShopFront pins that), so it is not in this list.
std::vector<std::string> pricedPages{ "/shop" };
for (const Product& pr : Content::Products()) {
if (!pr.donation) pricedPages.push_back("/shop/" + pr.slug);
}
for (const std::string& pg : pricedPages) {
const std::string body = srv.Body(pg);
const std::size_t n = CountOccurrences(body, "<script>");
Check(n == 1,
std::format("{} carries exactly one executable script (the price hint)", pg),
@ -87,8 +100,10 @@ int main(int argc, char** argv) {
}
Check(!network, std::format("{} script makes no network calls", pg));
}
srv.BodyHas("/shop/fp6-pmos", "cc-noneu", "price hint tags the non-EU outcome");
srv.BodyHas("/shop/fp6-pmos", "cc-eu", "price hint tags the confirmed-EU outcome too");
if (const Product* pr = FirstPricedProduct()) {
srv.BodyHas("/shop/" + pr->slug, "cc-noneu", "price hint tags the non-EU outcome");
srv.BodyHas("/shop/" + pr->slug, "cc-eu", "price hint tags the confirmed-EU outcome too");
}
// The renderer loads only where a demo entry declares needsWasm — the
// demo LIST is a content page and must stay free of it.
@ -127,7 +142,7 @@ int main(int argc, char** argv) {
// it is dead weight and one more thing that could retarget a future
// relative link.
srv.BodyLacks("/posts", "<base", "/posts has no base tag");
srv.BodyLacks("/shop/fp6-pmos", "<base", "/shop/<slug> has no base tag");
srv.BodyLacks("/shop/donation", "<base", "/shop/<slug> has no base tag");
// ── home page actions ─────────────────────────────────────────────
srv.BodyHas("/", "Browse projects", "home links to projects");