import React from 'react'; import { describe, it, expect, vi } from 'vitest'; import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { http, HttpResponse } from 'msw'; import { CreatePost } from '@/pages/CreatePost/CreatePost'; import notificationsReducer from '@/state/features/notificationsSlice'; import authReducer, { addUser } from '@/state/features/authSlice'; import globalReducer, { setCurrentBlog } from '@/state/features/globalSlice'; import blogReducer from '@/state/features/blogSlice'; import mailReducer from '@/state/features/mailSlice'; import bookmarksReducer from '@/state/features/bookmarksSlice'; import { server } from '../msw/server'; const createTestStore = () => configureStore({ reducer: { notifications: notificationsReducer, auth: authReducer, global: globalReducer, blog: blogReducer, mail: mailReducer, bookmarks: bookmarksReducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, }), }); type TestStore = ReturnType; const renderCreatePost = (store: TestStore) => render( } /> , ); const selectMinimalEditor = async () => { const user = userEvent.setup(); const option = await screen.findByText('Minimal Editor'); await user.click(option); await screen.findByPlaceholderText('Title'); return user; }; describe('CreatePost (new publish flow)', () => { const categoriesHandler = http.get('/arbitrary/categories', () => HttpResponse.json([])); it('surfaces an error when no blog is selected', async () => { server.use(categoriesHandler); const store = createTestStore(); globalThis.qortalRequest = vi.fn().mockResolvedValue({ ok: true }); store.dispatch(addUser({ address: 'QADDR', publicKey: 'PUB', name: 'alice' })); renderCreatePost(store); const user = await selectMinimalEditor(); const titleField = await screen.findByPlaceholderText('Title'); await user.type(titleField, 'Unsaved Draft'); const publishTrigger = await screen.findByRole('button', { name: /^Publish$/i }); await user.click(publishTrigger); const submitButton = await screen.findByRole('button', { name: /Submit/i }); await user.click(submitButton); await waitFor(() => { expect(store.getState().notifications.alertTypes.alertError).toBe( 'Cannot determine which blog to publish to. Open your blog and try again.', ); }); expect(globalThis.qortalRequest).not.toHaveBeenCalled(); }, 10000); it('publishes a new post when currentBlog is available', async () => { server.use(categoriesHandler); const store = createTestStore(); globalThis.qortalRequest = vi.fn().mockResolvedValue({ ok: true }); store.dispatch(addUser({ address: 'QADDR', publicKey: 'PUB', name: 'alice' })); store.dispatch( setCurrentBlog({ createdAt: Date.now(), blogId: 'q-blog-myblog', title: 'My Blog', description: '', blogImage: '', category: '', tags: [], wikiEnabled: false, editorWhitelist: [], editorBlacklist: [], }), ); renderCreatePost(store); const user = await selectMinimalEditor(); const titleField = await screen.findByPlaceholderText('Title'); await user.type(titleField, 'My New Post'); const publishTrigger = await screen.findByRole('button', { name: /^Publish$/i }); await user.click(publishTrigger); const submitButton = await screen.findByRole('button', { name: /Submit/i }); await user.click(submitButton); await waitFor(() => { expect(globalThis.qortalRequest).toHaveBeenCalled(); }); const publishCall = (globalThis.qortalRequest as any).mock.calls.find( (call: any[]) => call[0]?.action === 'PUBLISH_QDN_RESOURCE', ); expect(publishCall).toBeTruthy(); expect(publishCall?.[0]).toMatchObject({ action: 'PUBLISH_QDN_RESOURCE', service: 'BLOG_POST', }); expect(publishCall?.[0]?.identifier.startsWith('q-blog-myblog-post-')).toBe(true); await waitFor(() => { expect(store.getState().notifications.alertTypes.alertSuccess).toBe( 'Blog post successfully published', ); }); }, 10000); });