interface discovery, folders for messages, map nodes from discovery, maintenance tools.
This commit is contained in:
85
tests/backend/test_identity_restore.py
Normal file
85
tests/backend/test_identity_restore.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import base64
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
from meshchatx.src.backend.identity_manager import IdentityManager
|
||||
|
||||
|
||||
class TestIdentityRestore(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.identity_manager = IdentityManager(self.temp_dir)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
||||
@patch("RNS.Identity")
|
||||
@patch("meshchatx.src.backend.identity_manager.DatabaseProvider")
|
||||
@patch("meshchatx.src.backend.identity_manager.DatabaseSchema")
|
||||
def test_restore_identity_from_bytes(
|
||||
self, mock_schema, mock_provider, mock_rns_identity
|
||||
):
|
||||
# Setup mock identity
|
||||
mock_id_instance = MagicMock()
|
||||
mock_id_instance.hash = b"test_hash_32_bytes_long_01234567"
|
||||
mock_id_instance.get_private_key.return_value = b"test_private_key"
|
||||
mock_rns_identity.from_bytes.return_value = mock_id_instance
|
||||
|
||||
identity_bytes = b"some_identity_bytes"
|
||||
result = self.identity_manager.restore_identity_from_bytes(identity_bytes)
|
||||
|
||||
identity_hash = mock_id_instance.hash.hex()
|
||||
self.assertEqual(result["hash"], identity_hash)
|
||||
self.assertEqual(result["display_name"], "Restored Identity")
|
||||
|
||||
# Verify files were created
|
||||
identity_dir = os.path.join(self.temp_dir, "identities", identity_hash)
|
||||
self.assertTrue(os.path.exists(identity_dir))
|
||||
self.assertTrue(os.path.exists(os.path.join(identity_dir, "identity")))
|
||||
self.assertTrue(os.path.exists(os.path.join(identity_dir, "metadata.json")))
|
||||
|
||||
# Verify private key was written
|
||||
with open(os.path.join(identity_dir, "identity"), "rb") as f:
|
||||
self.assertEqual(f.read(), b"test_private_key")
|
||||
|
||||
@patch("RNS.Identity")
|
||||
@patch("meshchatx.src.backend.identity_manager.DatabaseProvider")
|
||||
@patch("meshchatx.src.backend.identity_manager.DatabaseSchema")
|
||||
def test_restore_identity_from_base32(
|
||||
self, mock_schema, mock_provider, mock_rns_identity
|
||||
):
|
||||
# Setup mock identity
|
||||
mock_id_instance = MagicMock()
|
||||
mock_id_instance.hash = b"test_hash_32_bytes_long_01234567"
|
||||
mock_id_instance.get_private_key.return_value = b"test_private_key"
|
||||
mock_rns_identity.from_bytes.return_value = mock_id_instance
|
||||
|
||||
identity_bytes = b"some_identity_bytes"
|
||||
base32_value = base64.b32encode(identity_bytes).decode("utf-8")
|
||||
|
||||
result = self.identity_manager.restore_identity_from_base32(base32_value)
|
||||
|
||||
identity_hash = mock_id_instance.hash.hex()
|
||||
self.assertEqual(result["hash"], identity_hash)
|
||||
|
||||
# Verify from_bytes was called with the decoded bytes
|
||||
mock_rns_identity.from_bytes.assert_called_with(identity_bytes)
|
||||
|
||||
@patch("RNS.Identity")
|
||||
def test_restore_identity_invalid_bytes(self, mock_rns_identity):
|
||||
mock_rns_identity.from_bytes.return_value = None
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
self.identity_manager.restore_identity_from_bytes(b"invalid")
|
||||
self.assertIn("Could not load identity from bytes", str(cm.exception))
|
||||
|
||||
@patch("RNS.Identity")
|
||||
def test_restore_identity_invalid_base32(self, mock_rns_identity):
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
self.identity_manager.restore_identity_from_base32("invalid-base32-!!!")
|
||||
self.assertIn("Invalid base32 identity", str(cm.exception))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
64
tests/backend/test_maintenance.py
Normal file
64
tests/backend/test_maintenance.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
from meshchatx.src.backend.database.messages import MessageDAO
|
||||
from meshchatx.src.backend.database.announces import AnnounceDAO
|
||||
from meshchatx.src.backend.database.misc import MiscDAO
|
||||
|
||||
|
||||
class TestMaintenance(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.provider = MagicMock()
|
||||
self.messages_dao = MessageDAO(self.provider)
|
||||
self.announces_dao = AnnounceDAO(self.provider)
|
||||
self.misc_dao = MiscDAO(self.provider)
|
||||
|
||||
def test_delete_all_lxmf_messages(self):
|
||||
self.messages_dao.delete_all_lxmf_messages()
|
||||
self.assertEqual(self.provider.execute.call_count, 2)
|
||||
calls = self.provider.execute.call_args_list
|
||||
self.assertIn("DELETE FROM lxmf_messages", calls[0][0][0])
|
||||
self.assertIn("DELETE FROM lxmf_conversation_read_state", calls[1][0][0])
|
||||
|
||||
def test_delete_all_announces(self):
|
||||
# Test without aspect
|
||||
self.announces_dao.delete_all_announces()
|
||||
self.provider.execute.assert_called_with("DELETE FROM announces")
|
||||
|
||||
# Test with aspect
|
||||
self.announces_dao.delete_all_announces(aspect="test_aspect")
|
||||
self.provider.execute.assert_called_with(
|
||||
"DELETE FROM announces WHERE aspect = ?", ("test_aspect",)
|
||||
)
|
||||
|
||||
def test_delete_all_favourites(self):
|
||||
# Test without aspect
|
||||
self.announces_dao.delete_all_favourites()
|
||||
self.provider.execute.assert_called_with("DELETE FROM favourite_destinations")
|
||||
|
||||
# Test with aspect
|
||||
self.announces_dao.delete_all_favourites(aspect="test_aspect")
|
||||
self.provider.execute.assert_called_with(
|
||||
"DELETE FROM favourite_destinations WHERE aspect = ?", ("test_aspect",)
|
||||
)
|
||||
|
||||
def test_delete_archived_pages(self):
|
||||
self.misc_dao.delete_archived_pages()
|
||||
self.provider.execute.assert_called_with("DELETE FROM archived_pages")
|
||||
|
||||
def test_upsert_lxmf_message(self):
|
||||
msg_data = {
|
||||
"hash": "test_hash",
|
||||
"source_hash": "source",
|
||||
"destination_hash": "dest",
|
||||
"peer_hash": "peer",
|
||||
"content": "hello",
|
||||
}
|
||||
self.messages_dao.upsert_lxmf_message(msg_data)
|
||||
self.provider.execute.assert_called()
|
||||
args, _ = self.provider.execute.call_args
|
||||
self.assertIn("INSERT INTO lxmf_messages", args[0])
|
||||
self.assertIn("ON CONFLICT(hash) DO UPDATE SET", args[0])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -22,10 +22,14 @@ class TestMessageHandler(unittest.TestCase):
|
||||
|
||||
def test_delete_conversation(self):
|
||||
self.handler.delete_conversation("local", "dest")
|
||||
self.db.provider.execute.assert_called()
|
||||
args, kwargs = self.db.provider.execute.call_args
|
||||
self.assertIn("DELETE FROM lxmf_messages", args[0])
|
||||
self.assertIn("dest", args[1])
|
||||
self.assertEqual(self.db.provider.execute.call_count, 2)
|
||||
call_args_list = self.db.provider.execute.call_args_list
|
||||
first_call_args, _ = call_args_list[0]
|
||||
second_call_args, _ = call_args_list[1]
|
||||
self.assertIn("DELETE FROM lxmf_messages", first_call_args[0])
|
||||
self.assertIn("dest", first_call_args[1])
|
||||
self.assertIn("DELETE FROM lxmf_conversation_folders", second_call_args[0])
|
||||
self.assertIn("dest", second_call_args[1])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import MessagesSidebar from "@/components/messages/MessagesSidebar.vue";
|
||||
|
||||
describe("MessagesSidebar.vue", () => {
|
||||
beforeEach(() => {
|
||||
// Mock localStorage
|
||||
global.localStorage = {
|
||||
getItem: vi.fn(() => null),
|
||||
setItem: vi.fn(),
|
||||
removeItem: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
const defaultProps = {
|
||||
peers: {},
|
||||
conversations: [],
|
||||
@@ -38,11 +48,13 @@ describe("MessagesSidebar.vue", () => {
|
||||
|
||||
const wrapper = mountMessagesSidebar({ conversations });
|
||||
|
||||
const nameElement = wrapper.find(".truncate");
|
||||
const nameElement = wrapper.find(".conversation-item .truncate");
|
||||
expect(nameElement.exists()).toBe(true);
|
||||
expect(nameElement.text()).toContain("Long Name");
|
||||
|
||||
const previewElement = wrapper.findAll(".truncate").find((el) => el.text().includes("Message"));
|
||||
const previewElement = wrapper
|
||||
.findAll(".conversation-item .truncate")
|
||||
.find((el) => el.text().includes("Message"));
|
||||
expect(previewElement.exists()).toBe(true);
|
||||
});
|
||||
|
||||
@@ -60,7 +72,7 @@ describe("MessagesSidebar.vue", () => {
|
||||
expect(scrollContainer.exists()).toBe(true);
|
||||
expect(scrollContainer.classes()).toContain("overflow-y-auto");
|
||||
|
||||
const conversationItems = wrapper.findAll("div.overflow-y-auto .cursor-pointer");
|
||||
const conversationItems = wrapper.findAll(".conversation-item");
|
||||
expect(conversationItems.length).toBe(100);
|
||||
});
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ describe("UI Performance and Memory Tests", () => {
|
||||
`Rendered ${numConvs} conversations in ${renderTime.toFixed(2)}ms, Memory growth: ${memGrowth.toFixed(2)}MB`
|
||||
);
|
||||
|
||||
expect(wrapper.findAll(".flex.cursor-pointer").length).toBe(numConvs);
|
||||
expect(wrapper.findAll(".conversation-item").length).toBe(numConvs);
|
||||
expect(renderTime).toBeLessThan(5000);
|
||||
expect(memGrowth).toBeLessThan(200); // Adjusted for JSDOM/Node.js overhead with 2000 items
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user