From 49fa5aa2a127bdf8924d02bf77e5086b39c7a447 Mon Sep 17 00:00:00 2001 From: Calvin Morrison Date: Wed, 3 Sep 2025 21:15:36 -0400 Subject: i vibe coded it --- server/test/jchat_SUITE.erl | 252 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 server/test/jchat_SUITE.erl (limited to 'server/test/jchat_SUITE.erl') diff --git a/server/test/jchat_SUITE.erl b/server/test/jchat_SUITE.erl new file mode 100644 index 0000000..ab6f375 --- /dev/null +++ b/server/test/jchat_SUITE.erl @@ -0,0 +1,252 @@ +-module(jchat_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include("../src/jchat.hrl"). + +%% CT callbacks +-export([all/0, init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([test_session_endpoint/1, + test_core_echo/1, + test_conversation_create/1, + test_conversation_get/1, + test_message_create/1, + test_message_get/1, + test_invalid_method/1, + test_invalid_json/1, + test_unknown_capability/1]). + +all() -> + [test_session_endpoint, + test_core_echo, + test_conversation_create, + test_conversation_get, + test_message_create, + test_message_get, + test_invalid_method, + test_invalid_json, + test_unknown_capability]. + +init_per_suite(Config) -> + % Start the application + application:ensure_all_started(jchat), + timer:sleep(1000), % Allow startup + Config. + +end_per_suite(_Config) -> + application:stop(jchat), + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +%% Test cases + +test_session_endpoint(_Config) -> + URL = "http://localhost:8080/jmap/session", + {ok, {{_, 200, _}, Headers, Body}} = httpc:request(get, {URL, []}, [], []), + + % Check content type + {"content-type", "application/json"} = lists:keyfind("content-type", 1, Headers), + + % Parse and validate session object + {ok, Session} = jchat_utils:json_decode(list_to_binary(Body)), + + % Validate required fields + true = maps:is_key(<<"capabilities">>, Session), + true = maps:is_key(<<"accounts">>, Session), + true = maps:is_key(<<"apiUrl">>, Session), + + % Check chat capability + Capabilities = maps:get(<<"capabilities">>, Session), + true = maps:is_key(<<"urn:ietf:params:jmap:chat">>, Capabilities). + +test_core_echo(_Config) -> + Request = #{ + <<"using">> => [<<"urn:ietf:params:jmap:core">>], + <<"methodCalls">> => [ + [<<"Core/echo">>, #{<<"hello">> => <<"world">>}, <<"c1">>] + ] + }, + + Response = make_jmap_request(Request), + + MethodResponses = maps:get(<<"methodResponses">>, Response), + [EchoResponse] = MethodResponses, + [<<"Core/echo">>, Args, <<"c1">>] = EchoResponse, + + <<"world">> = maps:get(<<"hello">>, Args). + +test_conversation_create(_Config) -> + Request = #{ + <<"using">> => [<<"urn:ietf:params:jmap:core">>, <<"urn:ietf:params:jmap:chat">>], + <<"methodCalls">> => [ + [<<"Conversation/set">>, #{ + <<"accountId">> => <<"default">>, + <<"create">> => #{ + <<"conv1">> => #{ + <<"title">> => <<"Test Conversation">>, + <<"participantIds">> => [<<"user1">>, <<"user2">>] + } + } + }, <<"c1">>] + ] + }, + + Response = make_jmap_request(Request), + + MethodResponses = maps:get(<<"methodResponses">>, Response), + [SetResponse] = MethodResponses, + [<<"Conversation/set">>, Args, <<"c1">>] = SetResponse, + + Created = maps:get(<<"created">>, Args), + true = maps:is_key(<<"conv1">>, Created). + +test_conversation_get(_Config) -> + % First create a conversation + {ok, Conv} = jchat_db:create_conversation(<<"test-conv-1">>, #{ + title => <<"Test Conversation">>, + participant_ids => [<<"user1">>] + }), + + Request = #{ + <<"using">> => [<<"urn:ietf:params:jmap:core">>, <<"urn:ietf:params:jmap:chat">>], + <<"methodCalls">> => [ + [<<"Conversation/get">>, #{ + <<"accountId">> => <<"default">>, + <<"ids">> => [<<"test-conv-1">>] + }, <<"c1">>] + ] + }, + + Response = make_jmap_request(Request), + + MethodResponses = maps:get(<<"methodResponses">>, Response), + [GetResponse] = MethodResponses, + [<<"Conversation/get">>, Args, <<"c1">>] = GetResponse, + + List = maps:get(<<"list">>, Args), + [ConvData] = List, + <<"test-conv-1">> = maps:get(<<"id">>, ConvData). + +test_message_create(_Config) -> + % First create a conversation + {ok, _Conv} = jchat_db:create_conversation(<<"test-conv-2">>, #{ + title => <<"Message Test Conversation">>, + participant_ids => [<<"user1">>] + }), + + Request = #{ + <<"using">> => [<<"urn:ietf:params:jmap:core">>, <<"urn:ietf:params:jmap:chat">>], + <<"methodCalls">> => [ + [<<"Message/set">>, #{ + <<"accountId">> => <<"default">>, + <<"create">> => #{ + <<"msg1">> => #{ + <<"conversationId">> => <<"test-conv-2">>, + <<"body">> => <<"Hello, World!">>, + <<"senderId">> => <<"user1">> + } + } + }, <<"c1">>] + ] + }, + + Response = make_jmap_request(Request), + + MethodResponses = maps:get(<<"methodResponses">>, Response), + [SetResponse] = MethodResponses, + [<<"Message/set">>, Args, <<"c1">>] = SetResponse, + + Created = maps:get(<<"created">>, Args), + true = maps:is_key(<<"msg1">>, Created). + +test_message_get(_Config) -> + % Create conversation and message + {ok, _Conv} = jchat_db:create_conversation(<<"test-conv-3">>, #{ + title => <<"Get Test Conversation">>, + participant_ids => [<<"user1">>] + }), + {ok, _Msg} = jchat_db:create_message(<<"test-msg-1">>, #{ + conversation_id => <<"test-conv-3">>, + sender_id => <<"user1">>, + body => <<"Test message">> + }), + + Request = #{ + <<"using">> => [<<"urn:ietf:params:jmap:core">>, <<"urn:ietf:params:jmap:chat">>], + <<"methodCalls">> => [ + [<<"Message/get">>, #{ + <<"accountId">> => <<"default">>, + <<"ids">> => [<<"test-msg-1">>] + }, <<"c1">>] + ] + }, + + Response = make_jmap_request(Request), + + MethodResponses = maps:get(<<"methodResponses">>, Response), + [GetResponse] = MethodResponses, + [<<"Message/get">>, Args, <<"c1">>] = GetResponse, + + List = maps:get(<<"list">>, Args), + [MsgData] = List, + <<"test-msg-1">> = maps:get(<<"id">>, MsgData). + +test_invalid_method(_Config) -> + Request = #{ + <<"using">> => [<<"urn:ietf:params:jmap:core">>], + <<"methodCalls">> => [ + [<<"Invalid/method">>, #{}, <<"c1">>] + ] + }, + + Response = make_jmap_request(Request), + + MethodResponses = maps:get(<<"methodResponses">>, Response), + [ErrorResponse] = MethodResponses, + [<<"error">>, ErrorArgs, <<"c1">>] = ErrorResponse, + + <<"unknownMethod">> = maps:get(<<"type">>, ErrorArgs). + +test_invalid_json(_Config) -> + URL = "http://localhost:8080/jmap/api", + InvalidJSON = "{ invalid json", + + {ok, {{_, 400, _}, _Headers, Body}} = httpc:request(post, + {URL, [], "application/json", InvalidJSON}, [], []), + + {ok, ErrorResponse} = jchat_utils:json_decode(list_to_binary(Body)), + <<"urn:ietf:params:jmap:error:notJSON">> = maps:get(<<"type">>, ErrorResponse). + +test_unknown_capability(_Config) -> + Request = #{ + <<"using">> => [<<"unknown:capability">>], + <<"methodCalls">> => [] + }, + + RequestJSON = jchat_utils:json_encode(Request), + URL = "http://localhost:8080/jmap/api", + + {ok, {{_, 400, _}, _Headers, Body}} = httpc:request(post, + {URL, [], "application/json", RequestJSON}, [], []), + + {ok, ErrorResponse} = jchat_utils:json_decode(list_to_binary(Body)), + <<"urn:ietf:params:jmap:error:unknownCapability">> = maps:get(<<"type">>, ErrorResponse). + +%% Helper functions + +make_jmap_request(Request) -> + RequestJSON = jchat_utils:json_encode(Request), + URL = "http://localhost:8080/jmap/api", + + {ok, {{_, 200, _}, _Headers, Body}} = httpc:request(post, + {URL, [], "application/json", RequestJSON}, [], []), + + {ok, Response} = jchat_utils:json_decode(list_to_binary(Body)), + Response. -- cgit v1.2.3