Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ on:
branches: [main, develop]

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# The serverless smoke tests serve the built `dist/` output, so the full
# suite only runs against a fresh build.
- run: pnpm build
- run: pnpm test

build:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/jsonld.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ describe('serializeJsonLd - script-breaking sequences', () => {
});

it('emits the escape sequences instead of stripping the content', () => {
const out = serializeJsonLd(hostileArticle('</script>'));
// Input must contain every character the serializer escapes (<, >, &)
// so each expected escape sequence is actually exercised.
const out = serializeJsonLd(hostileArticle('</script>&'));

for (const escape of EXPECTED_ESCAPES) {
expect(out).toContain(escape);
Expand Down
26 changes: 16 additions & 10 deletions src/__tests__/seo.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
*
* Covers:
* - canonicalUrl always returns the English (default) URL
* - hreflangAlternates emits en, es, pt-BR, and x-default entries all pointing
* at the same canonical URL
* - hreflangAlternates emits en, es, pt-BR, and x-default entries, each
* pointing at the locale-specific crawlable URL (en/x-default at the canonical
* English URL)
* - usePageSeo hook returns translated title/description for each locale
* - Stellar, Grants, Blog, and CaseStudies pages render locale-correct <title>
* and <meta name="description"> for Spanish and Portuguese
Expand Down Expand Up @@ -127,7 +128,8 @@ describe('locale-aware page metadata', () => {
window.history.replaceState({}, '', '/es/stellar');
const { default: App } = await import('../App');
render(<App />);
await screen.findByRole('heading', { level: 1, name: /integrac/i });
// Hero copy is English-only; the h1 renders "Stellar Integration" in every locale.
await screen.findByRole('heading', { level: 1, name: /stellar integration/i });
expect(getDocumentTitle()).toMatch(/Stellar/i);
// Spanish translation contains "Stellar" and "Wraith Protocol"
expect(getDocumentTitle()).toMatch(/Wraith Protocol/i);
Expand All @@ -141,7 +143,7 @@ describe('locale-aware page metadata', () => {
window.history.replaceState({}, '', '/pt/stellar');
const { default: App } = await import('../App');
render(<App />);
await screen.findByRole('heading', { level: 1, name: /stellar/i });
await screen.findByRole('heading', { level: 1, name: /stellar integration/i });
expect(getDocumentTitle()).toMatch(/Stellar/i);
expect(getDocumentTitle()).not.toBe('Stealth payments on Stellar – Wraith Protocol');
});
Expand All @@ -164,7 +166,8 @@ describe('locale-aware page metadata', () => {
window.history.replaceState({}, '', '/es/grants');
const { default: App } = await import('../App');
render(<App />);
await screen.findByRole('heading', { level: 1, name: /construye pagos privados/i });
// Hero copy is English-only; the h1 renders the English heading in every locale.
await screen.findByRole('heading', { level: 1, name: /build private payments/i });
// Spanish: "Subvenciones – Wraith Protocol"
expect(getDocumentTitle()).toMatch(/Subvenciones/i);
expect(getDocumentTitle()).toMatch(/Wraith Protocol/i);
Expand All @@ -176,7 +179,8 @@ describe('locale-aware page metadata', () => {
window.history.replaceState({}, '', '/pt/grants');
const { default: App } = await import('../App');
render(<App />);
await screen.findByRole('heading', { level: 1, name: /construa pagamentos privados/i });
// Hero copy is English-only; the h1 renders the English heading in every locale.
await screen.findByRole('heading', { level: 1, name: /build private payments/i });
// Portuguese: "Bolsas – Wraith Protocol"
expect(getDocumentTitle()).toMatch(/Bolsas/i);
expect(getDocumentTitle()).toMatch(/Wraith Protocol/i);
Expand Down Expand Up @@ -248,8 +252,8 @@ describe('locale-aware page metadata', () => {
level: 1,
name: /soluções de privacidade do mundo real/i,
});
// Portuguese: "Estudos de caso – Wraith Protocol"
expect(getDocumentTitle()).toMatch(/Estudos de caso/i);
// Portuguese: "Casos de Estudo — Wraith Protocol"
expect(getDocumentTitle()).toMatch(/Casos de Estudo/i);
expect(getDocumentTitle()).toMatch(/Wraith Protocol/i);
});

Expand Down Expand Up @@ -294,7 +298,8 @@ describe('locale-aware page metadata', () => {
window.history.replaceState({}, '', '/es/stellar');
const { default: App } = await import('../App');
render(<App />);
await screen.findByRole('heading', { level: 1, name: /integrac/i });
// Hero copy is English-only; the h1 renders "Stellar Integration" in every locale.
await screen.findByRole('heading', { level: 1, name: /stellar integration/i });

await waitFor(() => {
const links = Array.from(document.head.querySelectorAll('link[rel="alternate"][hreflang]'));
Expand All @@ -312,7 +317,8 @@ describe('locale-aware page metadata', () => {
window.history.replaceState({}, '', '/es/stellar');
const { default: App } = await import('../App');
render(<App />);
await screen.findByRole('heading', { level: 1, name: /integrac/i });
// Hero copy is English-only; the h1 renders "Stellar Integration" in every locale.
await screen.findByRole('heading', { level: 1, name: /stellar integration/i });

await waitFor(() => {
const links = Array.from(document.head.querySelectorAll('link[rel="alternate"][hreflang]'));
Expand Down
18 changes: 8 additions & 10 deletions src/pages/Stellar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,14 @@ export default function Stellar() {
return (
<>
<Helmet>
<title>Stealth payments on Stellar – Wraith Protocol</title>
<meta
name="description"
content="Low-cost, sub-second, ed25519 stealth payments on Stellar with Soroban smart contracts. Build private payment rails with the Wraith SDK."
/>
<meta property="og:title" content="Stealth payments on Stellar – Wraith Protocol" />
<meta
property="og:description"
content="Low-cost, sub-second, ed25519 stealth payments on Stellar with Soroban smart contracts."
/>
<title>{seo.title}</title>
<meta name="description" content={seo.description} />
<link rel="canonical" href={seo.canonical} />
{seo.alternates.map((alt) => (
<link key={alt.hrefLang} rel="alternate" hrefLang={alt.hrefLang} href={alt.href} />
))}
<meta property="og:title" content={seo.title} />
<meta property="og:description" content={seo.description} />
<meta property="og:image" content="https://usewraith.xyz/og/stellar.png" />
<meta property="og:url" content={seo.canonical} />
<meta property="og:type" content="website" />
Expand Down
Loading