"No","テストID","対象クラス","対象メソッド","テスト観点","テストケース名","前提条件","入力値","期待結果","優先度","備考"
"1","UT-CHN-001","Channel::Api","name","正常系","チャネル名がAPIとして返却されること","なし","なし","'API'が返却される","低","表示用メソッド"
"2","UT-CHN-002","Channel::Api","has_secure_token :identifier","正常系","識別子トークンが自動生成されること","新規Channel::Api作成時","なし","ユニークなidentifierが生成される","高","認証・識別に使用"
"3","UT-CHN-003","Channel::Api","has_secure_token :hmac_token","正常系","HMACトークンが自動生成されること","新規Channel::Api作成時","なし","ユニークなhmac_tokenが生成される","高","認証に使用"
"4","UT-CHN-004","Channel::Api","ensure_valid_agent_reply_time_window","正常系","agent_reply_time_windowが正の値の場合バリデーション通過","なし","additional_attributes['agent_reply_time_window'] = 10","バリデーションエラーなし","中","設定値のバリデーション"
"5","UT-CHN-005","Channel::Api","ensure_valid_agent_reply_time_window","異常系","agent_reply_time_windowが0以下の場合エラー","なし","additional_attributes['agent_reply_time_window'] = 0","バリデーションエラー発生","中","境界値チェック"
"6","UT-CHN-006","Channel::Api","ensure_valid_agent_reply_time_window","正常系","agent_reply_time_windowが空の場合バリデーション通過","なし","additional_attributes['agent_reply_time_window'] = nil","バリデーションエラーなし","中","オプション値の許容"
"7","UT-CHN-007","Channel::Api","webhook_url validation","異常系","webhook_urlが最大長を超える場合エラー","なし","webhook_url = 'a' * (Limits::URL_LENGTH_LIMIT + 1)","バリデーションエラー発生","中","URL長制限"
"8","UT-CHN-008","Channel::Email","name","正常系","チャネル名がEmailとして返却されること","なし","なし","'Email'が返却される","低","表示用メソッド"
"9","UT-CHN-009","Channel::Email","microsoft?","正常系","providerがmicrosoftの場合trueを返すこと","provider = 'microsoft'","なし","trueが返却される","中","プロバイダ判定"
"10","UT-CHN-010","Channel::Email","microsoft?","正常系","providerがmicrosoft以外の場合falseを返すこと","provider = 'google'","なし","falseが返却される","中","プロバイダ判定"
"11","UT-CHN-011","Channel::Email","google?","正常系","providerがgoogleの場合trueを返すこと","provider = 'google'","なし","trueが返却される","中","プロバイダ判定"
"12","UT-CHN-012","Channel::Email","google?","正常系","providerがgoogle以外の場合falseを返すこと","provider = 'microsoft'","なし","falseが返却される","中","プロバイダ判定"
"13","UT-CHN-013","Channel::Email","legacy_google?","正常系","IMAP有効かつGmailアドレスの場合trueを返すこと","imap_enabled = true, imap_address = 'imap.gmail.com'","なし","trueが返却される","中","レガシー判定"
"14","UT-CHN-014","Channel::Email","legacy_google?","正常系","IMAP無効の場合falseを返すこと","imap_enabled = false, imap_address = 'imap.gmail.com'","なし","falseが返却される","中","レガシー判定"
"15","UT-CHN-015","Channel::Email","ensure_forward_to_email","正常系","forward_to_emailが未設定の場合自動生成されること","forward_to_email = nil","なし","ランダムなメールアドレスが生成される","高","メール転送設定"
"16","UT-CHN-016","Channel::Email","ensure_forward_to_email","正常系","forward_to_emailが設定済みの場合変更されないこと","forward_to_email = 'test@example.com'","なし","'test@example.com'が維持される","中","メール転送設定"
"17","UT-CHN-017","Channel::Email","email validation","異常系","重複するemailでエラー","同一emailのChannel::Emailが存在","email = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"18","UT-CHN-018","Channel::Email","forward_to_email validation","異常系","重複するforward_to_emailでエラー","同一forward_to_emailが存在","forward_to_email = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"19","UT-CHN-019","Channel::FacebookPage","name","正常系","チャネル名がFacebookとして返却されること","なし","なし","'Facebook'が返却される","低","表示用メソッド"
"20","UT-CHN-020","Channel::FacebookPage","create_contact_inbox","正常系","ContactInboxが作成されること","inbox存在","instagram_id = '123', name = 'Test'","ContactInboxが返却される","高","コンタクト管理"
"21","UT-CHN-021","Channel::FacebookPage","subscribe","正常系","Webhookサブスクリプションが成功すること","有効なpage_access_token","なし","Facebook APIへのサブスクライブが成功","高","Webhook連携"
"22","UT-CHN-022","Channel::FacebookPage","subscribe","異常系","API失敗時にエラーがログされtrueを返すこと","無効なpage_access_token","なし","例外がrescueされtrueが返却される","中","エラーハンドリング"
"23","UT-CHN-023","Channel::FacebookPage","unsubscribe","正常系","Webhookサブスクリプション解除が成功すること","有効なpage_access_token","なし","Facebook APIへのアンサブスクライブが成功","高","Webhook連携"
"24","UT-CHN-024","Channel::FacebookPage","unsubscribe","異常系","API失敗時にエラーがログされtrueを返すこと","無効なpage_access_token","なし","例外がrescueされtrueが返却される","中","エラーハンドリング"
"25","UT-CHN-025","Channel::FacebookPage","page_id validation","異常系","同一account内で重複するpage_idでエラー","同一account_id, page_idが存在","page_id = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"26","UT-CHN-026","Channel::Instagram","name","正常系","チャネル名がInstagramとして返却されること","なし","なし","'Instagram'が返却される","低","表示用メソッド"
"27","UT-CHN-027","Channel::Instagram","create_contact_inbox","正常系","ContactInboxが作成されること","inbox存在","instagram_id = '123', name = 'Test'","ContactInboxが返却される","高","コンタクト管理"
"28","UT-CHN-028","Channel::Instagram","subscribe","正常系","Webhookサブスクリプションが成功すること","有効なaccess_token","なし","Instagram APIへのサブスクライブが成功","高","Webhook連携"
"29","UT-CHN-029","Channel::Instagram","subscribe","異常系","API失敗時にエラーがログされtrueを返すこと","無効なaccess_token","なし","例外がrescueされtrueが返却される","中","エラーハンドリング"
"30","UT-CHN-030","Channel::Instagram","unsubscribe","正常系","Webhookサブスクリプション解除が成功すること","有効なaccess_token","なし","Instagram APIへのアンサブスクライブが成功","高","Webhook連携"
"31","UT-CHN-031","Channel::Instagram","unsubscribe","異常系","API失敗時にエラーがログされtrueを返すこと","無効なaccess_token","なし","例外がrescueされtrueが返却される","中","エラーハンドリング"
"32","UT-CHN-032","Channel::Instagram","access_token","正常系","リフレッシュされたaccess_tokenが取得できること","有効なchannel","なし","RefreshOauthTokenServiceからトークンが返却される","高","OAuth認証"
"33","UT-CHN-033","Channel::Instagram","access_token validation","異常系","access_tokenが空の場合エラー","なし","access_token = nil","presenceエラー発生","高","必須チェック"
"34","UT-CHN-034","Channel::Instagram","instagram_id validation","異常系","instagram_idが重複する場合エラー","同一instagram_idが存在","instagram_id = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"35","UT-CHN-035","Channel::Line","name","正常系","チャネル名がLINEとして返却されること","なし","なし","'LINE'が返却される","低","表示用メソッド"
"36","UT-CHN-036","Channel::Line","client","正常系","Line::Bot::Clientが正しく初期化されること","有効なline_channel_id, secret, token","なし","設定されたクライアントが返却される","高","LINE SDK連携"
"37","UT-CHN-037","Channel::Line","line_channel_id validation","異常系","重複するline_channel_idでエラー","同一line_channel_idが存在","line_channel_id = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"38","UT-CHN-038","Channel::Line","line_channel_id validation","異常系","line_channel_idが空の場合エラー","なし","line_channel_id = nil","presenceエラー発生","高","必須チェック"
"39","UT-CHN-039","Channel::Line","line_channel_secret validation","異常系","line_channel_secretが空の場合エラー","なし","line_channel_secret = nil","presenceエラー発生","高","必須チェック"
"40","UT-CHN-040","Channel::Line","line_channel_token validation","異常系","line_channel_tokenが空の場合エラー","なし","line_channel_token = nil","presenceエラー発生","高","必須チェック"
"41","UT-CHN-041","Channel::Sms","name","正常系","チャネル名がSmsとして返却されること","なし","なし","'Sms'が返却される","低","表示用メソッド"
"42","UT-CHN-042","Channel::Sms","api_base_path","正常系","BandwidthのベースURLが返却されること","なし","なし","'https://messaging.bandwidth.com/api/v2'が返却される","中","API設定"
"43","UT-CHN-043","Channel::Sms","send_message","正常系","メッセージが正常に送信されること","有効なprovider_config, メッセージ存在","contact_number, message","message_idが返却される","高","メッセージ送信"
"44","UT-CHN-044","Channel::Sms","send_message","正常系","添付ファイル付きメッセージが送信されること","有効なprovider_config, 添付ファイルあり","contact_number, message with attachments","message_idが返却される","高","メディア送信"
"45","UT-CHN-045","Channel::Sms","send_message","異常系","API失敗時にメッセージがfailedになること","無効なprovider_config","contact_number, message","message.status = :failed, nilが返却される","高","エラーハンドリング"
"46","UT-CHN-046","Channel::Sms","send_text_message","正常系","テキストメッセージが正常に送信されること","有効なprovider_config","contact_number, message_content","message_idが返却される","高","テキスト送信"
"47","UT-CHN-047","Channel::Sms","phone_number validation","異常系","phone_numberが空の場合エラー","なし","phone_number = nil","presenceエラー発生","高","必須チェック"
"48","UT-CHN-048","Channel::Sms","phone_number validation","異常系","重複するphone_numberでエラー","同一phone_numberが存在","phone_number = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"49","UT-CHN-049","Channel::Telegram","name","正常系","チャネル名がTelegramとして返却されること","なし","なし","'Telegram'が返却される","低","表示用メソッド"
"50","UT-CHN-050","Channel::Telegram","telegram_api_url","正常系","TelegramのAPIURLが正しく構築されること","bot_token = 'test_token'","なし","'https://api.telegram.org/bottest_token'が返却される","中","API設定"
"51","UT-CHN-051","Channel::Telegram","send_message_on_telegram","正常系","テキストメッセージが送信されること","有効なbot_token, message.outgoing_content存在","message","message_idが返却される","高","メッセージ送信"
"52","UT-CHN-052","Channel::Telegram","send_message_on_telegram","正常系","添付ファイルが送信されること","有効なbot_token, message.attachments存在","message with attachments","message_idが返却される","高","メディア送信"
"53","UT-CHN-053","Channel::Telegram","get_telegram_profile_image","正常系","プロフィール画像URLが取得できること","有効なbot_token, ユーザーに画像あり","user_id","画像URLが返却される","中","プロフィール取得"
"54","UT-CHN-054","Channel::Telegram","get_telegram_profile_image","正常系","画像がない場合nilが返却されること","有効なbot_token, ユーザーに画像なし","user_id","nilが返却される","中","空データ処理"
"55","UT-CHN-055","Channel::Telegram","get_telegram_profile_image","異常系","API失敗時にnilが返却されること","無効なbot_token","user_id","nilが返却される","中","エラーハンドリング"
"56","UT-CHN-056","Channel::Telegram","get_telegram_file_path","正常系","ファイルパスURLが取得できること","有効なbot_token","file_id","ファイルURLが返却される","中","ファイル取得"
"57","UT-CHN-057","Channel::Telegram","get_telegram_file_path","異常系","API失敗時にnilが返却されること","無効なbot_token","file_id","nilが返却される","中","エラーハンドリング"
"58","UT-CHN-058","Channel::Telegram","process_error","正常系","APIエラー時にメッセージがfailedになること","response['ok'] = false","message, response","message.status = :failed, external_errorが設定される","高","エラーハンドリング"
"59","UT-CHN-059","Channel::Telegram","process_error","正常系","API成功時は何も変更されないこと","response['ok'] = true","message, response","messageに変更なし","中","正常処理"
"60","UT-CHN-060","Channel::Telegram","chat_id","正常系","会話からchat_idが取得できること","conversation.additional_attributes['chat_id']存在","message","chat_idが返却される","中","会話管理"
"61","UT-CHN-061","Channel::Telegram","business_connection_id","正常系","会話からbusiness_connection_idが取得できること","conversation.additional_attributes['business_connection_id']存在","message","business_connection_idが返却される","中","ビジネス連携"
"62","UT-CHN-062","Channel::Telegram","reply_to_message_id","正常系","返信先message_idが取得できること","message.content_attributes['in_reply_to_external_id']存在","message","in_reply_to_external_idが返却される","中","返信機能"
"63","UT-CHN-063","Channel::Telegram","ensure_valid_bot_token","正常系","有効なbot_tokenでbot_nameが設定されること","getMe API成功","なし","bot_nameが設定される","高","トークン検証"
"64","UT-CHN-064","Channel::Telegram","ensure_valid_bot_token","異常系","無効なbot_tokenでエラーが追加されること","getMe API失敗","なし","errors[:bot_token]にエラー追加","高","トークン検証"
"65","UT-CHN-065","Channel::Telegram","setup_telegram_webhook","正常系","Webhookが正常に設定されること","有効なbot_token","なし","setWebhook APIが成功","高","Webhook設定"
"66","UT-CHN-066","Channel::Telegram","setup_telegram_webhook","異常系","Webhook設定失敗時にエラーが追加されること","setWebhook API失敗","なし","errors[:bot_token]にエラー追加","高","Webhook設定"
"67","UT-CHN-067","Channel::Telegram","bot_token validation","異常系","bot_tokenが空の場合エラー","なし","bot_token = nil","presenceエラー発生","高","必須チェック"
"68","UT-CHN-068","Channel::Telegram","bot_token validation","異常系","重複するbot_tokenでエラー","同一bot_tokenが存在","bot_token = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"69","UT-CHN-069","Channel::Tiktok","name","正常系","チャネル名がTiktokとして返却されること","なし","なし","'Tiktok'が返却される","低","表示用メソッド"
"70","UT-CHN-070","Channel::Tiktok","validated_access_token","正常系","検証済みaccess_tokenが取得できること","有効なchannel","なし","TokenServiceからトークンが返却される","高","OAuth認証"
"71","UT-CHN-071","Channel::Tiktok","business_id validation","異常系","business_idが重複する場合エラー","同一business_idが存在","business_id = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"72","UT-CHN-072","Channel::Tiktok","business_id validation","異常系","business_idが空の場合エラー","なし","business_id = nil","presenceエラー発生","高","必須チェック"
"73","UT-CHN-073","Channel::Tiktok","access_token validation","異常系","access_tokenが空の場合エラー","なし","access_token = nil","presenceエラー発生","高","必須チェック"
"74","UT-CHN-074","Channel::Tiktok","refresh_token validation","異常系","refresh_tokenが空の場合エラー","なし","refresh_token = nil","presenceエラー発生","高","必須チェック"
"75","UT-CHN-075","Channel::Tiktok","expires_at validation","異常系","expires_atが空の場合エラー","なし","expires_at = nil","presenceエラー発生","高","必須チェック"
"76","UT-CHN-076","Channel::Tiktok","refresh_token_expires_at validation","異常系","refresh_token_expires_atが空の場合エラー","なし","refresh_token_expires_at = nil","presenceエラー発生","高","必須チェック"
"77","UT-CHN-077","Channel::TwilioSms","name","正常系","mediumがsmsの場合Twilio SMSが返却されること","medium = 'sms'","なし","'Twilio SMS'が返却される","低","表示用メソッド"
"78","UT-CHN-078","Channel::TwilioSms","name","正常系","mediumがwhatsappの場合Whatsappが返却されること","medium = 'whatsapp'","なし","'Whatsapp'が返却される","低","表示用メソッド"
"79","UT-CHN-079","Channel::TwilioSms","send_message","正常系","メッセージが正常に送信されること","有効なaccount_sid, auth_token","to, body","Twilio APIでメッセージ作成成功","高","メッセージ送信"
"80","UT-CHN-080","Channel::TwilioSms","send_message","正常系","メディア付きメッセージが送信されること","有効なaccount_sid, auth_token","to, body, media_url","media_url含むメッセージ作成成功","高","メディア送信"
"81","UT-CHN-081","Channel::TwilioSms","send_message","正常系","messaging_service_sid使用時に正しくfromが設定されること","messaging_service_sid設定済み","to, body","messaging_service_sidが使用される","中","送信元設定"
"82","UT-CHN-082","Channel::TwilioSms","send_message","正常系","phone_number使用時に正しくfromが設定されること","phone_number設定済み, messaging_service_sidなし","to, body","phone_numberがfromに使用される","中","送信元設定"
"83","UT-CHN-083","Channel::TwilioSms","client","正常系","api_key_sid存在時にAPIキー認証でクライアント作成","api_key_sid設定済み","なし","api_key_sidを使用したクライアント","中","認証方式"
"84","UT-CHN-084","Channel::TwilioSms","client","正常系","api_key_sidなしの場合account_sid認証でクライアント作成","api_key_sidなし","なし","account_sidを使用したクライアント","中","認証方式"
"85","UT-CHN-085","Channel::TwilioSms","account_sid validation","異常系","account_sidが空の場合エラー","なし","account_sid = nil","presenceエラー発生","高","必須チェック"
"86","UT-CHN-086","Channel::TwilioSms","auth_token validation","異常系","auth_tokenが空の場合エラー","なし","auth_token = nil","presenceエラー発生","高","必須チェック"
"87","UT-CHN-087","Channel::TwilioSms","messaging_service_sid validation","正常系","phone_numberなしでmessaging_service_sid必須","phone_number = nil","messaging_service_sid = 'MSG123'","バリデーション通過","中","条件付き必須"
"88","UT-CHN-088","Channel::TwilioSms","messaging_service_sid validation","異常系","phone_numberもmessaging_service_sidもない場合エラー","なし","phone_number = nil, messaging_service_sid = nil","presenceエラー発生","高","条件付き必須"
"89","UT-CHN-089","Channel::TwilioSms","phone_number validation","異常系","messaging_service_sid存在時にphone_numberありでエラー","messaging_service_sid設定済み","phone_number = '+1234567890'","absenceエラー発生","中","排他制約"
"90","UT-CHN-090","Channel::TwilioSms","phone_number validation","異常系","重複するphone_numberでエラー","同一phone_numberが存在","phone_number = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"91","UT-CHN-091","Channel::TwilioSms","messaging_service_sid validation","異常系","重複するmessaging_service_sidでエラー","同一messaging_service_sidが存在","messaging_service_sid = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"92","UT-CHN-092","Channel::TwitterProfile","name","正常系","チャネル名がTwitterとして返却されること","なし","なし","'Twitter'が返却される","低","表示用メソッド"
"93","UT-CHN-093","Channel::TwitterProfile","create_contact_inbox","正常系","ContactInboxが作成されること","inbox存在","profile_id, name, additional_attributes","ContactInboxが返却される","高","コンタクト管理"
"94","UT-CHN-094","Channel::TwitterProfile","twitter_client","正常系","Twitty::Facadeが正しく初期化されること","有効なtwitter_access_token, secret","なし","設定されたクライアントが返却される","高","Twitter SDK連携"
"95","UT-CHN-095","Channel::TwitterProfile","unsubscribe","正常系","サブスクリプション解除が成功すること","有効なtwitter_access_token","なし","remove_subscriptionが呼ばれる","中","Webhook連携"
"96","UT-CHN-096","Channel::TwitterProfile","unsubscribe","異常系","API失敗時にエラーがログされること","無効なtwitter_access_token","なし","例外がrescueされログ出力","中","エラーハンドリング"
"97","UT-CHN-097","Channel::TwitterProfile","profile_id validation","異常系","同一account内で重複するprofile_idでエラー","同一account_id, profile_idが存在","profile_id = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"98","UT-CHN-098","Channel::WebWidget","name","正常系","チャネル名がWebsiteとして返却されること","なし","なし","'Website'が返却される","低","表示用メソッド"
"99","UT-CHN-099","Channel::WebWidget","web_widget_script","正常系","埋め込みスクリプトが正しく生成されること","website_token存在","なし","website_tokenを含むscriptタグが返却される","中","ウィジェット埋め込み"
"100","UT-CHN-100","Channel::WebWidget","validate_pre_chat_options","正常系","pre_chat_fieldsが空の場合デフォルト値が設定されること","pre_chat_form_options = {}","なし","デフォルトのpre_chat_fieldsが設定される","中","デフォルト値設定"
"101","UT-CHN-101","Channel::WebWidget","validate_pre_chat_options","正常系","pre_chat_fieldsが設定済みの場合変更されないこと","pre_chat_form_options['pre_chat_fields']設定済み","なし","既存の設定が維持される","中","設定保持"
"102","UT-CHN-102","Channel::WebWidget","create_contact_inbox","正常系","ContactInboxが作成されること","inbox存在","additional_attributes = {browser: 'Chrome'}","ContactInboxが返却される","高","コンタクト管理"
"103","UT-CHN-103","Channel::WebWidget","has_secure_token :website_token","正常系","ウェブサイトトークンが自動生成されること","新規WebWidget作成時","なし","ユニークなwebsite_tokenが生成される","高","認証・識別に使用"
"104","UT-CHN-104","Channel::WebWidget","has_secure_token :hmac_token","正常系","HMACトークンが自動生成されること","新規WebWidget作成時","なし","ユニークなhmac_tokenが生成される","高","認証に使用"
"105","UT-CHN-105","Channel::WebWidget","website_url validation","異常系","website_urlが空の場合エラー","なし","website_url = nil","presenceエラー発生","高","必須チェック"
"106","UT-CHN-106","Channel::WebWidget","widget_color validation","異常系","widget_colorが空の場合エラー","なし","widget_color = nil","presenceエラー発生","高","必須チェック"
"107","UT-CHN-107","Channel::WebWidget","feature_flags","正常系","attachmentsフラグが正しく設定・取得できること","なし","attachments = true","attachmentsがtrueで取得される","中","機能フラグ"
"108","UT-CHN-108","Channel::WebWidget","feature_flags","正常系","emoji_pickerフラグが正しく設定・取得できること","なし","emoji_picker = true","emoji_pickerがtrueで取得される","中","機能フラグ"
"109","UT-CHN-109","Channel::WebWidget","feature_flags","正常系","end_conversationフラグが正しく設定・取得できること","なし","end_conversation = true","end_conversationがtrueで取得される","中","機能フラグ"
"110","UT-CHN-110","Channel::WebWidget","feature_flags","正常系","use_inbox_avatar_for_botフラグが正しく設定・取得できること","なし","use_inbox_avatar_for_bot = true","use_inbox_avatar_for_botがtrueで取得される","中","機能フラグ"
"111","UT-CHN-111","Channel::WebWidget","reply_time enum","正常系","reply_timeがin_a_few_minutesで設定できること","なし","reply_time = :in_a_few_minutes","reply_time = 0","中","列挙型"
"112","UT-CHN-112","Channel::WebWidget","reply_time enum","正常系","reply_timeがin_a_few_hoursで設定できること","なし","reply_time = :in_a_few_hours","reply_time = 1","中","列挙型"
"113","UT-CHN-113","Channel::WebWidget","reply_time enum","正常系","reply_timeがin_a_dayで設定できること","なし","reply_time = :in_a_day","reply_time = 2","中","列挙型"
"114","UT-CHN-114","Channel::WebWidget","portals association","正常系","関連するportalsが取得できること","portals存在","なし","portalsが返却される","中","リレーション"
"115","UT-CHN-115","Channel::Whatsapp","name","正常系","チャネル名がWhatsappとして返却されること","なし","なし","'Whatsapp'が返却される","低","表示用メソッド"
"116","UT-CHN-116","Channel::Whatsapp","provider_service","正常系","providerがwhatsapp_cloudの場合WhatsappCloudServiceが返却されること","provider = 'whatsapp_cloud'","なし","WhatsappCloudServiceインスタンス","高","プロバイダ切替"
"117","UT-CHN-117","Channel::Whatsapp","provider_service","正常系","providerがdefaultの場合Whatsapp360DialogServiceが返却されること","provider = 'default'","なし","Whatsapp360DialogServiceインスタンス","高","プロバイダ切替"
"118","UT-CHN-118","Channel::Whatsapp","mark_message_templates_updated","正常系","message_templates_last_updatedが更新されること","なし","なし","現在時刻が設定される","中","テンプレート管理"
"119","UT-CHN-119","Channel::Whatsapp","send_message","正常系","メッセージがprovider_service経由で送信されること","有効なprovider_config","メッセージパラメータ","provider_service.send_messageが呼ばれる","高","委譲メソッド"
"120","UT-CHN-120","Channel::Whatsapp","send_template","正常系","テンプレートがprovider_service経由で送信されること","有効なprovider_config","テンプレートパラメータ","provider_service.send_templateが呼ばれる","高","委譲メソッド"
"121","UT-CHN-121","Channel::Whatsapp","sync_templates","正常系","テンプレートがprovider_service経由で同期されること","有効なprovider_config","なし","provider_service.sync_templatesが呼ばれる","高","委譲メソッド"
"122","UT-CHN-122","Channel::Whatsapp","media_url","正常系","メディアURLがprovider_service経由で取得されること","有効なprovider_config","メディアID","provider_service.media_urlが呼ばれる","中","委譲メソッド"
"123","UT-CHN-123","Channel::Whatsapp","api_headers","正常系","APIヘッダーがprovider_service経由で取得されること","有効なprovider_config","なし","provider_service.api_headersが呼ばれる","中","委譲メソッド"
"124","UT-CHN-124","Channel::Whatsapp","setup_webhooks","正常系","Webhookが正常に設定されること","有効なprovider_config, whatsapp_cloud","なし","WebhookSetupServiceが実行される","高","Webhook設定"
"125","UT-CHN-125","Channel::Whatsapp","setup_webhooks","異常系","Webhook設定失敗時にreauthorization要求されること","無効なprovider_config","なし","prompt_reauthorization!が呼ばれる","高","エラーハンドリング"
"126","UT-CHN-126","Channel::Whatsapp","ensure_webhook_verify_token","正常系","whatsapp_cloudの場合webhook_verify_tokenが生成されること","provider = 'whatsapp_cloud', webhook_verify_tokenなし","なし","ランダムなトークンが設定される","中","トークン生成"
"127","UT-CHN-127","Channel::Whatsapp","ensure_webhook_verify_token","正常系","defaultの場合webhook_verify_tokenは生成されないこと","provider = 'default'","なし","webhook_verify_tokenは設定されない","中","プロバイダ依存"
"128","UT-CHN-128","Channel::Whatsapp","validate_provider_config","異常系","無効なprovider_configでエラー","provider_service.validate_provider_config? = false","なし","errors[:provider_config]にエラー追加","高","設定検証"
"129","UT-CHN-129","Channel::Whatsapp","provider validation","異常系","無効なproviderでエラー","なし","provider = 'invalid'","inclusionエラー発生","高","プロバイダ制限"
"130","UT-CHN-130","Channel::Whatsapp","phone_number validation","異常系","phone_numberが空の場合エラー","なし","phone_number = nil","presenceエラー発生","高","必須チェック"
"131","UT-CHN-131","Channel::Whatsapp","phone_number validation","異常系","重複するphone_numberでエラー","同一phone_numberが存在","phone_number = 既存と同じ値","uniquenessエラー発生","高","一意性制約"
"132","UT-CHN-132","Channel::Whatsapp","should_auto_setup_webhooks?","正常系","whatsapp_cloudかつ非embedded_signupの場合trueを返すこと","provider = 'whatsapp_cloud', source != 'embedded_signup'","なし","trueが返却される","中","条件判定"
"133","UT-CHN-133","Channel::Whatsapp","should_auto_setup_webhooks?","正常系","embedded_signupの場合falseを返すこと","provider = 'whatsapp_cloud', source = 'embedded_signup'","なし","falseが返却される","中","条件判定"
"134","UT-CHN-134","Channel::Whatsapp","should_auto_setup_webhooks?","正常系","defaultプロバイダの場合falseを返すこと","provider = 'default'","なし","falseが返却される","中","条件判定"
"1","UT-APP-001","Channelable","included","正常系","account_idのpresenceバリデーションが機能すること","なし","account_id=nil","バリデーションエラーが発生する","高","必須バリデーション"
"2","UT-APP-002","Channelable","included","正常系","accountとのbelongs_toリレーションが正しく機能すること","Accountが存在","account_id=1","Accountオブジェクトが返却される","高","リレーション定義"
"3","UT-APP-003","Channelable","included","正常系","inboxとのhas_oneリレーションが正しく機能すること","Inboxが存在","なし","Inboxオブジェクトが返却される","高","ポリモーフィックリレーション"
"4","UT-APP-004","Channelable","create_audit_log_entry","正常系","更新時にaudit_log_entryコールバックが呼ばれること","レコードが存在","属性を更新","create_audit_log_entryが呼ばれる","中","after_updateコールバック"
"5","UT-APP-005","MessageFilterHelpers","reportable?","正常系","incoming?がtrueの場合trueが返却されること","メッセージが受信","message_type=incoming","trueが返却される","中","フィルタメソッド"
"6","UT-APP-006","MessageFilterHelpers","reportable?","正常系","outgoing?がtrueの場合trueが返却されること","メッセージが送信","message_type=outgoing","trueが返却される","中","フィルタメソッド"
"7","UT-APP-007","MessageFilterHelpers","reportable?","異常系","incoming?もoutgoing?もfalseの場合falseが返却されること","メッセージがactivity","message_type=activity","falseが返却される","中","フィルタメソッド"
"8","UT-APP-008","MessageFilterHelpers","webhook_sendable?","正常系","template?がtrueの場合trueが返却されること","メッセージがテンプレート","message_type=template","trueが返却される","中","Webhook送信判定"
"9","UT-APP-009","MessageFilterHelpers","slack_hook_sendable?","正常系","outgoing?がtrueの場合trueが返却されること","メッセージが送信","message_type=outgoing","trueが返却される","中","Slack連携判定"
"10","UT-APP-010","MessageFilterHelpers","notifiable?","正常系","incoming?がtrueの場合trueが返却されること","メッセージが受信","message_type=incoming","trueが返却される","中","通知判定"
"11","UT-APP-011","MessageFilterHelpers","conversation_transcriptable?","正常系","outgoing?がtrueの場合trueが返却されること","メッセージが送信","message_type=outgoing","trueが返却される","中","トランスクリプト判定"
"12","UT-APP-012","MessageFilterHelpers","email_reply_summarizable?","正常系","input_csat?がtrueの場合trueが返却されること","メッセージがCSAT","message_type=input_csat","trueが返却される","中","メール返信要約判定"
"13","UT-APP-013","MessageFilterHelpers","instagram_story_mention?","正常系","Instagram inboxでstory_mentionの場合trueが返却されること","Instagram inbox, image_type=story_mention","content_attributes[:image_type]=story_mention","trueが返却される","中","Instagram連携"
"14","UT-APP-014","MessageFilterHelpers","instagram_story_mention?","異常系","Instagram inbox以外の場合falseが返却されること","Web inbox","なし","falseが返却される","中","Instagram連携"
"15","UT-APP-015","PushDataHelper","push_event_data","正常系","EventDataPresenterのpush_dataが呼ばれること","Conversationが存在","なし","push_dataの結果が返却される","中","イベントデータ取得"
"16","UT-APP-016","PushDataHelper","lock_event_data","正常系","EventDataPresenterのlock_dataが呼ばれること","Conversationが存在","なし","lock_dataの結果が返却される","中","ロックイベントデータ"
"17","UT-APP-017","PushDataHelper","webhook_data","正常系","EventDataPresenterのpush_dataが呼ばれること","Conversationが存在","なし","push_dataの結果が返却される","中","Webhookデータ取得"
"18","UT-APP-018","AssignmentHandler","ensure_assignee_is_from_team","正常系","チーム変更時に担当者がチームメンバーでない場合nullになること","担当者がチームメンバーでない","team_id変更, assignee_idがチーム外","assignee_id=nil","高","担当者検証"
"19","UT-APP-019","AssignmentHandler","ensure_assignee_is_from_team","正常系","チーム変更時にauto_assignが有効なら新担当者が割り当てられること","allow_auto_assign=true","team_id変更","新担当者が割り当てられる","高","自動割り当て"
"20","UT-APP-020","AssignmentHandler","notify_assignment_change","正常系","担当者変更時にASSIGNEE_CHANGEDイベントがdispatchされること","担当者が変更","assignee_id変更","ASSIGNEE_CHANGEDがdispatchされる","高","イベント通知"
"21","UT-APP-021","AssignmentHandler","notify_assignment_change","正常系","チーム変更時にTEAM_CHANGEDイベントがdispatchされること","チームが変更","team_id変更","TEAM_CHANGEDがdispatchされる","高","イベント通知"
"22","UT-APP-022","AssignmentHandler","self_assign?","正常系","Current.userと担当者が同じ場合trueが返却されること","Current.user.id=1","assignee_id=1","trueが返却される","中","自己割り当て判定"
"23","UT-APP-023","AssignmentHandler","self_assign?","異常系","assignee_idがnilの場合falseが返却されること","なし","assignee_id=nil","falseが返却される","中","自己割り当て判定"
"24","UT-APP-024","UserAttributeHelpers","available_name","正常系","display_nameが存在する場合display_nameが返却されること","display_name=Test","なし","Testが返却される","中","表示名取得"
"25","UT-APP-025","UserAttributeHelpers","available_name","正常系","display_nameがnilの場合nameが返却されること","display_name=nil, name=User","なし","Userが返却される","中","表示名取得"
"26","UT-APP-026","UserAttributeHelpers","availability_status","正常系","current_account_userのavailability_statusが返却されること","AccountUserが存在","なし","availability_statusが返却される","中","ステータス取得"
"27","UT-APP-027","UserAttributeHelpers","auto_offline","正常系","current_account_userのauto_offlineが返却されること","AccountUserが存在","なし","auto_offline値が返却される","中","オフライン設定取得"
"28","UT-APP-028","UserAttributeHelpers","current_account_user","正常系","Current.accountのaccount_userが返却されること","Current.account設定済み","なし","AccountUserが返却される","高","現在アカウントユーザー取得"
"29","UT-APP-029","UserAttributeHelpers","current_account_user","異常系","Current.accountがnilの場合nilが返却されること","Current.account=nil","なし","nilが返却される","中","現在アカウントユーザー取得"
"30","UT-APP-030","UserAttributeHelpers","administrator?","正常系","管理者の場合trueが返却されること","ユーザーが管理者","なし","trueが返却される","高","権限チェック"
"31","UT-APP-031","UserAttributeHelpers","agent?","正常系","エージェントの場合trueが返却されること","ユーザーがエージェント","なし","trueが返却される","高","権限チェック"
"32","UT-APP-032","UserAttributeHelpers","hmac_identifier","正常系","HMAC_KEYが設定されている場合HMACが返却されること","CHATWOOT_INBOX_HMAC_KEY設定済み","email=test@example.com","HMACハッシュが返却される","高","認証識別子"
"33","UT-APP-033","UserAttributeHelpers","hmac_identifier","異常系","HMAC_KEYが未設定の場合空文字が返却されること","CHATWOOT_INBOX_HMAC_KEY未設定","なし","空文字が返却される","中","認証識別子"
"34","UT-APP-034","AutoAssignmentHandler","run_auto_assignment","正常系","ステータスがopenに変更された場合自動割り当てが実行されること","status変更, enable_auto_assignment=true","status=open","AgentAssignmentServiceが呼ばれる","高","自動割り当て実行"
"35","UT-APP-035","AutoAssignmentHandler","run_auto_assignment","正常系","auto_assignment_v2が有効な場合Jobがキューされること","auto_assignment_v2_enabled=true","status=open","AssignmentJobがperform_laterされる","高","v2自動割り当て"
"36","UT-APP-036","AutoAssignmentHandler","should_run_auto_assignment?","異常系","enable_auto_assignment?がfalseの場合falseが返却されること","enable_auto_assignment=false","なし","falseが返却される","高","自動割り当て条件"
"37","UT-APP-037","AutoAssignmentHandler","should_run_auto_assignment?","正常系","担当者が空の場合trueが返却されること","assignee=nil","なし","trueが返却される","中","自動割り当て条件"
"38","UT-APP-038","SortHandler","sort_on_last_activity_at","正常系","last_activity_atでソートされること","複数レコードが存在","sort_direction=:desc","降順でソートされる","中","ソート機能"
"39","UT-APP-039","SortHandler","sort_on_created_at","正常系","created_atでソートされること","複数レコードが存在","sort_direction=:asc","昇順でソートされる","中","ソート機能"
"40","UT-APP-040","SortHandler","sort_on_priority","正常系","priorityでソートされNULLが最後になること","複数レコードが存在","sort_direction=:desc","NULLS LASTでソートされる","中","ソート機能"
"41","UT-APP-041","SortHandler","sort_on_waiting_since","正常系","waiting_sinceでソートされること","複数レコードが存在","sort_direction=:asc","昇順でソートされる","中","ソート機能"
"42","UT-APP-042","SortHandler","last_messaged_conversations","正常系","各会話の最新メッセージが取得されること","複数メッセージが存在","なし","DISTINCT ON conversation_idで取得","中","最新メッセージ取得"
"43","UT-APP-043","LlmFormattable","to_llm_text","正常系","LlmTextFormatterServiceが呼ばれること","オブジェクトが存在","config={}","フォーマットされたテキストが返却される","中","LLMフォーマット"
"44","UT-APP-044","LlmFormattable","to_llm_text","正常系","configオプションが渡されること","オブジェクトが存在","config={key: value}","configが適用されたテキストが返却される","中","LLMフォーマット"
"45","UT-APP-045","OutOfOffisable","out_of_office?","正常系","営業時間外の場合trueが返却されること","working_hours_enabled=true, 現在時刻が営業時間外","なし","trueが返却される","高","営業時間判定"
"46","UT-APP-046","OutOfOffisable","out_of_office?","正常系","営業時間内の場合falseが返却されること","working_hours_enabled=true, 現在時刻が営業時間内","なし","falseが返却される","高","営業時間判定"
"47","UT-APP-047","OutOfOffisable","out_of_office?","異常系","working_hours_enabledがfalseの場合falseが返却されること","working_hours_enabled=false","なし","falseが返却される","高","営業時間判定"
"48","UT-APP-048","OutOfOffisable","working_now?","正常系","out_of_office?の逆が返却されること","なし","なし","!out_of_office?が返却される","中","営業中判定"
"49","UT-APP-049","OutOfOffisable","weekly_schedule","正常系","曜日順のスケジュールが返却されること","working_hoursが設定済み","なし","day_of_week昇順の配列が返却される","中","週間スケジュール取得"
"50","UT-APP-050","OutOfOffisable","update_working_hours","正常系","working_hoursが更新されること","working_hoursが存在","params=[{day_of_week: 1, open_hour: 10}]","working_hoursが更新される","高","営業時間更新"
"51","UT-APP-051","OutOfOffisable","update_working_hours","正常系","トランザクション内で更新されること","working_hoursが存在","複数の更新params","全てが成功または全てロールバック","高","トランザクション処理"
"52","UT-APP-052","OutOfOffisable","create_default_working_hours","正常系","作成時にデフォルトの営業時間が作成されること","なし","なし","7日分のworking_hoursが作成される","高","初期データ作成"
"53","UT-APP-053","ActivityMessageHandler","create_activity","正常系","ステータス変更時にアクティビティが作成されること","status変更","なし","status_change_activityが呼ばれる","高","アクティビティ作成"
"54","UT-APP-054","ActivityMessageHandler","create_activity","正常系","優先度変更時にアクティビティが作成されること","priority変更","なし","priority_change_activityが呼ばれる","高","アクティビティ作成"
"55","UT-APP-055","ActivityMessageHandler","create_activity","正常系","ラベル変更時にアクティビティが作成されること","label_list変更","なし","create_label_changeが呼ばれる","中","アクティビティ作成"
"56","UT-APP-056","ActivityMessageHandler","create_activity","正常系","SLAポリシー変更時にアクティビティが作成されること","sla_policy_id変更","なし","create_sla_change_activityが呼ばれる","中","アクティビティ作成"
"57","UT-APP-057","ActivityMessageHandler","auto_resolve_message_key","正常系","1440分以上で日単位のキーが返却されること","なし","minutes=2880","key=auto_resolved_days, count=2","中","自動解決メッセージ"
"58","UT-APP-058","ActivityMessageHandler","auto_resolve_message_key","正常系","60分以上で時間単位のキーが返却されること","なし","minutes=120","key=auto_resolved_hours, count=2","中","自動解決メッセージ"
"59","UT-APP-059","ActivityMessageHandler","auto_resolve_message_key","正常系","60分未満で分単位のキーが返却されること","なし","minutes=30","key=auto_resolved_minutes, count=30","中","自動解決メッセージ"
"60","UT-APP-060","ActivityMessageHandler","create_muted_message","正常系","Current.userが存在する場合ミュートメッセージが作成されること","Current.user設定済み","なし","ActivityMessageJobがキューされる","中","ミュートアクティビティ"
"61","UT-APP-061","ActivityMessageHandler","create_unmuted_message","正常系","Current.userが存在する場合アンミュートメッセージが作成されること","Current.user設定済み","なし","ActivityMessageJobがキューされる","中","ミュートアクティビティ"
"62","UT-APP-062","ActivityMessageHandler","generate_assignee_change_activity_content","正常系","担当者割り当て時にassignedキーが使用されること","assignee_idが設定","assignee_id=1","assignedのI18nメッセージが返却される","中","担当者変更メッセージ"
"63","UT-APP-063","ActivityMessageHandler","generate_assignee_change_activity_content","正常系","担当者解除時にremovedキーが使用されること","assignee_idがnil","assignee_id=nil","removedのI18nメッセージが返却される","中","担当者変更メッセージ"
"64","UT-APP-064","ActivityMessageHandler","generate_assignee_change_activity_content","正常系","自己割り当て時にself_assignedキーが使用されること","Current.user.id=assignee_id","なし","self_assignedのI18nメッセージが返却される","中","担当者変更メッセージ"
"65","UT-APP-065","SlaActivityMessageHandler","create_sla_change_activity","正常系","SLA追加時にaddedメッセージが作成されること","SLA追加","change_type=added","addedのI18nメッセージでJobがキューされる","中","SLAアクティビティ"
"66","UT-APP-066","SlaActivityMessageHandler","create_sla_change_activity","正常系","SLA削除時にremovedメッセージが作成されること","SLA削除","change_type=removed","removedのI18nメッセージでJobがキューされる","中","SLAアクティビティ"
"67","UT-APP-067","SlaActivityMessageHandler","determine_sla_change_type","正常系","nil->有効でaddedが返却されること","なし","sla_policy_id: nil -> 1","addedが返却される","中","SLA変更タイプ判定"
"68","UT-APP-068","SlaActivityMessageHandler","determine_sla_change_type","正常系","有効->nilでremovedが返却されること","なし","sla_policy_id: 1 -> nil","removedが返却される","中","SLA変更タイプ判定"
"69","UT-APP-069","Reauthorizable","reauthorization_required?","正常系","Redisにキーが存在する場合trueが返却されること","reauthorization_required_key設定済み","なし","trueが返却される","高","再認証要否判定"
"70","UT-APP-070","Reauthorizable","reauthorization_required?","正常系","Redisにキーが存在しない場合falseが返却されること","reauthorization_required_key未設定","なし","falseが返却される","高","再認証要否判定"
"71","UT-APP-071","Reauthorizable","authorization_error_count","正常系","Redisの値が数値として返却されること","authorization_error_count_key=3","なし","3が返却される","中","エラーカウント取得"
"72","UT-APP-072","Reauthorizable","authorization_error!","正常系","エラーカウントがインクリメントされること","authorization_error_count=0","なし","authorization_error_count=1","高","認証エラー処理"
"73","UT-APP-073","Reauthorizable","authorization_error!","正常系","閾値超過時にprompt_reauthorization!が呼ばれること","authorization_error_count>=2","なし","reauthorization_requiredが設定される","高","再認証プロンプト"
"74","UT-APP-074","Reauthorizable","prompt_reauthorization!","正常系","reauthorization_required_keyが設定されること","なし","なし","Redisにキーが設定される","高","再認証プロンプト"
"75","UT-APP-075","Reauthorizable","prompt_reauthorization!","正常系","クラスに応じたハンドラが呼ばれること","Integrations::Hookの場合","なし","process_integration_hook_reauthorization_emailsが呼ばれる","高","再認証ハンドラ"
"76","UT-APP-076","Reauthorizable","reauthorized!","正常系","Redisのキーが削除されること","reauthorization_required_key設定済み","なし","両キーが削除される","高","再認証完了処理"
"77","UT-APP-077","Reauthorizable","send_channel_reauthorization_email","正常系","指定されたdisconnect_typeのメールが送信されること","なし","disconnect_type=:facebook_disconnect","facebook_disconnectメールが送信される","中","再認証メール送信"
"78","UT-APP-078","PriorityActivityMessageHandler","priority_change_activity","正常系","優先度追加時にaddedメッセージが作成されること","old_priority=nil, new_priority=high","なし","addedのI18nメッセージでJobがキューされる","中","優先度アクティビティ"
"79","UT-APP-079","PriorityActivityMessageHandler","priority_change_activity","正常系","優先度更新時にupdatedメッセージが作成されること","old_priority=low, new_priority=high","なし","updatedのI18nメッセージでJobがキューされる","中","優先度アクティビティ"
"80","UT-APP-080","PriorityActivityMessageHandler","priority_change_activity","正常系","優先度削除時にremovedメッセージが作成されること","old_priority=high, new_priority=nil","なし","removedのI18nメッセージでJobがキューされる","中","優先度アクティビティ"
"81","UT-APP-081","PriorityActivityMessageHandler","get_priority_change_type","正常系","両方存在でupdatedが返却されること","なし","old_priority=low, new_priority=high","updatedが返却される","中","変更タイプ判定"
"82","UT-APP-082","PriorityActivityMessageHandler","get_priority_change_type","正常系","新規のみでaddedが返却されること","なし","old_priority=nil, new_priority=high","addedが返却される","中","変更タイプ判定"
"83","UT-APP-083","CaptainFeaturable","captain_preferences","正常系","modelsとfeaturesを含むハッシュが返却されること","captain_models, captain_features設定済み","なし","両方を含むHashが返却される","中","設定取得"
"84","UT-APP-084","CaptainFeaturable","captain_xxx_enabled?","正常系","feature_keyに対応する有効状態が返却されること","captain_features設定済み","feature_key=editor","boolean値が返却される","中","機能有効判定"
"85","UT-APP-085","CaptainFeaturable","captain_xxx_model","正常系","feature_keyに対応するモデル名が返却されること","captain_models設定済み","feature_key=editor","モデル名が返却される","中","モデル取得"
"86","UT-APP-086","CaptainFeaturable","validate_captain_models","異常系","無効なモデル名でバリデーションエラーになること","なし","captain_models={editor: invalid_model}","バリデーションエラーが発生する","高","モデルバリデーション"
"87","UT-APP-087","CaptainFeaturable","captain_models_with_defaults","正常系","未設定のfeature_keyにはデフォルトが使用されること","captain_models未設定","なし","デフォルトモデルが返却される","中","デフォルト適用"
"88","UT-APP-088","LabelActivityMessageHandler","create_label_added","正常系","ラベル追加時にaddedメッセージが作成されること","user_name設定済み","labels=[tag1, tag2]","addedのI18nメッセージでJobがキューされる","中","ラベルアクティビティ"
"89","UT-APP-089","LabelActivityMessageHandler","create_label_removed","正常系","ラベル削除時にremovedメッセージが作成されること","user_name設定済み","labels=[tag1]","removedのI18nメッセージでJobがキューされる","中","ラベルアクティビティ"
"90","UT-APP-090","LabelActivityMessageHandler","create_label_change_activity","異常系","labelsが空の場合何もしないこと","なし","labels=[]","Jobがキューされない","低","ラベルアクティビティ"
"91","UT-APP-091","SsoAuthenticatable","generate_sso_auth_token","正常系","32バイトのトークンが生成されること","なし","なし","64文字のhex文字列が返却される","高","SSOトークン生成"
"92","UT-APP-092","SsoAuthenticatable","generate_sso_auth_token","正常系","Redisに5分のTTLで保存されること","なし","なし","5分後に期限切れになる","高","SSOトークン保存"
"93","UT-APP-093","SsoAuthenticatable","invalidate_sso_auth_token","正常系","指定トークンがRedisから削除されること","トークンが存在","token=xxx","トークンが削除される","高","SSOトークン無効化"
"94","UT-APP-094","SsoAuthenticatable","valid_sso_auth_token?","正常系","有効なトークンの場合trueが返却されること","トークンがRedisに存在","token=xxx","trueが返却される","高","SSOトークン検証"
"95","UT-APP-095","SsoAuthenticatable","valid_sso_auth_token?","正常系","無効なトークンの場合falseが返却されること","トークンがRedisに存在しない","token=invalid","falseが返却される","高","SSOトークン検証"
"96","UT-APP-096","SsoAuthenticatable","generate_sso_link","正常系","正しいフォーマットのURLが生成されること","email設定済み","なし","FRONTEND_URL/app/login?email=xxx&sso_auth_token=xxxの形式","高","SSOリンク生成"
"97","UT-APP-097","SsoAuthenticatable","generate_sso_link","正常系","emailがURLエンコードされること","email=test+user@example.com","なし","+が%2Bにエンコードされる","中","SSOリンク生成"
"98","UT-APP-098","SsoAuthenticatable","generate_sso_link_with_impersonation","正常系","impersonation=trueパラメータが付与されること","なし","なし","impersonation=trueが含まれる","中","代理ログインリンク"
"99","UT-APP-099","ConversationMuteHelpers","mute!","正常系","会話がresolvedになりcontactがblockedになること","contactが存在","なし","status=resolved, contact.blocked=true","高","ミュート処理"
"100","UT-APP-100","ConversationMuteHelpers","mute!","異常系","contactがnilの場合何もしないこと","contact=nil","なし","何も変更されない","中","ミュート処理"
"101","UT-APP-101","ConversationMuteHelpers","unmute!","正常系","contactのblockedがfalseになること","contactがblocked=true","なし","contact.blocked=false","高","ミュート解除"
"102","UT-APP-102","ConversationMuteHelpers","unmute!","異常系","contactがnilの場合何もしないこと","contact=nil","なし","何も変更されない","中","ミュート解除"
"103","UT-APP-103","ConversationMuteHelpers","muted?","正常系","contactがblockedの場合trueが返却されること","contact.blocked=true","なし","trueが返却される","中","ミュート判定"
"104","UT-APP-104","ConversationMuteHelpers","muted?","正常系","contactがblockedでない場合falseが返却されること","contact.blocked=false","なし","falseが返却される","中","ミュート判定"
"105","UT-APP-105","ConversationMuteHelpers","muted?","異常系","contactがnilの場合falseが返却されること","contact=nil","なし","falseが返却される","中","ミュート判定"
"106","UT-APP-106","Avatarable","avatar_url","正常系","アバターがattachされている場合URLが返却されること","avatar attached","なし","resize_to_fill: [250, nil]のURLが返却される","中","アバターURL取得"
"107","UT-APP-107","Avatarable","avatar_url","正常系","アバターがattachされていない場合空文字が返却されること","avatar not attached","なし","空文字が返却される","中","アバターURL取得"
"108","UT-APP-108","Avatarable","fetch_avatar_from_gravatar","正常系","email変更時にGravatarジョブがキューされること","emailが変更された","email変更","AvatarFromGravatarJobが30秒後にキューされる","中","Gravatar取得"
"109","UT-APP-109","Avatarable","fetch_avatar_from_gravatar","異常系","emailが空の場合ジョブがキューされないこと","emailが空","email=nil","Jobがキューされない","中","Gravatar取得"
"110","UT-APP-110","Avatarable","acceptable_avatar","異常系","15MBを超えるファイルでエラーになること","avatar attached","byte_size=16MB","avatar is too bigエラー","高","アバターバリデーション"
"111","UT-APP-111","Avatarable","acceptable_avatar","異常系","許可されていないファイルタイプでエラーになること","avatar attached","content_type=image/bmp","filetype not supportedエラー","高","アバターバリデーション"
"112","UT-APP-112","Avatarable","acceptable_avatar","正常系","JPEG/PNG/GIFは許可されること","avatar attached","content_type=image/png","バリデーションエラーなし","高","アバターバリデーション"
"113","UT-APP-113","JsonSchemaValidator","validate","正常系","スキーマに適合するJSONの場合エラーなしになること","スキーマ定義済み","適合するJSON","record.errors空","高","JSONスキーマ検証"
"114","UT-APP-114","JsonSchemaValidator","validate","異常系","必須フィールド欠落でis requiredエラーになること","スキーマ定義済み","必須フィールド欠落","is requiredエラー","高","JSONスキーマ検証"
"115","UT-APP-115","JsonSchemaValidator","validate","異常系","型不一致でmust be of typeエラーになること","スキーマ定義済み","型が違うJSON","must be of typeエラー","高","JSONスキーマ検証"
"116","UT-APP-116","JsonSchemaValidator","validate","異常系","minimum違反でgreater than or equal toエラーになること","スキーマ定義済み","値がminimum未満","must be greater than or equal toエラー","中","JSONスキーマ検証"
"117","UT-APP-117","JsonSchemaValidator","validate","異常系","maximum違反でless than or equal toエラーになること","スキーマ定義済み","値がmaximum超過","must be less than or equal toエラー","中","JSONスキーマ検証"
"118","UT-APP-118","AccessTokenable","create_access_token","正常系","作成時にAccessTokenが作成されること","なし","なし","AccessTokenが作成される","高","アクセストークン生成"
"119","UT-APP-119","AccessTokenable","included","正常系","access_tokenリレーションが定義されること","なし","なし","has_one :access_tokenが機能する","高","リレーション定義"
"120","UT-APP-120","Pubsubable","rotate_pubsub_token","正常系","パスワード変更時にトークンがローテートされること","Userモデル","encrypted_password変更","新しいpubsub_tokenが生成される","高","トークンローテート"
"121","UT-APP-121","Pubsubable","rotate_pubsub_token","正常系","User以外ではローテートされないこと","Contactモデル","encrypted_password変更","pubsub_tokenは変更されない","中","トークンローテート"
"122","UT-APP-122","Pubsubable","pubsub_token","正常系","トークンが空でpersistedの場合再生成されること","pubsub_token=nil, persisted=true","なし","新しいトークンが生成・保存される","高","トークン取得"
"123","UT-APP-123","Pubsubable","pubsub_token","正常系","トークンが存在する場合そのまま返却されること","pubsub_token=xxx","なし","xxxが返却される","中","トークン取得"
"124","UT-APP-124","Liquidable","process_liquid_in_content","正常系","outgoingメッセージでLiquidテンプレートが処理されること","message_type=outgoing, content=Hello {{contact.name}}","なし","contentがレンダリングされる","高","Liquid処理"
"125","UT-APP-125","Liquidable","process_liquid_in_content","正常系","templateメッセージでLiquidテンプレートが処理されること","message_type=template, content=Hello {{contact.name}}","なし","contentがレンダリングされる","高","Liquid処理"
"126","UT-APP-126","Liquidable","process_liquid_in_content","異常系","incomingメッセージでは処理されないこと","message_type=incoming","なし","contentは変更されない","中","Liquid処理"
"127","UT-APP-127","Liquidable","process_liquid_in_content","異常系","Liquid構文エラーの場合例外が握りつぶされること","content=invalid{{liquid","なし","例外が発生せずcontentは元のまま","中","Liquidエラー処理"
"128","UT-APP-128","Liquidable","modified_liquid_content","正常系","コードブロック内はrawタグでラップされること","content=`{{code}}`","なし","{% raw %}`{{code}}`{% endraw %}に変換","中","コードブロック保護"
"129","UT-APP-129","Liquidable","process_liquid_in_template_params","正常系","template_paramsのprocessed_paramsがレンダリングされること","template_params設定済み","なし","processed_paramsがレンダリングされる","中","テンプレートパラメータ処理"
"130","UT-APP-130","Liquidable","message_drops","正常系","contact, agent, conversation, inbox, accountのDropオブジェクトが返却されること","conversation設定済み","なし","5つのDropオブジェクトを含むHash","中","Dropオブジェクト生成"
"131","UT-APP-131","Featurable","enable_features","正常系","指定された機能が有効になること","なし","names=[:feature1, :feature2]","feature_feature1=true, feature_feature2=true","高","機能有効化"
"132","UT-APP-132","Featurable","enable_features!","正常系","有効化後に保存されること","なし","names=[:feature1]","DBに保存される","高","機能有効化と保存"
"133","UT-APP-133","Featurable","disable_features","正常系","指定された機能が無効になること","feature1=true","names=[:feature1]","feature_feature1=false","高","機能無効化"
"134","UT-APP-134","Featurable","disable_features!","正常系","無効化後に保存されること","feature1=true","names=[:feature1]","DBに保存される","高","機能無効化と保存"
"135","UT-APP-135","Featurable","feature_enabled?","正常系","有効な機能の場合trueが返却されること","feature1=true","name=feature1","trueが返却される","中","機能有効判定"
"136","UT-APP-136","Featurable","all_features","正常系","全機能の有効/無効状態がHashで返却されること","複数機能設定済み","なし","{feature1: true, feature2: false}形式","中","全機能状態取得"
"137","UT-APP-137","Featurable","enabled_features","正常系","有効な機能のみが返却されること","feature1=true, feature2=false","なし","{feature1: true}","中","有効機能取得"
"138","UT-APP-138","Featurable","disabled_features","正常系","無効な機能のみが返却されること","feature1=true, feature2=false","なし","{feature2: false}","中","無効機能取得"
"139","UT-APP-139","Featurable","enable_default_features","正常系","InstallationConfigに基づいてデフォルト機能が有効化されること","ACCOUNT_LEVEL_FEATURE_DEFAULTS設定済み","なし","設定された機能が有効化される","高","デフォルト機能有効化"
"140","UT-APP-140","TeamActivityMessageHandler","create_team_change_activity","正常系","チーム割り当て時にassignedメッセージが作成されること","team設定済み","なし","assignedのI18nメッセージでJobがキューされる","中","チームアクティビティ"
"141","UT-APP-141","TeamActivityMessageHandler","create_team_change_activity","正常系","チーム解除時にremovedメッセージが作成されること","team=nil","なし","removedのI18nメッセージでJobがキューされる","中","チームアクティビティ"
"142","UT-APP-142","TeamActivityMessageHandler","generate_team_change_activity_key","正常系","チームと担当者同時変更時にassigned_with_assigneeが返却されること","team変更, assignee変更","なし","assigned_with_assigneeが返却される","中","アクティビティキー生成"
"143","UT-APP-143","Labelable","update_labels","正常系","label_listが更新されること","labels設定済み","labels=[tag1, tag2]","label_listが[tag1, tag2]に更新","中","ラベル更新"
"144","UT-APP-144","Labelable","add_labels","正常系","既存ラベルに新ラベルが追加されること","labels=[tag1]","new_labels=[tag2]","label_listが[tag1, tag2]になる","中","ラベル追加"
"145","UT-APP-145","Labelable","add_labels","異常系","new_labelsがblankの場合何もしないこと","labels=[tag1]","new_labels=nil","label_listは変更されない","低","ラベル追加"
"146","UT-APP-146","Labelable","add_labels","正常系","単一文字列もArrayに変換されること","labels=[]","new_labels=tag1","label_listが[tag1]になる","中","ラベル追加"
"147","UT-APP-147","ContentAttributeValidator","validate","正常系","input_selectでitemsが存在する場合バリデーション通過すること","content_type=input_select","items=[{title: x, value: y}]","エラーなし","高","コンテンツ属性検証"
"148","UT-APP-148","ContentAttributeValidator","validate","異常系","itemsが空の場合エラーになること","content_type=input_select","items=[]","At least one item is requiredエラー","高","コンテンツ属性検証"
"149","UT-APP-149","ContentAttributeValidator","validate","異常系","itemsがHashでない場合エラーになること","content_type=input_select","items=[string]","Items should be a hashエラー","高","コンテンツ属性検証"
"150","UT-APP-150","ContentAttributeValidator","validate","異常系","無効なキーを含む場合エラーになること","content_type=input_select","items=[{invalid_key: x}]","contains invalid keysエラー","高","コンテンツ属性検証"
"151","UT-APP-151","ContentAttributeValidator","validate","異常系","cardsでactionsが欠落している場合エラーになること","content_type=cards","items=[{title: x}]","contains items missing actionsエラー","高","コンテンツ属性検証"
"152","UT-APP-152","InboxAgentAvailability","available_agents","正常系","オンラインエージェントのみが返却されること","agent1=online, agent2=offline","なし","agent1のみ返却される","高","オンラインエージェント取得"
"153","UT-APP-153","InboxAgentAvailability","available_agents","境界値","オンラインエージェントがいない場合空が返却されること","全員offline","なし","空のリレーションが返却される","高","オンラインエージェント取得"
"154","UT-APP-154","InboxAgentAvailability","member_ids_with_assignment_capacity","正常系","member_idsが返却されること","メンバーが存在","なし","member_idsが返却される","中","割り当て可能メンバー取得"
"155","UT-APP-155","AccountCacheRevalidator","update_account_cache","正常系","create時にaccountのupdate_cache_keyが呼ばれること","なし","createアクション","update_cache_keyが呼ばれる","中","キャッシュ更新"
"156","UT-APP-156","AccountCacheRevalidator","update_account_cache","正常系","update時にaccountのupdate_cache_keyが呼ばれること","レコードが存在","updateアクション","update_cache_keyが呼ばれる","中","キャッシュ更新"
"157","UT-APP-157","AccountCacheRevalidator","update_account_cache","正常系","destroy時にaccountのupdate_cache_keyが呼ばれること","レコードが存在","destroyアクション","update_cache_keyが呼ばれる","中","キャッシュ更新"
"158","UT-APP-158","Reportable","included","正常系","reporting_eventsリレーションが定義されること","なし","なし","has_many :reporting_eventsが機能する","中","リレーション定義"
"159","UT-APP-159","AvailabilityStatusable","online_presence?","正常系","OnlineStatusTrackerからプレゼンス情報が取得されること","なし","なし","get_presenceの結果が返却される","中","オンライン判定"
"160","UT-APP-160","AvailabilityStatusable","online_presence?","正常系","Contactの場合idが使用されること","Contactモデル","なし","Contact.idでget_presenceが呼ばれる","中","オンライン判定"
"161","UT-APP-161","AvailabilityStatusable","availability_status","正常系","Contactでオンラインの場合onlineが返却されること","Contact, online=true","なし","onlineが返却される","中","ステータス取得"
"162","UT-APP-162","AvailabilityStatusable","availability_status","正常系","Contactでオフラインの場合offlineが返却されること","Contact, online=false","なし","offlineが返却される","中","ステータス取得"
"163","UT-APP-163","AvailabilityStatusable","availability_status","正常系","AccountUserでauto_offline=falseの場合availabilityが返却されること","AccountUser, auto_offline=false","なし","availabilityが返却される","中","ステータス取得"
"164","UT-APP-164","AvailabilityStatusable","availability_status","正常系","AccountUserでオンラインの場合Redisのステータスが返却されること","AccountUser, online=true, auto_offline=true","なし","Redisのステータスが返却される","中","ステータス取得"
"165","UT-APP-165","CacheKeys","cache_keys","正常系","cacheable_modelsの各キーが取得されること","Label, Inbox, Teamのキャッシュ存在","なし","{label: x, inbox: y, team: z}形式","中","キャッシュキー取得"
"166","UT-APP-166","CacheKeys","update_cache_key","正常系","指定キーがRedisに保存されイベントがdispatchされること","なし","key=label","Redisに保存, ACCOUNT_CACHE_INVALIDATEDイベント発行","高","キャッシュ更新"
"167","UT-APP-167","CacheKeys","reset_cache_keys","正常系","全cacheable_modelsのキーがリセットされること","なし","なし","全モデルのキーがRedisに保存される","中","キャッシュリセット"
"168","UT-APP-168","CacheKeys","CACHE_KEYS_EXPIRY","正常系","72時間のTTLでキャッシュが保存されること","なし","なし","TTL=72時間","中","キャッシュ有効期限"
"1","UT-INT-001","Integrations::App","initialize","正常系","paramsが正しく設定されること","なし","params={id: 'slack', i18n_key: 'slack'}","@paramsにパラメータが設定される","中","コンストラクタ"
"2","UT-INT-002","Integrations::App","id","正常系","params[:id]が返却されること","paramsにidが設定済み","なし","params[:id]の値が返却される","中","アクセサ"
"3","UT-INT-003","Integrations::App","name","正常系","I18n翻訳された名前が返却されること","i18nキーが存在","params={i18n_key: 'slack'}","I18n.t(""integration_apps.slack.name"")の結果","中","I18n連携"
"4","UT-INT-004","Integrations::App","name","異常系","存在しないi18nキーの場合","i18nキーが存在しない","params={i18n_key: 'invalid'}","translation missing文字列が返却される","低","I18nエラーハンドリング"
"5","UT-INT-005","Integrations::App","description","正常系","I18n翻訳された説明が返却されること","i18nキーが存在","params={i18n_key: 'slack'}","I18n.t(""integration_apps.slack.description"")の結果","中","I18n連携"
"6","UT-INT-006","Integrations::App","short_description","正常系","I18n翻訳された短い説明が返却されること","i18nキーが存在","params={i18n_key: 'slack'}","I18n.t(""integration_apps.slack.short_description"")の結果","低","I18n連携"
"7","UT-INT-007","Integrations::App","logo","正常系","params[:logo]が返却されること","paramsにlogoが設定済み","params={logo: 'slack.png'}","'slack.png'が返却される","低","アクセサ"
"8","UT-INT-008","Integrations::App","fields","正常系","params[:fields]が返却されること","paramsにfieldsが設定済み","params={fields: [...]}","fields配列が返却される","低","アクセサ"
"9","UT-INT-009","Integrations::App","encode_state","正常系","Linear用のJWTトークンが生成されること","Current.accountが設定済み、LINEAR_CLIENT_SECRETが設定済み","なし","JWTトークン文字列が返却される","高","Linear認証連携"
"10","UT-INT-010","Integrations::App","encode_state","異常系","CLIENT_SECRETが未設定の場合","LINEAR_CLIENT_SECRETが未設定","なし","nilが返却される","高","設定不足時の挙動"
"11","UT-INT-011","Integrations::App","action","正常系","Slack統合の場合、OAuth URLが構築されること","SLACK_CLIENT_IDが設定済み","params={id: 'slack', action: 'https://slack.com/oauth'}","client_idとredirect_uriを含むURLが返却される","高","Slack OAuth"
"12","UT-INT-012","Integrations::App","action","正常系","Linear統合の場合、OAuth URLが構築されること","LINEAR_CLIENT_IDが設定済み","params={id: 'linear', action: 'https://linear.app/oauth'}","build_linear_actionの結果が返却される","高","Linear OAuth"
"13","UT-INT-013","Integrations::App","action","正常系","その他の統合の場合、params[:action]がそのまま返却されること","なし","params={id: 'dialogflow', action: '/dialogflow'}","'/dialogflow'が返却される","中","デフォルトaction"
"14","UT-INT-014","Integrations::App","active?","正常系","Slack統合でSLACK_CLIENT_SECRETが設定済みの場合trueが返却されること","SLACK_CLIENT_SECRETが設定済み","account, params={id: 'slack'}","trueが返却される","高","統合有効判定"
"15","UT-INT-015","Integrations::App","active?","正常系","Slack統合でSLACK_CLIENT_SECRETが未設定の場合falseが返却されること","SLACK_CLIENT_SECRETが未設定","account, params={id: 'slack'}","falseが返却される","高","統合無効判定"
"16","UT-INT-016","Integrations::App","active?","正常系","Linear統合でfeature_enabledかつCLIENT_IDが設定済みの場合trueが返却されること","linear_integration有効、LINEAR_CLIENT_ID設定済み","account, params={id: 'linear'}","trueが返却される","高","Linear有効判定"
"17","UT-INT-017","Integrations::App","active?","正常系","Linear統合でfeature_enabledがfalseの場合falseが返却されること","linear_integration無効","account, params={id: 'linear'}","falseが返却される","高","Linear無効判定"
"18","UT-INT-018","Integrations::App","active?","正常系","Shopify統合の有効判定","shopify_integration有効、SHOPIFY_CLIENT_ID設定済み","account, params={id: 'shopify'}","trueが返却される","高","Shopify有効判定"
"19","UT-INT-019","Integrations::App","active?","正常系","Leadsquared統合でcrm_integrationが有効の場合trueが返却されること","crm_integration有効","account, params={id: 'leadsquared'}","trueが返却される","高","CRM統合判定"
"20","UT-INT-020","Integrations::App","active?","正常系","Notion統合の有効判定","notion_integration有効、NOTION_CLIENT_ID設定済み","account, params={id: 'notion'}","trueが返却される","中","Notion有効判定"
"21","UT-INT-021","Integrations::App","active?","正常系","その他の統合は常にtrueが返却されること","なし","account, params={id: 'dialogflow'}","trueが返却される","中","デフォルト有効"
"22","UT-INT-022","Integrations::App","build_linear_action","正常系","Linear OAuth URLが正しく構築されること","LINEAR_CLIENT_ID設定済み、Current.account設定済み","なし","response_type, client_id, redirect_uri, state, scope, prompt, actorを含むURL","高","Linear OAuth URL構築"
"23","UT-INT-023","Integrations::App","enabled?","正常系","webhook統合でwebhooksが存在する場合trueが返却されること","account.webhooksが存在","account, params={id: 'webhook'}","trueが返却される","中","Webhook有効判定"
"24","UT-INT-024","Integrations::App","enabled?","正常系","webhook統合でwebhooksが存在しない場合falseが返却されること","account.webhooksが空","account, params={id: 'webhook'}","falseが返却される","中","Webhook無効判定"
"25","UT-INT-025","Integrations::App","enabled?","正常系","dashboard_apps統合でdashboard_appsが存在する場合trueが返却されること","account.dashboard_appsが存在","account, params={id: 'dashboard_apps'}","trueが返却される","中","Dashboard Apps有効判定"
"26","UT-INT-026","Integrations::App","enabled?","正常系","その他の統合でhooksが存在する場合trueが返却されること","account.hooksにapp_id一致のレコードが存在","account, params={id: 'slack'}","trueが返却される","中","Hook有効判定"
"27","UT-INT-027","Integrations::App","hooks","正常系","Current.accountのhooksからapp_id一致のものが返却されること","Current.account設定済み、hooks存在","なし","app_idが一致するhooksのコレクション","中","Hooks取得"
"28","UT-INT-028","Integrations::App","self.slack_integration_url","正常系","Slack統合のリダイレクトURLが返却されること","FRONTEND_URL設定済み、Current.account設定済み","なし","{FRONTEND_URL}/app/accounts/{account_id}/settings/integrations/slack","中","Slack URL生成"
"29","UT-INT-029","Integrations::App","self.linear_integration_url","正常系","Linear統合のリダイレクトURLが返却されること","FRONTEND_URL設定済み","なし","{FRONTEND_URL}/linear/callback","中","Linear URL生成"
"30","UT-INT-030","Integrations::App","self.apps","正常系","APPS_CONFIGがHashie::Mashとして返却されること","APPS_CONFIG定義済み","なし","Hashie::Mashオブジェクト","中","設定取得"
"31","UT-INT-031","Integrations::App","self.all","正常系","全ての統合アプリがIntegrations::Appインスタンスとして返却されること","APPS_CONFIG定義済み","なし","Integrations::Appの配列","中","全アプリ取得"
"32","UT-INT-032","Integrations::App","self.find","正常系","指定IDの統合アプリが返却されること","APPS_CONFIG定義済み","params={id: 'slack'}","Slackアプリのインスタンス","中","アプリ検索"
"33","UT-INT-033","Integrations::App","self.find","境界値","存在しないIDを指定した場合nilが返却されること","APPS_CONFIG定義済み","params={id: 'nonexistent'}","nilが返却される","中","アプリ検索失敗"
"34","UT-INT-034","Integrations::Hook","belongs_to :account","正常系","accountリレーションが正しく取得できること","Hookにaccount_idが設定済み","なし","関連するAccountオブジェクトが返却される","高","リレーション"
"35","UT-INT-035","Integrations::Hook","belongs_to :inbox","正常系","inboxリレーションが正しく取得できること（inbox hookの場合）","Hookにinbox_idが設定済み、hook_type=inbox","なし","関連するInboxオブジェクトが返却される","高","リレーション"
"36","UT-INT-036","Integrations::Hook","belongs_to :inbox","正常系","inboxがnilでもエラーにならないこと（account hookの場合）","hook_type=account","なし","nilが返却される","中","オプショナルリレーション"
"37","UT-INT-037","Integrations::Hook","validates :account_id","異常系","account_idが未設定の場合バリデーションエラーになること","なし","account_id=nil","バリデーションエラー（account_id presence）","高","必須バリデーション"
"38","UT-INT-038","Integrations::Hook","validates :app_id","異常系","app_idが未設定の場合バリデーションエラーになること","なし","app_id=nil","バリデーションエラー（app_id presence）","高","必須バリデーション"
"39","UT-INT-039","Integrations::Hook","validates :inbox_id","異常系","hook_type=inboxでinbox_idが未設定の場合バリデーションエラーになること","なし","hook_type='inbox', inbox_id=nil","バリデーションエラー（inbox_id presence）","高","条件付き必須バリデーション"
"40","UT-INT-040","Integrations::Hook","validates :inbox_id","正常系","hook_type=accountでinbox_idが未設定でもエラーにならないこと","なし","hook_type='account', inbox_id=nil","バリデーション成功","中","条件付きバリデーション"
"41","UT-INT-041","Integrations::Hook","validates :app_id uniqueness","異常系","同一account_idで同一app_idのHookを作成しようとした場合エラーになること（allow_multiple_hooks=false）","既存Hookが存在","account_id=1, app_id='slack'","バリデーションエラー（app_id uniqueness）","高","一意性バリデーション"
"42","UT-INT-042","Integrations::Hook","validates :app_id uniqueness","正常系","allow_multiple_hooks=trueの場合、同一app_idで複数作成可能なこと","既存Hookが存在","account_id=1, app_id='dialogflow'","バリデーション成功","高","複数Hook許可"
"43","UT-INT-043","Integrations::Hook","validate_settings_json_schema","異常系","settingsがJSON Schemaに違反する場合エラーになること","app.params[:settings_json_schema]が定義済み","settings={invalid: 'data'}","バリデーションエラー（settings invalid）","高","JSON Schemaバリデーション"
"44","UT-INT-044","Integrations::Hook","validate_settings_json_schema","正常系","settingsがJSON Schemaに適合する場合成功すること","app.params[:settings_json_schema]が定義済み","settings={api_key: 'valid_key'}","バリデーション成功","高","JSON Schemaバリデーション"
"45","UT-INT-045","Integrations::Hook","validate_settings_json_schema","正常系","settings_json_schemaが未定義の場合スキップされること","appにsettings_json_schemaなし","settings={any: 'data'}","バリデーション成功","中","Schemaなし時のスキップ"
"46","UT-INT-046","Integrations::Hook","ensure_feature_enabled","異常系","feature_flagが無効の場合エラーになること","app.params[:feature_flag]が定義、account.feature_enabled?=false","app_id='leadsquared'","バリデーションエラー（feature not enabled）","高","機能フラグバリデーション"
"47","UT-INT-047","Integrations::Hook","ensure_feature_enabled","正常系","feature_flagが有効の場合成功すること","app.params[:feature_flag]が定義、account.feature_enabled?=true","app_id='leadsquared'","バリデーション成功","高","機能フラグバリデーション"
"48","UT-INT-048","Integrations::Hook","ensure_hook_type","正常系","app.params[:hook_type]からhook_typeが設定されること","appが存在","app_id='slack'","hook_type='account'が設定される","中","hook_type自動設定"
"49","UT-INT-049","Integrations::Hook","ensure_hook_type","正常系","inbox hookの場合hook_type=inboxが設定されること","appが存在","app_id='dialogflow'","hook_type='inbox'が設定される","中","inbox hook_type設定"
"50","UT-INT-050","Integrations::Hook","enum status","正常系","status=enabledが正しく動作すること","なし","status: :enabled","status='enabled'として保存される","中","enumステータス"
"51","UT-INT-051","Integrations::Hook","enum status","正常系","status=disabledが正しく動作すること","なし","status: :disabled","status='disabled'として保存される","中","enumステータス"
"52","UT-INT-052","Integrations::Hook","enum hook_type","正常系","hook_type=accountが正しく動作すること","なし","hook_type: :account","hook_type='account'として保存される","中","enum hook_type"
"53","UT-INT-053","Integrations::Hook","enum hook_type","正常系","hook_type=inboxが正しく動作すること","なし","hook_type: :inbox","hook_type='inbox'として保存される","中","enum hook_type"
"54","UT-INT-054","Integrations::Hook","scope :account_hooks","正常系","hook_type=accountのレコードのみ返却されること","account/inbox両方のhookが存在","なし","hook_type='account'のレコードのみ","中","スコープ"
"55","UT-INT-055","Integrations::Hook","scope :inbox_hooks","正常系","hook_type=inboxのレコードのみ返却されること","account/inbox両方のhookが存在","なし","hook_type='inbox'のレコードのみ","中","スコープ"
"56","UT-INT-056","Integrations::Hook","app","正常系","関連するIntegrations::Appが返却されること","app_id='slack'","なし","Slackアプリのインスタンス","中","アプリ取得"
"57","UT-INT-057","Integrations::Hook","app","境界値","存在しないapp_idの場合nilが返却されること","app_id='nonexistent'","なし","nilが返却される","中","存在しないアプリ"
"58","UT-INT-058","Integrations::Hook","slack?","正常系","app_id='slack'の場合trueが返却されること","app_id='slack'","なし","trueが返却される","中","Slack判定"
"59","UT-INT-059","Integrations::Hook","slack?","正常系","app_id!='slack'の場合falseが返却されること","app_id='dialogflow'","なし","falseが返却される","中","Slack判定"
"60","UT-INT-060","Integrations::Hook","dialogflow?","正常系","app_id='dialogflow'の場合trueが返却されること","app_id='dialogflow'","なし","trueが返却される","中","Dialogflow判定"
"61","UT-INT-061","Integrations::Hook","dialogflow?","正常系","app_id!='dialogflow'の場合falseが返却されること","app_id='slack'","なし","falseが返却される","中","Dialogflow判定"
"62","UT-INT-062","Integrations::Hook","notion?","正常系","app_id='notion'の場合trueが返却されること","app_id='notion'","なし","trueが返却される","中","Notion判定"
"63","UT-INT-063","Integrations::Hook","notion?","正常系","app_id!='notion'の場合falseが返却されること","app_id='slack'","なし","falseが返却される","中","Notion判定"
"64","UT-INT-064","Integrations::Hook","disable","正常系","statusがdisabledに更新されること","status='enabled'","なし","status='disabled'に更新される","中","無効化処理"
"65","UT-INT-065","Integrations::Hook","process_event","正常系","エラーメッセージが返却されること","なし","event=任意","{error: 'No processor found'}が返却される","低","イベント処理（現在未実装）"
"66","UT-INT-066","Integrations::Hook","feature_allowed?","正常系","appがnilの場合trueが返却されること","app=nil","なし","trueが返却される","中","機能許可判定"
"67","UT-INT-067","Integrations::Hook","feature_allowed?","正常系","feature_flagがnilの場合trueが返却されること","app.params[:feature_flag]=nil","なし","trueが返却される","中","機能許可判定"
"68","UT-INT-068","Integrations::Hook","feature_allowed?","正常系","feature_enabled?がtrueの場合trueが返却されること","feature_flag設定済み、feature_enabled?=true","なし","trueが返却される","中","機能許可判定"
"69","UT-INT-069","Integrations::Hook","feature_allowed?","正常系","feature_enabled?がfalseの場合falseが返却されること","feature_flag設定済み、feature_enabled?=false","なし","falseが返却される","中","機能許可判定"
"70","UT-INT-070","Integrations::Hook","trigger_setup_if_crm","正常系","leadsquaredの場合Crm::SetupJobがキューに追加されること","app_id='leadsquared'","なし","Crm::SetupJob.perform_laterが呼び出される","高","CRMセットアップ"
"71","UT-INT-071","Integrations::Hook","trigger_setup_if_crm","正常系","leadsquared以外の場合Jobがキューに追加されないこと","app_id='slack'","なし","Crm::SetupJob.perform_laterが呼び出されない","中","CRMセットアップスキップ"
"72","UT-INT-072","Integrations::Hook","crm_integration?","正常系","app_id='leadsquared'の場合trueが返却されること","app_id='leadsquared'","なし","trueが返却される","中","CRM統合判定"
"73","UT-INT-073","Integrations::Hook","crm_integration?","正常系","その他のapp_idの場合falseが返却されること","app_id='slack'","なし","falseが返却される","中","CRM統合判定"
"74","UT-INT-074","Integrations::Hook","has_secure_token :access_token","正常系","access_tokenが自動生成されること","新規Hook作成","なし","access_tokenが自動生成される","高","セキュアトークン"
"75","UT-INT-075","Integrations::Hook","encrypts :access_token","正常系","access_tokenが暗号化されて保存されること","Chatwoot.encryption_configured?=true","なし","暗号化された状態でDBに保存される","高","暗号化"
"76","UT-INT-076","Integrations::Hook","attr_readonly","正常系","app_id, account_id, inbox_id, hook_typeが更新不可であること","既存Hook","app_id='new_value'を設定して保存","値が変更されない","高","読み取り専用属性"
"77","UT-INT-077","Integrations::Hook（Reauthorizable）","reauthorization_required?","正常系","Redis keyが存在する場合trueが返却されること","Redisにreauthorization_required_key設定済み","なし","trueが返却される","高","再認証要否判定"
"78","UT-INT-078","Integrations::Hook（Reauthorizable）","reauthorization_required?","正常系","Redis keyが存在しない場合falseが返却されること","Redisにreauthorization_required_keyなし","なし","falseが返却される","高","再認証要否判定"
"79","UT-INT-079","Integrations::Hook（Reauthorizable）","authorization_error_count","正常系","エラーカウントが正しく取得されること","Redisにauthorization_error_count_key=3","なし","3が返却される","中","エラーカウント取得"
"80","UT-INT-080","Integrations::Hook（Reauthorizable）","authorization_error_count","境界値","キーが存在しない場合0が返却されること","Redisにキーなし","なし","0が返却される","中","エラーカウント初期値"
"81","UT-INT-081","Integrations::Hook（Reauthorizable）","authorization_error!","正常系","エラーカウントがインクリメントされること","authorization_error_count=0","なし","authorization_error_count=1","高","エラーカウント増加"
"82","UT-INT-082","Integrations::Hook（Reauthorizable）","authorization_error!","正常系","閾値到達時にprompt_reauthorization!が呼び出されること","authorization_error_count=1","なし","reauthorization_required?=trueになる","高","閾値到達時の再認証要求"
"83","UT-INT-083","Integrations::Hook（Reauthorizable）","prompt_reauthorization!","正常系","Redisにreauthorization_required_keyが設定されること","なし","なし","reauthorization_required?=true","高","再認証要求フラグ設定"
"84","UT-INT-084","Integrations::Hook（Reauthorizable）","prompt_reauthorization!","正常系","Slackの場合slack_disconnectメールが送信されること","app_id='slack'","なし","slack_disconnectメールがキューに追加される","高","Slack切断通知"
"85","UT-INT-085","Integrations::Hook（Reauthorizable）","prompt_reauthorization!","正常系","Dialogflowの場合dialogflow_disconnectメールが送信されること","app_id='dialogflow'","なし","dialogflow_disconnectメールがキューに追加される","高","Dialogflow切断通知"
"86","UT-INT-086","Integrations::Hook（Reauthorizable）","reauthorized!","正常系","authorization_error_countがクリアされること","authorization_error_count=2","なし","authorization_error_count=0","高","再認証成功後のクリア"
"87","UT-INT-087","Integrations::Hook（Reauthorizable）","reauthorized!","正常系","reauthorization_required?がfalseになること","reauthorization_required?=true","なし","reauthorization_required?=false","高","再認証成功後のフラグクリア"
"1","UT-APP-001","Account","agents","正常系","エージェントロールのユーザーが取得できること","アカウントに複数のユーザーが存在","なし","agentロールのユーザーのみが返却される","高","リレーション経由のフィルタリング"
"2","UT-APP-002","Account","administrators","正常系","管理者ロールのユーザーが取得できること","アカウントに複数のユーザーが存在","なし","administratorロールのユーザーのみが返却される","高","リレーション経由のフィルタリング"
"3","UT-APP-003","Account","all_conversation_tags","正常系","全会話のタグが取得できること","複数の会話にラベルが付与されている","なし","全ラベル名の配列が返却される","中","ActsAsTaggableOn使用"
"4","UT-APP-004","Account","all_conversation_tags","境界値","会話が存在しない場合に空配列が返ること","会話が0件","なし","空の配列が返却される","中",""
"5","UT-APP-005","Account","webhook_data","正常系","Webhook用データが正しく生成されること","アカウントが存在","なし","id, nameを含むハッシュが返却される","中","外部連携用データ生成"
"6","UT-APP-006","Account","inbound_email_domain","正常系","ドメインが設定されている場合にドメインが返ること","domain属性が設定済み","domain='example.com'","'example.com'が返却される","中","メール受信設定"
"7","UT-APP-007","Account","inbound_email_domain","異常系","ドメイン未設定時にGlobalConfigから取得すること","domain属性が未設定","domain=nil","GlobalConfigの値が返却される","中","フォールバック処理"
"8","UT-APP-008","Account","support_email","正常系","サポートメールが設定されている場合にその値が返ること","support_email属性が設定済み","support_email='test@example.com'","'test@example.com'が返却される","中","メール送信設定"
"9","UT-APP-009","Account","support_email","異常系","サポートメール未設定時に環境変数から取得すること","support_email属性が未設定","support_email=nil","ENV['MAILER_SENDER_EMAIL']の値が返却される","中","フォールバック処理"
"10","UT-APP-010","Account","usage_limits","正常系","使用制限が正しく返却されること","なし","なし","agents, inboxesキーを含むハッシュが返却される","中","プラン制限管理"
"11","UT-APP-011","Account","locale_english_name","正常系","ロケールの英語名が返却されること","locale='ja'","なし","'japanese'が返却される","低","ISO_639使用"
"12","UT-APP-012","Account","locale_english_name","異常系","ロケール未設定時に'english'が返ること","locale=nil","なし","'english'が返却される","低","デフォルト値"
"13","UT-APP-013","Account","validate_limit_keys","正常系","バリデーションが正常に通過すること","有効なlimit設定","なし","エラーなし","中","Enterpriseでオーバーライド"
"14","UT-APP-014","Account","remove_account_sequences","正常系","シーケンスが削除されること","アカウント削除時","なし","conv_dpid_seq, camp_dpid_seqが削除される","高","クリーンアップ処理"
"15","UT-APP-015","Account","name validation","異常系","名前が空の場合にバリデーションエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"16","UT-APP-016","Account","domain validation","境界値","ドメインが100文字を超える場合にエラーになること","なし","domain='a'*101","length: maximumエラー","中","長さ制限"
"17","UT-APP-017","Account","settings validation","異常系","不正なsettingsスキーマの場合にエラーになること","なし","settings={invalid: 'data'}","JsonSchemaValidatorエラー","中","JSONスキーマ検証"
"18","UT-APP-018","User","send_devise_notification","正常系","Devise通知が送信されること","ユーザーが存在","notification=:confirmation_instructions","通知が非同期で送信される","高","認証通知"
"19","UT-APP-019","User","set_password_and_uid","正常系","UID がemailに設定されること","新規ユーザー作成時","email='test@example.com'","uid='test@example.com'になる","高","ユーザー初期化"
"20","UT-APP-020","User","assigned_inboxes","正常系","管理者の場合に全inboxが返ること","管理者ユーザー","なし","Current.accountの全inboxが返却される","高","権限による分岐"
"21","UT-APP-021","User","assigned_inboxes","正常系","エージェントの場合に割当inboxのみ返ること","エージェントユーザー","なし","ユーザーに割当されたinboxのみ返却される","高","権限による分岐"
"22","UT-APP-022","User","serializable_hash","正常系","confirmed属性が含まれること","ユーザーが存在","なし","confirmed: trueまたはfalseが含まれる","中","シリアライズ拡張"
"23","UT-APP-023","User","push_event_data","正常系","プッシュイベント用データが生成されること","ユーザーが存在","なし","id, name, avatar_url等を含むハッシュが返却される","中","WebSocket用データ"
"24","UT-APP-024","User","webhook_data","正常系","Webhook用データが生成されること","ユーザーが存在","なし","id, name, email, typeを含むハッシュが返却される","中","外部連携用データ"
"25","UT-APP-025","User","will_save_change_to_email?","正常系","メール変更時にtrueが返ること","email変更あり","email='new@example.com'","trueが返却される","中","メール再確認フロー"
"26","UT-APP-026","User","from_email","正常系","メールアドレスでユーザーが検索できること","ユーザーが存在","email='test@example.com'","該当ユーザーが返却される","中","クラスメソッド"
"27","UT-APP-027","User","from_email","異常系","存在しないメールでnilが返ること","該当ユーザーなし","email='notfound@example.com'","nilが返却される","中","該当なしケース"
"28","UT-APP-028","User","mfa_service","正常系","MfaManagementServiceインスタンスが返ること","ユーザーが存在","なし","Mfa::ManagementServiceインスタンスが返却される","中","2FA管理"
"29","UT-APP-029","User","mfa_enabled?","正常系","2FA有効時にtrueが返ること","otp_required_for_login=true","なし","trueが返却される","高","セキュリティ機能"
"30","UT-APP-030","User","mfa_feature_available?","正常系","MFA機能が利用可能かどうかが返ること","なし","なし","Chatwoot.mfa_enabled?の値が返却される","中","機能フラグ確認"
"31","UT-APP-031","User","remove_macros","正常系","ユーザー削除時に個人マクロが削除されること","ユーザーが個人マクロを持つ","なし","personalマクロのみ削除される","高","クリーンアップ"
"32","UT-APP-032","User","email validation","異常系","メールが空の場合にエラーになること","なし","email=''","presence: trueエラー","高","必須項目"
"33","UT-APP-033","Conversation","can_reply?","正常系","返信可能な場合にtrueが返ること","会話ウィンドウが有効","なし","trueが返却される","高","メッセージ送信判定"
"34","UT-APP-034","Conversation","can_reply?","異常系","返信不可の場合にfalseが返ること","会話ウィンドウが無効","なし","falseが返却される","高","24時間ルール等"
"35","UT-APP-035","Conversation","language","正常系","会話言語が取得できること","additional_attributesに言語設定あり","additional_attributes={'conversation_language': 'ja'}","'ja'が返却される","中","多言語対応"
"36","UT-APP-036","Conversation","language","異常系","言語設定がない場合にnilが返ること","additional_attributes={}","なし","nilが返却される","中","デフォルト値"
"37","UT-APP-037","Conversation","last_activity_at","正常系","最終活動時刻が返却されること","last_activity_atが設定済み","なし","設定された時刻が返却される","中","タイムスタンプ"
"38","UT-APP-038","Conversation","last_activity_at","異常系","未設定の場合にcreated_atが返ること","last_activity_at=nil","なし","created_atが返却される","中","フォールバック"
"39","UT-APP-039","Conversation","last_incoming_message","正常系","最後の受信メッセージが取得できること","複数メッセージが存在","なし","最新のincomingメッセージが返却される","中","メッセージ検索"
"40","UT-APP-040","Conversation","toggle_status","正常系","openからresolvedに変更できること","status=open","なし","status=resolvedになる","高","ステータス遷移"
"41","UT-APP-041","Conversation","toggle_status","正常系","resolvedからopenに変更できること","status=resolved","なし","status=openになる","高","ステータス遷移"
"42","UT-APP-042","Conversation","toggle_status","正常系","pendingからopenに変更できること","status=pending","なし","status=openになる","高","ステータス遷移"
"43","UT-APP-043","Conversation","toggle_status","正常系","snoozedからopenに変更できること","status=snoozed","なし","status=openになる","高","ステータス遷移"
"44","UT-APP-044","Conversation","toggle_priority","正常系","優先度が設定できること","なし","priority='high'","priority=highになる","中","優先度管理"
"45","UT-APP-045","Conversation","toggle_priority","正常系","優先度をクリアできること","priority=high","priority=nil","priority=nilになる","中","優先度リセット"
"46","UT-APP-046","Conversation","bot_handoff!","正常系","Bot引き継ぎ処理が実行されること","status=pending","なし","status=open, イベント発火","高","Bot連携"
"47","UT-APP-047","Conversation","unread_messages","正常系","未読メッセージが取得できること","agent_last_seen_at設定済み","なし","agent_last_seen_at以降のメッセージが返却される","中","未読管理"
"48","UT-APP-048","Conversation","unread_messages","境界値","agent_last_seen_at未設定時に全メッセージが返ること","agent_last_seen_at=nil","なし","全メッセージが返却される","中","フォールバック"
"49","UT-APP-049","Conversation","assignee_unread_messages","正常系","担当者未読メッセージが取得できること","assignee_last_seen_at設定済み","なし","assignee_last_seen_at以降のメッセージが返却される","中","担当者用未読"
"50","UT-APP-050","Conversation","unread_incoming_messages","正常系","未読受信メッセージ（最大10件）が取得できること","複数の未読メッセージが存在","なし","最大10件のincomingメッセージが返却される","中","通知用"
"51","UT-APP-051","Conversation","cached_label_list_array","正常系","キャッシュされたラベルが配列で取得できること","cached_label_list='tag1,tag2'","なし","['tag1', 'tag2']が返却される","中","タグ管理"
"52","UT-APP-052","Conversation","cached_label_list_array","境界値","cached_label_list=nilの場合に空配列が返ること","cached_label_list=nil","なし","空配列が返却される","中","nilハンドリング"
"53","UT-APP-053","Conversation","notifiable_assignee_change?","正常系","担当者変更通知が必要な場合にtrueが返ること","assignee_idが変更され自己アサインでない","なし","trueが返却される","中","通知判定"
"54","UT-APP-054","Conversation","notifiable_assignee_change?","異常系","自己アサインの場合にfalseが返ること","assignee_id変更が自己アサイン","なし","falseが返却される","中","自己アサイン除外"
"55","UT-APP-055","Conversation","assignee_type","正常系","AgentBot割当時に'AgentBot'が返ること","assignee_agent_bot_id設定済み","なし","'AgentBot'が返却される","中","ポリモーフィック対応"
"56","UT-APP-056","Conversation","assignee_type","正常系","User割当時に'User'が返ること","assignee_id設定済み","なし","'User'が返却される","中","ポリモーフィック対応"
"57","UT-APP-057","Conversation","assignee_type","異常系","未割当時にnilが返ること","両方nil","なし","nilが返却される","中","未割当ケース"
"58","UT-APP-058","Conversation","assigned_entity","正常系","割当エンティティが取得できること","assignee設定済み","なし","assignee_agent_botまたはassigneeが返却される","中","担当者取得"
"59","UT-APP-059","Conversation","tweet?","正常系","Twitter会話でtype=tweetの場合にtrueが返ること","inbox_type='Twitter', type='tweet'","なし","trueが返却される","中","チャネル判定"
"60","UT-APP-060","Conversation","recent_messages","正常系","直近5件のチャットメッセージが取得できること","10件のメッセージが存在","なし","最新5件のchatメッセージが返却される","中","サマリー用"
"61","UT-APP-061","Conversation","csat_survey_link","正常系","CSATアンケートリンクが生成されること","会話にuuidが設定済み","なし","FRONTEND_URL/survey/responses/{uuid}形式のURLが返却される","中","顧客満足度調査"
"62","UT-APP-062","Conversation","dispatch_conversation_updated_event","正常系","会話更新イベントが発火すること","会話が存在","previous_changes={}","CONVERSATION_UPDATEDイベントが発火される","中","イベント通知"
"63","UT-APP-063","Conversation","validate_additional_attributes","正常系","additional_attributesがHashでない場合に空ハッシュになること","additional_attributes='string'","なし","additional_attributes={}になる","中","データ正規化"
"64","UT-APP-064","Conversation","reset_agent_bot_when_assignee_present","正常系","assignee_id設定時にassignee_agent_bot_idがクリアされること","assignee_agent_bot_id設定済み","assignee_id=1","assignee_agent_bot_id=nilになる","中","排他制御"
"65","UT-APP-065","Conversation","determine_conversation_status","正常系","contact.blocked?時にresolvedになること","連絡先がブロック済み","なし","status=resolvedになる","高","ブロック対応"
"66","UT-APP-066","Conversation","determine_conversation_status","正常系","active_bot時にpendingになること","inbox.active_bot?=true","なし","status=pendingになる","高","Bot連携"
"67","UT-APP-067","Conversation","ensure_snooze_until_reset","正常系","snoozed以外の場合にsnoozed_untilがクリアされること","status=open","なし","snoozed_until=nilになる","中","スヌーズリセット"
"68","UT-APP-068","Conversation","validate_referer_url","異常系","不正なreferer URLがクリアされること","referer='invalid-url'","なし","referer=nilになる","中","URL検証"
"69","UT-APP-069","Conversation","account_id validation","異常系","account_idが空の場合にエラーになること","なし","account_id=nil","presence: trueエラー","高","必須項目"
"70","UT-APP-070","Conversation","inbox_id validation","異常系","inbox_idが空の場合にエラーになること","なし","inbox_id=nil","presence: trueエラー","高","必須項目"
"71","UT-APP-071","Conversation","contact_id validation","異常系","contact_idが空の場合にエラーになること","なし","contact_id=nil","presence: trueエラー","高","必須項目"
"72","UT-APP-072","Conversation","uuid validation","異常系","uuidが重複する場合にエラーになること","同一uuidの会話が存在","uuid='existing-uuid'","uniqueness: trueエラー","高","一意制約"
"73","UT-APP-073","Message","channel_token","正常系","チャネルトークンが取得できること","inbox.channelにpage_access_tokenが設定済み","なし","トークンが返却される","中","外部API連携"
"74","UT-APP-074","Message","push_event_data","正常系","プッシュイベント用データが生成されること","メッセージが存在","なし","必要な属性を含むハッシュが返却される","高","WebSocket用データ"
"75","UT-APP-075","Message","push_event_data","正常系","echo_id設定時にデータに含まれること","echo_idが設定済み","echo_id='temp-123'","echo_id属性が含まれる","中","フロントエンド同期"
"76","UT-APP-076","Message","push_event_data","正常系","添付ファイルがある場合にデータに含まれること","attachmentsが存在","なし","attachments配列が含まれる","中","ファイル添付"
"77","UT-APP-077","Message","conversation_push_event_data","正常系","会話プッシュデータが生成されること","会話に紐づくメッセージ","なし","assignee_id, unread_count等を含むハッシュが返却される","中","会話情報付加"
"78","UT-APP-078","Message","merge_sender_attributes","正常系","User送信者の場合にsender情報が含まれること","sender=User","なし","sender属性にpush_event_dataが含まれる","中","送信者情報"
"79","UT-APP-079","Message","merge_sender_attributes","正常系","AgentBot送信者の場合にinbox付きでデータ生成されること","sender=AgentBot","なし","sender属性にinbox付きpush_event_dataが含まれる","中","Bot送信者"
"80","UT-APP-080","Message","webhook_data","正常系","Webhook用データが生成されること","メッセージが存在","なし","account, content, conversation等を含むハッシュが返却される","高","外部連携"
"81","UT-APP-081","Message","outgoing_content","正常系","送信用コンテンツが取得できること","メッセージが存在","なし","MessageContentPresenterの結果が返却される","中","外部送信用"
"82","UT-APP-082","Message","email_notifiable_message?","正常系","メール通知可能なメッセージでtrueが返ること","outgoing, private=false","なし","trueが返却される","中","通知判定"
"83","UT-APP-083","Message","email_notifiable_message?","異常系","private=trueの場合にfalseが返ること","private=true","なし","falseが返却される","中","プライベート除外"
"84","UT-APP-084","Message","email_notifiable_message?","異常系","incomingの場合にfalseが返ること","message_type=incoming","なし","falseが返却される","中","受信除外"
"85","UT-APP-085","Message","auto_reply_email?","正常系","自動返信メールの場合にtrueが返ること","content_attributes={email: {auto_reply: true}}","なし","trueが返却される","中","自動返信判定"
"86","UT-APP-086","Message","valid_first_reply?","正常系","有効な初回返信の場合にtrueが返ること","human_response, first_reply_created_at=nil","なし","trueが返却される","高","初回返信判定"
"87","UT-APP-087","Message","valid_first_reply?","異常系","private=trueの場合にfalseが返ること","private=true","なし","falseが返却される","高","プライベート除外"
"88","UT-APP-088","Message","valid_first_reply?","異常系","既に初回返信がある場合にfalseが返ること","first_reply_created_at設定済み","なし","falseが返却される","高","重複防止"
"89","UT-APP-089","Message","save_story_info","正常系","Instagram Story情報が保存されること","Instagramメッセージ","story_info={id: '123', url: 'https://...'}","content_attributesにstory情報が追加される","中","Instagram連携"
"90","UT-APP-090","Message","send_update_event","正常系","更新イベントが発火すること","メッセージが存在","なし","MESSAGE_UPDATEDイベントが発火される","中","リアルタイム更新"
"91","UT-APP-091","Message","should_index?","正常系","インデックス対象の場合にtrueが返ること","advanced_search有効, incoming/outgoing","なし","trueが返却される","中","検索インデックス"
"92","UT-APP-092","Message","should_index?","異常系","activityメッセージの場合にfalseが返ること","message_type=activity","なし","falseが返却される","中","検索除外"
"93","UT-APP-093","Message","search_data","正常系","検索用データが生成されること","メッセージが存在","なし","SearchDataPresenterの結果が返却される","中","Elasticsearch連携"
"94","UT-APP-094","Message","content_for_llm","正常系","contentがある場合にcontentが返ること","content='Hello'","なし","'Hello'が返却される","中","LLM連携"
"95","UT-APP-095","Message","content_for_llm","正常系","音声添付ファイルの場合に文字起こしが返ること","content=nil, 音声添付あり","なし","'[Voice Message] 文字起こし'が返却される","中","音声文字起こし"
"96","UT-APP-096","Message","content_for_llm","正常系","その他の添付ファイルの場合に[Attachment]が返ること","content=nil, ファイル添付あり","なし","'[Attachment]'が返却される","中","添付プレースホルダー"
"97","UT-APP-097","Message","prevent_message_flooding","異常系","1分間に制限数以上のメッセージでエラーになること","1分間に大量メッセージ送信","なし","'Too many messages'エラー","高","DoS防止"
"98","UT-APP-098","Message","ensure_processed_message_content","正常系","処理済みコンテンツが設定されること","メッセージ保存時","content='test'","processed_message_contentが設定される","中","コンテンツ処理"
"99","UT-APP-099","Message","ensure_content_type","正常系","content_type未設定時にtextが設定されること","content_type=nil","なし","content_type=textになる","中","デフォルト値"
"100","UT-APP-100","Message","validate_attachments_limit","異常系","添付ファイルが15件を超える場合にエラーになること","既に15件の添付ファイル","新規添付追加","'exceeded maximum allowed'エラー","高","添付制限"
"101","UT-APP-101","Message","account_id validation","異常系","account_idが空の場合にエラーになること","なし","account_id=nil","presence: trueエラー","高","必須項目"
"102","UT-APP-102","Message","content validation","境界値","contentが150000文字を超える場合にエラーになること","なし","content='a'*150001","length: maximumエラー","中","長さ制限"
"103","UT-APP-103","Contact","get_source_id","正常系","source_idが取得できること","contact_inboxが存在","inbox_id=1","source_idが返却される","中","識別子取得"
"104","UT-APP-104","Contact","get_source_id","異常系","contact_inboxが存在しない場合に例外が発生すること","contact_inbox未存在","inbox_id=999","RecordNotFound例外","中","エラーハンドリング"
"105","UT-APP-105","Contact","push_event_data","正常系","プッシュイベント用データが生成されること","連絡先が存在","なし","additional_attributes, email等を含むハッシュが返却される","中","WebSocket用"
"106","UT-APP-106","Contact","webhook_data","正常系","Webhook用データが生成されること","連絡先が存在","なし","account, email, phone_number等を含むハッシュが返却される","中","外部連携"
"107","UT-APP-107","Contact","resolved_contacts","正常系","識別情報を持つ連絡先が取得できること","email, phone_number, identifierいずれか設定","なし","識別情報を持つ連絡先のみ返却される","中","クラスメソッド"
"108","UT-APP-108","Contact","discard_invalid_attrs","正常系","不正な電話番号がリセットされること","不正な電話番号形式","phone_number='invalid'","phone_number_wasにリセットされる","中","データ検証"
"109","UT-APP-109","Contact","discard_invalid_attrs","正常系","不正なメールがリセットされること","不正なメール形式","email='invalid'","email_wasにリセットされる","中","データ検証"
"110","UT-APP-110","Contact","from_email","正常系","メールアドレスで連絡先が検索できること","連絡先が存在","email='test@example.com'","該当連絡先が返却される","中","クラスメソッド"
"111","UT-APP-111","Contact","prepare_email_attribute","正常系","メールが小文字に変換されること","email='TEST@EXAMPLE.COM'","なし","email='test@example.com'になる","中","正規化"
"112","UT-APP-112","Contact","prepare_email_attribute","正常系","空メールがnilに変換されること","email=''","なし","email=nilになる","中","正規化"
"113","UT-APP-113","Contact","prepare_jsonb_attributes","正常系","空のJSONB属性が空ハッシュに初期化されること","additional_attributes=nil","なし","additional_attributes={}になる","中","初期化"
"114","UT-APP-114","Contact","email validation","異常系","不正なメール形式でエラーになること","なし","email='invalid-email'","format: withエラー","高","形式検証"
"115","UT-APP-115","Contact","email validation","異常系","同一アカウントで重複メールでエラーになること","同一メールの連絡先が存在","email='existing@example.com'","uniquenessエラー","高","一意制約"
"116","UT-APP-116","Contact","phone_number validation","異常系","不正な電話番号形式でエラーになること","なし","phone_number='123'","format: withエラー","高","形式検証"
"117","UT-APP-117","Contact","phone_number validation","正常系","E.164形式の電話番号が受け入れられること","なし","phone_number='+81901234567'","バリデーション成功","高","国際形式"
"118","UT-APP-118","Contact","identifier validation","異常系","同一アカウントで重複identifierでエラーになること","同一identifierの連絡先が存在","identifier='existing'","uniquenessエラー","高","一意制約"
"119","UT-APP-119","Inbox","add_members","正常系","複数メンバーが追加できること","inboxが存在","user_ids=[1, 2, 3]","3件のinbox_memberが作成される","高","メンバー管理"
"120","UT-APP-120","Inbox","remove_members","正常系","複数メンバーが削除できること","メンバーが存在","user_ids=[1, 2]","2件のinbox_memberが削除される","高","メンバー管理"
"121","UT-APP-121","Inbox","sanitized_name","正常系","名前が正しくサニタイズされること","name='Test <Inbox>'","なし","'Test Inbox'が返却される","中","メール互換性"
"122","UT-APP-122","Inbox","sanitized_name","境界値","空の名前の場合の処理","name=''","なし","デフォルト名または空文字が返却される","中","エッジケース"
"123","UT-APP-123","Inbox","sms?","正常系","SMSチャネルの場合にtrueが返ること","channel_type='Channel::Sms'","なし","trueが返却される","低","チャネル判定"
"124","UT-APP-124","Inbox","facebook?","正常系","Facebookチャネルの場合にtrueが返ること","channel_type='Channel::FacebookPage'","なし","trueが返却される","低","チャネル判定"
"125","UT-APP-125","Inbox","instagram?","正常系","Instagramチャネルの場合にtrueが返ること","channel.instagram_id設定済み","なし","trueが返却される","低","チャネル判定"
"126","UT-APP-126","Inbox","web_widget?","正常系","WebWidgetチャネルの場合にtrueが返ること","channel_type='Channel::WebWidget'","なし","trueが返却される","低","チャネル判定"
"127","UT-APP-127","Inbox","api?","正常系","APIチャネルの場合にtrueが返ること","channel_type='Channel::Api'","なし","trueが返却される","低","チャネル判定"
"128","UT-APP-128","Inbox","email?","正常系","Emailチャネルの場合にtrueが返ること","channel_type='Channel::Email'","なし","trueが返却される","低","チャネル判定"
"129","UT-APP-129","Inbox","twilio?","正常系","Twilioチャネルの場合にtrueが返ること","channel_type='Channel::TwilioSms'","なし","trueが返却される","低","チャネル判定"
"130","UT-APP-130","Inbox","whatsapp?","正常系","WhatsAppチャネルの場合にtrueが返ること","channel_type='Channel::Whatsapp'","なし","trueが返却される","低","チャネル判定"
"131","UT-APP-131","Inbox","assignable_agents","正常系","割当可能なエージェントが取得できること","メンバーと管理者が存在","なし","メンバー+管理者のユニークリストが返却される","高","担当者割当"
"132","UT-APP-132","Inbox","active_bot?","正常系","Bot有効時にtrueが返ること","agent_bot_inbox.active=true","なし","trueが返却される","高","Bot連携"
"133","UT-APP-133","Inbox","active_bot?","正常系","Dialogflowフック有効時にtrueが返ること","dialogflowフックがenabled","なし","trueが返却される","高","Bot連携"
"134","UT-APP-134","Inbox","inbox_type","正常系","チャネル名が返ること","channel設定済み","なし","channel.nameが返却される","低","表示用"
"135","UT-APP-135","Inbox","webhook_data","正常系","Webhook用データが生成されること","inboxが存在","なし","id, nameを含むハッシュが返却される","中","外部連携"
"136","UT-APP-136","Inbox","callback_webhook_url","正常系","TwilioSMSのコールバックURLが生成されること","channel_type='Channel::TwilioSms'","なし","/twilio/callback URLが返却される","中","Webhook設定"
"137","UT-APP-137","Inbox","callback_webhook_url","正常系","WhatsAppのコールバックURLが生成されること","channel_type='Channel::Whatsapp'","なし","/webhooks/whatsapp/{phone} URLが返却される","中","Webhook設定"
"138","UT-APP-138","Inbox","member_ids_with_assignment_capacity","正常系","メンバーIDが取得できること","メンバーが存在","なし","メンバーIDの配列が返却される","中","自動割当"
"139","UT-APP-139","Inbox","auto_assignment_v2_enabled?","正常系","assignment_v2機能有効時にtrueが返ること","feature_enabled?('assignment_v2')=true","なし","trueが返却される","中","機能フラグ"
"140","UT-APP-140","Inbox","name validation","異常系","名前が空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"141","UT-APP-141","Inbox","timezone validation","異常系","不正なタイムゾーンでエラーになること","なし","timezone='Invalid/Zone'","inclusionエラー","中","タイムゾーン検証"
"142","UT-APP-142","Team","add_members","正常系","複数メンバーが追加できること","チームが存在","user_ids=[1, 2, 3]","3件のteam_memberが作成される","高","メンバー管理"
"143","UT-APP-143","Team","add_members","正常系","追加されたユーザーが返却されること","チームが存在","user_ids=[1, 2]","追加されたUserの配列が返却される","中","戻り値確認"
"144","UT-APP-144","Team","remove_members","正常系","複数メンバーが削除できること","メンバーが存在","user_ids=[1, 2]","2件のteam_memberが削除される","高","メンバー管理"
"145","UT-APP-145","Team","messages","正常系","チームの会話に紐づくメッセージが取得できること","チームに会話が存在","なし","該当会話のメッセージが返却される","中","メッセージ集計"
"146","UT-APP-146","Team","reporting_events","正常系","チームの会話に紐づくイベントが取得できること","チームに会話が存在","なし","該当会話のreporting_eventsが返却される","中","レポート用"
"147","UT-APP-147","Team","push_event_data","正常系","プッシュイベント用データが生成されること","チームが存在","なし","id, nameを含むハッシュが返却される","中","WebSocket用"
"148","UT-APP-148","Team","name validation","異常系","名前が空の場合にエラーになること","なし","name=''","presenceエラー","高","必須項目"
"149","UT-APP-149","Team","name validation","異常系","同一アカウントで重複名でエラーになること","同一名のチームが存在","name='existing'","uniquenessエラー","高","一意制約"
"150","UT-APP-150","Team","name before_validation","正常系","名前が小文字に変換されること","name='TEST TEAM'","なし","name='test team'になる","中","正規化"
"151","UT-APP-151","AgentBot","accessible_to","正常系","アカウントに紐づくBotとシステムBotが取得できること","account_id=1のBotとaccount_id=nilのBotが存在","account_id=1","両方のBotが返却される","中","スコープ"
"152","UT-APP-152","AgentBot","available_name","正常系","Bot名が返却されること","name='TestBot'","なし","'TestBot'が返却される","低","表示用"
"153","UT-APP-153","AgentBot","push_event_data","正常系","プッシュイベント用データが生成されること","Botが存在","なし","id, name, avatar_url, typeを含むハッシュが返却される","中","WebSocket用"
"154","UT-APP-154","AgentBot","push_event_data","正常系","inbox指定時にavatar_urlがフォールバックすること","Bot.avatar_url=nil, inbox.avatar_url設定済み","inbox=inbox","inbox.avatar_urlが含まれる","中","アバター取得"
"155","UT-APP-155","AgentBot","webhook_data","正常系","Webhook用データが生成されること","Botが存在","なし","id, name, typeを含むハッシュが返却される","中","外部連携"
"156","UT-APP-156","AgentBot","system_bot?","正常系","システムBotの場合にtrueが返ること","account_id=nil","なし","trueが返却される","中","システムBot判定"
"157","UT-APP-157","AgentBot","system_bot?","正常系","アカウントBot の場合にfalseが返ること","account_id=1","なし","falseが返却される","中","アカウントBot判定"
"158","UT-APP-158","AgentBot","outgoing_url validation","境界値","URLが最大長を超える場合にエラーになること","なし","outgoing_url='a'*極長","length: maximumエラー","中","長さ制限"
"159","UT-APP-159","Campaign","trigger!","正常系","one_offキャンペーンが実行されること","campaign_type=one_off, status=active","なし","execute_campaignが呼ばれる","高","キャンペーン実行"
"160","UT-APP-160","Campaign","trigger!","異常系","ongoingキャンペーンでは実行されないこと","campaign_type=ongoing","なし","何も起こらない","中","タイプ判定"
"161","UT-APP-161","Campaign","trigger!","異常系","completedキャンペーンでは実行されないこと","campaign_status=completed","なし","何も起こらない","中","ステータス判定"
"162","UT-APP-162","Campaign","validate_campaign_inbox","異常系","非対応Inboxタイプでエラーになること","inbox_type='unsupported'","なし","'Unsupported Inbox type'エラー","中","Inbox検証"
"163","UT-APP-163","Campaign","validate_url","異常系","不正なURLでエラーになること","trigger_rules.url='invalid'","なし","'url invalid'エラー","中","URL検証"
"164","UT-APP-164","Campaign","ensure_correct_campaign_attributes","正常系","SMS/WhatsApp用にone_offが設定されること","inbox_type='Twilio SMS'","なし","campaign_type=one_offになる","中","自動設定"
"165","UT-APP-165","Campaign","prevent_completed_campaign_from_update","異常系","完了キャンペーンの更新でエラーになること","campaign_status=completed","なし","'already completed'エラー","中","更新制限"
"166","UT-APP-166","Campaign","account_id validation","異常系","account_idが空の場合にエラーになること","なし","account_id=nil","presence: trueエラー","高","必須項目"
"167","UT-APP-167","Campaign","title validation","異常系","titleが空の場合にエラーになること","なし","title=''","presence: trueエラー","高","必須項目"
"168","UT-APP-168","Campaign","message validation","異常系","messageが空の場合にエラーになること","なし","message=''","presence: trueエラー","高","必須項目"
"169","UT-APP-169","Label","conversations","正常系","ラベル付き会話が取得できること","ラベルが会話に付与されている","なし","tagged_with結果が返却される","中","タグ検索"
"170","UT-APP-170","Label","messages","正常系","ラベル付き会話のメッセージが取得できること","ラベルが会話に付与されている","なし","該当会話のメッセージが返却される","中","メッセージ集計"
"171","UT-APP-171","Label","reporting_events","正常系","ラベル付き会話のイベントが取得できること","ラベルが会話に付与されている","なし","該当会話のreporting_eventsが返却される","中","レポート用"
"172","UT-APP-172","Label","update_associated_models","正常系","タイトル変更時にジョブが実行されること","title変更","title='new_label'","Labels::UpdateJobがenqueueされる","中","連鎖更新"
"173","UT-APP-173","Label","title validation","異常系","タイトルが空の場合にエラーになること","なし","title=''","presenceエラー","高","必須項目"
"174","UT-APP-174","Label","title validation","異常系","不正な文字を含む場合にエラーになること","なし","title='invalid@char'","formatエラー","中","形式検証"
"175","UT-APP-175","Label","title validation","異常系","同一アカウントで重複titleでエラーになること","同一titleのラベルが存在","title='existing'","uniquenessエラー","高","一意制約"
"176","UT-APP-176","Label","title before_validation","正常系","タイトルが小文字に変換されること","title='TEST'","なし","title='test'になる","中","正規化"
"177","UT-APP-177","Webhook","ALLOWED_WEBHOOK_EVENTS","正常系","許可されたイベントリストが定数として定義されていること","なし","なし","定数配列が存在する","低","定数確認"
"178","UT-APP-178","Webhook","validate_webhook_subscriptions","異常系","subscriptionsが配列でない場合にエラーになること","なし","subscriptions='string'","subscriptionsエラー","中","型検証"
"179","UT-APP-179","Webhook","validate_webhook_subscriptions","異常系","subscriptionsが空の場合にエラーになること","なし","subscriptions=[]","subscriptionsエラー","中","空配列検証"
"180","UT-APP-180","Webhook","validate_webhook_subscriptions","異常系","許可されていないイベントを含む場合にエラーになること","なし","subscriptions=['invalid_event']","subscriptionsエラー","中","イベント検証"
"181","UT-APP-181","Webhook","url validation","異常系","不正なURL形式でエラーになること","なし","url='not-a-url'","formatエラー","高","URL形式"
"182","UT-APP-182","Webhook","url validation","異常系","同一アカウントで重複URLでエラーになること","同一URLのWebhookが存在","url='https://existing.com'","uniquenessエラー","高","一意制約"
"183","UT-APP-183","AutomationRule","conditions_attributes","正常系","条件属性リストが返却されること","なし","なし","定義済み属性キーの配列が返却される","低","定数確認"
"184","UT-APP-184","AutomationRule","actions_attributes","正常系","アクション属性リストが返却されること","なし","なし","定義済みアクションキーの配列が返却される","低","定数確認"
"185","UT-APP-185","AutomationRule","file_base_data","正常系","添付ファイルデータが生成されること","filesが添付されている","なし","ファイル情報の配列が返却される","中","ファイル管理"
"186","UT-APP-186","AutomationRule","json_conditions_format","異常系","サポートされていない条件でエラーになること","なし","conditions=[{attribute_key: 'invalid'}]","conditionsエラー","中","条件検証"
"187","UT-APP-187","AutomationRule","json_actions_format","異常系","サポートされていないアクションでエラーになること","なし","actions=[{action_name: 'invalid'}]","actionsエラー","中","アクション検証"
"188","UT-APP-188","AutomationRule","query_operator_presence","異常系","複数条件でquery_operatorがない場合にエラーになること","複数条件でoperator不足","なし","'should have query operator'エラー","中","演算子検証"
"189","UT-APP-189","AutomationRule","query_operator_value","異常系","AND/OR以外のoperatorでエラーになること","なし","query_operator='XOR'","'must be AND or OR'エラー","中","演算子検証"
"190","UT-APP-190","AutomationRule","account_id validation","異常系","account_idが空の場合にエラーになること","なし","account_id=nil","presence: trueエラー","高","必須項目"
"191","UT-APP-191","Notification","push_event_data","正常系","プッシュイベント用データが生成されること","通知が存在","なし","id, notification_type等を含むハッシュが返却される","高","WebSocket用"
"192","UT-APP-192","Notification","fcm_push_data","正常系","FCMプッシュ用データが生成されること","通知が存在","なし","id, notification_type, primary_actor等を含むハッシュが返却される","高","モバイル通知"
"193","UT-APP-193","Notification","push_message_title","正常系","通知タイプに応じたタイトルが生成されること","notification_type=conversation_creation","なし","I18n翻訳されたタイトルが返却される","中","タイトル生成"
"194","UT-APP-194","Notification","push_message_body","正常系","通知タイプに応じた本文が生成されること","notification_type=conversation_creation","なし","送信者名とコンテンツが結合された文字列が返却される","中","本文生成"
"195","UT-APP-195","Notification","conversation","正常系","primary_actorが返却されること","通知が存在","なし","primary_actorが返却される","低","エイリアス"
"196","UT-APP-196","Notification","process_notification_delivery","正常系","push通知サブスクライブ時にジョブがenqueueされること","user.push通知設定=true","なし","PushNotificationJobがenqueueされる","高","通知配信"
"197","UT-APP-197","Notification","process_notification_delivery","正常系","email通知サブスクライブ時にジョブがenqueueされること","user.email通知設定=true","なし","EmailNotificationJobがenqueueされる","高","メール配信"
"198","UT-APP-198","Notification","set_last_activity_at","正常系","created_atがlast_activity_atに設定されること","通知作成時","なし","last_activity_at=created_atになる","中","タイムスタンプ"
"199","UT-APP-199","Notification","notification_type validation","異常系","不正なnotification_typeでエラーになること","なし","notification_type=999","enumエラー","高","型検証"
"200","UT-APP-200","Attachment","push_event_data","正常系","プッシュイベント用データが生成されること","添付ファイルが存在","なし","base_dataとメタデータを含むハッシュが返却される","中","WebSocket用"
"201","UT-APP-201","Attachment","push_event_data","異常系","file_type未設定時にnilが返ること","file_type=nil","なし","nilが返却される","中","nilハンドリング"
"202","UT-APP-202","Attachment","file_url","正常系","ファイルURLが生成されること","file添付済み","なし","url_for結果が返却される","中","URL生成"
"203","UT-APP-203","Attachment","file_url","境界値","file未添付時に空文字が返ること","file未添付","なし","空文字が返却される","中","未添付ケース"
"204","UT-APP-204","Attachment","download_url","正常系","ダウンロードURLが生成されること","file添付済み","なし","file.blob.urlが返却される","中","ダウンロード用"
"205","UT-APP-205","Attachment","thumb_url","正常系","サムネイルURLが生成されること","image添付済み","なし","リサイズ済み画像URLが返却される","中","サムネイル"
"206","UT-APP-206","Attachment","thumb_url","境界値","非画像の場合に空文字が返ること","file_type=file","なし","空文字が返却される","中","画像限定"
"207","UT-APP-207","Attachment","with_attached_file?","正常系","添付ファイルタイプの場合にtrueが返ること","file_type=image","なし","trueが返却される","低","タイプ判定"
"208","UT-APP-208","Attachment","with_attached_file?","正常系","locationタイプの場合にfalseが返ること","file_type=location","なし","falseが返却される","低","タイプ判定"
"209","UT-APP-209","Attachment","acceptable_file","異常系","WebWidgetで許可されないファイル形式でエラーになること","Channel::WebWidget, 不正ファイル形式","なし","'type not supported'エラー","高","ファイル検証"
"210","UT-APP-210","Attachment","validate_file_size","異常系","ファイルサイズが制限を超える場合にエラーになること","巨大ファイル","なし","'size is too big'エラー","高","サイズ制限"
"211","UT-APP-211","AccountUser","create_notification_setting","正常系","通知設定が作成されること","AccountUser作成時","なし","NotificationSettingが作成される","高","初期設定"
"212","UT-APP-212","AccountUser","remove_user_from_account","正常系","削除時にDestroyJobがenqueueされること","AccountUser削除時","なし","Agents::DestroyJobがenqueueされる","高","クリーンアップ"
"213","UT-APP-213","AccountUser","permissions","正常系","管理者の場合に'administrator'が返ること","role=administrator","なし","['administrator']が返却される","中","権限取得"
"214","UT-APP-214","AccountUser","permissions","正常系","エージェントの場合に'agent'が返ること","role=agent","なし","['agent']が返却される","中","権限取得"
"215","UT-APP-215","AccountUser","push_event_data","正常系","プッシュイベント用データが生成されること","AccountUserが存在","なし","id, availability, role, user_idを含むハッシュが返却される","中","WebSocket用"
"216","UT-APP-216","AccountUser","update_presence_in_redis","正常系","availability変更時にRedisが更新されること","availability変更","availability=busy","OnlineStatusTracker.set_statusが呼ばれる","高","オンライン状態"
"217","UT-APP-217","AccountUser","user_id validation","異常系","同一アカウントで重複user_idでエラーになること","同一user_idのAccountUserが存在","user_id=1","uniquenessエラー","高","一意制約"
"218","UT-APP-218","Note","ensure_account_id","正常系","contactからaccount_idが設定されること","contact設定済み","なし","account_id=contact.account_idになる","中","自動設定"
"219","UT-APP-219","Note","content validation","異常系","contentが空の場合にエラーになること","なし","content=''","presence: trueエラー","高","必須項目"
"220","UT-APP-220","Note","account_id validation","異常系","account_idが空の場合にエラーになること","contact未設定","account_id=nil","presence: trueエラー","高","必須項目"
"221","UT-APP-221","Note","contact_id validation","異常系","contact_idが空の場合にエラーになること","なし","contact_id=nil","presence: trueエラー","高","必須項目"
"222","UT-APP-222","Portal","file_base_data","正常系","ロゴファイルデータが生成されること","logo添付済み","なし","id, file_type, file_url等を含むハッシュが返却される","中","ファイル管理"
"223","UT-APP-223","Portal","default_locale","正常系","設定されたデフォルトロケールが返ること","config['default_locale']='ja'","なし","'ja'が返却される","中","多言語対応"
"224","UT-APP-224","Portal","default_locale","異常系","未設定時に'en'が返ること","config['default_locale']未設定","なし","'en'が返却される","中","デフォルト値"
"225","UT-APP-225","Portal","config_json_format","異常系","許可されていないキーでエラーになること","なし","config={'invalid_key': 'value'}","cofigエラー","中","設定検証"
"226","UT-APP-226","Portal","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"227","UT-APP-227","Portal","slug validation","異常系","slugが空の場合にエラーになること","なし","slug=''","presence: trueエラー","高","必須項目"
"228","UT-APP-228","Portal","slug validation","異常系","重複slugでエラーになること","同一slugのPortalが存在","slug='existing'","uniquenessエラー","高","一意制約"
"229","UT-APP-229","Portal","custom_domain validation","異常系","重複custom_domainでエラーになること","同一domainのPortalが存在","custom_domain='existing.com'","uniquenessエラー","中","一意制約"
"230","UT-APP-230","CannedResponse","content validation","異常系","contentが空の場合にエラーになること","なし","content=''","presence: trueエラー","高","必須項目"
"231","UT-APP-231","CannedResponse","short_code validation","異常系","short_codeが空の場合にエラーになること","なし","short_code=''","presence: trueエラー","高","必須項目"
"232","UT-APP-232","CannedResponse","short_code validation","異常系","同一アカウントで重複short_codeでエラーになること","同一short_codeが存在","short_code='existing'","uniquenessエラー","高","一意制約"
"233","UT-APP-233","CannedResponse","order_by_search","正常系","検索スコア順にソートされること","複数の定型文が存在","search='hello'","スコア順の結果が返却される","中","検索順序"
"234","UT-APP-234","Article","search","正常系","複合条件で記事が検索できること","複数の記事が存在","params={locale: 'en', status: 'published'}","条件に合う記事が返却される","中","検索機能"
"235","UT-APP-235","Article","associate_root_article","正常系","関連記事が正しく関連付けられること","関連先記事が存在","associated_article_id=1","associated_article_idが設定される","中","記事関連付け"
"236","UT-APP-236","Article","find_root_article_id","正常系","ルート記事IDが取得できること","記事が存在","なし","root記事のIDが返却される","中","階層管理"
"237","UT-APP-237","Article","draft!","正常系","記事がdraft状態になること","status=published","なし","status=draftになる","中","ステータス変更"
"238","UT-APP-238","Article","increment_view_count","正常系","閲覧数が増加すること","views=10","なし","views=11になる","中","閲覧カウント"
"239","UT-APP-239","Article","increment_view_count","境界値","views=nilから1になること","views=nil","なし","views=1になる","中","初回閲覧"
"240","UT-APP-240","Article","update_positions","正常系","記事の位置が更新されること","複数記事が存在","positions_hash={1=>10, 2=>20}","各記事のpositionが更新される","中","並び順管理"
"241","UT-APP-241","Article","title validation","異常系","titleが空の場合にエラーになること","なし","title=''","presence: trueエラー","高","必須項目"
"242","UT-APP-242","Article","content validation","異常系","contentが空の場合にエラーになること","なし","content=''","presence: trueエラー","高","必須項目"
"243","UT-APP-243","Category","search","正常系","ロケールで絞り込み検索できること","複数カテゴリが存在","params={locale: 'ja'}","jaロケールのカテゴリが返却される","中","検索機能"
"244","UT-APP-244","Category","current_page","正常系","現在ページが取得できること","なし","params={page: 2}","2が返却される","低","ページング"
"245","UT-APP-245","Category","ensure_account_id","正常系","portalからaccount_idが設定されること","portal設定済み","なし","account_id=portal.account_idになる","中","自動設定"
"246","UT-APP-246","Category","allowed_locales","異常系","許可されていないロケールでエラーになること","portal.config['allowed_locales']=['en']","locale='ja'","localeエラー","中","ロケール検証"
"247","UT-APP-247","Category","slug validation","異常系","slugが空の場合にエラーになること","なし","slug=''","presence: trueエラー","高","必須項目"
"248","UT-APP-248","Category","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"249","UT-APP-249","Category","locale validation","異常系","同一slug/locale/portalで重複する場合にエラーになること","同一組み合わせのカテゴリが存在","slug='existing', locale='en'","uniquenessエラー","高","複合一意制約"
"250","UT-APP-250","Folder","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"251","UT-APP-251","Folder","category_id validation","異常系","category_idが空の場合にエラーになること","なし","category_id=nil","presence: trueエラー","高","必須項目"
"252","UT-APP-252","CustomFilter","validate_number_of_filters","異常系","フィルタ数制限を超える場合にエラーになること","既にMAX_CUSTOM_FILTERS_PER_USER件のフィルタが存在","なし","number_of_recordsエラー","中","数量制限"
"253","UT-APP-253","CustomFilter","filter_type enum","正常系","conversation/contact/reportが設定できること","なし","filter_type=:contact","filter_type=contactになる","低","enum確認"
"254","UT-APP-254","Macro","set_visibility","正常系","管理者が指定したvisibilityが設定されること","user=administrator","visibility='global'","visibility=globalになる","中","可視性設定"
"255","UT-APP-255","Macro","set_visibility","正常系","エージェントは常にpersonalになること","user=agent","visibility='global'","visibility=personalになる","中","権限制限"
"256","UT-APP-256","Macro","with_visibility","正常系","ユーザーに見えるマクロが取得できること","global+自分のpersonalマクロが存在","なし","global + 自分のpersonalマクロが返却される","中","可視性フィルタ"
"257","UT-APP-257","Macro","file_base_data","正常系","添付ファイルデータが生成されること","filesが添付されている","なし","ファイル情報の配列が返却される","中","ファイル管理"
"258","UT-APP-258","Macro","json_actions_format","異常系","サポートされていないアクションでエラーになること","なし","actions=[{action_name: 'invalid'}]","actionsエラー","中","アクション検証"
"259","UT-APP-259","CustomAttributeDefinition","STANDARD_ATTRIBUTES","正常系","標準属性リストが定数として定義されていること","なし","なし","conversation/contact用の属性配列が存在する","低","定数確認"
"260","UT-APP-260","CustomAttributeDefinition","attribute_must_not_conflict","異常系","標準属性キーと競合する場合にエラーになること","なし","attribute_key='status'","key_conflictエラー","高","キー検証"
"261","UT-APP-261","CustomAttributeDefinition","attribute_key validation","異常系","attribute_keyが空の場合にエラーになること","なし","attribute_key=''","presence: trueエラー","高","必須項目"
"262","UT-APP-262","CustomAttributeDefinition","attribute_key validation","異常系","同一account/modelで重複keyでエラーになること","同一keyが存在","attribute_key='existing'","uniquenessエラー","高","一意制約"
"263","UT-APP-263","ContactInbox","webhook_data","正常系","Webhook用データが生成されること","ContactInboxが存在","なし","contact, inbox, account, source_id等を含むハッシュが返却される","中","外部連携"
"264","UT-APP-264","ContactInbox","current_conversation","正常系","最新の会話が取得できること","複数会話が存在","なし","conversations.lastが返却される","中","会話取得"
"265","UT-APP-265","ContactInbox","validate_twilio_source_id","異常系","Twilio SMS用に不正なsource_idでエラーになること","Channel::TwilioSms, medium='sms'","source_id='invalid'","source_idエラー","中","形式検証"
"266","UT-APP-266","ContactInbox","validate_whatsapp_source_id","異常系","WhatsApp用に不正なsource_idでエラーになること","Channel::Whatsapp","source_id='invalid'","source_idエラー","中","形式検証"
"267","UT-APP-267","ContactInbox","inbox_id validation","異常系","inbox_idが空の場合にエラーになること","なし","inbox_id=nil","presence: trueエラー","高","必須項目"
"268","UT-APP-268","ContactInbox","source_id validation","異常系","source_idが空の場合にエラーになること","なし","source_id=''","presence: trueエラー","高","必須項目"
"269","UT-APP-269","InboxMember","add_agent_to_round_robin","正常系","作成時にラウンドロビンキューに追加されること","InboxMember作成時","なし","add_agent_to_queueが呼ばれる","高","自動割当"
"270","UT-APP-270","InboxMember","remove_agent_from_round_robin","正常系","削除時にラウンドロビンキューから削除されること","InboxMember削除時","なし","remove_agent_from_queueが呼ばれる","高","自動割当"
"271","UT-APP-271","InboxMember","user_id validation","異常系","同一inboxで重複user_idでエラーになること","同一user_idのInboxMemberが存在","user_id=1","uniquenessエラー","高","一意制約"
"272","UT-APP-272","TeamMember","user_id validation","異常系","同一チームで重複user_idでエラーになること","同一user_idのTeamMemberが存在","user_id=1","uniquenessエラー","高","一意制約"
"273","UT-APP-273","WorkingHour","today","正常系","今日の営業時間が取得できること","営業時間が設定済み","なし","今日の曜日のWorkingHourが返却される","中","営業時間判定"
"274","UT-APP-274","WorkingHour","open_at?","正常系","指定時刻が営業時間内の場合にtrueが返ること","営業時間内","time=営業時間内の時刻","trueが返却される","高","時間判定"
"275","UT-APP-275","WorkingHour","open_at?","正常系","closed_all_dayの場合にfalseが返ること","closed_all_day=true","time=任意","falseが返却される","高","終日休業"
"276","UT-APP-276","WorkingHour","open_now?","正常系","現在営業中の場合にtrueが返ること","営業時間内","なし","trueが返却される","高","リアルタイム判定"
"277","UT-APP-277","WorkingHour","closed_now?","正常系","現在営業外の場合にtrueが返ること","営業時間外","なし","trueが返却される","高","リアルタイム判定"
"278","UT-APP-278","WorkingHour","close_after_open","異常系","閉店時刻が開店時刻より前の場合にエラーになること","なし","open_hour=18, close_hour=9","close_hourエラー","中","時間検証"
"279","UT-APP-279","WorkingHour","ensure_open_all_day_hours","正常系","open_all_day時に0:00-23:59が設定されること","open_all_day=true","なし","open=0:00, close=23:59になる","中","終日営業"
"280","UT-APP-280","WorkingHour","open_all_day_and_closed_all_day","異常系","両方trueの場合にエラーになること","open_all_day=true, closed_all_day=true","なし","baseエラー","中","矛盾検証"
"281","UT-APP-281","NotificationSetting","EMAIL_NOTIFICATION_FLAGS","正常系","メール通知フラグが定数として定義されていること","なし","なし","定数ハッシュが存在する","低","定数確認"
"282","UT-APP-282","NotificationSetting","PUSH_NOTIFICATION_FLAGS","正常系","プッシュ通知フラグが定数として定義されていること","なし","なし","定数ハッシュが存在する","低","定数確認"
"283","UT-APP-283","NotificationSubscription","identifier validation","異常系","identifierが空の場合にエラーになること","なし","identifier=''","presence: trueエラー","高","必須項目"
"284","UT-APP-284","NotificationSubscription","subscription_type enum","正常系","browser_push/fcmが設定できること","なし","subscription_type=:fcm","subscription_type=fcmになる","低","enum確認"
"285","UT-APP-285","CsatSurveyResponse","rating validation","異常系","範囲外のratingでエラーになること","なし","rating=6","inclusionエラー","高","範囲検証"
"286","UT-APP-286","CsatSurveyResponse","rating validation","異常系","ratingが空の場合にエラーになること","なし","rating=nil","presence: trueエラー","高","必須項目"
"287","UT-APP-287","CsatSurveyResponse","filter_by_created_at","正常系","日付範囲でフィルタできること","複数レスポンスが存在","range=1.week.ago..Time.now","範囲内のレスポンスが返却される","中","スコープ"
"288","UT-APP-288","Mention","ensure_account_id","正常系","conversationからaccount_idが設定されること","conversation設定済み","なし","account_id=conversation.account_idになる","中","自動設定"
"289","UT-APP-289","Mention","notify_mentioned_user","正常系","メンション作成時にイベントが発火すること","Mention作成時","なし","CONVERSATION_MENTIONEDイベントが発火される","高","通知"
"290","UT-APP-290","Mention","user validation","異常系","同一会話で重複userでエラーになること","同一user/conversationのMentionが存在","user_id=1","uniquenessエラー","高","一意制約"
"291","UT-APP-291","ConversationParticipant","ensure_account_id","正常系","conversationからaccount_idが設定されること","conversation設定済み","なし","account_id=conversation.account_idになる","中","自動設定"
"292","UT-APP-292","ConversationParticipant","ensure_inbox_access","異常系","inbox権限がない場合にエラーになること","userがinboxにアクセス不可","なし","'must have inbox access'エラー","高","権限検証"
"293","UT-APP-293","ConversationParticipant","user_id validation","異常系","同一会話で重複user_idでエラーになること","同一user_idの参加者が存在","user_id=1","uniquenessエラー","高","一意制約"
"294","UT-APP-294","DataImport","data_type validation","異常系","許可されていないdata_typeでエラーになること","なし","data_type='invalid'","data_typeエラー","中","型検証"
"295","UT-APP-295","DataImport","process_data_import","正常系","作成後にインポートジョブがenqueueされること","DataImport作成時","なし","DataImportJobがenqueueされる","高","非同期処理"
"296","UT-APP-296","ReportingEvent","account_id validation","異常系","account_idが空の場合にエラーになること","なし","account_id=nil","presence: trueエラー","高","必須項目"
"297","UT-APP-297","ReportingEvent","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"298","UT-APP-298","ReportingEvent","value validation","異常系","valueが空の場合にエラーになること","なし","value=nil","presence: trueエラー","高","必須項目"
"299","UT-APP-299","AgentBotInbox","ensure_account_id","正常系","inboxからaccount_idが設定されること","inbox設定済み","なし","account_id=inbox.account_idになる","中","自動設定"
"300","UT-APP-300","AgentBotInbox","status enum","正常系","active/inactiveが設定できること","なし","status=:inactive","status=inactiveになる","低","enum確認"
"301","UT-APP-301","PlatformApp","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"302","UT-APP-302","PlatformAppPermissible","platform_app_id validation","異常系","同一permissibleで重複platform_app_idでエラーになること","同一組み合わせが存在","platform_app_id=1","uniquenessエラー","高","一意制約"
"303","UT-APP-303","DashboardApp","validate_content","異常系","contentが配列でない場合にエラーになること","なし","content='string'","contentエラー","中","型検証"
"304","UT-APP-304","DashboardApp","validate_content","異常系","不正なcontent構造でエラーになること","なし","content=[{type: 'invalid'}]","contentエラー","中","スキーマ検証"
"305","UT-APP-305","InstallationConfig","value getter","正常系","valueが取得できること","serialized_value設定済み","なし","serialized_value[:value]が返却される","中","値アクセス"
"306","UT-APP-306","InstallationConfig","value setter","正常系","valueが設定できること","なし","value='test'","serialized_value={value: 'test'}になる","中","値設定"
"307","UT-APP-307","InstallationConfig","saml_sso_users_check","異常系","SAMLユーザー存在時にSSO無効化でエラーになること","SAMLユーザーが存在","value=false","baseエラー","高","SSO保護"
"308","UT-APP-308","InstallationConfig","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"309","UT-APP-309","SuperAdmin","継承確認","正常系","Userを継承していること","なし","なし","User < SuperAdminであること","低","継承関係"
"310","UT-APP-310","AccessToken","token generation","正常系","トークンが自動生成されること","AccessToken作成時","なし","tokenが設定される","高","セキュリティ"
"311","UT-APP-311","ApplicationRecord","validates_column_content_length","正常系","string列の最大255文字バリデーション","文字列が256文字","なし","lengthエラー","中","汎用バリデーション"
"312","UT-APP-312","ApplicationRecord","validates_column_content_length","正常系","text列の最大20000文字バリデーション","テキストが20001文字","なし","lengthエラー","中","汎用バリデーション"
"313","UT-APP-313","ApplicationRecord","to_drop","正常系","Liquidable対象の場合にDropオブジェクトが返ること","Account等のドロップ可能モデル","なし","AccountDropインスタンスが返却される","中","Liquid連携"
"314","UT-APP-314","ApplicationRecord","to_drop","異常系","Liquidable対象外の場合にnilが返ること","非対象モデル","なし","nilが返却される","中","Liquid対象外"
"315","UT-APP-315","ApplicationRecord","normalize_empty_string_to_nil","正常系","空文字列がnilに変換されること","attr=''","attrs=[:attr]","attr=nilになる","中","正規化"
"316","UT-APP-316","EmailTemplate","resolver","正常系","DbResolverServiceが返却されること","なし","なし","DbResolverServiceインスタンスが返却される","低","テンプレート解決"
"317","UT-APP-317","EmailTemplate","name validation","異常系","同一accountで重複nameでエラーになること","同一nameのテンプレートが存在","name='existing'","uniquenessエラー","中","一意制約"
"318","UT-APP-318","RelatedCategory","belongs_to associations","正常系","category/related_category関連が取得できること","関連が設定済み","なし","両方のCategoryが返却される","中","関連取得"
"319","UT-APP-319","AssignmentPolicy","name validation","異常系","nameが空の場合にエラーになること","なし","name=''","presence: trueエラー","高","必須項目"
"320","UT-APP-320","AssignmentPolicy","name validation","異常系","同一アカウントで重複nameでエラーになること","同一nameのポリシーが存在","name='existing'","uniquenessエラー","高","一意制約"
"321","UT-APP-321","AssignmentPolicy","fair_distribution_limit validation","異常系","0以下の場合にエラーになること","なし","fair_distribution_limit=0","numericalityエラー","中","数値検証"
"322","UT-APP-322","AssignmentPolicy","fair_distribution_window validation","異常系","0以下の場合にエラーになること","なし","fair_distribution_window=0","numericalityエラー","中","数値検証"
"323","UT-APP-323","InboxAssignmentPolicy","inbox_id validation","異常系","重複inbox_idでエラーになること","同一inbox_idのポリシーが存在","inbox_id=1","uniquenessエラー","高","一意制約"
"324","UT-APP-324","JsonbAttributesLengthValidator","validate_keys String","異常系","文字列が1500文字を超える場合にエラーになること","なし","key='a'*1501","lengthエラー","中","文字列長検証"
"325","UT-APP-325","JsonbAttributesLengthValidator","validate_keys Integer","異常系","数値が9999999999を超える場合にエラーになること","なし","key=10000000000","valueエラー","中","数値上限検証"
"1","UT-CPT-001","Captain::Assistant","belongs_to :account","正常系","アカウントとのリレーションが正しく取得できること","Assistant、Accountが存在","assistant.account","関連するAccountが返却される","中","リレーション"
"2","UT-CPT-002","Captain::Assistant","has_many :documents","正常系","documentsリレーションが正しく取得できること","Assistantに複数のDocumentが存在","assistant.documents","関連するDocument一覧が返却される","中","リレーション"
"3","UT-CPT-003","Captain::Assistant","has_many :responses","正常系","responsesリレーションが正しく取得できること","Assistantに複数のAssistantResponseが存在","assistant.responses","関連するAssistantResponse一覧が返却される","中","リレーション"
"4","UT-CPT-004","Captain::Assistant","has_many :captain_inboxes","正常系","captain_inboxesリレーションが正しく取得できること","AssistantにCaptainInboxが関連付け","assistant.captain_inboxes","関連するCaptainInbox一覧が返却される","中","リレーション"
"5","UT-CPT-005","Captain::Assistant","has_many :inboxes, through: :captain_inboxes","正常系","inboxesリレーションがthroughで正しく取得できること","AssistantにCaptainInbox経由でInboxが関連付け","assistant.inboxes","関連するInbox一覧が返却される","中","リレーション"
"6","UT-CPT-006","Captain::Assistant","has_many :messages, as: :sender","正常系","polymorphic messagesリレーションが正しく取得できること","Assistantがsenderとして複数のMessageを持つ","assistant.messages","関連するMessage一覧が返却される","中","ポリモーフィックリレーション"
"7","UT-CPT-007","Captain::Assistant","has_many :copilot_threads","正常系","copilot_threadsリレーションが正しく取得できること","Assistantに複数のCopilotThreadが存在","assistant.copilot_threads","関連するCopilotThread一覧が返却される","中","リレーション"
"8","UT-CPT-008","Captain::Assistant","has_many :scenarios","正常系","scenariosリレーションが正しく取得できること","Assistantに複数のScenarioが存在","assistant.scenarios","関連するScenario一覧が返却される","中","リレーション"
"9","UT-CPT-009","Captain::Assistant","validates :name, presence: true","異常系","名前が空の場合バリデーションエラーになること","なし","name: nil","バリデーションエラー発生","高","必須バリデーション"
"10","UT-CPT-010","Captain::Assistant","validates :description, presence: true","異常系","descriptionが空の場合バリデーションエラーになること","なし","description: nil","バリデーションエラー発生","高","必須バリデーション"
"11","UT-CPT-011","Captain::Assistant","validates :account_id, presence: true","異常系","account_idが空の場合バリデーションエラーになること","なし","account_id: nil","バリデーションエラー発生","高","必須バリデーション"
"12","UT-CPT-012","Captain::Assistant","store_accessor :config, :temperature","正常系","configからtemperatureが取得できること","config = { temperature: 0.8 }","assistant.temperature","0.8が返却される","中","store_accessor"
"13","UT-CPT-013","Captain::Assistant","store_accessor :config, :feature_faq","正常系","configからfeature_faqが取得できること","config = { feature_faq: true }","assistant.feature_faq","trueが返却される","中","store_accessor"
"14","UT-CPT-014","Captain::Assistant","store_accessor :config, :feature_memory","正常系","configからfeature_memoryが取得できること","config = { feature_memory: true }","assistant.feature_memory","trueが返却される","中","store_accessor"
"15","UT-CPT-015","Captain::Assistant","store_accessor :config, :product_name","正常系","configからproduct_nameが取得できること","config = { product_name: ""Test Product"" }","assistant.product_name","""Test Product""が返却される","中","store_accessor"
"16","UT-CPT-016","Captain::Assistant","scope :ordered","正常系","orderedスコープでcreated_at降順でソートされること","複数のAssistantが存在","Captain::Assistant.ordered","created_at降順でソートされた結果が返却される","低","スコープ"
"17","UT-CPT-017","Captain::Assistant","scope :for_account","正常系","for_accountスコープで指定アカウントのみフィルタされること","複数アカウントにAssistantが存在","Captain::Assistant.for_account(account_id)","指定アカウントのAssistantのみ返却される","中","スコープ"
"18","UT-CPT-018","Captain::Assistant","available_name","正常系","nameがそのまま返却されること","name: ""Test Assistant""","assistant.available_name","""Test Assistant""が返却される","低","アクセサ"
"19","UT-CPT-019","Captain::Assistant","available_agent_tools","正常系","built_in_agent_toolsとcustom_toolsが結合されて返却されること","custom_toolsが存在","assistant.available_agent_tools","built-inとcustomのツール一覧が返却される","高","ツール管理"
"20","UT-CPT-020","Captain::Assistant","available_agent_tools","境界値","custom_toolsが空の場合built_in_agent_toolsのみ返却されること","custom_toolsが存在しない","assistant.available_agent_tools","built-inツールのみが返却される","中","ツール管理"
"21","UT-CPT-021","Captain::Assistant","available_tool_ids","正常系","ツールIDの配列が返却されること","ツールが存在","assistant.available_tool_ids","ツールID配列が返却される","中","ツール管理"
"22","UT-CPT-022","Captain::Assistant","push_event_data","正常系","WebSocket用のイベントデータが正しく生成されること","Assistant存在","assistant.push_event_data","id, name, avatar_url, description, created_at, typeを含むHashが返却される","中","イベントデータ"
"23","UT-CPT-023","Captain::Assistant","push_event_data","境界値","avatar_urlがnilの場合デフォルトURLが使用されること","avatar_urlが設定されていない","assistant.push_event_data","default_avatar_urlが含まれる","低","イベントデータ"
"24","UT-CPT-024","Captain::Assistant","webhook_data","正常系","Webhook用のデータが正しく生成されること","Assistant存在","assistant.webhook_data","id, name, avatar_url, description, created_at, typeを含むHashが返却される","中","Webhookデータ"
"25","UT-CPT-025","Captain::Assistant","agent_name","正常系","名前がparameterize形式で返却されること","name: ""Test Assistant""","assistant.send(:agent_name)","test_assistantが返却される","低","privateメソッド"
"26","UT-CPT-026","Captain::Assistant","agent_tools","正常系","faq_lookupとhandoffツールが返却されること","Assistant存在","assistant.send(:agent_tools)","2つのツールインスタンスが返却される","中","privateメソッド"
"27","UT-CPT-027","Captain::Assistant","prompt_context","正常系","プロンプトコンテキストが正しく構築されること","Assistantにscenarios、response_guidelines、guardrailsが設定済み","assistant.send(:prompt_context)","name, description, product_name, scenarios, response_guidelines, guardrailsを含むHashが返却される","高","プロンプト生成"
"28","UT-CPT-028","Captain::Assistant","prompt_context","境界値","product_nameがnilの場合デフォルト値が使用されること","configにproduct_nameなし","assistant.send(:prompt_context)","""this product""が使用される","低","プロンプト生成"
"29","UT-CPT-029","Captain::Assistant","default_avatar_url","正常系","デフォルトアバターURLが正しく生成されること","FRONTEND_URL環境変数が設定済み","assistant.send(:default_avatar_url)","captain/logo.svgのパスが返却される","低","privateメソッド"
"30","UT-CPT-030","Captain::AssistantResponse","belongs_to :assistant","正常系","assistantリレーションが正しく取得できること","AssistantResponseとAssistantが存在","response.assistant","関連するCaptain::Assistantが返却される","中","リレーション"
"31","UT-CPT-031","Captain::AssistantResponse","belongs_to :account","正常系","accountリレーションが正しく取得できること","AssistantResponseとAccountが存在","response.account","関連するAccountが返却される","中","リレーション"
"32","UT-CPT-032","Captain::AssistantResponse","belongs_to :documentable, polymorphic: true","正常系","polymorphic documentableリレーションが正しく取得できること","documentable_type, documentable_idが設定済み","response.documentable","関連するドキュメントオブジェクトが返却される","中","ポリモーフィックリレーション"
"33","UT-CPT-033","Captain::AssistantResponse","belongs_to :documentable, polymorphic: true","境界値","documentableがnilでも有効であること","documentable未設定","response.documentable","nilが返却される（optional: true）","低","ポリモーフィックリレーション"
"34","UT-CPT-034","Captain::AssistantResponse","has_neighbors :embedding","正常系","embeddingベクトル検索が利用可能であること","embeddingが設定済み","response.nearest_neighbors(:embedding, vector, distance: 'cosine')","類似レスポンスが返却される","高","ベクトル検索"
"35","UT-CPT-035","Captain::AssistantResponse","validates :question, presence: true","異常系","questionが空の場合バリデーションエラーになること","なし","question: nil","バリデーションエラー発生","高","必須バリデーション"
"36","UT-CPT-036","Captain::AssistantResponse","validates :answer, presence: true","異常系","answerが空の場合バリデーションエラーになること","なし","answer: nil","バリデーションエラー発生","高","必須バリデーション"
"37","UT-CPT-037","Captain::AssistantResponse","scope :ordered","正常系","orderedスコープでcreated_at降順でソートされること","複数のAssistantResponseが存在","Captain::AssistantResponse.ordered","created_at降順でソートされた結果が返却される","低","スコープ"
"38","UT-CPT-038","Captain::AssistantResponse","scope :by_account","正常系","by_accountスコープで指定アカウントのみフィルタされること","複数アカウントにResponseが存在","Captain::AssistantResponse.by_account(account_id)","指定アカウントのResponseのみ返却される","中","スコープ"
"39","UT-CPT-039","Captain::AssistantResponse","scope :by_assistant","正常系","by_assistantスコープで指定アシスタントのみフィルタされること","複数アシスタントにResponseが存在","Captain::AssistantResponse.by_assistant(assistant_id)","指定アシスタントのResponseのみ返却される","中","スコープ"
"40","UT-CPT-040","Captain::AssistantResponse","enum status","正常系","pendingステータスが正しく設定されること","なし","response.status = :pending","status == 0（pending）","中","enum"
"41","UT-CPT-041","Captain::AssistantResponse","enum status","正常系","approvedステータスが正しく設定されること","なし","response.status = :approved","status == 1（approved）","中","enum"
"42","UT-CPT-042","Captain::AssistantResponse","self.search","正常系","クエリに類似したレスポンスが検索できること","embeddingが設定されたResponseが存在","Captain::AssistantResponse.search(""query"", account_id: 1)","類似度の高い5件が返却される","高","ベクトル検索"
"43","UT-CPT-043","Captain::AssistantResponse","ensure_status","正常系","statusがnilの場合approvedに設定されること","status未設定","response.valid?","statusがapprovedに設定される","中","before_validation"
"44","UT-CPT-044","Captain::AssistantResponse","ensure_account","正常系","accountがassistantのaccountに設定されること","assistantが設定済み","response.valid?","accountがassistant.accountに設定される","中","before_validation"
"45","UT-CPT-045","Captain::AssistantResponse","update_response_embedding","正常系","questionが変更された場合embeddingが更新されること","question変更","response.update(question: ""new question"")","UpdateEmbeddingJobがenqueueされる","高","after_commit"
"46","UT-CPT-046","Captain::AssistantResponse","update_response_embedding","正常系","answerが変更された場合embeddingが更新されること","answer変更","response.update(answer: ""new answer"")","UpdateEmbeddingJobがenqueueされる","高","after_commit"
"47","UT-CPT-047","Captain::AssistantResponse","update_response_embedding","境界値","question/answer以外の変更ではembeddingが更新されないこと","status変更","response.update(status: :pending)","UpdateEmbeddingJobがenqueueされない","中","after_commit"
"48","UT-CPT-048","Captain::Document","belongs_to :assistant","正常系","assistantリレーションが正しく取得できること","DocumentとAssistantが存在","document.assistant","関連するCaptain::Assistantが返却される","中","リレーション"
"49","UT-CPT-049","Captain::Document","has_many :responses","正常系","responsesリレーションが正しく取得できること","DocumentにAssistantResponseが関連付け","document.responses","関連するAssistantResponse一覧が返却される","中","ポリモーフィックリレーション"
"50","UT-CPT-050","Captain::Document","belongs_to :account","正常系","accountリレーションが正しく取得できること","DocumentとAccountが存在","document.account","関連するAccountが返却される","中","リレーション"
"51","UT-CPT-051","Captain::Document","has_one_attached :pdf_file","正常系","pdf_fileがアタッチ可能であること","PDFファイルが存在","document.pdf_file.attach(io: file, filename: 'test.pdf')","ファイルがアタッチされる","中","ActiveStorage"
"52","UT-CPT-052","Captain::Document","validates :external_link, presence: true","異常系","pdf_file未添付かつexternal_link空の場合バリデーションエラーになること","pdf_file未添付","external_link: nil","バリデーションエラー発生","高","条件付きバリデーション"
"53","UT-CPT-053","Captain::Document","validates :external_link, presence: true","正常系","pdf_file添付時はexternal_link空でも有効であること","pdf_fileが添付済み","external_link: nil","バリデーション成功","中","条件付きバリデーション"
"54","UT-CPT-054","Captain::Document","validates :external_link, uniqueness","異常系","同一assistant_idで重複するexternal_linkの場合エラーになること","同一external_linkのDocumentが存在","external_link: 既存と同じ","バリデーションエラー発生","高","一意性バリデーション"
"55","UT-CPT-055","Captain::Document","validates :content, length: { maximum: 200_000 }","異常系","contentが200,000文字を超える場合エラーになること","なし","content: 200,001文字の文字列","バリデーションエラー発生","中","長さバリデーション"
"56","UT-CPT-056","Captain::Document","validates :content, length: { maximum: 200_000 }","境界値","contentが200,000文字の場合有効であること","なし","content: 200,000文字の文字列","バリデーション成功","中","長さバリデーション境界値"
"57","UT-CPT-057","Captain::Document","validates :pdf_file, presence: true","異常系","PDFドキュメントでpdf_file未添付の場合エラーになること","external_linkが.pdfで終わる","pdf_file未添付","バリデーションエラー発生","高","条件付きバリデーション"
"58","UT-CPT-058","Captain::Document","validate_pdf_format","異常系","pdf_fileがPDF以外の場合エラーになること","jpegファイルがアタッチ","pdf_file: image/jpeg","バリデーションエラー発生","高","フォーマットバリデーション"
"59","UT-CPT-059","Captain::Document","validate_file_attachment","異常系","pdf_fileが10MBを超える場合エラーになること","11MBのPDFがアタッチ","pdf_file: 11MB","バリデーションエラー発生","高","サイズバリデーション"
"60","UT-CPT-060","Captain::Document","validate_file_attachment","境界値","pdf_fileが10MBの場合有効であること","10MBのPDFがアタッチ","pdf_file: 10MB","バリデーション成功","中","サイズバリデーション境界値"
"61","UT-CPT-061","Captain::Document","enum status","正常系","in_progressステータスが正しく設定されること","なし","document.status = :in_progress","status == 0（in_progress）","中","enum"
"62","UT-CPT-062","Captain::Document","enum status","正常系","availableステータスが正しく設定されること","なし","document.status = :available","status == 1（available）","中","enum"
"63","UT-CPT-063","Captain::Document","scope :ordered","正常系","orderedスコープでcreated_at降順でソートされること","複数のDocumentが存在","Captain::Document.ordered","created_at降順でソートされた結果が返却される","低","スコープ"
"64","UT-CPT-064","Captain::Document","scope :for_account","正常系","for_accountスコープで指定アカウントのみフィルタされること","複数アカウントにDocumentが存在","Captain::Document.for_account(account_id)","指定アカウントのDocumentのみ返却される","中","スコープ"
"65","UT-CPT-065","Captain::Document","scope :for_assistant","正常系","for_assistantスコープで指定アシスタントのみフィルタされること","複数アシスタントにDocumentが存在","Captain::Document.for_assistant(assistant_id)","指定アシスタントのDocumentのみ返却される","中","スコープ"
"66","UT-CPT-066","Captain::Document","pdf_document?","正常系","PDFファイルがアタッチされている場合trueを返却すること","application/pdfがアタッチ済み","document.pdf_document?","trueが返却される","中","ドキュメント判定"
"67","UT-CPT-067","Captain::Document","pdf_document?","正常系","external_linkが.pdfで終わる場合trueを返却すること","external_link: 'https://example.com/test.pdf'","document.pdf_document?","trueが返却される","中","ドキュメント判定"
"68","UT-CPT-068","Captain::Document","pdf_document?","正常系","非PDFドキュメントの場合falseを返却すること","external_link: 'https://example.com/page'","document.pdf_document?","falseが返却される","中","ドキュメント判定"
"69","UT-CPT-069","Captain::Document","content_type","正常系","pdf_fileのcontent_typeが返却されること","pdf_fileがアタッチ済み","document.content_type","'application/pdf'が返却される","低","アクセサ"
"70","UT-CPT-070","Captain::Document","content_type","境界値","pdf_file未アタッチの場合nilを返却すること","pdf_file未アタッチ","document.content_type","nilが返却される","低","アクセサ"
"71","UT-CPT-071","Captain::Document","file_size","正常系","pdf_fileのバイトサイズが返却されること","pdf_fileがアタッチ済み","document.file_size","ファイルサイズ(bytes)が返却される","低","アクセサ"
"72","UT-CPT-072","Captain::Document","file_size","境界値","pdf_file未アタッチの場合nilを返却すること","pdf_file未アタッチ","document.file_size","nilが返却される","低","アクセサ"
"73","UT-CPT-073","Captain::Document","openai_file_id","正常系","metadataからopenai_file_idが取得できること","metadata: { 'openai_file_id' => 'file-123' }","document.openai_file_id","'file-123'が返却される","中","メタデータアクセス"
"74","UT-CPT-074","Captain::Document","openai_file_id","境界値","metadataがnilの場合nilを返却すること","metadata: nil","document.openai_file_id","nilが返却される","低","メタデータアクセス"
"75","UT-CPT-075","Captain::Document","store_openai_file_id","正常系","openai_file_idがmetadataに保存されること","Document存在","document.store_openai_file_id('file-456')","metadata['openai_file_id'] == 'file-456'","中","メタデータ更新"
"76","UT-CPT-076","Captain::Document","store_openai_file_id","正常系","既存metadataとマージされること","metadata: { 'key' => 'value' }","document.store_openai_file_id('file-789')","既存キーも保持される","中","メタデータ更新"
"77","UT-CPT-077","Captain::Document","display_url","正常系","external_linkがそのまま返却されること","external_link: 'https://example.com'","document.display_url","'https://example.com'が返却される","低","URL生成"
"78","UT-CPT-078","Captain::Document","display_url","正常系","PDF:で始まる場合はblob_urlが返却されること","external_link: 'PDF: test_...'、pdf_file添付済み","document.display_url","rails_blob_urlが返却される","中","URL生成"
"79","UT-CPT-079","Captain::Document","ensure_account_id","正常系","account_idがassistantから自動設定されること","assistant設定済み、account_id未設定","document.valid?","account_idがassistant.account_idに設定される","中","before_validation"
"80","UT-CPT-080","Captain::Document","ensure_within_plan_limit","異常系","プラン制限を超えている場合LimitExceededErrorが発生すること","利用可能ドキュメント数が0","document.save!","LimitExceededErrorが発生","高","プラン制限"
"81","UT-CPT-081","Captain::Document","set_external_link_for_pdf","正常系","pdf_file添付時にexternal_linkが自動生成されること","pdf_file添付済み、external_link空","document.valid?","'PDF: filename_timestamp'形式のexternal_linkが設定される","中","before_validation"
"82","UT-CPT-082","Captain::Document","normalize_external_link","正常系","末尾のスラッシュが削除されること","external_link: 'https://example.com/'","document.valid?","external_link: 'https://example.com'","低","URL正規化"
"83","UT-CPT-083","Captain::Document","normalize_external_link","正常系","PDFドキュメントの場合は正規化しないこと","external_link: 'PDF: test/'","document.valid?","external_linkが変更されない","低","URL正規化"
"84","UT-CPT-084","Captain::Document","enqueue_crawl_job","正常系","作成時にstatus=in_progressならCrawlJobがenqueueされること","status: :in_progress","document作成","CrawlJobがenqueueされる","高","after_create_commit"
"85","UT-CPT-085","Captain::Document","enqueue_crawl_job","境界値","status=availableの場合CrawlJobがenqueueされないこと","status: :available","document作成","CrawlJobがenqueueされない","中","after_create_commit"
"86","UT-CPT-086","Captain::Document","enqueue_response_builder_job","正常系","availableかつstatus変更時にResponseBuilderJobがenqueueされること","status: in_progress→available","document.update(status: :available)","ResponseBuilderJobがenqueueされる","高","after_commit"
"87","UT-CPT-087","Captain::Document","enqueue_response_builder_job","正常系","content変更時にResponseBuilderJobがenqueueされること","status: available、content変更","document.update(content: 'new content')","ResponseBuilderJobがenqueueされる","高","after_commit"
"88","UT-CPT-088","Captain::Document","enqueue_response_builder_job","境界値","destroyedの場合はJobがenqueueされないこと","document削除","document.destroy","ResponseBuilderJobがenqueueされない","中","after_commit"
"89","UT-CPT-089","Captain::Document","update_document_usage","正常系","作成時にaccountのdocument_usageが更新されること","Document作成","document作成","account.update_document_usageが呼ばれる","中","after_create_commit"
"90","UT-CPT-090","Captain::Document","update_document_usage","正常系","削除時にaccountのdocument_usageが更新されること","Document存在","document.destroy","account.update_document_usageが呼ばれる","中","after_destroy"
"91","UT-CPT-091","Captain::Document::LimitExceededError","LimitExceededError","正常系","カスタム例外クラスが定義されていること","なし","raise Captain::Document::LimitExceededError","例外が発生する","低","例外クラス"
"92","UT-CPT-092","Captain::Scenario","belongs_to :assistant","正常系","assistantリレーションが正しく取得できること","ScenarioとAssistantが存在","scenario.assistant","関連するCaptain::Assistantが返却される","中","リレーション"
"93","UT-CPT-093","Captain::Scenario","belongs_to :account","正常系","accountリレーションが正しく取得できること","ScenarioとAccountが存在","scenario.account","関連するAccountが返却される","中","リレーション"
"94","UT-CPT-094","Captain::Scenario","validates :title, presence: true","異常系","titleが空の場合バリデーションエラーになること","なし","title: nil","バリデーションエラー発生","高","必須バリデーション"
"95","UT-CPT-095","Captain::Scenario","validates :description, presence: true","異常系","descriptionが空の場合バリデーションエラーになること","なし","description: nil","バリデーションエラー発生","高","必須バリデーション"
"96","UT-CPT-096","Captain::Scenario","validates :instruction, presence: true","異常系","instructionが空の場合バリデーションエラーになること","なし","instruction: nil","バリデーションエラー発生","高","必須バリデーション"
"97","UT-CPT-097","Captain::Scenario","validates :assistant_id, presence: true","異常系","assistant_idが空の場合バリデーションエラーになること","なし","assistant_id: nil","バリデーションエラー発生","高","必須バリデーション"
"98","UT-CPT-098","Captain::Scenario","validates :account_id, presence: true","異常系","account_idが空の場合バリデーションエラーになること","なし","account_id: nil","バリデーションエラー発生","高","必須バリデーション"
"99","UT-CPT-099","Captain::Scenario","validate_instruction_tools","異常系","instructionに無効なツール参照がある場合エラーになること","instructionに存在しないツールを参照","instruction: '[Invalid](tool://invalid_tool)'","バリデーションエラー発生","高","カスタムバリデーション"
"100","UT-CPT-100","Captain::Scenario","validate_instruction_tools","正常系","instructionに有効なツール参照がある場合は成功すること","有効なツールが存在","instruction: '[Valid](tool://valid_tool)'","バリデーション成功","中","カスタムバリデーション"
"101","UT-CPT-101","Captain::Scenario","validate_instruction_tools","境界値","instruction空の場合はバリデーションスキップされること","instruction: nil","scenario.valid?","ツールバリデーションがスキップされる","低","カスタムバリデーション"
"102","UT-CPT-102","Captain::Scenario","scope :enabled","正常系","enabledスコープでenabled=trueのみフィルタされること","enabled=true/falseのScenarioが存在","Captain::Scenario.enabled","enabled=trueのScenarioのみ返却される","中","スコープ"
"103","UT-CPT-103","Captain::Scenario","delegate :temperature","正常系","assistantのtemperatureが委譲されること","assistant.temperature設定済み","scenario.temperature","assistant.temperatureが返却される","中","delegate"
"104","UT-CPT-104","Captain::Scenario","delegate :feature_faq","正常系","assistantのfeature_faqが委譲されること","assistant.feature_faq設定済み","scenario.feature_faq","assistant.feature_faqが返却される","中","delegate"
"105","UT-CPT-105","Captain::Scenario","delegate :feature_memory","正常系","assistantのfeature_memoryが委譲されること","assistant.feature_memory設定済み","scenario.feature_memory","assistant.feature_memoryが返却される","中","delegate"
"106","UT-CPT-106","Captain::Scenario","delegate :product_name","正常系","assistantのproduct_nameが委譲されること","assistant.product_name設定済み","scenario.product_name","assistant.product_nameが返却される","中","delegate"
"107","UT-CPT-107","Captain::Scenario","delegate :response_guidelines","正常系","assistantのresponse_guidelinesが委譲されること","assistant.response_guidelines設定済み","scenario.response_guidelines","assistant.response_guidelinesが返却される","中","delegate"
"108","UT-CPT-108","Captain::Scenario","delegate :guardrails","正常系","assistantのguardrailsが委譲されること","assistant.guardrails設定済み","scenario.guardrails","assistant.guardrailsが返却される","中","delegate"
"109","UT-CPT-109","Captain::Scenario","prompt_context","正常系","プロンプトコンテキストが正しく構築されること","Scenario設定済み","scenario.prompt_context","title, instructions, tools, assistant_name, response_guidelines, guardrailsを含むHashが返却される","高","プロンプト生成"
"110","UT-CPT-110","Captain::Scenario","prompt_context","境界値","response_guidelinesがnilの場合空配列が使用されること","response_guidelines: nil","scenario.prompt_context","response_guidelinesが[]になる","低","プロンプト生成"
"111","UT-CPT-111","Captain::Scenario","agent_name","正常系","タイトルからagent名が生成されること","title: ""Test Scenario""","scenario.send(:agent_name)","""test_scenario_agent""が返却される","低","privateメソッド"
"112","UT-CPT-112","Captain::Scenario","agent_tools","正常系","resolved_toolsからツールインスタンスが生成されること","toolsにツールIDが設定済み","scenario.send(:agent_tools)","ツールインスタンスの配列が返却される","中","privateメソッド"
"113","UT-CPT-113","Captain::Scenario","resolved_instructions","正常系","ツール参照がテキスト形式に変換されること","instruction: '[Tool](tool://tool_id)'","scenario.send(:resolved_instructions)","'`tool_id` tool'に変換される","中","privateメソッド"
"114","UT-CPT-114","Captain::Scenario","resolved_tools","正常系","toolsのIDから利用可能なツールメタデータが取得されること","tools: ['tool_id1', 'tool_id2']","scenario.send(:resolved_tools)","ツールメタデータの配列が返却される","中","privateメソッド"
"115","UT-CPT-115","Captain::Scenario","resolved_tools","境界値","tools空の場合は空配列を返却すること","tools: nil","scenario.send(:resolved_tools)","空配列が返却される","低","privateメソッド"
"116","UT-CPT-116","Captain::Scenario","resolve_tool_instance","正常系","customツールのインスタンスが生成されること","custom: trueのツールメタデータ","scenario.send(:resolve_tool_instance, metadata)","CustomToolのtoolインスタンスが返却される","中","privateメソッド"
"117","UT-CPT-117","Captain::Scenario","resolve_tool_instance","正常系","built-inツールのインスタンスが生成されること","custom: falseのツールメタデータ","scenario.send(:resolve_tool_instance, metadata)","built-inツールのインスタンスが返却される","中","privateメソッド"
"118","UT-CPT-118","Captain::Scenario","resolve_tool_references","正常系","instructionからツール参照が抽出されtoolsに設定されること","instruction: '[Tool1](tool://tool1) [Tool2](tool://tool2)'","scenario.save!","tools: ['tool1', 'tool2']","高","before_save"
"119","UT-CPT-119","Captain::Scenario","resolve_tool_references","境界値","ツール参照がない場合toolsがnilになること","instruction: 'No tools here'","scenario.save!","tools: nil","低","before_save"
"120","UT-CPT-120","Captain::CustomTool","belongs_to :account","正常系","accountリレーションが正しく取得できること","CustomToolとAccountが存在","custom_tool.account","関連するAccountが返却される","中","リレーション"
"121","UT-CPT-121","Captain::CustomTool","enum :http_method","正常系","GETメソッドが設定できること","なし","custom_tool.http_method = 'GET'","http_method == 'GET'","中","enum"
"122","UT-CPT-122","Captain::CustomTool","enum :http_method","正常系","POSTメソッドが設定できること","なし","custom_tool.http_method = 'POST'","http_method == 'POST'","中","enum"
"123","UT-CPT-123","Captain::CustomTool","enum :http_method","異常系","不正なHTTPメソッドでエラーになること","なし","custom_tool.http_method = 'DELETE'","バリデーションエラー発生","中","enum"
"124","UT-CPT-124","Captain::CustomTool","enum :auth_type - none","正常系","auth_type noneが設定できること","なし","custom_tool.auth_type = 'none'","auth_type == 'none'","中","enum"
"125","UT-CPT-125","Captain::CustomTool","enum :auth_type - bearer","正常系","auth_type bearerが設定できること","なし","custom_tool.auth_type = 'bearer'","auth_type == 'bearer'","中","enum"
"126","UT-CPT-126","Captain::CustomTool","enum :auth_type - basic","正常系","auth_type basicが設定できること","なし","custom_tool.auth_type = 'basic'","auth_type == 'basic'","中","enum"
"127","UT-CPT-127","Captain::CustomTool","enum :auth_type - api_key","正常系","auth_type api_keyが設定できること","なし","custom_tool.auth_type = 'api_key'","auth_type == 'api_key'","中","enum"
"128","UT-CPT-128","Captain::CustomTool","validates :slug, presence: true","異常系","slugが空の場合バリデーションエラーになること（generate_slug後）","title空でslug未設定","slug: nil, title: nil","バリデーションエラー発生","高","必須バリデーション"
"129","UT-CPT-129","Captain::CustomTool","validates :slug, uniqueness: { scope: :account_id }","異常系","同一account内で重複するslugの場合エラーになること","同一slugのCustomToolが存在","slug: 既存と同じ","バリデーションエラー発生","高","一意性バリデーション"
"130","UT-CPT-130","Captain::CustomTool","validates :title, presence: true","異常系","titleが空の場合バリデーションエラーになること","なし","title: nil","バリデーションエラー発生","高","必須バリデーション"
"131","UT-CPT-131","Captain::CustomTool","validates :endpoint_url, presence: true","異常系","endpoint_urlが空の場合バリデーションエラーになること","なし","endpoint_url: nil","バリデーションエラー発生","高","必須バリデーション"
"132","UT-CPT-132","Captain::CustomTool","JsonSchemaValidator for param_schema","正常系","param_schemaが有効なJSONスキーマの場合成功すること","param_schema: [{ name: 'id', type: 'string', description: 'ID' }]","custom_tool.valid?","バリデーション成功","高","スキーマバリデーション"
"133","UT-CPT-133","Captain::CustomTool","JsonSchemaValidator for param_schema","異常系","param_schemaに必須フィールドがない場合エラーになること","param_schema: [{ name: 'id' }]","custom_tool.valid?","バリデーションエラー発生","高","スキーマバリデーション"
"134","UT-CPT-134","Captain::CustomTool","scope :enabled","正常系","enabledスコープでenabled=trueのみフィルタされること","enabled=true/falseのCustomToolが存在","Captain::CustomTool.enabled","enabled=trueのCustomToolのみ返却される","中","スコープ"
"135","UT-CPT-135","Captain::CustomTool","to_tool_metadata","正常系","ツールメタデータが正しく生成されること","CustomTool設定済み","custom_tool.to_tool_metadata","id(slug), title, description, custom: trueを含むHashが返却される","中","メタデータ生成"
"136","UT-CPT-136","Captain::CustomTool","generate_slug","正常系","titleからslugが自動生成されること","title: 'My Custom Tool', slug未設定","custom_tool.valid?","slug: 'custom_my_custom_tool'が設定される","中","before_validation"
"137","UT-CPT-137","Captain::CustomTool","generate_slug","境界値","slug既存の場合はslugが変更されないこと","slug: 'existing_slug'","custom_tool.valid?","slugが変更されない","低","before_validation"
"138","UT-CPT-138","Captain::CustomTool","generate_slug","境界値","title空の場合はslug生成がスキップされること","title: nil, slug未設定","custom_tool.valid?","slugがnilのまま","低","before_validation"
"139","UT-CPT-139","Captain::CustomTool","find_unique_slug","正常系","重複する場合はランダム文字列が付加されること","同一base_slugのCustomToolが存在","custom_tool.valid?","'custom_title_xxxxxx'形式のslugが設定される","中","privateメソッド"
"140","UT-CPT-140","Captain::CustomTool","find_unique_slug","異常系","5回試行しても一意なslugが見つからない場合エラーになること","slug重複が5回連続発生","custom_tool.valid?","RecordNotUniqueエラーが発生","低","privateメソッド"
"141","UT-CPT-141","Captain::CustomTool","slug_exists?","正常系","同一account_idでslugが存在する場合trueを返却すること","同一slugのCustomToolが存在","custom_tool.send(:slug_exists?, 'existing_slug')","trueが返却される","低","privateメソッド"
"142","UT-CPT-142","Captain::CustomTool","slug_exists?","正常系","slugが存在しない場合falseを返却すること","slugが存在しない","custom_tool.send(:slug_exists?, 'new_slug')","falseが返却される","低","privateメソッド"
"143","UT-CPT-143","Captain::CustomTool (Concerns::Toolable)","tool","正常系","動的にツールクラスが生成されること","param_schema設定済み","custom_tool.tool(assistant)","Captain::Tools::HttpToolのサブクラスインスタンスが返却される","高","ツール生成"
"144","UT-CPT-144","Captain::CustomTool (Concerns::Toolable)","build_request_url","正常系","テンプレート変数が置換されてURLが構築されること","endpoint_url: 'https://api.example.com/{{id}}'","custom_tool.build_request_url({ 'id' => '123' })","'https://api.example.com/123'が返却される","高","URL構築"
"145","UT-CPT-145","Captain::CustomTool (Concerns::Toolable)","build_request_url","境界値","テンプレート変数がない場合はそのまま返却されること","endpoint_url: 'https://api.example.com/data'","custom_tool.build_request_url({})","endpoint_urlがそのまま返却される","中","URL構築"
"146","UT-CPT-146","Captain::CustomTool (Concerns::Toolable)","build_request_body","正常系","テンプレートからリクエストボディが構築されること","request_template: '{ ""id"": ""{{id}}"" }'","custom_tool.build_request_body({ 'id' => '123' })","'{ ""id"": ""123"" }'が返却される","高","ボディ構築"
"147","UT-CPT-147","Captain::CustomTool (Concerns::Toolable)","build_request_body","境界値","request_template空の場合nilを返却すること","request_template: nil","custom_tool.build_request_body({})","nilが返却される","中","ボディ構築"
"148","UT-CPT-148","Captain::CustomTool (Concerns::Toolable)","build_auth_headers - none","正常系","auth_type=noneの場合空ハッシュを返却すること","auth_type: 'none'","custom_tool.build_auth_headers","{}が返却される","中","認証ヘッダー"
"149","UT-CPT-149","Captain::CustomTool (Concerns::Toolable)","build_auth_headers - bearer","正常系","auth_type=bearerの場合Authorizationヘッダーが返却されること","auth_type: 'bearer', auth_config: { 'token' => 'xxx' }","custom_tool.build_auth_headers","{ 'Authorization' => 'Bearer xxx' }が返却される","高","認証ヘッダー"
"150","UT-CPT-150","Captain::CustomTool (Concerns::Toolable)","build_auth_headers - api_key header","正常系","auth_type=api_key(header)の場合カスタムヘッダーが返却されること","auth_type: 'api_key', auth_config: { 'location' => 'header', 'name' => 'X-API-Key', 'key' => 'xxx' }","custom_tool.build_auth_headers","{ 'X-API-Key' => 'xxx' }が返却される","高","認証ヘッダー"
"151","UT-CPT-151","Captain::CustomTool (Concerns::Toolable)","build_auth_headers - api_key query","正常系","auth_type=api_key(query)の場合空ハッシュが返却されること","auth_type: 'api_key', auth_config: { 'location' => 'query' }","custom_tool.build_auth_headers","{}が返却される","中","認証ヘッダー"
"152","UT-CPT-152","Captain::CustomTool (Concerns::Toolable)","build_basic_auth_credentials","正常系","auth_type=basicの場合資格情報が返却されること","auth_type: 'basic', auth_config: { 'username' => 'user', 'password' => 'pass' }","custom_tool.build_basic_auth_credentials","['user', 'pass']が返却される","高","Basic認証"
"153","UT-CPT-153","Captain::CustomTool (Concerns::Toolable)","build_basic_auth_credentials","正常系","auth_type!=basicの場合nilを返却すること","auth_type: 'bearer'","custom_tool.build_basic_auth_credentials","nilが返却される","中","Basic認証"
"154","UT-CPT-154","Captain::CustomTool (Concerns::Toolable)","build_metadata_headers","正常系","メタデータヘッダーが構築されること","state: { account_id: 1, assistant_id: 2 }","custom_tool.build_metadata_headers(state)","X-Chatwoot-Account-Id, X-Chatwoot-Assistant-Id等が含まれる","中","メタデータヘッダー"
"155","UT-CPT-155","Captain::CustomTool (Concerns::Toolable)","add_conversation_headers","正常系","会話関連ヘッダーが追加されること","conversation: { id: 1, display_id: 10 }","custom_tool.add_conversation_headers({}, conversation)","X-Chatwoot-Conversation-Id, Display-Idが含まれる","低","メタデータヘッダー"
"156","UT-CPT-156","Captain::CustomTool (Concerns::Toolable)","add_contact_headers","正常系","連絡先関連ヘッダーが追加されること","contact: { id: 1, email: 'test@example.com', phone_number: '+1234' }","custom_tool.add_contact_headers({}, contact)","X-Chatwoot-Contact-Id, Email, Phoneが含まれる","低","メタデータヘッダー"
"157","UT-CPT-157","Captain::CustomTool (Concerns::Toolable)","format_response","正常系","レスポンステンプレートで整形されること","response_template: '{{ response.data }}'","custom_tool.format_response('{""data"": ""value""}')","'value'が返却される","中","レスポンス整形"
"158","UT-CPT-158","Captain::CustomTool (Concerns::Toolable)","format_response","境界値","response_template空の場合はそのまま返却すること","response_template: nil","custom_tool.format_response('raw_response')","'raw_response'が返却される","中","レスポンス整形"
"159","UT-CPT-159","Captain::CustomTool (Concerns::Toolable)","render_template","異常系","Liquidテンプレートエラーの場合例外が発生すること","テンプレート構文エラー","custom_tool.send(:render_template, '{{ invalid }', {})","Template rendering failed例外が発生","中","テンプレートレンダリング"
"160","UT-CPT-160","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","正常系","HTTPSの有効なURLの場合成功すること","endpoint_url: 'https://api.example.com'","custom_tool.valid?","バリデーション成功","高","エンドポイントバリデーション"
"161","UT-CPT-161","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","異常系","HTTPの場合エラーになること","endpoint_url: 'http://api.example.com'","custom_tool.valid?","'must use HTTPS protocol'エラー","高","エンドポイントバリデーション"
"162","UT-CPT-162","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","異常系","localhostの場合エラーになること","endpoint_url: 'https://localhost/api'","custom_tool.valid?","'cannot use disallowed hostname'エラー","高","エンドポイントバリデーション"
"163","UT-CPT-163","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","異常系","IPアドレスの場合エラーになること","endpoint_url: 'https://192.168.1.1/api'","custom_tool.valid?","'cannot be an IP address'エラー","高","エンドポイントバリデーション"
"164","UT-CPT-164","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","異常系","FRONTEND_URLと同じホストの場合エラーになること","endpoint_url: FRONTEND_URLと同じホスト","custom_tool.valid?","'cannot point to the application itself'エラー","高","エンドポイントバリデーション"
"165","UT-CPT-165","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","異常系",".localで終わるホストの場合エラーになること","endpoint_url: 'https://myserver.local/api'","custom_tool.valid?","'cannot use disallowed hostname'エラー","中","エンドポイントバリデーション"
"166","UT-CPT-166","Captain::CustomTool (Concerns::SafeEndpointValidatable)","validate_safe_endpoint_url","異常系","非ASCII文字を含むホストの場合エラーになること","endpoint_url: 'https://例え.com/api'","custom_tool.valid?","'hostname cannot contain non-ASCII characters'エラー","中","エンドポイントバリデーション"
"167","UT-CPT-167","Captain::CustomTool (Concerns::SafeEndpointValidatable)","parse_endpoint_uri","正常系","Liquidテンプレート構文が除去されてパースされること","endpoint_url: 'https://api.example.com/{{id}}'","custom_tool.valid?","バリデーション成功（placeholderに置換されてパース）","中","URIパース"
"168","UT-CPT-168","Captain::CustomTool (Concerns::SafeEndpointValidatable)","parse_endpoint_uri","異常系","無効なURIの場合エラーになること","endpoint_url: 'not a valid url'","custom_tool.valid?","'must be a valid URL'エラー","中","URIパース"
"1","UT-ENC-001","Channel::Voice","phone_number validation","正常系","E.164形式の電話番号が登録できること","なし","phone_number=""+81901234567""","バリデーションが通過する","高","国際電話番号フォーマット"
"2","UT-ENC-002","Channel::Voice","phone_number validation","異常系","プラス記号なしの電話番号が拒否されること","なし","phone_number=""81901234567""","バリデーションエラー（format）","高","E.164フォーマット必須"
"3","UT-ENC-003","Channel::Voice","phone_number validation","異常系","空の電話番号が拒否されること","なし","phone_number=nil","バリデーションエラー（presence）","高","必須項目チェック"
"4","UT-ENC-004","Channel::Voice","phone_number validation","異常系","重複した電話番号が拒否されること","同じ電話番号のチャネルが存在","phone_number=""+81901234567""（既存）","バリデーションエラー（uniqueness）","高","一意性制約"
"5","UT-ENC-005","Channel::Voice","phone_number validation","境界値","最小桁数（+と2桁）の電話番号","なし","phone_number=""+12""","バリデーションが通過する","中","境界値テスト"
"6","UT-ENC-006","Channel::Voice","phone_number validation","境界値","最大桁数（+と15桁）の電話番号","なし","phone_number=""+123456789012345""","バリデーションが通過する","中","E.164最大長"
"7","UT-ENC-007","Channel::Voice","phone_number validation","境界値","最大桁数超過（+と16桁）の電話番号","なし","phone_number=""+1234567890123456""","バリデーションエラー（format）","中","E.164最大長超過"
"8","UT-ENC-008","Channel::Voice","phone_number validation","異常系","+0で始まる電話番号が拒否されること","なし","phone_number=""+0123456789""","バリデーションエラー（format）","中","国番号0は無効"
"9","UT-ENC-009","Channel::Voice","provider validation","正常系","providerが設定されていること","なし","provider=""twilio""","バリデーションが通過する","高","必須項目"
"10","UT-ENC-010","Channel::Voice","provider validation","異常系","空のproviderが拒否されること","なし","provider=nil","バリデーションエラー（presence）","高","必須項目チェック"
"11","UT-ENC-011","Channel::Voice","provider_config validation","正常系","provider_configが設定されていること","なし","provider_config={account_sid: ""xxx"", ...}","バリデーションが通過する","高","必須項目"
"12","UT-ENC-012","Channel::Voice","provider_config validation","異常系","空のprovider_configが拒否されること","なし","provider_config=nil","バリデーションエラー（presence）","高","必須項目チェック"
"13","UT-ENC-013","Channel::Voice","validate_twilio_config","正常系","必要なTwilio設定がすべて存在する場合","provider=""twilio""","provider_config={account_sid, auth_token, api_key_sid, api_key_secret, twiml_app_sid}","バリデーションが通過する","高","Twilio必須キー検証"
"14","UT-ENC-014","Channel::Voice","validate_twilio_config","異常系","account_sidが欠けている場合","provider=""twilio""","provider_config={auth_token, api_key_sid, api_key_secret, twiml_app_sid}","バリデーションエラー（account_sid is required）","高","Twilio必須キー検証"
"15","UT-ENC-015","Channel::Voice","validate_twilio_config","異常系","auth_tokenが欠けている場合","provider=""twilio""","provider_config={account_sid, api_key_sid, api_key_secret, twiml_app_sid}","バリデーションエラー（auth_token is required）","高","Twilio必須キー検証"
"16","UT-ENC-016","Channel::Voice","validate_twilio_config","異常系","api_key_sidが欠けている場合","provider=""twilio""","provider_config={account_sid, auth_token, api_key_secret, twiml_app_sid}","バリデーションエラー（api_key_sid is required）","高","Twilio必須キー検証"
"17","UT-ENC-017","Channel::Voice","validate_twilio_config","異常系","api_key_secretが欠けている場合","provider=""twilio""","provider_config={account_sid, auth_token, api_key_sid, twiml_app_sid}","バリデーションエラー（api_key_secret is required）","高","Twilio必須キー検証"
"18","UT-ENC-018","Channel::Voice","validate_twilio_config","異常系","twiml_app_sidが欠けている場合","provider=""twilio""","provider_config={account_sid, auth_token, api_key_sid, api_key_secret}","バリデーションエラー（twiml_app_sid is required）","高","Twilio必須キー検証"
"19","UT-ENC-019","Channel::Voice","account_id validation","正常系","account_idが設定されていること（Channelable）","アカウントが存在","account_id=1","バリデーションが通過する","高","Channelable由来"
"20","UT-ENC-020","Channel::Voice","account_id validation","異常系","空のaccount_idが拒否されること（Channelable）","なし","account_id=nil","バリデーションエラー（presence）","高","Channelable由来"
"21","UT-ENC-021","Channel::Voice","account relation","正常系","accountリレーションが正しく取得できること（Channelable）","関連するアカウントが存在","channel.account","Accountオブジェクトが返却される","中","Channelable由来"
"22","UT-ENC-022","Channel::Voice","inbox relation","正常系","inboxリレーションが正しく取得できること（Channelable）","関連するInboxが存在","channel.inbox","Inboxオブジェクトが返却される","中","Channelable由来"
"23","UT-ENC-023","Channel::Voice","inbox relation","正常系","チャネル削除時にinboxが非同期削除されること（Channelable）","関連するInboxが存在","channel.destroy","Inboxがdestroy_asyncで削除される","中","Channelable dependent設定"
"24","UT-ENC-024","Channel::Voice","name","正常系","チャネル名が正しく返却されること","phone_number=""+81901234567""","channel.name","""Voice (+81901234567)""が返却される","低","表示用メソッド"
"25","UT-ENC-025","Channel::Voice","messaging_window_enabled?","正常系","falseが返却されること","なし","channel.messaging_window_enabled?","falseが返却される","低","音声チャネルはメッセージングウィンドウ無効"
"26","UT-ENC-026","Channel::Voice","initiate_call","正常系","Twilioプロバイダーで電話発信できること","provider=""twilio""、有効な設定","initiate_call(to: ""+81909876543"")","Twilio::Adapterが呼び出される","高","電話発信機能"
"27","UT-ENC-027","Channel::Voice","initiate_call","正常系","conference_sidを指定して電話発信できること","provider=""twilio""、有効な設定","initiate_call(to: ""+81909876543"", conference_sid: ""CFxxx"")","conference_sidがAdapterに渡される","高","会議通話機能"
"28","UT-ENC-028","Channel::Voice","initiate_call","正常系","agent_idを指定して電話発信できること","provider=""twilio""、有効な設定","initiate_call(to: ""+81909876543"", agent_id: 1)","agent_idがAdapterに渡される","高","エージェント指定発信"
"29","UT-ENC-029","Channel::Voice","initiate_call","異常系","未サポートプロバイダーでエラーになること","provider=""unknown""","initiate_call(to: ""+81909876543"")","例外""Unsupported voice provider: unknown""が発生","高","プロバイダー検証"
"30","UT-ENC-030","Channel::Voice","voice_call_webhook_url","正常系","コールウェブフックURLが正しく生成されること","phone_number=""+81901234567""","channel.voice_call_webhook_url","twilio_voice_call_url(phone: ""81901234567"")が返却される","中","Webhook URL生成"
"31","UT-ENC-031","Channel::Voice","voice_call_webhook_url","正常系","電話番号から+が除去されること","phone_number=""+12025551234""","channel.voice_call_webhook_url","phone=""12025551234""でURLが生成される","中","プレフィックス除去"
"32","UT-ENC-032","Channel::Voice","voice_status_webhook_url","正常系","ステータスウェブフックURLが正しく生成されること","phone_number=""+81901234567""","channel.voice_status_webhook_url","twilio_voice_status_url(phone: ""81901234567"")が返却される","中","Webhook URL生成"
"33","UT-ENC-033","Channel::Voice","voice_status_webhook_url","正常系","電話番号から+が除去されること","phone_number=""+12025551234""","channel.voice_status_webhook_url","phone=""12025551234""でURLが生成される","中","プレフィックス除去"
"34","UT-ENC-034","Channel::Voice","provider_config_hash","正常系","Hashの場合そのまま返却されること","provider_config={key: ""value""}","channel.provider_config_hash","{key: ""value""}が返却される","中","型変換なし"
"35","UT-ENC-035","Channel::Voice","provider_config_hash","正常系","Hash以外の場合JSON.parseされること","provider_config=""{\""key\"": \""value\""}""","channel.provider_config_hash","{""key"" => ""value""}が返却される","中","JSON文字列からの変換"
"36","UT-ENC-036","Channel::Voice","twilio?","正常系","providerがtwilioの場合trueが返却されること","provider=""twilio""","channel.send(:twilio?)","trueが返却される","低","プライベートメソッド"
"37","UT-ENC-037","Channel::Voice","twilio?","正常系","providerがtwilio以外の場合falseが返却されること","provider=""other""","channel.send(:twilio?)","falseが返却される","低","プライベートメソッド"
"38","UT-ENC-038","Channel::Voice","provision_twilio_on_create","正常系","新規作成時にTwilio TwiML Appがプロビジョニングされること","provider=""twilio""、有効な設定、create実行","channel.create","provider_configにtwiml_app_sidが追加される","高","自動プロビジョニング"
"39","UT-ENC-039","Channel::Voice","provision_twilio_on_create","異常系","プロビジョニング失敗時にエラーが記録されること","provider=""twilio""、Twilioサービスがエラー","channel.create","エラーログが出力され、baseにエラーが追加される","高","エラーハンドリング"
"40","UT-ENC-040","Channel::Voice","provision_twilio_on_create","正常系","app_sidが空の場合provider_configが更新されないこと","provider=""twilio""、サービスが空を返す","channel.create","provider_configが変更されない","中","空レスポンスの処理"
"41","UT-ENC-041","Channel::Voice","provision_twilio_on_create","正常系","provider=""other""の場合プロビジョニングがスキップされること","provider=""other""","channel.create","provision_twilio_on_createが呼び出されない","中","条件付きコールバック"
"42","UT-ENC-042","Channel::Voice","validate_provider_config","正常系","provider_configが空の場合バリデーションがスキップされること","provider=""twilio""","provider_config=nil（presenceは別でチェック）","validate_twilio_configが呼び出されない","中","早期リターン"
"43","UT-ENC-043","Channel::Voice","table_name","正常系","テーブル名がchannel_voiceであること","なし","Channel::Voice.table_name","""channel_voice""が返却される","低","テーブル名設定"
"44","UT-ENC-044","Channel::Voice","EDITABLE_ATTRS","正常系","編集可能属性が正しく定義されていること","なし","Channel::Voice::EDITABLE_ATTRS","[:phone_number, :provider, {provider_config: {}}]が返却される","低","定数定義"
"45","UT-ENC-045","Channel::Voice","create_audit_log_entry","正常系","更新時にaudit_log_entryが作成されること（Channelable）","チャネルが存在","channel.update(phone_number: ""+81909999999"")","create_audit_log_entryが呼び出される","中","Channelable コールバック"
"1","UT-EMC-001","Concerns::CaptainToolsHelpers","built_in_agent_tools","正常系","組み込みエージェントツール一覧が取得できること","tools.ymlに有効なツール設定が存在する","なし","ツール情報（id, title, description, icon）を含むハッシュ配列が返却される","高","クラスメソッド、メモ化あり"
"2","UT-EMC-002","Concerns::CaptainToolsHelpers","built_in_agent_tools","正常系","結果がメモ化されること","初回呼び出し完了済み","なし","2回目以降は同じインスタンスが返却される","中","@built_in_agent_toolsインスタンス変数"
"3","UT-EMC-003","Concerns::CaptainToolsHelpers","built_in_agent_tools","異常系","解決できないツールがフィルタリングされること","tools.ymlに存在しないクラスのツールが定義されている","なし","解決できないツールは除外され、警告ログが出力される","中","filter_mapによるnil除外"
"4","UT-EMC-004","Concerns::CaptainToolsHelpers","resolve_tool_class","正常系","スネークケースのIDからツールクラスが解決できること","Captain::Tools::SomeToolが存在する","tool_id=""some""","Captain::Tools::SomeToolクラスが返却される","高","classifyメソッドでPascalCase変換"
"5","UT-EMC-005","Concerns::CaptainToolsHelpers","resolve_tool_class","異常系","存在しないツールIDの場合nilが返却されること","対応するクラスが存在しない","tool_id=""nonexistent""","nilが返却される","高","safe_constantizeによる安全な解決"
"6","UT-EMC-006","Concerns::CaptainToolsHelpers","resolve_tool_class","正常系","アンダースコア区切りのIDが正しく解決されること","Captain::Tools::MyCustomToolが存在する","tool_id=""my_custom""","Captain::Tools::MyCustomToolクラスが返却される","中","複合語のID処理"
"7","UT-EMC-007","Concerns::CaptainToolsHelpers","built_in_tool_ids","正常系","組み込みツールIDの配列が取得できること","built_in_agent_toolsが正常に動作する","なし","ツールIDの文字列配列が返却される","中","クラスメソッド"
"8","UT-EMC-008","Concerns::CaptainToolsHelpers","built_in_tool_ids","正常系","結果がメモ化されること","初回呼び出し完了済み","なし","2回目以降は同じインスタンスが返却される","低","@built_in_tool_idsインスタンス変数"
"9","UT-EMC-009","Concerns::CaptainToolsHelpers","extract_tool_ids_from_text","正常系","テキストからツールIDが抽出できること","なし","text=""[Tool](tool://my_tool)""","[""my_tool""]が返却される","高","TOOL_REFERENCE_REGEX使用"
"10","UT-EMC-010","Concerns::CaptainToolsHelpers","extract_tool_ids_from_text","正常系","複数のツール参照が抽出できること","なし","text=""[A](tool://t1) [B](tool://t2)""","[""t1"", ""t2""]が返却される","高","複数マッチ処理"
"11","UT-EMC-011","Concerns::CaptainToolsHelpers","extract_tool_ids_from_text","正常系","重複するツールIDが一意化されること","なし","text=""[A](tool://t1) [B](tool://t1)""","[""t1""]が返却される","中","uniqメソッド"
"12","UT-EMC-012","Concerns::CaptainToolsHelpers","extract_tool_ids_from_text","境界値","空文字列の場合は空配列が返却されること","なし","text=""""","[]が返却される","中","blank?チェック"
"13","UT-EMC-013","Concerns::CaptainToolsHelpers","extract_tool_ids_from_text","境界値","nilの場合は空配列が返却されること","なし","text=nil","[]が返却される","中","blank?チェック"
"14","UT-EMC-014","Concerns::CaptainToolsHelpers","extract_tool_ids_from_text","正常系","ツール参照がないテキストの場合は空配列が返却されること","なし","text=""Hello World""","[]が返却される","中","マッチなしケース"
"15","UT-EMC-015","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","正常系","有効なHTTPS URLがバリデーションを通過すること","なし","endpoint_url=""https://example.com/api""","エラーなし","高","正常系バリデーション"
"16","UT-EMC-016","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","HTTP URLがバリデーションエラーになること","なし","endpoint_url=""http://example.com/api""","endpoint_url: must use HTTPS protocol","高","スキーム検証"
"17","UT-EMC-017","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","localhostがバリデーションエラーになること","なし","endpoint_url=""https://localhost/api""","endpoint_url: cannot use disallowed hostname","高","禁止ホスト検証"
"18","UT-EMC-018","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系",".localドメインがバリデーションエラーになること","なし","endpoint_url=""https://server.local/api""","endpoint_url: cannot use disallowed hostname","高","正規表現パターン検証"
"19","UT-EMC-019","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","FRONTEND_URLと同じホストがバリデーションエラーになること","FRONTEND_URL=http://myapp.comが設定されている","endpoint_url=""https://myapp.com/api""","endpoint_url: cannot point to the application itself","高","自己参照防止"
"20","UT-EMC-020","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","IPv4アドレスがバリデーションエラーになること","なし","endpoint_url=""https://192.168.1.1/api""","endpoint_url: cannot be an IP address, must be a hostname","高","IPアドレス検証"
"21","UT-EMC-021","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","IPv6アドレスがバリデーションエラーになること","なし","endpoint_url=""https://[::1]/api""","endpoint_url: cannot be an IP address, must be a hostname","高","IPv6検証"
"22","UT-EMC-022","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","Unicodeホスト名がバリデーションエラーになること","なし","endpoint_url=""https://exаmple.com/api""（キリル文字のa）","endpoint_url: hostname cannot contain non-ASCII characters","高","ホモグリフ攻撃対策"
"23","UT-EMC-023","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","境界値","空のendpoint_urlはバリデーションをスキップすること","なし","endpoint_url=""""","エラーなし","中","blank?による早期リターン"
"24","UT-EMC-024","Concerns::SafeEndpointValidatable","validate_safe_endpoint_url","異常系","不正なURL形式がバリデーションエラーになること","なし","endpoint_url=""not-a-url""","endpoint_url: must be a valid URL","中","URI.parseエラー"
"25","UT-EMC-025","Concerns::SafeEndpointValidatable","parse_endpoint_uri","正常系","Liquid変数を含むURLが正しくパースされること","なし","endpoint_url=""https://api.com/{{id}}""","Liquid変数がplaceholderに置換されてパースされる","中","Liquidテンプレート対応"
"26","UT-EMC-026","Concerns::SafeEndpointValidatable","parse_endpoint_uri","異常系","不正なURLでnilが返却されること","なし","endpoint_url="":::invalid:::""","nilが返却される","中","URI::InvalidURIError処理"
"27","UT-EMC-027","Concerns::SafeEndpointValidatable","validate_endpoint_host","異常系","ホスト名がない場合エラーになること","なし","endpoint_url=""https:///path""","endpoint_url: must have a valid hostname","中","空ホスト検証"
"28","UT-EMC-028","Concerns::Agentable","agent","正常系","Agents::Agentインスタンスが正しく生成されること","agent_nameとprompt_contextが実装されている","なし","適切な設定でAgents::Agentが生成される","高","メインメソッド"
"29","UT-EMC-029","Concerns::Agentable","agent","正常系","temperatureが正しく設定されること","temperature=0.5が設定されている","なし","temperature: 0.5でAgentが生成される","中","to_f変換"
"30","UT-EMC-030","Concerns::Agentable","agent","正常系","temperatureが未設定の場合デフォルト値が使用されること","temperatureが未設定","なし","temperature: 0.7でAgentが生成される","中","デフォルト値フォールバック"
"31","UT-EMC-031","Concerns::Agentable","agent_instructions","正常系","コンテキストなしでプロンプトがレンダリングされること","prompt_contextが実装されている","context=nil","prompt_contextのみでレンダリングされる","高","基本レンダリング"
"32","UT-EMC-032","Concerns::Agentable","agent_instructions","正常系","コンテキストありでプロンプトがレンダリングされること","prompt_contextが実装されている","context=conversation/contactデータ付き","conversation/contactデータがマージされてレンダリングされる","高","拡張コンテキスト"
"33","UT-EMC-033","Concerns::Agentable","agent_name","異常系","未実装の場合NotImplementedErrorがスローされること","サブクラスで未実装","なし","NotImplementedErrorがスローされる","高","抽象メソッド"
"34","UT-EMC-034","Concerns::Agentable","template_name","正常系","クラス名からテンプレート名が生成されること","MyCustomAgentクラスに適用","なし","""my_custom_agent""が返却される","中","demodulize.underscore"
"35","UT-EMC-035","Concerns::Agentable","agent_tools","正常系","デフォルトで空配列が返却されること","オーバーライドなし","なし","[]が返却される","低","デフォルト実装"
"36","UT-EMC-036","Concerns::Agentable","agent_model","正常系","InstallationConfigからモデル名が取得されること","CAPTAIN_OPEN_AI_MODELが設定されている","なし","設定されたモデル名が返却される","中","設定値取得"
"37","UT-EMC-037","Concerns::Agentable","agent_model","正常系","設定がない場合デフォルトモデルが使用されること","CAPTAIN_OPEN_AI_MODELが未設定","なし","LlmConstants::DEFAULT_MODELが返却される","中","デフォルトフォールバック"
"38","UT-EMC-038","Concerns::Agentable","prompt_context","異常系","未実装の場合NotImplementedErrorがスローされること","サブクラスで未実装","なし","NotImplementedErrorがスローされる","高","抽象メソッド"
"39","UT-EMC-039","Concerns::Toolable","tool","正常系","動的にツールクラスが生成されること","slug, description, param_schemaが設定されている","assistant=有効なアシスタント","Captain::Tools::HttpToolを継承したクラスが生成される","高","動的クラス生成"
"40","UT-EMC-040","Concerns::Toolable","tool","正常系","パラメータスキーマが正しく設定されること","param_schema=[{name: ""query"", type: ""string"", ...}]","assistant=有効なアシスタント","queryパラメータが設定されたツールが生成される","高","paramメソッド呼び出し"
"41","UT-EMC-041","Concerns::Toolable","tool","正常系","既存の定数が更新されること","同じslugで2回目の呼び出し","assistant=有効なアシスタント","既存の定数が削除され、新しいクラスで置換される","中","remove_const処理"
"42","UT-EMC-042","Concerns::Toolable","build_request_url","正常系","Liquid変数がパラメータで置換されること","endpoint_url=""https://api.com/{{id}}""","params={id: ""123""}","https://api.com/123が返却される","高","テンプレートレンダリング"
"43","UT-EMC-043","Concerns::Toolable","build_request_url","正常系","変数がないURLはそのまま返却されること","endpoint_url=""https://api.com/static""","params={}","https://api.com/staticが返却される","中","早期リターン"
"44","UT-EMC-044","Concerns::Toolable","build_request_url","境界値","空のURLはそのまま返却されること","endpoint_url=""""","params={}","""""が返却される","低","blank?チェック"
"45","UT-EMC-045","Concerns::Toolable","build_request_body","正常系","リクエストテンプレートがレンダリングされること","request_template=""{\"\"query\"\": \"\"{{q}}\"\"}""","params={q: ""test""}","JSONボディが生成される","高","テンプレートレンダリング"
"46","UT-EMC-046","Concerns::Toolable","build_request_body","境界値","テンプレートが空の場合nilが返却されること","request_template=""""","params={}","nilが返却される","中","blank?チェック"
"47","UT-EMC-047","Concerns::Toolable","build_auth_headers","正常系","Bearer認証ヘッダーが生成されること","auth_type=""bearer"", auth_config={token: ""abc123""}","なし","{""Authorization"": ""Bearer abc123""}が返却される","高","Bearer認証"
"48","UT-EMC-048","Concerns::Toolable","build_auth_headers","正常系","APIキー（ヘッダー）認証が生成されること","auth_type=""api_key"", auth_config={location: ""header"", name: ""X-API-Key"", key: ""secret""}","なし","{""X-API-Key"": ""secret""}が返却される","高","APIキー認証"
"49","UT-EMC-049","Concerns::Toolable","build_auth_headers","正常系","認証なしの場合は空ハッシュが返却されること","auth_type=""none""またはauth_none?=true","なし","{}が返却される","中","認証なしケース"
"50","UT-EMC-050","Concerns::Toolable","build_auth_headers","正常系","APIキー（非ヘッダー）の場合は空ハッシュが返却されること","auth_type=""api_key"", auth_config={location: ""query""}","なし","{}が返却される","中","クエリパラメータ認証"
"51","UT-EMC-051","Concerns::Toolable","build_basic_auth_credentials","正常系","Basic認証情報が返却されること","auth_type=""basic"", auth_config={username: ""user"", password: ""pass""}","なし","[""user"", ""pass""]が返却される","高","Basic認証"
"52","UT-EMC-052","Concerns::Toolable","build_basic_auth_credentials","正常系","Basic認証以外の場合はnilが返却されること","auth_type=""bearer""","なし","nilが返却される","中","認証タイプチェック"
"53","UT-EMC-053","Concerns::Toolable","build_metadata_headers","正常系","基本メタデータヘッダーが生成されること","slug=""my-tool""","state={account_id: 1, assistant_id: 2}","X-Chatwoot-Account-Id, X-Chatwoot-Assistant-Id, X-Chatwoot-Tool-Slugが設定される","高","メタデータヘッダー"
"54","UT-EMC-054","Concerns::Toolable","build_metadata_headers","正常系","会話メタデータヘッダーが追加されること","なし","state={conversation: {id: 10, display_id: 20}}","X-Chatwoot-Conversation-Id, X-Chatwoot-Conversation-Display-Idが設定される","中","会話ヘッダー"
"55","UT-EMC-055","Concerns::Toolable","build_metadata_headers","正常系","連絡先メタデータヘッダーが追加されること","なし","state={contact: {id: 5, email: ""a@b.com"", phone_number: ""+1234""}}","X-Chatwoot-Contact-Id, X-Chatwoot-Contact-Email, X-Chatwoot-Contact-Phoneが設定される","中","連絡先ヘッダー"
"56","UT-EMC-056","Concerns::Toolable","format_response","正常系","レスポンステンプレートがレンダリングされること","response_template=""Result: {{response.data}}""","raw_response_body=""{\"\"data\"\": \"\"value\"\"}""","""Result: value""が返却される","高","レスポンスフォーマット"
"57","UT-EMC-057","Concerns::Toolable","format_response","正常系","テンプレートがない場合は生のレスポンスが返却されること","response_template=""""","raw_response_body=""raw data""","""raw data""が返却される","中","早期リターン"
"58","UT-EMC-058","Concerns::Toolable","render_template","異常系","Liquid構文エラーで例外がスローされること","なし","template=""{% invalid %}""","例外がスローされ、エラーログが出力される","高","Liquid::SyntaxError処理"
"59","UT-EMC-059","Concerns::Toolable","render_template","異常系","未定義変数で例外がスローされること","strict_variables=true","template=""{{undefined_var}}""","例外がスローされる","中","Liquid::UndefinedVariable処理"
"60","UT-EMC-060","Concerns::Toolable","parse_response_body","正常系","有効なJSONがパースされること","なし","body=""{\"\"key\"\": \"\"value\"\"}""","{""key"": ""value""}ハッシュが返却される","中","JSONパース"
"61","UT-EMC-061","Concerns::Toolable","parse_response_body","正常系","無効なJSONは文字列のまま返却されること","なし","body=""not json""","""not json""がそのまま返却される","中","JSON::ParserError処理"
"1","UT-ENT-001","Enterprise::Account","manually_managed_features","正常系","仮想属性メソッドが正常に呼び出せること","なし","なし","nilが返却される","低","administrate互換用の空メソッド"
"2","UT-ENT-002","Enterprise::Account","mark_for_deletion","正常系","手動削除理由で削除マーク設定が成功すること","アカウントが存在","reason='manual_deletion'","custom_attributesにmarked_for_deletion_atとmarked_for_deletion_reasonが設定される","高","削除予約機能"
"3","UT-ENT-003","Enterprise::Account","mark_for_deletion","正常系","非アクティブ理由で削除マーク設定が成功すること","アカウントが存在","reason='inactivity'","custom_attributesにinactivityが設定される","高","削除予約機能"
"4","UT-ENT-004","Enterprise::Account","mark_for_deletion","正常系","不正な理由が渡された場合inactivityに変換されること","アカウントが存在","reason='invalid_reason'","marked_for_deletion_reasonがinactivityになる","中","入力値のサニタイズ"
"5","UT-ENT-005","Enterprise::Account","mark_for_deletion","正常系","削除マーク成功時に通知メールが送信されること","アカウントが存在","reason='manual_deletion'","AdministratorNotifications::AccountNotificationMailerが呼び出される","高","通知機能"
"6","UT-ENT-006","Enterprise::Account","unmark_for_deletion","正常系","削除マークが解除されること","削除マークが設定済み","なし","custom_attributesからmarked_for_deletion_atとmarked_for_deletion_reasonが削除される","高","削除取り消し機能"
"7","UT-ENT-007","Enterprise::Account","unmark_for_deletion","境界値","削除マークが設定されていない場合も正常終了すること","削除マークなし","なし","エラーなく処理が完了する","中","冪等性確認"
"8","UT-ENT-008","Enterprise::Account","saml_enabled?","正常系","SAML設定が有効な場合trueが返却されること","saml_settingsが存在しsaml_enabled?がtrue","なし","trueが返却される","高","認証機能"
"9","UT-ENT-009","Enterprise::Account","saml_enabled?","正常系","SAML設定が無効な場合falseが返却されること","saml_settingsが存在しsaml_enabled?がfalse","なし","falseが返却される","高","認証機能"
"10","UT-ENT-010","Enterprise::Account","saml_enabled?","境界値","saml_settingsがnilの場合falseが返却されること","saml_settingsがnil","なし","falseが返却される","高","null安全性"
"11","UT-ENT-011","Enterprise::AccountUser","permissions","正常系","カスタムロールがある場合権限にcustom_roleが追加されること","custom_roleが設定済み","なし","custom_roleの権限 + ['custom_role']が返却される","高","権限管理"
"12","UT-ENT-012","Enterprise::AccountUser","permissions","正常系","カスタムロールがない場合親クラスの権限が返却されること","custom_roleがnil","なし","superの結果が返却される","高","権限管理"
"13","UT-ENT-013","Enterprise::ActivityMessageHandler","automation_status_change_activity_content","正常系","Captain::Assistantによる解決時のメッセージが返却されること","Current.executed_byがCaptain::Assistantでresolved?がtrue","なし","captain.resolvedのi18nメッセージが返却される","中","アクティビティログ"
"14","UT-ENT-014","Enterprise::ActivityMessageHandler","automation_status_change_activity_content","正常系","Captain::Assistantによるオープン時のメッセージが返却されること","Current.executed_byがCaptain::Assistantでopen?がtrue","なし","captain.openのi18nメッセージが返却される","中","アクティビティログ"
"15","UT-ENT-015","Enterprise::ActivityMessageHandler","automation_status_change_activity_content","正常系","Captain::Assistant以外の場合親クラスのメソッドが呼ばれること","Current.executed_byがUser","なし","superの結果が返却される","中","アクティビティログ"
"16","UT-ENT-016","Enterprise::ApplicationRecord","droppables","正常系","SlaPolicyが追加されたドロップ可能リストが返却されること","なし","なし","親クラスのdroppables + ['SlaPolicy']が返却される","低","ドロップ対象設定"
"17","UT-ENT-017","Enterprise::AuditLog","log_additional_information","正常系","Account監査時にassociated_typeとusernameが設定されること","auditable_type='Account'でauditable_idが存在","なし","associated_type、associated_id、usernameが更新される","高","監査ログ"
"18","UT-ENT-018","Enterprise::AuditLog","log_additional_information","正常系","Account以外の監査時にusernameのみが設定されること","auditable_type='Inbox'","なし","usernameのみが更新される","高","監査ログ"
"19","UT-ENT-019","Enterprise::AuditLog","log_additional_information","境界値","userがnilの場合usernameがnilになること","userがnil","なし","usernameがnilで設定される","中","null安全性"
"20","UT-ENT-020","Enterprise::AutomationRule","conditions_attributes","正常系","sla_policy_idが条件属性に追加されること","なし","なし","親クラスの条件属性 + ['sla_policy_id']が返却される","中","自動化ルール拡張"
"21","UT-ENT-021","Enterprise::AutomationRule","actions_attributes","正常系","add_slaがアクション属性に追加されること","なし","なし","親クラスのアクション属性 + ['add_sla']が返却される","中","自動化ルール拡張"
"22","UT-ENT-022","Enterprise::Channelable","create_audit_log_entry","正常系","変更があった場合に監査ログが作成されること","inboxが存在し変更がある","saved_changesに変更あり","Enterprise::AuditLogが作成される","高","監査ログ"
"23","UT-ENT-023","Enterprise::Channelable","create_audit_log_entry","境界値","inboxがnilの場合ログが作成されないこと","inboxがnil","なし","early returnで処理終了","中","null安全性"
"24","UT-ENT-024","Enterprise::Channelable","create_audit_log_entry","境界値","変更がない場合ログが作成されないこと","saved_changesが空","なし","early returnで処理終了","中","冪等性確認"
"25","UT-ENT-025","Enterprise::Channelable","messaging_template_updates?","正常系","message_templates_last_updatedのみの変更でtrueが返却されること","なし","changes={'message_templates_last_updated'=>[old, new]}","trueが返却される","中","テンプレート更新判定"
"26","UT-ENT-026","Enterprise::Channelable","messaging_template_updates?","正常系","複数の変更がある場合falseが返却されること","なし","changes={'key1'=>[old, new], 'key2'=>[old, new]}","falseが返却される","中","テンプレート更新判定"
"27","UT-ENT-027","Enterprise::Conversation","list_of_keys","正常系","sla_policy_idがキーリストに追加されること","なし","なし","親クラスのキーリスト + ['sla_policy_id']が返却される","中","会話拡張"
"28","UT-ENT-028","Enterprise::Conversation","allowed_keys?","正常系","親クラスがtrueを返す場合trueが返却されること","superがtrue","なし","trueが返却される","中","会話拡張"
"29","UT-ENT-029","Enterprise::Conversation","allowed_keys?","正常系","call_statusの変更がある場合trueが返却されること","previous_changes['additional_attributes']にcall_statusを含む","なし","trueが返却される","中","通話ステータス対応"
"30","UT-ENT-030","Enterprise::Conversation","allowed_keys?","境界値","attrs_changeがArrayでない場合falseが返却されること","previous_changes['additional_attributes']がnil","なし","falseが返却される","中","型チェック"
"31","UT-ENT-031","Enterprise::Inbox","member_ids_with_assignment_capacity","正常系","自動割り当て無効時に親クラスの結果が返却されること","enable_auto_assignment?がfalse","なし","superの結果が返却される","高","エージェント割り当て"
"32","UT-ENT-032","Enterprise::Inbox","member_ids_with_assignment_capacity","正常系","上限超過エージェントが除外されること","enable_auto_assignment?がtrue、max_assignment_limitが5","なし","上限超過エージェントを除いたメンバーIDリストが返却される","高","エージェント割り当て"
"33","UT-ENT-033","Enterprise::Inbox","member_ids_with_assignment_capacity","境界値","max_assignment_limitが未設定の場合全員が返却されること","max_assignment_limitがblank","なし","superの結果がそのまま返却される","中","設定なし時の挙動"
"34","UT-ENT-034","Enterprise::Inbox","active_bot?","正常系","親クラスのactive_bot?がtrueの場合trueが返却されること","superがtrue","なし","trueが返却される","中","ボット判定"
"35","UT-ENT-035","Enterprise::Inbox","active_bot?","正常系","captain_active?がtrueの場合trueが返却されること","superがfalse、captain_active?がtrue","なし","trueが返却される","中","Captain対応"
"36","UT-ENT-036","Enterprise::Inbox","captain_active?","正常系","captain_assistantが存在しレスポンス残量がある場合trueが返却されること","captain_assistantが存在、current_available > 0","なし","trueが返却される","高","Captain判定"
"37","UT-ENT-037","Enterprise::Inbox","captain_active?","境界値","captain_assistantがnilの場合falseが返却されること","captain_assistantがnil","なし","falseが返却される","高","null安全性"
"38","UT-ENT-038","Enterprise::Inbox","captain_active?","境界値","レスポンス残量が0の場合falseが返却されること","captain_assistantが存在、current_available = 0","なし","falseが返却される","高","制限チェック"
"39","UT-ENT-039","Enterprise::Inbox","ensure_valid_max_assignment_limit","正常系","max_assignment_limitが正の値の場合エラーなし","auto_assignment_config['max_assignment_limit'] = 5","なし","エラーが追加されない","中","バリデーション"
"40","UT-ENT-040","Enterprise::Inbox","ensure_valid_max_assignment_limit","異常系","max_assignment_limitが0以下の場合エラーが追加されること","auto_assignment_config['max_assignment_limit'] = 0","なし","errors.add(:auto_assignment_config)が呼ばれる","中","バリデーション"
"41","UT-ENT-041","Enterprise::InboxAgentAvailability","member_ids_with_assignment_capacity","正常系","キャパシティフィルタリング無効時にmember_idsが返却されること","capacity_filtering_enabled?がfalse","なし","member_idsが返却される","高","エージェント割り当て"
"42","UT-ENT-042","Enterprise::InboxAgentAvailability","member_ids_with_assignment_capacity","正常系","キャパシティフィルタリング有効時にフィルタ後のIDが返却されること","capacity_filtering_enabled?がtrue","なし","キャパシティのあるエージェントのuser_idリストが返却される","高","エージェント割り当て"
"43","UT-ENT-043","Enterprise::InboxAgentAvailability","filter_by_capacity","正常系","キャパシティのあるエージェントのみが返却されること","capacity_filtering_enabled?がtrue","inbox_membersのスコープ","capacity_service.agent_has_capacity?がtrueのメンバーのみ返却","高","キャパシティフィルタ"
"44","UT-ENT-044","Enterprise::InboxAgentAvailability","capacity_filtering_enabled?","正常系","assignment_v2フィーチャーが有効でポリシーが存在する場合trueが返却されること","feature_enabled?('assignment_v2')がtrue、agent_capacity_policyが存在","なし","trueが返却される","中","フィーチャーフラグ"
"45","UT-ENT-045","Enterprise::InboxAgentAvailability","capacity_filtering_enabled?","境界値","assignment_v2フィーチャーが無効の場合falseが返却されること","feature_enabled?('assignment_v2')がfalse","なし","falseが返却される","中","フィーチャーフラグ"
"46","UT-ENT-046","Enterprise::Account::PlanUsageAndLimits","usage_limits","正常系","正しい形式の使用量制限が返却されること","アカウントが存在","なし","{agents:, inboxes:, captain:{documents:, responses:}}が返却される","高","プラン制限"
"47","UT-ENT-047","Enterprise::Account::PlanUsageAndLimits","increment_response_usage","正常系","レスポンス使用量が1増加すること","captain_responses_usage = 5","なし","captain_responses_usage = 6になる","高","使用量追跡"
"48","UT-ENT-048","Enterprise::Account::PlanUsageAndLimits","increment_response_usage","境界値","初回使用時に0から1になること","captain_responses_usageがnil","なし","captain_responses_usage = 1になる","高","初期化処理"
"49","UT-ENT-049","Enterprise::Account::PlanUsageAndLimits","reset_response_usage","正常系","レスポンス使用量が0にリセットされること","captain_responses_usage = 100","なし","captain_responses_usage = 0になる","高","使用量リセット"
"50","UT-ENT-050","Enterprise::Account::PlanUsageAndLimits","update_document_usage","正常系","ドキュメント使用量がドキュメント数に更新されること","captain_documents.count = 10","なし","captain_documents_usage = 10になる","高","使用量追跡"
"51","UT-ENT-051","Enterprise::Account::PlanUsageAndLimits","subscribed_features","正常系","プラン機能が返却されること","CHATWOOT_CLOUD_PLAN_FEATURESが設定済み","なし","plan_featuresの該当プラン配列が返却される","中","プラン機能"
"52","UT-ENT-052","Enterprise::Account::PlanUsageAndLimits","subscribed_features","境界値","設定がない場合空配列が返却されること","CHATWOOT_CLOUD_PLAN_FEATURESがblank","なし","[]が返却される","中","設定なし時"
"53","UT-ENT-053","Enterprise::Account::PlanUsageAndLimits","captain_monthly_limit","正常系","limitsから設定値が取得されること","limits['captain_documents'] = 100","なし","{documents: 100, responses: デフォルト値}が返却される","高","月間制限"
"54","UT-ENT-054","Enterprise::Account::PlanUsageAndLimits","get_captain_limits","正常系","正しい残量が計算されること","total_count = 100, consumed = 30","type = :responses","current_available = 70が返却される","高","制限計算"
"55","UT-ENT-055","Enterprise::Account::PlanUsageAndLimits","get_captain_limits","境界値","consumedが負の場合0として計算されること","consumed = -10","type = :responses","consumed = 0として計算される","中","負数ガード"
"56","UT-ENT-056","Enterprise::Account::PlanUsageAndLimits","get_captain_limits","境界値","使用量が上限を超えた場合current_availableが0になること","total_count = 100, consumed = 150","type = :responses","current_available = 0が返却される","高","上限超過時"
"57","UT-ENT-057","Enterprise::Account::PlanUsageAndLimits","default_captain_limits","正常系","プランに応じた制限が返却されること","CAPTAIN_CLOUD_PLAN_LIMITSが設定済み、plan_nameが有効","なし","該当プランの制限が返却される","高","デフォルト制限"
"58","UT-ENT-058","Enterprise::Account::PlanUsageAndLimits","default_captain_limits","境界値","設定がない場合max_limitが返却されること","CAPTAIN_CLOUD_PLAN_LIMITSがblank","なし","max_limits（無制限）が返却される","中","設定なし時"
"59","UT-ENT-059","Enterprise::Account::PlanUsageAndLimits","default_captain_limits","境界値","plan_nameがない場合zero_limitsが返却されること","plan_nameがblank","なし","zero_limits（0制限）が返却される","中","プラン未設定時"
"60","UT-ENT-060","Enterprise::Account::PlanUsageAndLimits","default_captain_limits","異常系","JSON解析エラー時にmax_limitsが返却されること","CAPTAIN_CLOUD_PLAN_LIMITSが不正なJSON","なし","max_limits（無制限）が返却される","中","エラーハンドリング"
"61","UT-ENT-061","Enterprise::Account::PlanUsageAndLimits","validate_limit_keys","正常系","有効なlimitsでエラーなし","limits = {inboxes: 10, agents: 5}","なし","エラーが追加されない","高","バリデーション"
"62","UT-ENT-062","Enterprise::Account::PlanUsageAndLimits","validate_limit_keys","異常系","limitsがHashでない場合エラーが追加されること","limits = 'invalid'","なし","errors.add(:limits)が呼ばれる","高","バリデーション"
"63","UT-ENT-063","Enterprise::Account::PlanUsageAndLimits","validate_limit_keys","異常系","不正なキーがある場合エラーが追加されること","limits = {invalid_key: 10}","なし","errors.add(:limits)が呼ばれる","高","バリデーション"
"64","UT-ENT-064","Enterprise::Audit::Macro","included","正常系","accountに関連付けて監査されること","Macroモデル","なし","audited associated_with: :accountが設定される","中","監査設定"
"65","UT-ENT-065","Enterprise::Audit::Account","included","正常系","update時のみ監査されること","Accountモデル","なし","audited on: [:update]が設定される","中","監査設定"
"66","UT-ENT-066","Enterprise::Audit::Account","included","正常系","関連監査が有効化されること","Accountモデル","なし","has_associated_auditsが設定される","中","監査設定"
"67","UT-ENT-067","Enterprise::Audit::Inbox","included","正常系","create/update時に監査されること","Inboxモデル","なし","audited on: [:create, :update]が設定される","中","監査設定"
"68","UT-ENT-068","Enterprise::Audit::AccountUser","included","正常系","指定カラムのみ監査されること","AccountUserモデル","なし","availability, role, account_id, inviter_id, user_idのみ監査される","中","監査設定"
"69","UT-ENT-069","Enterprise::Audit::Team","included","正常系","accountに関連付けて監査されること","Teamモデル","なし","audited associated_with: :accountが設定される","中","監査設定"
"70","UT-ENT-070","Enterprise::Audit::Conversation","included","正常系","destroy時のみ監査されること","Conversationモデル","なし","audited only: [], on: [:destroy]が設定される","中","監査設定"
"71","UT-ENT-071","Enterprise::Audit::AutomationRule","included","正常系","accountに関連付けて監査されること","AutomationRuleモデル","なし","audited associated_with: :accountが設定される","中","監査設定"
"72","UT-ENT-072","Enterprise::Audit::Webhook","included","正常系","accountに関連付けて監査されること","Webhookモデル","なし","audited associated_with: :accountが設定される","中","監査設定"
"73","UT-ENT-073","Enterprise::Audit::InboxMember","create_audit_log_entry_on_create","正常系","作成時に監査ログが作成されること","InboxMemberが作成される","なし","Enterprise::AuditLogがaction='create'で作成される","高","監査ログ"
"74","UT-ENT-074","Enterprise::Audit::InboxMember","create_audit_log_entry_on_delete","正常系","削除時に監査ログが作成されること","InboxMemberが削除される","なし","Enterprise::AuditLogがaction='destroy'で作成される","高","監査ログ"
"75","UT-ENT-075","Enterprise::Audit::InboxMember","create_audit_log_entry","境界値","inboxがblankの場合ログが作成されないこと","inboxがnil","action='create'","early returnで処理終了","中","null安全性"
"76","UT-ENT-076","Enterprise::Audit::TeamMember","create_audit_log_entry_on_create","正常系","作成時に監査ログが作成されること","TeamMemberが作成される","なし","Enterprise::AuditLogがaction='create'で作成される","高","監査ログ"
"77","UT-ENT-077","Enterprise::Audit::TeamMember","create_audit_log_entry_on_delete","正常系","削除時に監査ログが作成されること","TeamMemberが削除される","なし","Enterprise::AuditLogがaction='destroy'で作成される","高","監査ログ"
"78","UT-ENT-078","Enterprise::Audit::TeamMember","create_audit_log_entry","境界値","teamがblankの場合ログが作成されないこと","teamがnil","action='create'","early returnで処理終了","中","null安全性"
"79","UT-ENT-079","Enterprise::Audit::User","included","正常系","指定カラムのみ監査対象となること","Userモデル","なし","availability, display_name, email, nameのみ対象になる","中","監査設定"
"80","UT-ENT-080","Enterprise::Audit::User","included","正常系","常にfalseを返すprocで監査が無効化されること","Userモデル","なし","unless条件により通常操作では監査されない","中","監査設定"
"81","UT-ENT-081","Enterprise::Concerns::CustomAttributeDefinition","cleanup_conversation_required_attributes","正常系","会話属性削除時にrequired_attributesから除外されること","conversation_attribute?がtrue、attribute_keyがrequired_attributesに含まれる","なし","account.conversation_required_attributesからattribute_keyが削除される","高","属性クリーンアップ"
"82","UT-ENT-082","Enterprise::Concerns::CustomAttributeDefinition","cleanup_conversation_required_attributes","境界値","会話属性でない場合処理がスキップされること","conversation_attribute?がfalse","なし","early returnで処理終了","中","条件チェック"
"83","UT-ENT-083","Enterprise::Concerns::CustomAttributeDefinition","cleanup_conversation_required_attributes","境界値","required_attributesに含まれない場合処理がスキップされること","attribute_keyがrequired_attributesに含まれない","なし","early returnで処理終了","中","条件チェック"
"84","UT-ENT-084","Enterprise::Concerns::Account","included","正常系","SLAポリシーのリレーションが定義されること","Accountモデル","なし","has_many :sla_policiesが設定される","中","リレーション定義"
"85","UT-ENT-085","Enterprise::Concerns::Account","included","正常系","カスタムロールのリレーションが定義されること","Accountモデル","なし","has_many :custom_rolesが設定される","中","リレーション定義"
"86","UT-ENT-086","Enterprise::Concerns::Account","included","正常系","Captain関連のリレーションが定義されること","Accountモデル","なし","captain_assistants, captain_documents等が設定される","中","リレーション定義"
"87","UT-ENT-087","Enterprise::Concerns::Account","included","正常系","SAML設定のリレーションが定義されること","Accountモデル","なし","has_one :saml_settingsが設定される","中","リレーション定義"
"88","UT-ENT-088","Enterprise::Concerns::Article","add_article_embedding","正常系","help_center_embedding_search有効時にジョブがキューされること","feature_enabled?がtrue、タイトルが変更された","なし","Portal::ArticleIndexingJobがperform_laterされる","高","埋め込み検索"
"89","UT-ENT-089","Enterprise::Concerns::Article","add_article_embedding","境界値","フィーチャーが無効の場合ジョブがキューされないこと","feature_enabled?がfalse","なし","ジョブがキューされない","中","フィーチャーフラグ"
"90","UT-ENT-090","Enterprise::Concerns::Article","vector_search","正常系","ベクトル検索で関連記事が返却されること","ArticleEmbeddingが存在","query='検索ワード'","最大5件の関連記事が返却される","高","検索機能"
"91","UT-ENT-091","Enterprise::Concerns::Article","generate_and_save_article_seach_terms","正常系","検索語が生成され埋め込みが保存されること","記事が存在","なし","article_embeddingsが作成される","中","検索語生成"
"92","UT-ENT-092","Enterprise::Concerns::Article","generate_article_search_terms","正常系","OpenAI APIから検索語が取得されること","OPENAI_API_KEYが設定済み","なし","search_terms配列が返却される","中","外部API連携"
"93","UT-ENT-093","Enterprise::Concerns::Article","openai_api_url","正常系","カスタムエンドポイントが使用されること","CAPTAIN_OPEN_AI_ENDPOINTが設定済み","なし","カスタムエンドポイントのURLが返却される","低","設定取得"
"94","UT-ENT-094","Enterprise::Concerns::Article","openai_api_url","境界値","デフォルトエンドポイントが使用されること","CAPTAIN_OPEN_AI_ENDPOINTが未設定","なし","https://api.openai.com/v1/chat/completionsが返却される","低","デフォルト設定"
"95","UT-ENT-095","Enterprise::Concerns::Contact","associate_company_from_email","正常系","メール設定時に会社が関連付けられること","email有効、company_id未設定、email初回設定","なし","Contacts::CompanyAssociationServiceが呼ばれる","高","会社関連付け"
"96","UT-ENT-096","Enterprise::Concerns::Contact","should_associate_company?","正常系","条件を満たす場合trueが返却されること","email有効、company_id nil、email変更あり、前回nil","なし","trueが返却される","中","条件判定"
"97","UT-ENT-097","Enterprise::Concerns::Contact","should_associate_company?","境界値","emailがない場合falseが返却されること","emailがblank","なし","falseが返却される","中","条件判定"
"98","UT-ENT-098","Enterprise::Concerns::Contact","should_associate_company?","境界値","company_idが設定済みの場合falseが返却されること","company_idが設定済み","なし","falseが返却される","中","条件判定"
"99","UT-ENT-099","Enterprise::Concerns::Contact","associate_company_from_email","異常系","サービスエラー時にログ出力のみで処理続行すること","CompanyAssociationServiceがエラー","なし","エラーログ出力後、例外は発生しない","中","エラーハンドリング"
"100","UT-ENT-100","Enterprise::Concerns::AssignmentPolicy","included","正常系","Enterprise環境でenumが定義されること","ChatwootApp.enterprise?がtrue","なし","assignment_order enumが定義される","中","条件付き定義"
"101","UT-ENT-101","Enterprise::Concerns::AssignmentPolicy","included","境界値","非Enterprise環境でenumが定義されないこと","ChatwootApp.enterprise?がfalse","なし","enumが定義されない","中","条件付き定義"
"102","UT-ENT-102","Enterprise::Concerns::Inbox","included","正常系","captain_inboxリレーションが定義されること","Inboxモデル","なし","has_one :captain_inboxが設定される","中","リレーション定義"
"103","UT-ENT-103","Enterprise::Concerns::Inbox","included","正常系","captain_assistantがthrough関係で定義されること","Inboxモデル","なし","has_one :captain_assistant, through: :captain_inboxが設定される","中","リレーション定義"
"104","UT-ENT-104","Enterprise::Concerns::Inbox","included","正常系","inbox_capacity_limitsリレーションが定義されること","Inboxモデル","なし","has_many :inbox_capacity_limitsが設定される","中","リレーション定義"
"105","UT-ENT-105","Enterprise::Concerns::AccountUser","included","正常系","custom_roleリレーションが定義されること","AccountUserモデル","なし","belongs_to :custom_roleが設定される","中","リレーション定義"
"106","UT-ENT-106","Enterprise::Concerns::AccountUser","included","正常系","agent_capacity_policyリレーションが定義されること","AccountUserモデル","なし","belongs_to :agent_capacity_policyが設定される","中","リレーション定義"
"107","UT-ENT-107","Enterprise::Concerns::Attachment","enqueue_audio_transcription","正常系","音声ファイル作成時に文字起こしジョブがキューされること","file_type = :audio","なし","Messages::AudioTranscriptionJobがperform_laterされる","高","音声文字起こし"
"108","UT-ENT-108","Enterprise::Concerns::Attachment","enqueue_audio_transcription","境界値","音声以外のファイルではジョブがキューされないこと","file_type = :image","なし","ジョブがキューされない","中","ファイルタイプチェック"
"109","UT-ENT-109","Enterprise::Concerns::Conversation","validate_sla_policy","正常系","有効なSLAポリシー設定でエラーなし","sla_policyが存在、account_idが一致、既存ポリシーなし","sla_policy_id = 1","エラーが追加されない","高","SLAバリデーション"
"110","UT-ENT-110","Enterprise::Concerns::Conversation","validate_sla_policy","異常系","SLAポリシー削除時にエラーが追加されること","既存sla_policy_idあり","sla_policy_id = nil","errors.add(:sla_policy)が呼ばれる","高","SLAバリデーション"
"111","UT-ENT-111","Enterprise::Concerns::Conversation","validate_sla_policy","異常系","既にSLAポリシーがある場合エラーが追加されること","既存sla_policy_idあり","新しいsla_policy_id","errors.add(:sla_policy)が呼ばれる","高","SLAバリデーション"
"112","UT-ENT-112","Enterprise::Concerns::Conversation","validate_sla_policy","異常系","アカウント不一致時にエラーが追加されること","sla_policy.account_id != conversation.account_id","sla_policy_id = 1","errors.add(:sla_policy)が呼ばれる","高","SLAバリデーション"
"113","UT-ENT-113","Enterprise::Concerns::Conversation","ensure_applied_sla_is_created","正常系","SLAポリシー設定時にAppliedSlaが作成されること","applied_slaがblank","sla_policy_id変更","create_applied_slaが呼ばれる","高","SLA適用"
"114","UT-ENT-114","Enterprise::Concerns::Conversation","ensure_applied_sla_is_created","境界値","既にAppliedSlaがある場合作成されないこと","applied_slaが存在","sla_policy_id変更","create_applied_slaが呼ばれない","中","冪等性確認"
"115","UT-ENT-115","Enterprise::Concerns::Conversation","ensure_applied_sla_is_created","異常系","RecordInvalid時にロールバックされること","AppliedSla作成がRecordInvalidを発生","sla_policy_id変更","ActiveRecord::Rollbackが発生","高","トランザクション"
"116","UT-ENT-116","Enterprise::Concerns::Portal","enqueue_cloudflare_verification","正常系","カスタムドメイン設定時にCloudflare検証ジョブがキューされること","custom_domainが設定、chatwoot_cloud?がtrue","なし","Enterprise::CloudflareVerificationJobがperform_laterされる","高","ドメイン検証"
"117","UT-ENT-117","Enterprise::Concerns::Portal","enqueue_cloudflare_verification","境界値","custom_domainがblankの場合ジョブがキューされないこと","custom_domainがblank","なし","early returnで処理終了","中","条件チェック"
"118","UT-ENT-118","Enterprise::Concerns::Portal","enqueue_cloudflare_verification","境界値","chatwoot_cloudでない場合ジョブがキューされないこと","chatwoot_cloud?がfalse","なし","early returnで処理終了","中","環境チェック"
"119","UT-ENT-119","Enterprise::Concerns::User","ensure_installation_pricing_plan_quantity","正常系","premium以外のプランではエラーなし","pricing_plan = 'free'","なし","エラーが追加されない","中","プラン制限"
"120","UT-ENT-120","Enterprise::Concerns::User","ensure_installation_pricing_plan_quantity","正常系","premiumプランで上限内の場合エラーなし","pricing_plan = 'premium'、User.count < pricing_plan_quantity","なし","エラーが追加されない","高","プラン制限"
"121","UT-ENT-121","Enterprise::Concerns::User","ensure_installation_pricing_plan_quantity","異常系","premiumプランで上限超過の場合エラーが追加されること","pricing_plan = 'premium'、User.count >= pricing_plan_quantity","なし","errors.add(:base)が呼ばれる","高","プラン制限"
"122","UT-ENT-122","Enterprise::Concerns::User","included","正常系","captain_responsesリレーションが定義されること","Userモデル","なし","has_many :captain_responsesが設定される","中","リレーション定義"
"123","UT-ENT-123","Enterprise::Concerns::User","included","正常系","copilot_threadsリレーションが定義されること","Userモデル","なし","has_many :copilot_threadsが設定される","中","リレーション定義"
"1","UT-ENT-001","AccountSamlSettings","belongs_to :account","正常系","accountリレーションが正しく取得できること","AccountSamlSettingsとAccountが存在","account_id=有効なアカウントID","関連するAccountオブジェクトが返却される","高","SAML認証設定の基本リレーション"
"2","UT-ENT-002","AccountSamlSettings","validates :account_id","異常系","account_idがnilの場合バリデーションエラーになること","なし","account_id=nil","presenceエラーが発生する","高","必須項目の検証"
"3","UT-ENT-003","AccountSamlSettings","validates :sso_url","異常系","sso_urlがnilの場合バリデーションエラーになること","なし","sso_url=nil","presenceエラーが発生する","高","SSO URL必須"
"4","UT-ENT-004","AccountSamlSettings","validates :certificate","異常系","certificateがnilの場合バリデーションエラーになること","なし","certificate=nil","presenceエラーが発生する","高","証明書必須"
"5","UT-ENT-005","AccountSamlSettings","validates :idp_entity_id","異常系","idp_entity_idがnilの場合バリデーションエラーになること","なし","idp_entity_id=nil","presenceエラーが発生する","高","IdPエンティティID必須"
"6","UT-ENT-006","AccountSamlSettings","certificate_must_be_valid_x509","正常系","有効なX509証明書が受け入れられること","なし","certificate=有効なX509証明書文字列","バリデーションエラーなし","高","証明書形式の検証"
"7","UT-ENT-007","AccountSamlSettings","certificate_must_be_valid_x509","異常系","無効な証明書文字列の場合エラーになること","なし","certificate=""invalid_cert""","certificateにエラーが追加される","高","不正な証明書の拒否"
"8","UT-ENT-008","AccountSamlSettings","saml_enabled?","正常系","sso_urlとcertificateが存在する場合trueを返すこと","sso_urlとcertificateが設定済み","なし","trueが返却される","中","SAML有効状態の判定"
"9","UT-ENT-009","AccountSamlSettings","saml_enabled?","境界値","sso_urlが空の場合falseを返すこと","certificateのみ設定済み","sso_url=""""","falseが返却される","中","部分設定時の無効判定"
"10","UT-ENT-010","AccountSamlSettings","saml_enabled?","境界値","certificateが空の場合falseを返すこと","sso_urlのみ設定済み","certificate=""""","falseが返却される","中","部分設定時の無効判定"
"11","UT-ENT-011","AccountSamlSettings","certificate_fingerprint","正常系","有効な証明書のフィンガープリントが返却されること","有効なX509証明書が設定済み","なし","SHA1フィンガープリント文字列（コロン区切り大文字16進数）","中","証明書識別用"
"12","UT-ENT-012","AccountSamlSettings","certificate_fingerprint","境界値","certificateがnilの場合nilを返すこと","なし","certificate=nil","nilが返却される","中","null安全性"
"13","UT-ENT-013","AccountSamlSettings","certificate_fingerprint","異常系","無効な証明書の場合nilを返すこと","なし","certificate=""invalid""","nilが返却される","中","エラーハンドリング"
"14","UT-ENT-014","AccountSamlSettings","set_sp_entity_id","正常系","sp_entity_idが空の場合自動生成されること","sp_entity_id未設定","account_id=123","sp_entity_idが""http://localhost:3000/saml/sp/123""形式で設定される","中","SP Entity IDの自動生成"
"15","UT-ENT-015","AccountSamlSettings","set_sp_entity_id","境界値","sp_entity_idが既に設定済みの場合変更されないこと","sp_entity_id=""existing_id""","なし","sp_entity_idが変更されない","低","既存値の保持"
"16","UT-ENT-016","AccountSamlSettings","update_account_users_provider","正常系","作成後にSaml::UpdateAccountUsersProviderJobがenqueueされること","なし","有効なAccountSamlSettingsデータ","ジョブがenqueueされる（provider=""saml""）","高","ユーザープロバイダ更新"
"17","UT-ENT-017","AccountSamlSettings","reset_account_users_provider","正常系","削除後にSaml::UpdateAccountUsersProviderJobがenqueueされること","AccountSamlSettingsが存在","destroyを実行","ジョブがenqueueされる（provider=""email""）","高","ユーザープロバイダリセット"
"18","UT-ENT-018","AgentCapacityPolicy","belongs_to :account","正常系","accountリレーションが正しく取得できること","AgentCapacityPolicyとAccountが存在","account_id=有効なアカウントID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"19","UT-ENT-019","AgentCapacityPolicy","has_many :inbox_capacity_limits","正常系","inbox_capacity_limitsリレーションが正しく取得できること","関連するInboxCapacityLimitが存在","なし","関連するInboxCapacityLimitのコレクションが返却される","高","受信箱制限の取得"
"20","UT-ENT-020","AgentCapacityPolicy","has_many :inbox_capacity_limits","正常系","dependent: :destroyで関連レコードも削除されること","関連するInboxCapacityLimitが存在","AgentCapacityPolicyを削除","関連するInboxCapacityLimitも削除される","高","カスケード削除"
"21","UT-ENT-021","AgentCapacityPolicy","has_many :inboxes","正常系","inboxesがthrough関連で取得できること","InboxCapacityLimitを経由した関連が存在","なし","関連するInboxのコレクションが返却される","中","through関連"
"22","UT-ENT-022","AgentCapacityPolicy","has_many :account_users","正常系","account_usersリレーションが正しく取得できること","関連するAccountUserが存在","なし","関連するAccountUserのコレクションが返却される","中","ユーザー割り当て"
"23","UT-ENT-023","AgentCapacityPolicy","has_many :account_users","正常系","dependent: :nullifyで関連レコードの外部キーがnullになること","関連するAccountUserが存在","AgentCapacityPolicyを削除","AccountUserのagent_capacity_policy_idがnullになる","中","nullify動作"
"24","UT-ENT-024","AgentCapacityPolicy","validates :name","異常系","nameがnilの場合バリデーションエラーになること","なし","name=nil","presenceエラーが発生する","高","必須項目"
"25","UT-ENT-025","AgentCapacityPolicy","validates :name","境界値","nameが255文字の場合バリデーション成功すること","なし","name=""a"" * 255","バリデーションエラーなし","中","最大長境界値"
"26","UT-ENT-026","AgentCapacityPolicy","validates :name","境界値","nameが256文字の場合バリデーションエラーになること","なし","name=""a"" * 256","lengthエラーが発生する","中","最大長超過"
"27","UT-ENT-027","AgentCapacityPolicy","validates :account","異常系","accountがnilの場合バリデーションエラーになること","なし","account=nil","presenceエラーが発生する","高","必須項目"
"28","UT-ENT-028","AppliedSla","belongs_to :account","正常系","accountリレーションが正しく取得できること","AppliedSlaとAccountが存在","account_id=有効なアカウントID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"29","UT-ENT-029","AppliedSla","belongs_to :sla_policy","正常系","sla_policyリレーションが正しく取得できること","関連するSlaPolicyが存在","sla_policy_id=有効なID","関連するSlaPolicyオブジェクトが返却される","高","SLAポリシー参照"
"30","UT-ENT-030","AppliedSla","belongs_to :conversation","正常系","conversationリレーションが正しく取得できること","関連するConversationが存在","conversation_id=有効なID","関連するConversationオブジェクトが返却される","高","会話参照"
"31","UT-ENT-031","AppliedSla","has_many :sla_events","正常系","sla_eventsリレーションが正しく取得できること","関連するSlaEventが存在","なし","関連するSlaEventのコレクションが返却される","高","SLAイベント取得"
"32","UT-ENT-032","AppliedSla","validates :account_id uniqueness","異常系","同一account/sla_policy/conversationの組み合わせが重複する場合エラーになること","同一組み合わせのAppliedSlaが存在","重複するaccount_id/sla_policy_id/conversation_id","uniquenessエラーが発生する","高","ユニーク制約"
"33","UT-ENT-033","AppliedSla","enum sla_status","正常系","sla_status=activeが正しく設定されること","なし","sla_status=:active","sla_statusが0として保存される","中","enumマッピング"
"34","UT-ENT-034","AppliedSla","enum sla_status","正常系","sla_status=hitが正しく設定されること","なし","sla_status=:hit","sla_statusが1として保存される","中","enumマッピング"
"35","UT-ENT-035","AppliedSla","enum sla_status","正常系","sla_status=missedが正しく設定されること","なし","sla_status=:missed","sla_statusが2として保存される","中","enumマッピング"
"36","UT-ENT-036","AppliedSla","enum sla_status","正常系","sla_status=active_with_missesが正しく設定されること","なし","sla_status=:active_with_misses","sla_statusが3として保存される","中","enumマッピング"
"37","UT-ENT-037","AppliedSla","scope :filter_by_date_range","正常系","日付範囲でフィルタリングできること","複数のAppliedSlaが存在（異なる作成日）","range=1.week.ago..Time.current","指定範囲内のレコードのみ返却される","中","日付フィルタ"
"38","UT-ENT-038","AppliedSla","scope :filter_by_date_range","境界値","rangeがnilの場合全件返却されること","複数のAppliedSlaが存在","range=nil","全レコードが返却される","低","null安全性"
"39","UT-ENT-039","AppliedSla","scope :filter_by_inbox_id","正常系","inbox_idでフィルタリングできること","複数のAppliedSlaが存在（異なるinbox）","inbox_id=有効なID","指定inbox_idに関連するレコードのみ返却される","中","受信箱フィルタ"
"40","UT-ENT-040","AppliedSla","scope :filter_by_team_id","正常系","team_idでフィルタリングできること","複数のAppliedSlaが存在（異なるteam）","team_id=有効なID","指定team_idに関連するレコードのみ返却される","中","チームフィルタ"
"41","UT-ENT-041","AppliedSla","scope :filter_by_sla_policy_id","正常系","sla_policy_idでフィルタリングできること","複数のAppliedSlaが存在（異なるsla_policy）","sla_policy_id=有効なID","指定sla_policy_idのレコードのみ返却される","中","ポリシーフィルタ"
"42","UT-ENT-042","AppliedSla","scope :filter_by_label_list","正常系","label_listでフィルタリングできること","cached_label_listに""urgent""を含む会話が存在","label_list=""urgent""","該当ラベルを含むレコードのみ返却される","中","ラベルフィルタ"
"43","UT-ENT-043","AppliedSla","scope :filter_by_assigned_agent_id","正常系","assigned_agent_idでフィルタリングできること","assignee_idが設定された会話が存在","assigned_agent_id=有効なID","該当エージェントに割り当てられたレコードのみ返却される","中","エージェントフィルタ"
"44","UT-ENT-044","AppliedSla","scope :missed","正常系","missed/active_with_missesステータスのレコードが返却されること","各ステータスのAppliedSlaが存在","なし","sla_statusがmissedまたはactive_with_missesのレコードのみ返却される","高","SLAミス抽出"
"45","UT-ENT-045","AppliedSla","push_event_data","正常系","イベントデータが正しい形式で返却されること","AppliedSlaとSlaPolicyが存在","なし","id/sla_id/sla_status/created_at/updated_at/sla_*を含むハッシュ","中","イベント通知用データ"
"46","UT-ENT-046","AppliedSla","push_conversation_event","正常系","sla_statusが変更された場合にdispatch_conversation_updated_eventが呼ばれること","AppliedSlaが存在","sla_statusをactiveからhitに変更","conversation.dispatch_conversation_updated_eventが呼ばれる","高","イベント発火"
"47","UT-ENT-047","AppliedSla","push_conversation_event","境界値","sla_statusが変更されない場合イベントが発火しないこと","AppliedSlaが存在","他の属性のみ変更","dispatch_conversation_updated_eventが呼ばれない","中","不要なイベント抑制"
"48","UT-ENT-048","AppliedSla","ensure_account_id","正常系","account_idが未設定の場合sla_policyから取得されること","sla_policyが設定済み","account_id=nil","sla_policy.account_idが設定される","中","自動補完"
"49","UT-ENT-049","ArticleEmbedding","belongs_to :article","正常系","articleリレーションが正しく取得できること","ArticleEmbeddingとArticleが存在","article_id=有効なID","関連するArticleオブジェクトが返却される","高","記事参照"
"50","UT-ENT-050","ArticleEmbedding","has_neighbors :embedding","正常系","embeddingカラムでneighbor検索が利用できること","複数のArticleEmbeddingが存在","embedding=ベクトル値","類似したembeddingを持つレコードが返却される","高","ベクトル検索"
"51","UT-ENT-051","ArticleEmbedding","delegate :account_id","正常系","account_idがarticleから委譲されること","ArticleとAccountが存在","なし","article.account_idが返却される","中","委譲メソッド"
"52","UT-ENT-052","ArticleEmbedding","update_response_embedding","正常系","termが変更された場合にUpdateEmbeddingJobがenqueueされること","ArticleEmbeddingが存在","termを変更して保存","Captain::Llm::UpdateEmbeddingJobがenqueueされる","高","埋め込み更新"
"53","UT-ENT-053","ArticleEmbedding","update_response_embedding","正常系","embeddingがnilの場合にUpdateEmbeddingJobがenqueueされること","embedding=nilのArticleEmbeddingが存在","保存","Captain::Llm::UpdateEmbeddingJobがenqueueされる","高","初回埋め込み生成"
"54","UT-ENT-054","ArticleEmbedding","update_response_embedding","境界値","termが変更されずembeddingが存在する場合ジョブがenqueueされないこと","termとembeddingが設定済み","他の属性のみ変更","ジョブがenqueueされない","中","不要なジョブ抑制"
"55","UT-ENT-055","CaptainInbox","belongs_to :captain_assistant","正常系","captain_assistantリレーションが正しく取得できること","CaptainInboxとCaptain::Assistantが存在","captain_assistant_id=有効なID","関連するCaptain::Assistantオブジェクトが返却される","高","アシスタント参照"
"56","UT-ENT-056","CaptainInbox","belongs_to :inbox","正常系","inboxリレーションが正しく取得できること","CaptainInboxとInboxが存在","inbox_id=有効なID","関連するInboxオブジェクトが返却される","高","受信箱参照"
"57","UT-ENT-057","CaptainInbox","validates :inbox_id uniqueness","異常系","同一inbox_idが重複する場合エラーになること","同一inbox_idのCaptainInboxが存在","重複するinbox_id","uniquenessエラーが発生する","高","1対1制約"
"58","UT-ENT-058","CaptainInbox","validates :inbox_id uniqueness","正常系","異なるinbox_idであれば作成できること","CaptainInboxが存在","異なるinbox_id","バリデーションエラーなし","中","正常作成"
"59","UT-ENT-059","Company","include Avatarable","正常系","Avatarableモジュールのメソッドが利用できること","Companyが存在","なし","avatar関連メソッドが利用可能","中","Mixin確認"
"60","UT-ENT-060","Company","validates :account_id","異常系","account_idがnilの場合バリデーションエラーになること","なし","account_id=nil","presenceエラーが発生する","高","必須項目"
"61","UT-ENT-061","Company","validates :name","異常系","nameがnilの場合バリデーションエラーになること","なし","name=nil","presenceエラーが発生する","高","必須項目"
"62","UT-ENT-062","Company","validates :name","境界値","nameがCOMPANY_NAME_LENGTH_LIMITを超える場合エラーになること","なし","name=制限を超える長さの文字列","lengthエラーが発生する","中","最大長超過"
"63","UT-ENT-063","Company","validates :domain","正常系","有効なドメイン形式が受け入れられること","なし","domain=""example.com""","バリデーションエラーなし","中","ドメイン形式"
"64","UT-ENT-064","Company","validates :domain","異常系","無効なドメイン形式の場合エラーになること","なし","domain=""invalid_domain""","formatエラーが発生する","中","不正ドメイン拒否"
"65","UT-ENT-065","Company","validates :domain","異常系","ハイフンで始まるドメインの場合エラーになること","なし","domain=""-example.com""","formatエラーが発生する","中","不正ドメイン拒否"
"66","UT-ENT-066","Company","validates :domain uniqueness","異常系","同一account内で同じdomainが重複する場合エラーになること","同一accountに同じdomainのCompanyが存在","重複するdomain","uniquenessエラーが発生する","高","ユニーク制約"
"67","UT-ENT-067","Company","validates :domain uniqueness","正常系","domainがnilの場合はユニーク制約が適用されないこと","同一accountにdomain=nilのCompanyが存在","domain=nil","バリデーションエラーなし","中","条件付きユニーク"
"68","UT-ENT-068","Company","validates :description","境界値","descriptionがCOMPANY_DESCRIPTION_LENGTH_LIMITを超える場合エラーになること","なし","description=制限を超える長さの文字列","lengthエラーが発生する","低","最大長超過"
"69","UT-ENT-069","Company","belongs_to :account","正常系","accountリレーションが正しく取得できること","CompanyとAccountが存在","account_id=有効なID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"70","UT-ENT-070","Company","has_many :contacts","正常系","contactsリレーションが正しく取得できること","関連するContactが存在","なし","関連するContactのコレクションが返却される","高","顧客関連"
"71","UT-ENT-071","Company","has_many :contacts","正常系","dependent: :nullifyで関連レコードの外部キーがnullになること","関連するContactが存在","Companyを削除","Contactのcompany_idがnullになる","中","nullify動作"
"72","UT-ENT-072","Company","scope :ordered_by_name","正常系","名前順でソートされること","複数のCompanyが存在","なし","name昇順でソートされたコレクションが返却される","低","ソート"
"73","UT-ENT-073","Company","scope :search_by_name_or_domain","正常系","nameで部分一致検索できること","複数のCompanyが存在","query=""acme""","nameに""acme""を含むレコードが返却される","中","名前検索"
"74","UT-ENT-074","Company","scope :search_by_name_or_domain","正常系","domainで部分一致検索できること","複数のCompanyが存在","query=""example.com""","domainに""example.com""を含むレコードが返却される","中","ドメイン検索"
"75","UT-ENT-075","Company","scope :order_on_contacts_count","正常系","contacts_countで昇順ソートできること","複数のCompanyが存在（異なるcontacts_count）","direction=""ASC""","contacts_count昇順でソートされる","低","カウントソート"
"76","UT-ENT-076","Company","scope :order_on_contacts_count","正常系","contacts_countで降順ソートできること","複数のCompanyが存在（異なるcontacts_count）","direction=""DESC""","contacts_count降順でソートされる（NULLは最後）","低","カウントソート"
"77","UT-ENT-077","CopilotMessage","belongs_to :copilot_thread","正常系","copilot_threadリレーションが正しく取得できること","CopilotMessageとCopilotThreadが存在","copilot_thread_id=有効なID","関連するCopilotThreadオブジェクトが返却される","高","スレッド参照"
"78","UT-ENT-078","CopilotMessage","belongs_to :account","正常系","accountリレーションが正しく取得できること","CopilotMessageとAccountが存在","account_id=有効なID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"79","UT-ENT-079","CopilotMessage","enum message_type","正常系","message_type=userが正しく設定されること","なし","message_type=:user","message_typeが0として保存される","中","enumマッピング"
"80","UT-ENT-080","CopilotMessage","enum message_type","正常系","message_type=assistantが正しく設定されること","なし","message_type=:assistant","message_typeが1として保存される","中","enumマッピング"
"81","UT-ENT-081","CopilotMessage","enum message_type","正常系","message_type=assistant_thinkingが正しく設定されること","なし","message_type=:assistant_thinking","message_typeが2として保存される","中","enumマッピング"
"82","UT-ENT-082","CopilotMessage","validates :message_type","異常系","message_typeがnilの場合バリデーションエラーになること","なし","message_type=nil","presenceエラーが発生する","高","必須項目"
"83","UT-ENT-083","CopilotMessage","validates :message","異常系","messageがnilの場合バリデーションエラーになること","なし","message=nil","presenceエラーが発生する","高","必須項目"
"84","UT-ENT-084","CopilotMessage","validate_message_attributes","正常系","許可されたキーのみを含むmessageが受け入れられること","なし","message={""content"": ""test""}","バリデーションエラーなし","中","メッセージ形式"
"85","UT-ENT-085","CopilotMessage","validate_message_attributes","正常系","全許可キーを含むmessageが受け入れられること","なし","message={""content"": """", ""reasoning"": """", ""function_name"": """", ""reply_suggestion"": """"}","バリデーションエラーなし","中","全キー許可"
"86","UT-ENT-086","CopilotMessage","validate_message_attributes","異常系","不正なキーを含むmessageの場合エラーになること","なし","message={""content"": """", ""invalid_key"": """"}","messageにエラーが追加される","中","不正キー拒否"
"87","UT-ENT-087","CopilotMessage","ensure_account","正常系","account_idがcopilot_threadから自動設定されること","copilot_threadが設定済み","account_id=nil","copilot_thread.account_idが設定される","中","自動補完"
"88","UT-ENT-088","CopilotMessage","push_event_data","正常系","イベントデータが正しい形式で返却されること","CopilotMessageが存在","なし","id/message/message_type/created_at/copilot_threadを含むハッシュ","中","イベント通知用データ"
"89","UT-ENT-089","CopilotMessage","enqueue_response_job","正常系","ResponseJobがenqueueされること","CopilotMessageが存在","conversation_id=1, user_id=1","Captain::Copilot::ResponseJobがenqueueされる","高","レスポンス生成"
"90","UT-ENT-090","CopilotMessage","broadcast_message","正常系","作成後にCOPILOT_MESSAGE_CREATEDイベントがdispatchされること","なし","有効なCopilotMessageデータ","dispatcherにイベントが送信される","高","リアルタイム通知"
"91","UT-ENT-091","CopilotThread","belongs_to :user","正常系","userリレーションが正しく取得できること","CopilotThreadとUserが存在","user_id=有効なID","関連するUserオブジェクトが返却される","高","ユーザー参照"
"92","UT-ENT-092","CopilotThread","belongs_to :account","正常系","accountリレーションが正しく取得できること","CopilotThreadとAccountが存在","account_id=有効なID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"93","UT-ENT-093","CopilotThread","belongs_to :assistant","正常系","assistantリレーションが正しく取得できること","CopilotThreadとCaptain::Assistantが存在","assistant_id=有効なID","関連するCaptain::Assistantオブジェクトが返却される","高","アシスタント参照"
"94","UT-ENT-094","CopilotThread","has_many :copilot_messages","正常系","copilot_messagesリレーションが正しく取得できること","関連するCopilotMessageが存在","なし","関連するCopilotMessageのコレクションが返却される","高","メッセージ取得"
"95","UT-ENT-095","CopilotThread","has_many :copilot_messages","正常系","dependent: :destroy_asyncで関連レコードが非同期削除されること","関連するCopilotMessageが存在","CopilotThreadを削除","関連するCopilotMessageの削除ジョブがenqueueされる","中","非同期削除"
"96","UT-ENT-096","CopilotThread","validates :title","異常系","titleがnilの場合バリデーションエラーになること","なし","title=nil","presenceエラーが発生する","高","必須項目"
"97","UT-ENT-097","CopilotThread","push_event_data","正常系","イベントデータが正しい形式で返却されること","CopilotThreadが存在","なし","id/title/created_at/user/account_idを含むハッシュ","中","イベント通知用データ"
"98","UT-ENT-098","CopilotThread","previous_history","正常系","user/assistantメッセージの履歴が時系列順で返却されること","複数のCopilotMessageが存在","なし","content/roleを含むハッシュの配列（created_at昇順）","高","履歴取得"
"99","UT-ENT-099","CopilotThread","previous_history","境界値","assistant_thinkingメッセージが除外されること","assistant_thinkingタイプのメッセージが存在","なし","assistant_thinkingタイプを除く履歴が返却される","中","フィルタリング"
"100","UT-ENT-100","CopilotThread","previous_history","境界値","メッセージがない場合空配列が返却されること","メッセージなし","なし","空配列が返却される","低","空状態"
"101","UT-ENT-101","CustomRole","belongs_to :account","正常系","accountリレーションが正しく取得できること","CustomRoleとAccountが存在","account_id=有効なID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"102","UT-ENT-102","CustomRole","has_many :account_users","正常系","account_usersリレーションが正しく取得できること","関連するAccountUserが存在","なし","関連するAccountUserのコレクションが返却される","高","ユーザー割り当て"
"103","UT-ENT-103","CustomRole","has_many :account_users","正常系","dependent: :nullifyで関連レコードの外部キーがnullになること","関連するAccountUserが存在","CustomRoleを削除","AccountUserのcustom_role_idがnullになる","中","nullify動作"
"104","UT-ENT-104","CustomRole","validates :name","異常系","nameがnilの場合バリデーションエラーになること","なし","name=nil","presenceエラーが発生する","高","必須項目"
"105","UT-ENT-105","CustomRole","validates :permissions","正常系","有効なpermissionsが受け入れられること","なし","permissions=[""conversation_manage""]","バリデーションエラーなし","高","権限設定"
"106","UT-ENT-106","CustomRole","validates :permissions","正常系","複数の有効なpermissionsが受け入れられること","なし","permissions=[""conversation_manage"", ""contact_manage""]","バリデーションエラーなし","高","複数権限"
"107","UT-ENT-107","CustomRole","validates :permissions","異常系","無効なpermissionが含まれる場合エラーになること","なし","permissions=[""invalid_permission""]","inclusionエラーが発生する","高","不正権限拒否"
"108","UT-ENT-108","CustomRole","PERMISSIONS","正常系","定義されたPERMISSIONS定数が正しい値を含むこと","なし","なし","6つの権限文字列を含む配列","中","定数確認"
"109","UT-ENT-109","InboxCapacityLimit","belongs_to :agent_capacity_policy","正常系","agent_capacity_policyリレーションが正しく取得できること","InboxCapacityLimitとAgentCapacityPolicyが存在","agent_capacity_policy_id=有効なID","関連するAgentCapacityPolicyオブジェクトが返却される","高","ポリシー参照"
"110","UT-ENT-110","InboxCapacityLimit","belongs_to :inbox","正常系","inboxリレーションが正しく取得できること","InboxCapacityLimitとInboxが存在","inbox_id=有効なID","関連するInboxオブジェクトが返却される","高","受信箱参照"
"111","UT-ENT-111","InboxCapacityLimit","validates :conversation_limit","異常系","conversation_limitがnilの場合バリデーションエラーになること","なし","conversation_limit=nil","presenceエラーが発生する","高","必須項目"
"112","UT-ENT-112","InboxCapacityLimit","validates :conversation_limit","異常系","conversation_limitが0の場合バリデーションエラーになること","なし","conversation_limit=0","greater_thanエラーが発生する","高","最小値制約"
"113","UT-ENT-113","InboxCapacityLimit","validates :conversation_limit","異常系","conversation_limitが負数の場合バリデーションエラーになること","なし","conversation_limit=-1","greater_thanエラーが発生する","高","負数拒否"
"114","UT-ENT-114","InboxCapacityLimit","validates :conversation_limit","異常系","conversation_limitが小数の場合バリデーションエラーになること","なし","conversation_limit=1.5","only_integerエラーが発生する","中","整数制約"
"115","UT-ENT-115","InboxCapacityLimit","validates :conversation_limit","正常系","conversation_limitが1の場合バリデーション成功すること","なし","conversation_limit=1","バリデーションエラーなし","中","最小値境界"
"116","UT-ENT-116","InboxCapacityLimit","validates :inbox_id uniqueness","異常系","同一policy内で同じinbox_idが重複する場合エラーになること","同一policyに同じinbox_idのInboxCapacityLimitが存在","重複するinbox_id","uniquenessエラーが発生する","高","ユニーク制約"
"117","UT-ENT-117","InboxCapacityLimit","validates :inbox_id uniqueness","正常系","異なるpolicyであれば同じinbox_idでも作成できること","異なるpolicyに同じinbox_idが存在","同じinbox_id","バリデーションエラーなし","中","スコープ付きユニーク"
"118","UT-ENT-118","SlaEvent","belongs_to :account","正常系","accountリレーションが正しく取得できること","SlaEventとAccountが存在","account_id=有効なID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"119","UT-ENT-119","SlaEvent","belongs_to :inbox","正常系","inboxリレーションが正しく取得できること","SlaEventとInboxが存在","inbox_id=有効なID","関連するInboxオブジェクトが返却される","高","受信箱参照"
"120","UT-ENT-120","SlaEvent","belongs_to :conversation","正常系","conversationリレーションが正しく取得できること","SlaEventとConversationが存在","conversation_id=有効なID","関連するConversationオブジェクトが返却される","高","会話参照"
"121","UT-ENT-121","SlaEvent","belongs_to :sla_policy","正常系","sla_policyリレーションが正しく取得できること","SlaEventとSlaPolicyが存在","sla_policy_id=有効なID","関連するSlaPolicyオブジェクトが返却される","高","ポリシー参照"
"122","UT-ENT-122","SlaEvent","belongs_to :applied_sla","正常系","applied_slaリレーションが正しく取得できること","SlaEventとAppliedSlaが存在","applied_sla_id=有効なID","関連するAppliedSlaオブジェクトが返却される","高","適用SLA参照"
"123","UT-ENT-123","SlaEvent","enum event_type","正常系","event_type=frtが正しく設定されること","なし","event_type=:frt","event_typeが0として保存される","中","enumマッピング（初回応答時間）"
"124","UT-ENT-124","SlaEvent","enum event_type","正常系","event_type=nrtが正しく設定されること","なし","event_type=:nrt","event_typeが1として保存される","中","enumマッピング（次回応答時間）"
"125","UT-ENT-125","SlaEvent","enum event_type","正常系","event_type=rtが正しく設定されること","なし","event_type=:rt","event_typeが2として保存される","中","enumマッピング（解決時間）"
"126","UT-ENT-126","SlaEvent","ensure_applied_sla_id","正常系","applied_sla_idが未設定の場合conversationから取得されること","conversation_idに紐づくAppliedSlaが存在","applied_sla_id=nil","該当するAppliedSlaのidが設定される","中","自動補完"
"127","UT-ENT-127","SlaEvent","ensure_account_id","正常系","account_idが未設定の場合conversationから取得されること","conversationが設定済み","account_id=nil","conversation.account_idが設定される","中","自動補完"
"128","UT-ENT-128","SlaEvent","ensure_inbox_id","正常系","inbox_idが未設定の場合conversationから取得されること","conversationが設定済み","inbox_id=nil","conversation.inbox_idが設定される","中","自動補完"
"129","UT-ENT-129","SlaEvent","ensure_sla_policy_id","正常系","sla_policy_idが未設定の場合applied_slaから取得されること","applied_slaが設定済み","sla_policy_id=nil","applied_sla.sla_policy_idが設定される","中","自動補完"
"130","UT-ENT-130","SlaEvent","push_event_data","正常系","イベントデータが正しい形式で返却されること","SlaEventが存在","なし","id/event_type/meta/created_at/updated_atを含むハッシュ","中","イベント通知用データ"
"131","UT-ENT-131","SlaEvent","create_notifications","正常系","作成後に関係者に通知が送信されること","会話参加者とアサイン担当者が存在","event_type=:frt","sla_missed_first_responseタイプの通知が作成される","高","SLAミス通知"
"132","UT-ENT-132","SlaEvent","create_notifications","正常系","nrtイベントでsla_missed_next_response通知が作成されること","会話参加者が存在","event_type=:nrt","sla_missed_next_responseタイプの通知が作成される","高","次回応答ミス通知"
"133","UT-ENT-133","SlaEvent","create_notifications","正常系","rtイベントでsla_missed_resolution通知が作成されること","会話参加者が存在","event_type=:rt","sla_missed_resolutionタイプの通知が作成される","高","解決ミス通知"
"134","UT-ENT-134","SlaEvent","create_notifications","正常系","管理者にも通知が送信されること","アカウント管理者が存在","任意のevent_type","管理者に通知が作成される","高","管理者通知"
"135","UT-ENT-135","SlaEvent","create_notifications","正常系","assigneeにも通知が送信されること","会話にassigneeが設定済み","任意のevent_type","assigneeに通知が作成される","高","担当者通知"
"136","UT-ENT-136","SlaEvent","create_notifications","境界値","重複するユーザーには1回のみ通知されること","参加者と管理者が同一ユーザー","任意のevent_type","重複なく通知が作成される","中","重複排除"
"137","UT-ENT-137","SlaPolicy","belongs_to :account","正常系","accountリレーションが正しく取得できること","SlaPolicyとAccountが存在","account_id=有効なID","関連するAccountオブジェクトが返却される","高","基本リレーション"
"138","UT-ENT-138","SlaPolicy","validates :name","異常系","nameがnilの場合バリデーションエラーになること","なし","name=nil","presenceエラーが発生する","高","必須項目"
"139","UT-ENT-139","SlaPolicy","has_many :conversations","正常系","conversationsリレーションが正しく取得できること","関連するConversationが存在","なし","関連するConversationのコレクションが返却される","高","会話参照"
"140","UT-ENT-140","SlaPolicy","has_many :conversations","正常系","dependent: :nullifyで関連レコードの外部キーがnullになること","関連するConversationが存在","SlaPolicyを削除","Conversationのsla_policy_idがnullになる","中","nullify動作"
"141","UT-ENT-141","SlaPolicy","has_many :applied_slas","正常系","applied_slasリレーションが正しく取得できること","関連するAppliedSlaが存在","なし","関連するAppliedSlaのコレクションが返却される","高","適用SLA取得"
"142","UT-ENT-142","SlaPolicy","has_many :applied_slas","正常系","dependent: :destroy_asyncで関連レコードが非同期削除されること","関連するAppliedSlaが存在","SlaPolicyを削除","関連するAppliedSlaの削除ジョブがenqueueされる","中","非同期削除"
"143","UT-ENT-143","SlaPolicy","push_event_data","正常系","イベントデータが正しい形式で返却されること","SlaPolicyが存在","なし","id/name/frt/nrt/rtを含むハッシュ","中","イベント通知用データ"
"144","UT-ENT-144","SlaPolicy","push_event_data","境界値","threshold値がnilの場合もハッシュに含まれること","thresholdが未設定のSlaPolicy","なし","frt/nrt/rtがnilとして含まれるハッシュ","低","null値の処理"
