feat(07-02): implement REST API chat methods getChatMessages and sendChatMessage

Implement chat API methods using native fetch:
- getChatMessages: Fetch messages with pagination support
- sendChatMessage: Send messages to session/global channels
- URL construction with URLSearchParams for clean query strings
- Error handling for all HTTP status codes
- Credentials and headers included for session auth
- JSDoc comments for API documentation

All 14 unit tests passing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Nuwan 2026-01-27 08:14:42 +05:30
parent b6ce5010ac
commit 95483da6fe
2 changed files with 63 additions and 6 deletions

View File

@ -165,14 +165,16 @@ describe('sendChatMessage', () => {
expect(fetch).toHaveBeenCalledWith(
expect.stringContaining('/api/chat'),
expect.objectContaining({
method: 'POST',
body: JSON.stringify({
channel: 'session',
session_id: 'session-abc',
message: 'Hello world'
})
method: 'POST'
})
);
// Check body content separately (key order doesn't matter)
const body = JSON.parse(fetch.mock.calls[0][1].body);
expect(body).toEqual({
channel: 'session',
session_id: 'session-abc',
message: 'Hello world'
});
expect(result.message.id).toBe('msg-new');
});

View File

@ -952,3 +952,58 @@ export const openMetronome = options => {
.catch(error => reject(error));
});
};
/**
* Fetch chat messages for a channel
* @param {Object} params - Request parameters
* @param {string} params.channel - Channel type ('session', 'global', 'lesson')
* @param {string} [params.sessionId] - Session ID (required for session channel)
* @param {number} [params.before] - Pagination cursor
* @returns {Promise<{messages: Array, next: number|null}>} Message list with pagination
*/
export const getChatMessages = async ({ channel, sessionId, before }) => {
const params = new URLSearchParams({ channel });
if (sessionId) params.append('session_id', sessionId);
if (before !== undefined) params.append('before', before);
const baseUrl = process.env.REACT_APP_API_BASE_URL;
const response = await fetch(`${baseUrl}/chat?${params}`, {
method: 'GET',
credentials: 'include',
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) {
throw new Error(`${response.status} ${response.statusText}`);
}
return response.json();
};
/**
* Send a chat message to a channel
* @param {Object} params - Request parameters
* @param {string} params.channel - Channel type ('session', 'global', 'lesson')
* @param {string} [params.sessionId] - Session ID (required for session channel)
* @param {string} params.message - Message content
* @returns {Promise<{message: Object}>} Created message object
*/
export const sendChatMessage = async ({ channel, sessionId, message }) => {
const body = { channel, message };
if (sessionId) body.session_id = sessionId;
const baseUrl = process.env.REACT_APP_API_BASE_URL;
const response = await fetch(`${baseUrl}/chat`, {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.error || `${response.status} ${response.statusText}`);
}
return response.json();
};