import fetchMock from 'fetch-mock'; import { cloneDeep } from 'lodash'; import { afterEach, describe, expect, it, vi } from 'vitest'; import RootState from '../types/RootStateModel'; import { CmsStore, storeConfig } from '../index'; import { CreatePageFromCopyPayload, CreatePagePayload, Folder, Page, PublishedPage } from '../../types/api'; import { page, pageVersion, pages } from '../../constants/test-constants'; const publishedPages: PublishedPage[] = [ { pageId: 'page1', publishedVersionId: 'version1' }, { pageId: 'page2', publishedVersionId: 'version2' } ]; const folders: Folder[] = [ { pageId: 'folder1', publishedVersionId: 'version1' }, { pageId: 'folder2', publishedVersionId: 'version2' } ]; const schema = { properties: {}, oneOf: [] }; const mockAllPagesFetch = (status = 200, body: Page[] = pages) => fetchMock.get(/api\/pages\/load/, { status, body }); const mockPublishedPagesFetch = (status = 200, body: PublishedPage[] = publishedPages) => fetchMock.get(/api\/pages\/published/, { status, body }); const mockFoldersFetch = (status = 200, body: Folder[] = folders) => fetchMock.get(/api\/pages\/folders/, { status, body }); const mockSchemaFetch = (status = 200, body: any = schema) => fetchMock.get(/api\/versions\/schema/, { status, body }); describe('Page store', () => { afterEach(() => { fetchMock.restore(); }); function createLocalStore(config = storeConfig): CmsStore { return new CmsStore(cloneDeep(config)); } it('should fetch all pages and schema on initialize', () => { const store = createLocalStore(); store.dispatch = vi.fn(); expect(store.dispatch).not.toHaveBeenCalled(); store.initialize(); expect(store.dispatch).toHaveBeenCalledWith('pages/fetchPages', undefined); expect(store.dispatch).toHaveBeenCalledWith('pages/fetchSchema', undefined); }); it('should fetch all pages and commit them to the store', async () => { mockAllPagesFetch(); mockPublishedPagesFetch(); mockFoldersFetch(); const store = createLocalStore(); store.commit = vi.fn(); expect(store.commit).not.toHaveBeenCalled(); await store.dispatch('pages/fetchPages'); await store.dispatch('pages/fetchPublishedPageIds'); expect(store.commit).toHaveBeenCalledWith('pages/pages', pages, undefined); }); it('should update loading state on fetching all pages', async () => { mockAllPagesFetch(); mockPublishedPagesFetch(); mockFoldersFetch(); const store = createLocalStore(); store.commit = vi.fn(); expect(store.commit).not.toHaveBeenCalled(); expect(store.state.pages.isLoadingPages).toBeFalsy(); await store.dispatch('pages/fetchPages'); await store.dispatch('pages/fetchPublishedPageIds'); expect(store.commit).toHaveBeenCalledWith('pages/isLoadingPages', true, undefined); expect(store.commit).toHaveBeenCalledWith('pages/isLoadingPages', false, undefined); expect(store.state.pages.isLoadingPages).toBeFalsy(); }); it('should set loading state to false after fetching published pages', async () => { mockPublishedPagesFetch(); mockFoldersFetch(); const store = createLocalStore(); store.commit = vi.fn(); await store.dispatch('pages/fetchPublishedPageIds'); expect(store.commit).toHaveBeenCalledWith('pages/isLoadingPublishedPages', false, undefined); }); it('should commit fetched published pages and folders to string array', async () => { fetchMock.get(/api\/pages\/published/, { status: 200, body: publishedPages }); mockAllPagesFetch(); mockFoldersFetch(); const store = createLocalStore(); await store.dispatch('pages/fetchPublishedPageIds'); const publishedPageIds = [...publishedPages, ...folders].map((p) => p.pageId); expect(store.state.pages.publishedPageIds).toEqual(publishedPageIds); }); it('should return pagetree items from pagetree getter', () => { const store = createLocalStore(); store.state.pages.pages = pages; expect(store.getters['pages/pageTree']).toEqual(pages); }); it('should fetch schema and commit schema to state', async () => { mockSchemaFetch(); const store = createLocalStore(); store.commit = vi.fn(); await store.dispatch('pages/fetchSchema'); expect(store.commit).toHaveBeenCalledWith('pages/schema', schema, undefined); }); it('should update loading state on fetching schema', async () => { mockSchemaFetch(); const store = createLocalStore(); store.commit = vi.fn(); expect(store.commit).not.toHaveBeenCalled(); expect(store.state.pages.isLoadingPages).toBeFalsy(); await store.dispatch('pages/fetchSchema'); expect(store.commit).toHaveBeenCalledWith('pages/isLoadingPages', true, undefined); expect(store.commit).toHaveBeenCalledWith('pages/isLoadingPages', false, undefined); expect(store.state.pages.isLoadingPages).toBeFalsy(); }); it('should create and return a page version', async () => { fetchMock.post( /api\/versions\/create/, { status: 200, body: pageVersion }, { query: { name: 'new-page', parentId: '123', language: 'en-US' } } ); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const payload: CreatePagePayload = { name: 'new-page', parentId: '123', language: 'en-US', version: 'xxx' }; const createdVersion = await store.dispatch('pages/create', payload); expect(pageVersion).toEqual(createdVersion); }); it('should create from copy and return a page version', async () => { fetchMock.post( /api\/versions\/create-from-copy/, { status: 200, body: pageVersion }, { query: { name: 'page-copy', parentId: '456', language: 'en-US', sourceVersionId: 'xxx' } } ); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const payload: CreatePageFromCopyPayload = { name: 'page-copy', parentId: '456', language: 'en-US', sourceVersionId: 'xxx' }; const createdVersion = await store.dispatch('pages/createFromCopy', payload); expect(pageVersion).toEqual(createdVersion); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); }); it('should update and return a page version', async () => { fetchMock.put(/api\/versions\/update/, { status: 200, body: pageVersion }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const updatedVersion = await store.dispatch('pages/updateVersion', pageVersion); expect(pageVersion).toEqual(updatedVersion); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); }); it('should publish and return a page version', async () => { fetchMock.post(`/api/versions/publish/${pageVersion.id}`, { status: 200, body: pageVersion }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const publishedVersion = await store.dispatch('pages/publishVersion', pageVersion); expect(pageVersion).toEqual(publishedVersion); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); }); it('should depublish and return a page version', async () => { fetchMock.post(`/api/versions/depublish/${pageVersion.id}`, { status: 200, body: pageVersion }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const depublishedVersion = await store.dispatch('pages/depublishVersion', pageVersion); expect(pageVersion).toEqual(depublishedVersion); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); }); it('should delete a version', async () => { const path = `/api/versions/${pageVersion.id}`; fetchMock.delete(path, { status: 200 }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); await store.dispatch('pages/deleteVersion', pageVersion); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); expect(fetchMock.called(path)).toEqual(true); }); it('should move and return a page', async () => { const newParentId = '1'; fetchMock.post(`/api/pages/${page.id}/move?newParentId=${newParentId}`, { status: 200, body: page }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const movedPage = await store.dispatch('pages/move', { page, newParentId }); expect(page).toEqual(movedPage); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); }); it('should rename and return a page', async () => { const name = 'page'; fetchMock.post(`/api/pages/${page.id}/rename?name=${name}`, { status: 200, body: page }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); const renamedPage = await store.dispatch('pages/rename', { page, name }); expect(page).toEqual(renamedPage); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); }); it('should delete a page', async () => { const path = `/api/pages/${page.id}`; fetchMock.delete(path, { status: 200 }); const config = storeConfig; storeConfig.modules!.pages.actions!.fetchPages = vi.fn(); const store = createLocalStore(config); await store.dispatch('pages/deletePage', page); expect(storeConfig.modules!.pages.actions!.fetchPages).toHaveBeenCalled(); expect(fetchMock.called(path)).toEqual(true); }); });