tests + version bump: group chat surface

Extends chat.test.js to cover the new conversation shape (kind/key
fields), the /api/chat/rooms endpoint, the thread-settings
round-trip, and the group-creation pick-view toggle. Room-info view
DOM is structurally checked. Bumps to 1.9.4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
thandClaude Opus 4.6 committed 2026-04-15 20:15:55 +02:00
1 parent 9267c7c6a1
commit 0fd97e5d71
3 files changed
+76 -3

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
<?php
define('APP_NAME', 'hyprcrd');
define('APP_VERSION', '1.9.3');
define('APP_VERSION', '1.9.4');
// Database path — writable directory, outside webroot
// DB_PATH / UPLOAD_DIR can be pre-defined by the Electron router for app isolation
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hyprcrd",
"version": "1.9.3",
"version": "1.9.4",
"description": "hyprcrd — self-hosted card manager",
"main": "main.js",
"scripts": {
+74 -1
View File
@@ -86,9 +86,14 @@ describe('Chat: API', () => {
const res = await fetch('api/chat/conversations').then(r => r.json());
expect(Array.isArray(res.conversations)).toBe(true);
expect(typeof res.total_unread).toBe('number');
// Every entry carries kind + key so the UI can route 1:1 vs. room.
for (const c of res.conversations) {
expect(c.kind === 'peer' || c.kind === 'room').toBe(true);
expect(typeof c.key).toBe('string');
}
});
it('/api/chat/messages without peer returns 400', async () => {
it('/api/chat/messages without peer or room_uid returns 400', async () => {
const r = await fetch('api/chat/messages');
expect(r.status).toBe(400);
});
@@ -99,4 +104,72 @@ describe('Chat: API', () => {
expect(Array.isArray(res.messages)).toBe(true);
expect(res.messages.length).toBe(0);
});
it('/api/chat/messages with unknown room returns empty array', async () => {
const res = await fetch('api/chat/messages?room_uid=__no_such_room__')
.then(r => r.json());
expect(Array.isArray(res.messages)).toBe(true);
expect(res.messages.length).toBe(0);
});
it('/api/chat/rooms returns rooms array', async () => {
const res = await fetch('api/chat/rooms').then(r => r.json());
expect(res.ok).toBe(true);
expect(Array.isArray(res.rooms)).toBe(true);
});
it('/api/chat/thread-settings round-trips disposable flag', async () => {
const peer = '__test_disposable_flip__';
// Default: 0
const initial = await fetch('api/chat/thread-settings?peer=' + encodeURIComponent(peer))
.then(r => r.json());
expect(initial.disposable).toBe(0);
// Set to 1
const csrf = document.querySelector('meta[name="csrf"]')?.content || '';
const set = await fetch('api/chat/thread-settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf },
body: JSON.stringify({ peer, disposable: true }),
}).then(r => r.json());
expect(set.disposable).toBe(1);
// Verify
const after = await fetch('api/chat/thread-settings?peer=' + encodeURIComponent(peer))
.then(r => r.json());
expect(after.disposable).toBe(1);
});
});
describe('Chat: group creation UI', () => {
const ensureFlyoutClosed = async () => {
const f = $('#chat-flyout');
if (!f) return;
if (!f.classList.contains('hidden')) {
click('#chat-close-btn');
await waitFor(() => f.classList.contains('hidden'));
}
};
it('pick view has 1:1 / group mode switch', async () => {
await ensureFlyoutClosed();
click('#chat-footer-btn');
await waitFor(() => !$('#chat-flyout').classList.contains('hidden'));
await sleep(80);
click('#chat-new-btn');
await sleep(60);
const mode = document.querySelectorAll('.chat-pick-mode-btn');
expect(mode.length).toBe(2);
// Toggling to group reveals the name input and action bar.
const groupBtn = document.querySelector('.chat-pick-mode-btn[data-mode="group"]');
click(groupBtn);
await sleep(30);
expect($('#chat-group-name').classList.contains('hidden')).toBe(false);
expect($('#chat-group-actions').classList.contains('hidden')).toBe(false);
await ensureFlyoutClosed();
});
it('room-info view element exists', () => {
expect($('#chat-room-info-view')).toExist();
expect($('#chat-room-info-back')).toExist();
expect($('#chat-room-info-body')).toExist();
});
});