Skip to content
Open
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
11 changes: 8 additions & 3 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import sitemap from '@astrojs/sitemap';
import tailwindcss from '@tailwindcss/vite';
import vercel from '@astrojs/vercel';

// https://astro.build/config
export default defineConfig({
// Shared base configuration (without db)
export const baseConfig = {
output: 'static',
adapter: vercel({
imageService: true,
Expand Down Expand Up @@ -62,7 +62,6 @@ export default defineConfig({
site: 'https://whiskey.fm',
trailingSlash: 'never',
integrations: [
db(),
preact(),
sitemap({
filter: (page) => {
Expand All @@ -84,4 +83,10 @@ export default defineConfig({
vite: {
plugins: [tailwindcss()]
}
};

// https://astro.build/config - Default configuration with astro:db
export default defineConfig({
...baseConfig,
integrations: [db(), ...baseConfig.integrations]
});
8 changes: 8 additions & 0 deletions astro.config.no-db.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'astro/config';

// Import the shared base configuration (which doesn't include db)
import { baseConfig } from './astro.config.mjs';

// https://astro.build/config - Configuration without astro:db for testing
// Note: Use with --tsconfig tsconfig.no-db.json to exclude db files from type checking
export default defineConfig(baseConfig);
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"scripts": {
"astro": "astro",
"build": "astro check && astro build --remote",
"check:no-db": "astro check --config astro.config.no-db.mjs --tsconfig tsconfig.no-db.json",
"db:seed": "pnpm astro db execute db/seed.ts --remote",
"dev": "astro dev",
"lint": "eslint . --cache",
Expand All @@ -18,6 +19,8 @@
"start": "astro dev",
"test": "concurrently \"pnpm:test:*(!fix)\" --names \"test:\"",
"test:e2e": "pnpm exec playwright test",
"test:e2e:with-db": "pnpm exec playwright test --project=chromium-with-db",
"test:e2e:no-db": "pnpm exec playwright test --project=chromium-no-db",
"test:unit": "vitest"
},
"dependencies": {
Expand Down
41 changes: 30 additions & 11 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,30 @@ export default defineConfig({
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] }
name: 'chromium-with-db',
use: { ...devices['Desktop Chrome'] },
testDir: './tests/e2e'
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] }
name: 'firefox-with-db',
use: { ...devices['Desktop Firefox'] },
testDir: './tests/e2e'
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] }
name: 'webkit-with-db',
use: { ...devices['Desktop Safari'] },
testDir: './tests/e2e'
},

{
name: 'chromium-no-db',
use: {
...devices['Desktop Chrome'],
baseURL: 'http://localhost:4322'
},
testDir: './tests/e2e-no-db'
}

/* Test against mobile viewports. */
Expand All @@ -69,9 +81,16 @@ export default defineConfig({
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm dev',
url: 'http://localhost:4321',
reuseExistingServer: !process.env.CI
}
webServer: [
{
command: 'pnpm dev',
url: 'http://localhost:4321',
reuseExistingServer: !process.env.CI
},
{
command: 'pnpm astro dev --config astro.config.no-db.mjs --port 4322',
url: 'http://localhost:4322',
reuseExistingServer: !process.env.CI
}
]
});
78 changes: 43 additions & 35 deletions src/pages/[episode].astro
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
import { getEntry } from 'astro:content';
import {
db,
eq,
Episode as DbEpisode,
HostOrGuest,
Person,
Sponsor,
SponsorForEpisode
} from 'astro:db';

// Check if astro:db integration is available by looking for the virtual module
let astroDB;

try {
astroDB = await import('astro:db');
} catch {
// astro:db is not available
}

import { Schema } from 'astro-seo-schema';

Expand Down Expand Up @@ -55,32 +55,40 @@ if (episode.episodeNumber && episode.episodeNumber !== 'Bonus') {

const canonicalURL = new URL(`/${episode.episodeSlug}`, Astro.url);

const hostsAndGuests = await db
.select({
id: Person.id,
img: Person.img,
isHost: HostOrGuest.isHost,
name: Person.name
})
.from(HostOrGuest)
.innerJoin(DbEpisode, eq(HostOrGuest.episodeSlug, DbEpisode.episodeSlug))
.innerJoin(Person, eq(HostOrGuest.personId, Person.id))
.where(eq(DbEpisode.episodeSlug, episode.episodeSlug));

const sponsors = await db
.select({
id: Sponsor.id,
img: Sponsor.img,
name: Sponsor.name,
url: Sponsor.url
})
.from(SponsorForEpisode)
.innerJoin(
DbEpisode,
eq(SponsorForEpisode.episodeSlug, DbEpisode.episodeSlug)
)
.innerJoin(Sponsor, eq(SponsorForEpisode.sponsorId, Sponsor.id))
.where(eq(DbEpisode.episodeSlug, episode.episodeSlug));
let hostsAndGuests: any[] = [];
let sponsors: any[] = [];

if (astroDB) {
// @ts-ignore - These table exports only exist when astro:db integration is enabled
const { db, eq, Episode: DbEpisode, HostOrGuest, Person, Sponsor, SponsorForEpisode } = astroDB;

hostsAndGuests = await db
.select({
id: Person.id,
img: Person.img,
isHost: HostOrGuest.isHost,
name: Person.name
})
.from(HostOrGuest)
.innerJoin(DbEpisode, eq(HostOrGuest.episodeSlug, DbEpisode.episodeSlug))
.innerJoin(Person, eq(HostOrGuest.personId, Person.id))
.where(eq(DbEpisode.episodeSlug, episode.episodeSlug));

sponsors = await db
.select({
id: Sponsor.id,
img: Sponsor.img,
name: Sponsor.name,
url: Sponsor.url
})
.from(SponsorForEpisode)
.innerJoin(
DbEpisode,
eq(SponsorForEpisode.episodeSlug, DbEpisode.episodeSlug)
)
.innerJoin(Sponsor, eq(SponsorForEpisode.sponsorId, Sponsor.id))
.where(eq(DbEpisode.episodeSlug, episode.episodeSlug));
}

const title = `${episode.title} - ${show.title} - Episode ${episode.episodeNumber}`;
---
Expand Down
63 changes: 63 additions & 0 deletions tests/e2e-no-db/episode-no-db.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { expect, test } from '@playwright/test';

const episode1 = {
title:
'Throwback Frameworks, Tailwind Fandom, and CSS with Jhey Tompkins - Whiskey Web and Whatnot: Web Development, Neat - Episode 120',
description:
/^Have you ever reflected on the tools that shaped your journey as a developer?/,
image:
'https://play.cdnstream1.com/zjb/image/download/d6/c4/9e/d6c49e16-ed89-45f9-b5d4-60dac61e44b0_1400.jpg'
};

test('episode page works without astro:db sections', async ({ page }) => {
await page.goto('/120');

// Core episode content should always be present
await expect(page.locator('h1')).toContainText('120:');
await expect(page.locator('h3:has-text("Show Notes")')).toBeVisible();
await expect(page.locator('h3:has-text("Episode Transcript")')).toBeVisible();

// The page should load successfully
await expect(page).toHaveTitle(episode1.title);
});

test('hosts and guests section should not appear without astro:db', async ({
page
}) => {
await page.goto('/120');

// Check that the "Creators and Guests" section does NOT exist
const creatorsSection = page.locator('h3:has-text("Creators and Guests")');
await expect(creatorsSection).not.toBeVisible();
});

test('sponsors section should not appear without astro:db', async ({
page
}) => {
await page.goto('/120');

// Check that the "Sponsors" section does NOT exist
const sponsorsSection = page.locator('h3:has-text("Sponsors")');
await expect(sponsorsSection).not.toBeVisible();
});

test('episode page meta data works without astro:db', async ({ page }) => {
await page.goto('/120');

await expect(page).toHaveTitle(episode1.title);

const ogTitle = page.locator('meta[property="og:title"]');
await expect(ogTitle).toHaveAttribute('content', episode1.title);

const twitterTitle = page.locator('meta[name="twitter:title"]');
await expect(twitterTitle).toHaveAttribute('content', episode1.title);

const description = page.locator('meta[name="description"]');
await expect(description).toHaveAttribute('content', episode1.description);

const ogImage = page.locator('meta[property="og:image"]');
await expect(ogImage).toHaveAttribute('content', episode1.image);

const twitterImage = page.locator('meta[name="twitter:image:src"]');
await expect(twitterImage).toHaveAttribute('content', episode1.image);
});
38 changes: 38 additions & 0 deletions tests/e2e/episode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,41 @@ test('works for bonus episodes with no episode number', async ({ page }) => {
const twitterImage = page.locator('meta[name="twitter:image:src"]');
await expect(twitterImage).toHaveAttribute('content', episode2.image);
});

test('displays hosts and guests when astro:db is available', async ({
page
}) => {
await page.goto('/120');

// Check if the "Creators and Guests" section exists
const creatorsSection = page.locator('h3:has-text("Creators and Guests")');
await expect(creatorsSection).toBeVisible();

// Check if at least one host/guest is displayed in the grid
const hostGuestGrid = page.locator(
'h3:has-text("Creators and Guests") + div'
);
await expect(hostGuestGrid).toBeVisible();

// Check that there are actual host/guest items
const hostGuestItems = page.locator(
'h3:has-text("Creators and Guests") + div > div'
);
await expect(hostGuestItems.first()).toBeVisible();
});

test('displays sponsors when astro:db is available', async ({ page }) => {
await page.goto('/120');

// Check if the "Sponsors" section exists
const sponsorsSection = page.locator('h3:has-text("Sponsors")');
await expect(sponsorsSection).toBeVisible();

// Check if at least one sponsor is displayed in the grid
const sponsorGrid = page.locator('h3:has-text("Sponsors") + div');
await expect(sponsorGrid).toBeVisible();

// Check that there are actual sponsor items
const sponsorItems = page.locator('h3:has-text("Sponsors") + div > a');
await expect(sponsorItems.first()).toBeVisible();
});
14 changes: 14 additions & 0 deletions tsconfig.no-db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"esModuleInterop": true,
"strictNullChecks": true,
"verbatimModuleSyntax": true,
"jsx": "react-jsx",
"jsxImportSource": "preact"
},
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist", "db"]
}
Loading