This commit is contained in:
parent
eb655b24b6
commit
25805a093a
20 changed files with 788 additions and 805 deletions
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in a new issue