diff --git a/src/backend/services/resource_mapper.ts b/src/backend/services/resource_mapper.ts index e503e158..3104347f 100644 --- a/src/backend/services/resource_mapper.ts +++ b/src/backend/services/resource_mapper.ts @@ -20,7 +20,7 @@ export type ResourceRow = { updatedAt?: DateTime | string | null; }; -export const extractResourceUrl = ( +export const extractResourceContent = ( type: string, bundle: ResourceBundle, ): string | undefined => { @@ -29,22 +29,20 @@ export const extractResourceUrl = ( return 'video' in bundle ? bundle.video.url : undefined; case 'url': return 'url' in bundle ? bundle.url : undefined; + case 'text': + return 'content' in bundle ? bundle.content : undefined; default: return undefined; } }; -const formatResourceDate = ( - value: DateTime | string | undefined | null, -): string => { +const formatResourceDate = (value: DateTime | string | undefined | null): string => { if (!value) return ''; if (typeof value === 'string') return value.split('T')[0]; return value.toISODate() ?? value.toISO()?.split('T')[0] ?? ''; }; -const formatResourceDateTime = ( - value: DateTime | string | undefined | null, -): string => { +const formatResourceDateTime = (value: DateTime | string | undefined | null): string => { if (!value) return ''; if (typeof value === 'string') return value; return value.toUTC().toISO() ?? value.toUTC().toString(); @@ -58,7 +56,7 @@ export const toResourceItem = (model: ResourceRow): ResourceItem => { title: model.title, type: model.type as ResourceType, imageUrl: model.imageUrl, - url: extractResourceUrl(model.type, bundle), + content: extractResourceContent(model.type, bundle), label: model.label, visibility: model.visibility as VisibilityType, description: model.description, diff --git a/src/frontend/test/mocks.ts b/src/frontend/test/mocks.ts index 4b0273f0..e83fe0b2 100644 --- a/src/frontend/test/mocks.ts +++ b/src/frontend/test/mocks.ts @@ -4356,6 +4356,7 @@ const availableResourceItems: Omit[] = [ title: 'Introduction to Biblical Archaeology', type: 'video', imageUrl: 'https://images.unsplash.com/photo-1574269909862-7e1d70bb8078?w=400', + content: 'https://example.com/intro-archaeology.mp4', label: 'Supplementary Videos', visibility: 'public', description: 'A comprehensive overview of archaeological findings in the Holy Land', @@ -4364,7 +4365,8 @@ const availableResourceItems: Omit[] = [ id: 'r2', title: 'The Historical Jesus: Scholarly Perspectives', type: 'text', - url: 'https://example.com/historical-jesus', + content: + '## Historical Evidence\n\nThis article surveys scholarly approaches to the historical Jesus, examining primary sources and archaeological context.', label: 'Academic Reading', visibility: 'public', description: @@ -4374,7 +4376,8 @@ const availableResourceItems: Omit[] = [ id: 'r3', title: 'Understanding the Gospels', type: 'text', - url: 'https://example.com/gospels.pdf', + content: + '## The Four Gospels\n\nMatthew, Mark, Luke, and John each offer distinct perspectives on the life and ministry of Jesus.', label: 'Supplementary Reading', visibility: 'public', description: 'A detailed guide to the four Gospels and their contexts', @@ -4383,7 +4386,7 @@ const availableResourceItems: Omit[] = [ id: 'r4', title: 'Early Church History Timeline', type: 'url', - url: 'https://example.com/timeline', + content: 'https://example.com/timeline', label: 'Reference Materials', visibility: 'public', description: 'Interactive timeline of the first 500 years of Christianity', @@ -4393,6 +4396,7 @@ const availableResourceItems: Omit[] = [ title: 'Hebrew Language Basics', type: 'video', imageUrl: 'https://images.unsplash.com/photo-1456513080510-7bf3a84b82f8?w=400', + content: 'https://example.com/hebrew-basics.mp4', label: 'Language Resources', visibility: 'public', description: 'Learn the basics of Biblical Hebrew', @@ -4402,6 +4406,7 @@ const availableResourceItems: Omit[] = [ title: 'Old Testament Survey', type: 'video', imageUrl: 'https://images.unsplash.com/photo-1516979187457-637abb4f9353?w=400', + content: 'https://example.com/ot-survey.mp4', label: 'Supplementary Videos', visibility: 'public', description: 'Comprehensive overview of Old Testament books and themes', @@ -4410,7 +4415,8 @@ const availableResourceItems: Omit[] = [ id: 'r7', title: 'The Sermon on the Mount Study Guide', type: 'text', - url: 'https://example.com/sermon-mount.pdf', + content: + '## Matthew 5–7\n\nStudy questions and reflection prompts for the Sermon on the Mount.', label: 'Study Guides', visibility: 'leaders', description: 'In-depth study guide for Matthew 5-7', @@ -4420,6 +4426,7 @@ const availableResourceItems: Omit[] = [ title: 'Church History Documentary Series', type: 'video', imageUrl: 'https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=400', + content: 'https://example.com/church-history-series.mp4', label: 'Supplementary Videos', visibility: 'public', description: '10-part series on the history of Christianity', @@ -4428,7 +4435,7 @@ const availableResourceItems: Omit[] = [ id: 'r9', title: 'Biblical Greek Resources', type: 'url', - url: 'https://example.com/greek', + content: 'https://example.com/greek', label: 'Language Resources', visibility: 'public', description: 'Collection of tools for learning Biblical Greek', @@ -4437,7 +4444,7 @@ const availableResourceItems: Omit[] = [ id: 'r10', title: 'Theological Dictionary', type: 'url', - url: 'https://example.com/dictionary', + content: 'https://example.com/dictionary', label: 'Reference Materials', visibility: 'public', description: 'Comprehensive theological terms and definitions', @@ -4446,7 +4453,8 @@ const availableResourceItems: Omit[] = [ id: 'r11', title: 'Leader Discussion Guide', type: 'text', - url: 'https://example.com/leader-guide.pdf', + content: + '## Facilitator Notes\n\nDiscussion questions and leader prompts for small group sessions.', label: 'Study Guides', visibility: 'leaders', description: 'Facilitator notes and discussion questions', @@ -4455,7 +4463,8 @@ const availableResourceItems: Omit[] = [ id: 'r12', title: 'Parables of Jesus Explained', type: 'text', - url: 'https://example.com/parables', + content: + '## Major Parables\n\nAnalysis of the parables of the sower, the prodigal son, and the good Samaritan.', label: 'Academic Reading', visibility: 'public', description: 'Analysis of major parables in the Gospels', @@ -4466,6 +4475,7 @@ const availableResourceItems: Omit[] = [ 'Archaeological Discoveries and Their Impact on New Testament Historical Studies: A Case study of the Gospel of Luke and Acts while referencing the Gospel of John and ignoring the Gospel of Matthew', type: 'video', imageUrl: 'https://images.unsplash.com/photo-1574269909862-7e1d70bb8078?w=400', + content: 'https://example.com/archaeology-nt-studies.mp4', label: 'Supplementary Videos', visibility: 'public', description: @@ -4475,7 +4485,8 @@ const availableResourceItems: Omit[] = [ id: 'r14', title: 'A Critical Introduction to the Synoptic Problem and Gospel Source Criticism', type: 'text', - url: 'https://example.com/synoptic-problem', + content: + '## Overview\n\nThis article introduces the Synoptic Problem and compares major scholarly hypotheses.\n\n- Two-Source hypothesis\n- Farrer hypothesis\n- Augustinian hypothesis', label: 'Academic Reading', visibility: 'guests', description: @@ -4486,7 +4497,7 @@ const availableResourceItems: Omit[] = [ title: 'Patristic Writings on Scripture, Tradition, and the Formation of the Biblical Canon', type: 'url', - url: 'https://example.com/patristic-canon', + content: 'https://example.com/patristic-canon', label: 'Reference Materials', visibility: 'leaders', description: @@ -4639,7 +4650,7 @@ export const mockEditUrlLinkResource: ResourceEditProps = toEditResource( description: availableResources[3].description ?? '', label: availableResources[3].label ?? '', visibility: availableResources[3].visibility, - url: availableResources[3].url ?? 'https://example.com/timeline', + url: availableResources[3].content ?? 'https://example.com/timeline', }, ); diff --git a/src/types.ts b/src/types.ts index 23006fd8..b1846e5c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -178,7 +178,7 @@ export interface ResourceItem { title: string; type: ResourceType; imageUrl?: string | null; - url?: string; + content?: string; label: string | null; visibility: VisibilityType; description?: string | null; diff --git a/tests/unit/resourceService.spec.ts b/tests/unit/resourceService.spec.ts index 7204d50d..6106311b 100644 --- a/tests/unit/resourceService.spec.ts +++ b/tests/unit/resourceService.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from '@playwright/test'; import { DateTime } from 'luxon'; import { - extractResourceUrl, + extractResourceContent, toResourceItem, toResourceIndexItem, } from '../../src/backend/services/resource_mapper.js'; @@ -9,19 +9,19 @@ import { compareResourcesByRecentlyEdited } from '../../src/frontend/stories/com import type { LinkBundle, TextBundle, VideoBundle } from '../../src/types.js'; test.describe('Resource mapper', () => { - test('extractResourceUrl returns video url from bundle', () => { + test('extractResourceContent returns video url from bundle', () => { const bundle: VideoBundle = { video: { url: 'https://example.com/v.mp4' } }; - expect(extractResourceUrl('video', bundle)).toBe('https://example.com/v.mp4'); + expect(extractResourceContent('video', bundle)).toBe('https://example.com/v.mp4'); }); - test('extractResourceUrl returns url from bundle', () => { + test('extractResourceContent returns url from bundle', () => { const bundle: LinkBundle = { url: 'https://example.com/info' }; - expect(extractResourceUrl('url', bundle)).toBe('https://example.com/info'); + expect(extractResourceContent('url', bundle)).toBe('https://example.com/info'); }); - test('extractResourceUrl returns undefined for text type', () => { + test('extractResourceContent returns content from text bundle', () => { const bundle: TextBundle = { content: 'Hello world' }; - expect(extractResourceUrl('text', bundle)).toBeUndefined(); + expect(extractResourceContent('text', bundle)).toBe('Hello world'); }); test('toResourceDto maps model fields to Resource DTO', () => { @@ -42,7 +42,7 @@ test.describe('Resource mapper', () => { title: 'Test Resource', type: 'url', imageUrl: 'https://example.com/img.jpg', - url: 'https://example.com/link', + content: 'https://example.com/link', label: 'Reading', visibility: 'guests', description: 'A description', @@ -65,7 +65,7 @@ test.describe('Resource mapper', () => { expect(dto.label).toBeNull(); expect(dto.description).toBeNull(); - expect(dto.url).toBeUndefined(); + expect(dto.content).toBe('Body text'); expect(dto.type).toBe('text'); expect(dto.updatedAt).toBe('2024-02-12T08:00:00.000Z'); }); @@ -86,7 +86,7 @@ test.describe('Resource mapper', () => { expect(item.createdAt).toBe('2024-01-15'); expect(item.updatedAt).toBe('2024-03-01T12:00:00.000Z'); - expect(item.url).toBe('https://example.com/v.mp4'); + expect(item.content).toBe('https://example.com/v.mp4'); }); test('toResourceIndexItem handles string timestamps', () => {