card view, minor css bugfixes
This commit is contained in:
@@ -23,13 +23,14 @@ describe('RssFeeds', () => {
|
||||
|
||||
// useFeeds() returns module-level singleton refs shared across the whole
|
||||
// app (and this spec file) — reset them so state doesn't leak between tests.
|
||||
const { feeds, showMessage, message, showModal, viewMode, currentIndex } = useFeeds()
|
||||
const { feeds, showMessage, message, showModal, viewMode, currentIndex, layout } = useFeeds()
|
||||
feeds.value = []
|
||||
showMessage.value = false
|
||||
message.value = ''
|
||||
showModal.value = false
|
||||
viewMode.value = 'list'
|
||||
currentIndex.value = 0
|
||||
layout.value = 'list'
|
||||
})
|
||||
|
||||
it('fetches the current user articles and shows the empty state', async () => {
|
||||
@@ -70,6 +71,72 @@ describe('RssFeeds', () => {
|
||||
expect(wrapper.text()).not.toContain('No unread articles.')
|
||||
})
|
||||
|
||||
it('renders the list as cards when the card layout is selected', async () => {
|
||||
axios.get.mockResolvedValueOnce({
|
||||
data: {
|
||||
feeds: [
|
||||
{
|
||||
title: 'My Feed',
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Article one',
|
||||
content: '<p>hello</p>',
|
||||
url: 'https://example.test/1',
|
||||
timestamp: '2026-01-01',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const { layout } = useFeeds()
|
||||
layout.value = 'cards'
|
||||
|
||||
const wrapper = mount(RssFeeds)
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.find('.article').classes()).toContain('article--cards')
|
||||
})
|
||||
|
||||
it('lets a card grow to fit the full article once its readable content has loaded', async () => {
|
||||
axios.get.mockResolvedValueOnce({
|
||||
data: {
|
||||
feeds: [
|
||||
{
|
||||
title: 'My Feed',
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Article one',
|
||||
content: '<p>short summary</p>',
|
||||
url: 'https://example.test/1',
|
||||
timestamp: '2026-01-01',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
axios.post.mockResolvedValueOnce({ data: { content: '<html><body><article><p>full text</p></article></body></html>' } })
|
||||
|
||||
const { layout } = useFeeds()
|
||||
layout.value = 'cards'
|
||||
|
||||
const wrapper = mount(RssFeeds)
|
||||
await flushPromises()
|
||||
|
||||
// Clamped to a fixed number of lines while only the short summary is shown...
|
||||
expect(wrapper.find('.feed-content').classes()).toContain('feed-content--clamped')
|
||||
|
||||
await wrapper.find('.feed-title').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
// ...but allowed to grow once the user has loaded the full readable article.
|
||||
expect(wrapper.find('.feed-content').classes()).not.toContain('feed-content--clamped')
|
||||
})
|
||||
|
||||
it('sorts articles by date across feeds, newest first', async () => {
|
||||
axios.get.mockResolvedValueOnce({
|
||||
data: {
|
||||
@@ -209,4 +276,58 @@ describe('RssFeeds', () => {
|
||||
|
||||
expect(wrapper.find('.article-single .feed-title').text()).toBe('Article one')
|
||||
})
|
||||
|
||||
it('drops articles read while paging through article view once back in the list', async () => {
|
||||
axios.get.mockResolvedValueOnce({
|
||||
data: {
|
||||
feeds: [
|
||||
{
|
||||
title: 'My Feed',
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Article one',
|
||||
content: '<p>one</p>',
|
||||
url: 'https://example.test/1',
|
||||
timestamp: '2026-03-01 10:00:00',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Article two',
|
||||
content: '<p>two</p>',
|
||||
url: 'https://example.test/2',
|
||||
timestamp: '2026-02-01 10:00:00',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Article three',
|
||||
content: '<p>three</p>',
|
||||
url: 'https://example.test/3',
|
||||
timestamp: '2026-01-01 10:00:00',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
axios.put.mockResolvedValue({ status: 200 })
|
||||
|
||||
const wrapper = mount(RssFeeds)
|
||||
await flushPromises()
|
||||
|
||||
const { toggleViewMode, leaveArticleView } = useFeeds()
|
||||
|
||||
// Enter article view (marks "Article one" read), page forward to "Article
|
||||
// two" (marks it read too), then leave without visiting "Article three".
|
||||
toggleViewMode()
|
||||
await flushPromises()
|
||||
await wrapper.findAll('.article-nav__btn')[1].trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
leaveArticleView()
|
||||
await flushPromises()
|
||||
|
||||
const titles = wrapper.findAll('.feed-title').map(el => el.text())
|
||||
expect(titles).toEqual(['Article three'])
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user