-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfundraising-copy.test.ts
More file actions
122 lines (104 loc) · 4.1 KB
/
Copy pathfundraising-copy.test.ts
File metadata and controls
122 lines (104 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { describe, it, expect } from 'vitest';
import { readFileSync } from 'node:fs';
import path from 'node:path';
const read = (rel: string) =>
readFileSync(path.join(__dirname, '..', rel), 'utf8');
const page = read('app/fundraising/FundraisingClient.tsx');
const layout = read('app/fundraising/layout.tsx');
describe('fundraising page copy contract', () => {
it('has no dateline', () => {
expect(page).not.toMatch(/August · September/);
});
it('is titled Investor Preview (mailto subject may still say Investor Memo)', () => {
expect(page).toContain('Investor Preview');
// Plain-text "Investor Memo" (with a space) is gone; the mailto subject
// uses "Investor%20Memo", which this regex cannot match.
expect(page).not.toMatch(/Investor Memo/);
});
it('has no $25M or raise range anywhere', () => {
expect(page).not.toMatch(/25M/);
expect(layout).not.toMatch(/25M/);
});
it('hero contains no raise ask', () => {
expect(page.indexOf('<header')).toBeGreaterThan(-1);
const hero = page.slice(page.indexOf('<header'), page.indexOf('</header>'));
expect(hero).not.toMatch(/raising/i);
expect(hero).not.toMatch(/\$1?5M/);
});
it('names the team', () => {
expect(page).toContain('Hugh Francis');
expect(page).toContain('Yatú Pelaez-Espinosa');
// Source uses an HTML entity for the apostrophe (O’Hagan)
expect(page).toMatch(/Norm O.{0,8}Hagan/);
});
it('does not claim the agency in past tense', () => {
expect(page).not.toMatch(/\bran\b.*agency/i);
expect(page).toMatch(/oversees/);
});
it('follows the pitch arc section order', () => {
const order = [
'The Context',
'Our First Device',
'Why This Wins',
'Who We Are',
'The Ask',
'Clarifications',
];
const idx = order.map(t => page.indexOf(`title="${t}"`));
expect(idx.every(i => i >= 0)).toBe(true);
expect([...idx].sort((a, b) => a - b)).toEqual(idx);
expect(page).not.toContain('Business Concept');
expect(page).not.toContain('Our Experience');
});
it('asks for $15M exactly once, in The Ask section', () => {
expect(page.match(/\$15M/g)).toHaveLength(1);
expect(page.indexOf('$15M')).toBeGreaterThan(
page.indexOf('title="The Ask"')
);
});
it('gates from Our First Device onward; The Context is public', () => {
const gateStart = page.indexOf('/* ===== Email gate');
expect(page.indexOf('title="The Context"')).toBeLessThan(gateStart);
expect(page.indexOf('title="Our First Device"')).toBeGreaterThan(gateStart);
expect(page.indexOf('title="Clarifications"')).toBeGreaterThan(gateStart);
});
it('opens on the category-creation lane', () => {
expect(page).toMatch(/newly possible category of\s+computing/);
});
it('cites verified category proof', () => {
expect(page).toMatch(/tonies/i);
expect(page).toContain('Yoto');
expect(page).toContain('630');
expect(page).toContain('86%');
expect(page).toContain('95M');
expect(page).toContain('in 2024');
});
it('has stage-1 economics only (no model outputs)', () => {
expect(page).toContain('$899');
expect(page).toContain('$9/month');
expect(page).toContain('91,000');
expect(page).not.toMatch(/52\.5|2\.7x|LTV/);
});
it('renders the trajectory diagram as a Figma embed', () => {
expect(page).toContain(
'https://embed.figma.com/board/CXl5xhLZOzBHkGiz8CgCUh'
);
expect(page).toMatch(/loading="lazy"/);
});
});
describe('clarifications content contract', () => {
const md = read('app/fundraising/clarifications.md');
it('covers the four investor objections', () => {
const questions = md.match(/^## .+$/gm) ?? [];
expect(questions.length).toBeGreaterThanOrEqual(4);
expect(md).toMatch(/\$899|price/i);
expect(md).toMatch(/subscription/i);
expect(md).toMatch(/narrow|niche|memory/i);
expect(md).toMatch(/industrial design/i);
});
it('mentions the raise figure only as a question heading, never as a second ask', () => {
expect(md.match(/\$15M/g)).toHaveLength(1);
expect(md).toMatch(/^## .*\$15M/m);
expect(md).not.toMatch(/raising \$15M/i);
});
});