mirror of
https://github.com/ajurna/cbwebreader.git
synced 2026-11-02 10:36:55 +00:00
**Add Vitest support and migrate frontend tests**
- Added Vitest configuration (`vitest.config.mjs`) for frontend unit testing with a `jsdom` environment. - Migrated and rewrote key frontend tests (`api.test.js`, `comiclist.test.js`, `comicreader.test.js`, `historytable.test.js`, `router.test.js`, `store.test.js`) to Vitest, improving maintainability. - Removed `tsconfig.json` and related TypeScript loaders from `webpack` configurations (`webpack.dev.js`, `webpack.prod.js`). - Adjusted `eslint.config.mjs` to support Vitest tests. - Updated `package-lock.json` to include Vitest, test utilities (`jsdom`, `@vue/test-utils`), and other associated packages. - Updated Nginx configuration for better compression on assets (`gzip` adjustments). - Enhanced `entrypoint.sh` to include first-run library indexing (`--if-empty` argument). - Simplified the `scan_comics` command with a dedicated test for empty database scans. This transition improves testing workflows and backend/frontend synergy while removing unused TypeScript dependencies.
This commit is contained in:
1 parent
ce809ed1a9
commit
cc557543c5
19 files changed
+2388
-586
No files matched your search
@@ -0,0 +1,133 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
|
||||
const api = vi.hoisted(() => ({ get: vi.fn(), post: vi.fn(), put: vi.fn() }))
|
||||
const store = vi.hoisted(() => ({ state: { filters: {} }, getters: { isAuthenticated: true, is_superuser: false } }))
|
||||
|
||||
vi.mock('@/api', () => ({ default: api }))
|
||||
vi.mock('@/store', () => ({ default: store }))
|
||||
|
||||
import TheComicList from '@/components/TheComicList.vue'
|
||||
|
||||
const BOOKS = [
|
||||
{ selector: 'a1', title: 'Alpha', type: 'ComicBook', finished: true, unread: false, thumbnail: '' },
|
||||
{ selector: 'b2', title: 'Beta', type: 'ComicBook', finished: false, unread: true, thumbnail: '' },
|
||||
{ selector: 'c3', title: 'Gamma Subfolder', type: 'Directory', thumbnail: '' },
|
||||
]
|
||||
|
||||
function mountList(props = {}) {
|
||||
return mount(TheComicList, {
|
||||
props: { selector: props.selector ?? '' },
|
||||
global: {
|
||||
stubs: {
|
||||
'font-awesome-icon': true,
|
||||
ComicCard: {
|
||||
name: 'ComicCard',
|
||||
props: ['data'],
|
||||
template: '<div class="card-stub" :data-selector="data.title">{{ data.title }}</div>',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
api.get.mockReset()
|
||||
api.post.mockReset()
|
||||
api.put.mockReset()
|
||||
api.get.mockResolvedValue({ data: [...BOOKS] })
|
||||
store.state.filters = {}
|
||||
})
|
||||
|
||||
describe('TheComicList', () => {
|
||||
it('loads the home listing when it is mounted', async () => {
|
||||
const wrapper = mountList()
|
||||
await flushPromises()
|
||||
|
||||
expect(api.get).toHaveBeenCalledWith('/api/browse/')
|
||||
expect(wrapper.text()).toContain('Alpha')
|
||||
})
|
||||
|
||||
it('loads the listing for the folder it was given', async () => {
|
||||
const wrapper = mountList({ selector: 'c3' })
|
||||
await flushPromises()
|
||||
|
||||
expect(api.get).toHaveBeenCalledWith('/api/browse/c3/')
|
||||
expect(wrapper.vm.comics).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('filters by name without changing the loaded data', async () => {
|
||||
const wrapper = mountList()
|
||||
await flushPromises()
|
||||
|
||||
wrapper.vm.filters.search_string = 'beta'
|
||||
expect(wrapper.vm.filteredComics.map((c) => c.title)).toEqual(['Beta'])
|
||||
|
||||
wrapper.vm.filters.search_string = 'ga'
|
||||
expect(wrapper.vm.filteredComics.map((c) => c.title)).toEqual(['Gamma Subfolder'])
|
||||
})
|
||||
|
||||
it('filters read and unread entries separately', async () => {
|
||||
const wrapper = mountList()
|
||||
await flushPromises()
|
||||
|
||||
wrapper.vm.filters.filter_read = true
|
||||
expect(wrapper.vm.filteredComics.map((c) => c.title)).toEqual(['Alpha'])
|
||||
|
||||
wrapper.vm.filters.filter_read = false
|
||||
wrapper.vm.filters.filter_unread = true
|
||||
expect(wrapper.vm.filteredComics.map((c) => c.title)).toEqual(['Beta'])
|
||||
})
|
||||
|
||||
it('keeps the filters in the store so they survive a folder change', async () => {
|
||||
const wrapper = mountList({ selector: 'c3' })
|
||||
await flushPromises()
|
||||
|
||||
wrapper.vm.filters.search_string = 'alpha'
|
||||
expect(store.state.filters.c3.search_string).toBe('alpha')
|
||||
})
|
||||
|
||||
it('scans the folder on disk and uses the returned listing', async () => {
|
||||
let resolvePost
|
||||
api.post.mockImplementation(() => new Promise((resolve) => { resolvePost = resolve }))
|
||||
|
||||
const wrapper = mountList({ selector: 'c3' })
|
||||
await flushPromises()
|
||||
|
||||
const button = wrapper.find('button[title="Read this folder from disk again"]')
|
||||
button.trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(api.post).toHaveBeenCalledWith('/api/browse/scan/', { selector: 'c3' })
|
||||
expect(wrapper.vm.scanning).toBe(true)
|
||||
expect(button.element.disabled).toBe(true)
|
||||
|
||||
resolvePost({ data: [{ selector: 'd4', title: 'Delta', type: 'ComicBook' }] })
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.vm.comics).toHaveLength(1)
|
||||
expect(wrapper.vm.scanning).toBe(false)
|
||||
})
|
||||
|
||||
it('marks every book in the folder, ignoring subfolders', async () => {
|
||||
const wrapper = mountList()
|
||||
await flushPromises()
|
||||
|
||||
api.put.mockResolvedValue({ data: [] })
|
||||
wrapper.vm.markAll('mark_read')
|
||||
await flushPromises()
|
||||
|
||||
expect(api.put).toHaveBeenCalledWith('/api/action/mark_read/', { selectors: ['a1', 'b2'] })
|
||||
})
|
||||
|
||||
it('marks everything before the card that asked for it', async () => {
|
||||
const wrapper = mountList()
|
||||
await flushPromises()
|
||||
|
||||
api.put.mockResolvedValue({ data: [] })
|
||||
wrapper.vm.markPreviousRead('b2')
|
||||
await flushPromises()
|
||||
|
||||
expect(api.put).toHaveBeenCalledWith('/api/action/mark_read/', { selectors: ['a1', 'b2'] })
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user