Skip to content

Commit

Permalink
Merge pull request #141 from JHWelch/styled-titles
Browse files Browse the repository at this point in the history
Styled titles
  • Loading branch information
JHWelch authored Sep 11, 2024
2 parents bf8196d + 3d32b10 commit d64432c
Show file tree
Hide file tree
Showing 16 changed files with 524 additions and 56 deletions.
66 changes: 66 additions & 0 deletions client/src/__tests__/utils/factories/richTextFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { RichText, TextStyle } from '@shared/dtos'
import Factory from '@tests/utils/factories/factory'

export default class RichTextFactory extends Factory<RichText> {
protected state: RichText = {
type: 'text',
text: {
content: 'The',
link: null,
},
annotations: {
bold: false,
italic: false,
strikethrough: false,
underline: false,
code: false,
color: 'default',
},
plain_text: 'The',
href: null,
}

public text (text: string): RichTextFactory {
this.state.text.content = text
this.state.plain_text = text

return this
}

public bold (): RichTextFactory {
this.state.annotations.bold = true

return this
}


public italic (): RichTextFactory {
this.state.annotations.italic = true

return this
}

public strikethrough (): RichTextFactory {
this.state.annotations.strikethrough = true

return this
}

public underline (): RichTextFactory {
this.state.annotations.underline = true

return this
}

public code (): RichTextFactory {
this.state.annotations.code = true

return this
}

public color (color: TextStyle['color']): RichTextFactory {
this.state.annotations.color = color

return this
}
}
1 change: 1 addition & 0 deletions client/src/__tests__/utils/factories/weekFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default class WeekFactory extends Factory<WeekDto> {
date: '2020-01-01',
isSkipped: false,
slug: null,
styledTheme: [],
movies: [],
}

Expand Down
10 changes: 2 additions & 8 deletions client/src/components/WeekItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ import { WeekDto } from '@shared/dtos'
import { rsvpModal } from '@client/state/modalState'
import MovieList from '@components/MovieList.vue'
import SkippedBanner from '@components/SkippedBanner.vue'
import Theme from '@components/week/Theme.vue'
defineProps<{
week: WeekDto
showEventDetails: boolean
}>()
const weekTitle = (week: WeekDto) => {
return week.isSkipped ? 'No movies this week!' : week.theme
}
</script>

<template>
Expand All @@ -28,10 +25,7 @@ const weekTitle = (week: WeekDto) => {
v-text="week.date"
/>
<span
class="text-3xl font-semibold"
v-text="weekTitle(week)"
/>
<Theme :week="week" />
</h3>
<button
Expand Down
37 changes: 37 additions & 0 deletions client/src/components/week/Theme.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script lang="ts" setup>
import { WeekDto } from '@shared/dtos'
defineProps<{
week: WeekDto
}>()
</script>

<template>
<span
v-if="week.styledTheme.length > 0"
class="text-3xl font-semibold"
data-testid="theme"
>
<span
v-for="(theme, index) in week.styledTheme"
:key="index"
:class="{
'font-bold': theme.annotations.bold,
'italic': theme.annotations.italic,
'underline': theme.annotations.underline,
'line-through': theme.annotations.strikethrough,
}"
>
{{ theme.text.content }}
</span>
</span>

<span
v-else
class="text-3xl font-semibold"
data-testid="theme"
>
{{ week.isSkipped ? 'No movies this week!' : week.theme }}
</span>
</template>
94 changes: 94 additions & 0 deletions client/src/components/week/__tests__/Theme.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/** @vitest-environment jsdom */

import { beforeEach, describe, expect, it } from 'vitest'
import { mount } from '@vue/test-utils'
import Theme from '@components/week/Theme.vue'
import { WeekDto } from '@shared/dtos'
import RichTextFactory from '@tests/utils/factories/richTextFactory'
import WeekFactory from '@tests/utils/factories/weekFactory'

let week: WeekDto

describe('Just a theme, no styled theme', () => {
beforeEach(() => {
week = new WeekFactory().build({
theme: 'The Matrix',
})
})

it('shows the theme', () => {
const wrapper = mount(Theme, {
props: { week: week },
})
expect(wrapper.text()).toContain(week.theme)
})
})

describe('Styled theme', () => {
beforeEach(() => {
week = new WeekFactory().build({
theme: 'The Matrix',
styledTheme: [
new RichTextFactory().text('The').bold().build(),
new RichTextFactory().text('Matrix').italic().build(),
new RichTextFactory().text('is').underline().build(),
new RichTextFactory().text('the best').strikethrough().build(),
],
})
})

it('shows the styled theme', () => {
const wrapper = mount(Theme, {
props: { week },
})

const component = wrapper.find('[data-testid="theme"]')
expect(component.exists()).toBe(true)
expect(component.element.children[0].innerHTML).toBe('The')
expect(component.element.children[0].classList).toContain('font-bold')
expect(component.element.children[1].innerHTML).toBe('Matrix')
expect(component.element.children[1].classList).toContain('italic')
expect(component.element.children[2].innerHTML).toBe('is')
expect(component.element.children[2].classList).toContain('underline')
expect(component.element.children[3].innerHTML).toBe('the best')
expect(component.element.children[3].classList).toContain('line-through')
})
})

describe('Week skipped', () => {
beforeEach(() => {
week = new WeekFactory().build({
theme: 'The Matrix',
isSkipped: true,
})
})

it('shows the theme', () => {
const wrapper = mount(Theme, {
props: { week: week },
})
expect(wrapper.text()).toContain('No movies this week!')
})

describe('with styled Theme', () => {
beforeEach(() => {
week.styledTheme = [
new RichTextFactory().text('The').bold().build(),
new RichTextFactory().text('Matrix').italic().build(),
]
})

it('shows the styled theme', () => {
const wrapper = mount(Theme, {
props: { week },
})

const component = wrapper.find('[data-testid="theme"]')
expect(component.exists()).toBe(true)
expect(component.element.children[0].innerHTML).toBe('The')
expect(component.element.children[0].classList).toContain('font-bold')
expect(component.element.children[1].innerHTML).toBe('Matrix')
expect(component.element.children[1].classList).toContain('italic')
})
})
})
98 changes: 86 additions & 12 deletions server/__tests__/controllers/cacheController.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { mockConfig } from '@tests/support/mockConfig'
import fs from 'fs'
import MovieFactory from '@tests/support/factories/movieFactory'
import MockDate from 'mockdate'
import { RichText } from '@shared/dtos'

let notionMock: NotionMock

Expand Down Expand Up @@ -68,12 +69,64 @@ describe('cacheWeeks', () => {
})

describe('when the cache is empty', () => {
const styled: RichText[] = [
{
type: 'text',
text: {
content: 'week',
link: null,
},
annotations: {
bold: true,
italic: false,
strikethrough: false,
underline: false,
code: false,
color: 'default',
},
plain_text: 'week',
href: null,
},
{
type: 'text',
text: {
content: 'id 3',
link: null,
},
annotations: {
bold: false,
italic: true,
strikethrough: false,
underline: false,
code: false,
color: 'red',
},
plain_text: 'id 3',
href: null,
},
]

beforeEach(() => {
notionMock.mockIsFullPageOrDatabase(true)
notionMock.mockQuery([
NotionMock.mockWeek('id1', '2021-01-01', 'theme1'),
NotionMock.mockWeek('id2', '2021-01-08', 'theme2'),
NotionMock.mockWeek('id3', '2021-01-15', 'theme3'),
NotionMock.mockWeek({
id: 'id1',
date: '2021-01-01',
theme: 'theme1',
}),
NotionMock.mockWeek({
id: 'id2',
date: '2021-01-08',
theme: 'theme2',
skipped: true,
}),
NotionMock.mockWeek({
id: 'id3',
date: '2021-01-15',
theme: 'theme3',
slug: 'slug',
styledTheme: styled,
}),
])
})

Expand All @@ -85,17 +138,32 @@ describe('cacheWeeks', () => {
expect(transaction.set)
.toHaveBeenCalledWith(
FirebaseMock.mockDoc('weeks', '2021-01-01'),
FirebaseMock.mockWeek('id1', 'theme1', '2021-01-01'),
FirebaseMock.mockWeek({
id: 'id1',
theme: 'theme1',
date: '2021-01-01',
}),
)
expect(transaction.set)
.toHaveBeenCalledWith(
FirebaseMock.mockDoc('weeks', '2021-01-08'),
FirebaseMock.mockWeek('id2', 'theme2', '2021-01-08'),
FirebaseMock.mockWeek({
id: 'id2',
theme: 'theme2',
date: '2021-01-08',
isSkipped: true,
}),
)
expect(transaction.set)
.toHaveBeenCalledWith(
FirebaseMock.mockDoc('weeks', '2021-01-15'),
FirebaseMock.mockWeek('id3', 'theme3', '2021-01-15'),
FirebaseMock.mockWeek({
id: 'id3',
theme: 'theme3',
date: '2021-01-15',
slug: 'slug',
styledTheme: styled,
}),
)
})
})
Expand Down Expand Up @@ -127,9 +195,12 @@ describe('cacheWeeks', () => {
const notionResponse = new NotionMovie({ id: 'notionId', title: 'title' })
notionMock.mockIsFullPageOrDatabase(true)
notionMock.mockQuery([
NotionMock.mockWeek(
'id1', '2021-01-01', 'theme1', false, null, [notionResponse],
),
NotionMock.mockWeek({
id: 'id1',
date: '2021-01-01',
theme: 'theme1',
movies: [notionResponse],
}),
])
notionMock.mockRetrieve(notionResponse)
req = getMockReq()
Expand Down Expand Up @@ -167,9 +238,12 @@ describe('cacheWeeks', () => {
const notionResponse = movies.map(NotionMovie.fromMovie)
notionMock.mockIsFullPageOrDatabase(true)
notionMock.mockQuery([
NotionMock.mockWeek(
'id1', date, 'theme1', false, null, notionResponse,
),
NotionMock.mockWeek({
id: 'id1',
date,
theme: 'theme1',
movies: notionResponse,
}),
])
notionResponse.forEach((movie) => notionMock.mockRetrieve(movie))
}
Expand Down
Loading

0 comments on commit d64432c

Please sign in to comment.