385 lines · 11.3 KB · Rust
RawDownload
use crate::channel_chat::ChannelChatEvent; use super::*;use client::{test::FakeServer, Client, UserStore};use clock::FakeSystemClock;use gpui::{App, AppContext as _, Entity, SemanticVersion, TestAppContext};use http_client::FakeHttpClient;use rpc::proto::{self};use settings::SettingsStore; #[gpui::test]fn test_update_channels(cx: &mut App) {    let channel_store = init_test(cx);     update_channels(        &channel_store,        proto::UpdateChannels {            channels: vec![                proto::Channel {                    id: 1,                    name: "b".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: Vec::new(),                },                proto::Channel {                    id: 2,                    name: "a".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: Vec::new(),                },            ],            ..Default::default()        },        cx,    );    assert_channels(        &channel_store,        &[            //            (0, "a".to_string()),            (0, "b".to_string()),        ],        cx,    );     update_channels(        &channel_store,        proto::UpdateChannels {            channels: vec![                proto::Channel {                    id: 3,                    name: "x".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: vec![1],                },                proto::Channel {                    id: 4,                    name: "y".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: vec![2],                },            ],            ..Default::default()        },        cx,    );    assert_channels(        &channel_store,        &[            (0, "a".to_string()),            (1, "y".to_string()),            (0, "b".to_string()),            (1, "x".to_string()),        ],        cx,    );} #[gpui::test]fn test_dangling_channel_paths(cx: &mut App) {    let channel_store = init_test(cx);     update_channels(        &channel_store,        proto::UpdateChannels {            channels: vec![                proto::Channel {                    id: 0,                    name: "a".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: vec![],                },                proto::Channel {                    id: 1,                    name: "b".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: vec![0],                },                proto::Channel {                    id: 2,                    name: "c".to_string(),                    visibility: proto::ChannelVisibility::Members as i32,                    parent_path: vec![0, 1],                },            ],            ..Default::default()        },        cx,    );    // Sanity check    assert_channels(        &channel_store,        &[            //            (0, "a".to_string()),            (1, "b".to_string()),            (2, "c".to_string()),        ],        cx,    );     update_channels(        &channel_store,        proto::UpdateChannels {            delete_channels: vec![1, 2],            ..Default::default()        },        cx,    );     // Make sure that the 1/2/3 path is gone    assert_channels(&channel_store, &[(0, "a".to_string())], cx);} #[gpui::test]async fn test_channel_messages(cx: &mut TestAppContext) {    let user_id = 5;    let channel_id = 5;    let channel_store = cx.update(init_test);    let client = channel_store.update(cx, |s, _| s.client());    let server = FakeServer::for_client(user_id, &client, cx).await;     // Get the available channels.    server.send(proto::UpdateChannels {        channels: vec![proto::Channel {            id: channel_id,            name: "the-channel".to_string(),            visibility: proto::ChannelVisibility::Members as i32,            parent_path: vec![],        }],        ..Default::default()    });    cx.executor().run_until_parked();    cx.update(|cx| {        assert_channels(&channel_store, &[(0, "the-channel".to_string())], cx);    });     let get_users = server.receive::<proto::GetUsers>().await.unwrap();    assert_eq!(get_users.payload.user_ids, vec![5]);    server.respond(        get_users.receipt(),        proto::UsersResponse {            users: vec![proto::User {                id: 5,                github_login: "nathansobo".into(),                avatar_url: "http://avatar.com/nathansobo".into(),                name: None,                email: None,            }],        },    );     // Join a channel and populate its existing messages.    let channel = channel_store.update(cx, |store, cx| {        let channel_id = store.ordered_channels().next().unwrap().1.id;        store.open_channel_chat(channel_id, cx)    });    let join_channel = server.receive::<proto::JoinChannelChat>().await.unwrap();    server.respond(        join_channel.receipt(),        proto::JoinChannelChatResponse {            messages: vec![                proto::ChannelMessage {                    id: 10,                    body: "a".into(),                    timestamp: 1000,                    sender_id: 5,                    mentions: vec![],                    nonce: Some(1.into()),                    reply_to_message_id: None,                    edited_at: None,                },                proto::ChannelMessage {                    id: 11,                    body: "b".into(),                    timestamp: 1001,                    sender_id: 6,                    mentions: vec![],                    nonce: Some(2.into()),                    reply_to_message_id: None,                    edited_at: None,                },            ],            done: false,        },    );     cx.executor().start_waiting();     // Client requests all users for the received messages    let mut get_users = server.receive::<proto::GetUsers>().await.unwrap();    get_users.payload.user_ids.sort();    assert_eq!(get_users.payload.user_ids, vec![6]);    server.respond(        get_users.receipt(),        proto::UsersResponse {            users: vec![proto::User {                id: 6,                github_login: "maxbrunsfeld".into(),                avatar_url: "http://avatar.com/maxbrunsfeld".into(),                name: None,                email: None,            }],        },    );     let channel = channel.await.unwrap();    channel.update(cx, |channel, _| {        assert_eq!(            channel                .messages_in_range(0..2)                .map(|message| (message.sender.github_login.clone(), message.body.clone()))                .collect::<Vec<_>>(),            &[                ("nathansobo".into(), "a".into()),                ("maxbrunsfeld".into(), "b".into())            ]        );    });     // Receive a new message.    server.send(proto::ChannelMessageSent {        channel_id,        message: Some(proto::ChannelMessage {            id: 12,            body: "c".into(),            timestamp: 1002,            sender_id: 7,            mentions: vec![],            nonce: Some(3.into()),            reply_to_message_id: None,            edited_at: None,        }),    });     // Client requests user for message since they haven't seen them yet    let get_users = server.receive::<proto::GetUsers>().await.unwrap();    assert_eq!(get_users.payload.user_ids, vec![7]);    server.respond(        get_users.receipt(),        proto::UsersResponse {            users: vec![proto::User {                id: 7,                github_login: "as-cii".into(),                avatar_url: "http://avatar.com/as-cii".into(),                name: None,                email: None,            }],        },    );     assert_eq!(        channel.next_event(cx).await,        ChannelChatEvent::MessagesUpdated {            old_range: 2..2,            new_count: 1,        }    );    channel.update(cx, |channel, _| {        assert_eq!(            channel                .messages_in_range(2..3)                .map(|message| (message.sender.github_login.clone(), message.body.clone()))                .collect::<Vec<_>>(),            &[("as-cii".into(), "c".into())]        )    });     // Scroll up to view older messages.    channel.update(cx, |channel, cx| {        channel.load_more_messages(cx).unwrap().detach();    });    let get_messages = server.receive::<proto::GetChannelMessages>().await.unwrap();    assert_eq!(get_messages.payload.channel_id, 5);    assert_eq!(get_messages.payload.before_message_id, 10);    server.respond(        get_messages.receipt(),        proto::GetChannelMessagesResponse {            done: true,            messages: vec![                proto::ChannelMessage {                    id: 8,                    body: "y".into(),                    timestamp: 998,                    sender_id: 5,                    nonce: Some(4.into()),                    mentions: vec![],                    reply_to_message_id: None,                    edited_at: None,                },                proto::ChannelMessage {                    id: 9,                    body: "z".into(),                    timestamp: 999,                    sender_id: 6,                    nonce: Some(5.into()),                    mentions: vec![],                    reply_to_message_id: None,                    edited_at: None,                },            ],        },    );     assert_eq!(        channel.next_event(cx).await,        ChannelChatEvent::MessagesUpdated {            old_range: 0..0,            new_count: 2,        }    );    channel.update(cx, |channel, _| {        assert_eq!(            channel                .messages_in_range(0..2)                .map(|message| (message.sender.github_login.clone(), message.body.clone()))                .collect::<Vec<_>>(),            &[                ("nathansobo".into(), "y".into()),                ("maxbrunsfeld".into(), "z".into())            ]        );    });} fn init_test(cx: &mut App) -> Entity<ChannelStore> {    let settings_store = SettingsStore::test(cx);    cx.set_global(settings_store);    release_channel::init(SemanticVersion::default(), cx);    client::init_settings(cx);     let clock = Arc::new(FakeSystemClock::new());    let http = FakeHttpClient::with_404_response();    let client = Client::new(clock, http.clone(), cx);    let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));     client::init(&client, cx);    crate::init(&client, user_store, cx);     ChannelStore::global(cx)} fn update_channels(    channel_store: &Entity<ChannelStore>,    message: proto::UpdateChannels,    cx: &mut App,) {    let task = channel_store.update(cx, |store, cx| store.update_channels(message, cx));    assert!(task.is_none());} #[track_caller]fn assert_channels(    channel_store: &Entity<ChannelStore>,    expected_channels: &[(usize, String)],    cx: &mut App,) {    let actual = channel_store.update(cx, |store, _| {        store            .ordered_channels()            .map(|(depth, channel)| (depth, channel.name.to_string()))            .collect::<Vec<_>>()    });    assert_eq!(actual, expected_channels);}