feat: redesign homepage from flat card list to book-style pitch page

This commit is contained in:
Ken
2026-05-27 01:25:52 +00:00
parent adc487e63b
commit 29b7dcc51d
3 changed files with 374 additions and 104 deletions
+26 -20
View File
@@ -35,39 +35,45 @@ describe('Clean build output', () => {
});
// ============================================================
// 2. Index page structure
// 2. Index page structure (book-style pitch page)
// ============================================================
describe('Index page', () => {
const html = readDist('index.html');
test('contains two article cards', () => {
const cardMatches = html.match(/<article[^>]*class="card"/g);
assert.ok(cardMatches, 'No article cards found');
assert.equal(cardMatches.length, 2, `Expected 2 article cards, got ${cardMatches.length}`);
test('has hero section with site title', () => {
assert.ok(html.includes('class="hero"') || html.includes('class=\"hero\"'),
'Should have hero section');
assert.ok(html.includes('Crash Test Dev'), 'Should have site title');
});
test('card surface uses warm off-white (--surface-card)', () => {
assert.ok(html.includes('var(--surface-card)'), 'Card should use --surface-card token');
test('has featured excerpt section', () => {
assert.ok(html.includes('class="featured"') || html.includes('class=\"featured\"'),
'Should have featured section');
assert.ok(html.includes('class="excerpt"') || html.includes('class=\"excerpt\"'),
'Should have excerpt blockquote');
});
test('card has subtle shadow (--shadow-sm)', () => {
assert.ok(html.includes('var(--shadow-sm)'), 'Card should use --shadow-sm token');
test('has series section with Rage', () => {
assert.ok(html.includes('class="series"') || html.includes('class=\"series\"'),
'Should have series section');
assert.ok(html.includes('Rage'), 'Should mention Rage series');
});
test('card hover shows deeper shadow (--shadow-md)', () => {
assert.ok(html.includes('var(--shadow-md)'), 'Card hover should use --shadow-md token');
test('has all-posts section with post entries', () => {
assert.ok(html.includes('class="all-posts"') || html.includes('class=\"all-posts\"'),
'Should have all-posts section');
const entryMatches = html.match(/class="post-entry"/g);
assert.ok(entryMatches, 'No post entries found');
assert.ok(entryMatches.length >= 2, `Expected at least 2 post entries, got ${entryMatches.length}`);
});
test('card hover shows terracotta title (--accent-primary)', () => {
assert.ok(
html.includes(':hover .title') || html.includes(':hover .title{'),
'Card hover should style the title'
);
assert.ok(html.includes('var(--accent-primary)'), 'Title hover should use terracotta accent');
test('uses terracotta accent (--accent-primary)', () => {
// Astro scoped styles compile to external CSS, check source instead
const source = readFileSync('src/pages/index.astro', 'utf-8');
assert.ok(source.includes('var(--accent-primary)'), 'Should use terracotta accent in source');
});
test('card links have correct URL format with slash separator', () => {
// The base is /crashtestdev and posts must be at /crashtestdev/posts/...
test('post links have correct URL format with slash separator', () => {
const linkRegex = /href="([^"]*posts[^"]*)"/g;
let match;
let found = false;
@@ -83,7 +89,7 @@ describe('Index page', () => {
`URL "${url}" should not concatenate base and posts without slash`
);
}
assert.ok(found, 'Should find article card links');
assert.ok(found, 'Should find post links');
});
});