diff --git a/app/__tests__/search_bar.test.tsx b/app/__tests__/search_bar.test.tsx index 0535d0ec..2892e754 100644 --- a/app/__tests__/search_bar.test.tsx +++ b/app/__tests__/search_bar.test.tsx @@ -1,68 +1,66 @@ +import React from 'react'; import SearchBar from '../lib/components/search_bar'; // Make sure to adjust the import path import "@testing-library/jest-dom"; import { render, fireEvent } from '@testing-library/react'; +describe('SearchBar Component', () => { + let originalConsoleError: jest.Mock; + let mockOnSearch: jest.Mock; -test('renders the SearchBar component', () => { - render(); -}); -; + beforeEach(() => { + // Mock console.error + originalConsoleError = console.error; + console.error = jest.fn(); + + // Create a mock function for onSearch + mockOnSearch = jest.fn(); + }); + + afterEach(() => { + // Restore original console.error + console.error = originalConsoleError; + }); + + test('renders the SearchBar component', () => { + render(); + }); -test('updates the search input when the user types', () => { - const { getByPlaceholderText } = render(); + test('updates the search input when the user types', () => { + const { getByPlaceholderText } = render(); const searchInput = getByPlaceholderText('Search...'); // Assuming 'Search...' is the placeholder text - - // Simulate user input + fireEvent.change(searchInput, { target: { value: 'Sample Query' } }); - - // Check if the search input value updates correctly expect(searchInput).toHaveValue('Sample Query'); + expect(mockOnSearch).toHaveBeenCalledWith('Sample Query'); }); test('triggers search on pressing Enter key', () => { - const { getByPlaceholderText, getByTestId, queryByText } = render(); + const { getByPlaceholderText } = render(); const searchInput = getByPlaceholderText('Search...'); // Assuming 'Search...' is the placeholder text - const searchButton = getByTestId('search-button'); // Use your custom Test ID here - - // Enter a search query + fireEvent.change(searchInput, { target: { value: 'Sample Query' } }); - - // Press the Enter key fireEvent.keyPress(searchInput, { key: 'Enter', code: 'Enter', charCode: 13 }); - + expect(mockOnSearch).toHaveBeenCalledWith('Sample Query'); }); test('handles large amount of search input', () => { - const { getByPlaceholderText, getByTestId, queryByText } = render(); + const { getByPlaceholderText } = render(); const searchInput = getByPlaceholderText('Search...'); // Assuming 'Search...' is the placeholder text - const searchButton = getByTestId('search-button'); // Use your custom Test ID here - - // Enter a large amount of text in the search input const largeText = 'Lorem ipsum '.repeat(1000); // Creating a large text - + fireEvent.change(searchInput, { target: { value: largeText } }); - - // Press the Enter key fireEvent.keyPress(searchInput, { key: 'Enter', code: 'Enter', charCode: 13 }); - - // Check if the search is aborted or if the component handles it gracefully - // You can check if there are any performance issues - expect(queryByText('Sample Query')).not.toBeInTheDocument(); + expect(mockOnSearch).toHaveBeenCalledWith(largeText); }); test('handles search input with special characters', () => { - const { getByPlaceholderText, getByTestId, queryByText } = render(); + const { getByPlaceholderText } = render(); const searchInput = getByPlaceholderText('Search...'); // Assuming 'Search...' is the placeholder text - const searchButton = getByTestId('search-button'); // Use your custom Test ID here - - // Enter a search query with special characters const specialCharacters = '!@#$%^&*()'; - + fireEvent.change(searchInput, { target: { value: specialCharacters } }); - - // Press the Enter key fireEvent.keyPress(searchInput, { key: 'Enter', code: 'Enter', charCode: 13 }); - - // Check if the search is handled correctly or if any special characters are sanitized - expect(queryByText('Sample Query')).not.toBeInTheDocument(); - }); \ No newline at end of file + expect(mockOnSearch).toHaveBeenCalledWith(specialCharacters); + }); + +}); diff --git a/app/__tests__/sidebar.test.tsx b/app/__tests__/sidebar.test.tsx index fcaee888..1f5bb2b5 100644 --- a/app/__tests__/sidebar.test.tsx +++ b/app/__tests__/sidebar.test.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { useRouter } from 'next/router'; import Sidebar from '../lib/components/side_bar'; // Update the path to your Sidebar component accordingly +import moxios from 'moxios'; jest.mock('next/router', () => ({ useRouter: jest.fn(), @@ -9,12 +10,28 @@ jest.mock('next/router', () => ({ describe('Sidebar Component', () => { let mockPush: jest.Mock; + let originalConsoleError: jest.Mock; beforeEach(() => { + // Install Moxios before each test + moxios.install(); + mockPush = jest.fn(); (useRouter as jest.Mock).mockImplementation(() => ({ push: mockPush, })); + + // Mock console.error + originalConsoleError = console.error; + console.error = jest.fn(); + }); + + afterEach(() => { + // Uninstall Moxios after each test + moxios.uninstall(); + + // Restore original console.error + console.error = originalConsoleError; }); it('renders the sidebar correctly', () => { @@ -34,7 +51,6 @@ describe('Sidebar Component', () => { expect(linkElement).toBeInTheDocument(); }); - - + // ... any other tests ... }); diff --git a/app/lib/components/note_listview 2.tsx b/app/lib/components/note_listview 2.tsx deleted file mode 100644 index 9f8726f3..00000000 --- a/app/lib/components/note_listview 2.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// note_listview.tsx -import React, { useState, useEffect } from 'react'; -import { User } from "../models/user_class"; -import ApiService from '../utils/api_service'; -import { Note } from '../../types'; - -const NoteListView: React.FC = () => { - const [notes, setNotes] = useState([]); - - useEffect(() => { - const fetchNotes = async () => { - const user = User.getInstance(); - const userId = await user.getId(); - if (userId) { - try { - const userNotes = await ApiService.fetchMessages(false, false, userId); - setNotes(userNotes); - } catch (error) { - console.error('Error fetching notes:', error); - // Handle the error as appropriate for your application - } - } - }; - - fetchNotes(); - }, []); - - return ( -
- {notes.map((note) => ( -
-

{note.title}

-

{note.text}

- {/* Render other note properties as needed */} -
- ))} -
- ); -}; - -export default NoteListView; diff --git a/app/lib/components/note_listview.tsx b/app/lib/components/note_listview.tsx index 2e18e96e..d4387e41 100644 --- a/app/lib/components/note_listview.tsx +++ b/app/lib/components/note_listview.tsx @@ -7,41 +7,21 @@ import { Button } from "@/components/ui/button"; import DataConversion from "../utils/data_conversion"; type NoteListViewProps = { + notes: Note[]; onNoteSelect: (note: Note) => void; }; -const NoteListView: React.FC = ({ onNoteSelect }) => { - const [notes, setNotes] = useState([]); +const NoteListView: React.FC = ({ notes, onNoteSelect }) => { const [fresh, setFresh] = useState(true); useEffect(() => { if (notes.length > 0 && fresh) { onNoteSelect(notes[0]); setFresh(false); + console.log("NoteListView: useEffect: onNoteSelect", notes[0]) } }, [notes, onNoteSelect]); - useEffect(() => { - const fetchNotes = async () => { - const user = User.getInstance(); - const userId = await user.getId(); - if (userId) { - try { - const userNotes = await ApiService.fetchMessages( - false, - false, - userId - ); - setNotes(DataConversion.convertMediaTypes(userNotes).reverse()); - } catch (error) { - console.error("Error fetching notes:", error); - } - } - }; - - fetchNotes(); - }, []); - const handleLoadText = (note: Note) => { onNoteSelect(note); }; diff --git a/app/lib/components/search_bar.tsx b/app/lib/components/search_bar.tsx index c9f4fd5d..24e4ec70 100644 --- a/app/lib/components/search_bar.tsx +++ b/app/lib/components/search_bar.tsx @@ -5,21 +5,17 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { MagnifyingGlassIcon } from "@radix-ui/react-icons"; -const SearchBar = () => { +type SearchBarProps = { + onSearch: (query: string) => void; +}; + +const SearchBar: React.FC = ({ onSearch }) => { const [searchText, setSearchText] = useState(""); - const handleSearch = async () => { - console.log("Search text:", searchText); - if (!searchText) { - console.log("Search text is empty. Aborting search."); - return; - } - try { - const response = await ApiService.searchMessages(searchText); - console.log("API Response:", response); - } catch (error) { - console.error("API Error:", error); - } + const handleInputChange = (e: React.ChangeEvent) => { + const query = e.target.value; + setSearchText(query); + onSearch(query); }; return ( @@ -29,14 +25,10 @@ const SearchBar = () => { placeholder="Search..." className="border border-gray-300 rounded-md p-2 flex-grow" value={searchText} - onChange={(e) => setSearchText(e.target.value)} + onChange={handleInputChange} /> - ); diff --git a/app/lib/components/side_bar.tsx b/app/lib/components/side_bar.tsx index bfcfa3d7..f96a9183 100644 --- a/app/lib/components/side_bar.tsx +++ b/app/lib/components/side_bar.tsx @@ -7,26 +7,63 @@ import { Button } from "@/components/ui/button"; import SearchBar from "./search_bar"; import NoteListView from "./note_listview"; import { Note } from "@/app/types"; +import ApiService from "../utils/api_service"; type SidebarProps = { onNoteSelect: (note: Note) => void; }; const user = User.getInstance(); +const userId = user.getId(); + const Sidebar: React.FC = ({ onNoteSelect }) => { + const [notes, setNotes] = useState([]); + const [filteredNotes, setFilteredNotes] = useState([]); + + useEffect(() => { + const fetchUserMessages = async () => { + try { + const userId = await user.getId(); + if (userId) { + const userNotes = await ApiService.fetchUserMessages(userId); + setNotes(userNotes); + setFilteredNotes(userNotes); + } else { + console.error("User not logged in"); + } + } catch (error) { + console.error("Error fetching user messages:", error); + } + }; + + fetchUserMessages(); + }, []); + + const handleSearch = (searchQuery: string) => { + if (!searchQuery.trim()) { + setFilteredNotes(notes); + return; + } + const filtered = notes.filter(note => + note.title.toLowerCase().includes(searchQuery.toLowerCase()) + ); + setFilteredNotes(filtered); + }; + return (
-
- +
+
- +
); -} +}; + export default Sidebar; diff --git a/app/lib/utils/api_service.ts b/app/lib/utils/api_service.ts index 4b24a076..1f2169fc 100644 --- a/app/lib/utils/api_service.ts +++ b/app/lib/utils/api_service.ts @@ -174,5 +174,38 @@ export default class ApiService { } } + /** + * Fetches all messages for a specific user. + * @param {string} userId - The ID of the user whose messages are to be fetched. + * @returns {Promise} - The array of messages fetched from the API. + */ + static async fetchUserMessages(userId: string): Promise { + try { + const url = "http://lived-religion-dev.rerum.io/deer-lr/query"; + const headers = { + "Content-Type": "application/json", + }; + + // Body for the request: fetch messages of type 'message' created by the specified user + const body = { + type: "message", + creator: userId + }; + + const response = await fetch(url, { + method: "POST", + headers, + body: JSON.stringify(body), + }); + + const data = await response.json(); + return data; + } catch (error) { + console.error("Error fetching user messages:", error); + throw error; + } +} + + } \ No newline at end of file