Remove dev servers (#19638)
TODO: - [ ] Check that workspace migration worked - [ ] Add server migrations and make sure SeaORM files are in sync (maybe?) Release Notes: - N/A --------- Co-authored-by: Conrad <conrad@zed.dev> Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
b5f816dde5
commit
02718284ef
55 changed files with 391 additions and 5024 deletions
|
@ -1,643 +0,0 @@
|
|||
use std::{path::Path, sync::Arc};
|
||||
|
||||
use call::ActiveCall;
|
||||
use editor::Editor;
|
||||
use fs::Fs;
|
||||
use gpui::{TestAppContext, VisualTestContext, WindowHandle};
|
||||
use rpc::{proto::DevServerStatus, ErrorCode, ErrorExt};
|
||||
use serde_json::json;
|
||||
use workspace::{AppState, Workspace};
|
||||
|
||||
use crate::tests::{following_tests::join_channel, TestServer};
|
||||
|
||||
use super::TestClient;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext) {
|
||||
let (server, client) = TestServer::start1(cx).await;
|
||||
|
||||
let store = cx.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
let resp = store
|
||||
.update(cx, |store, cx| {
|
||||
store.create_dev_server("server-1".to_string(), None, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
store.update(cx, |store, _| {
|
||||
assert_eq!(store.dev_servers().len(), 1);
|
||||
assert_eq!(store.dev_servers()[0].name, "server-1");
|
||||
assert_eq!(store.dev_servers()[0].status, DevServerStatus::Offline);
|
||||
});
|
||||
|
||||
let dev_server = server.create_dev_server(resp.access_token, cx2).await;
|
||||
cx.executor().run_until_parked();
|
||||
store.update(cx, |store, _| {
|
||||
assert_eq!(store.dev_servers()[0].status, DevServerStatus::Online);
|
||||
});
|
||||
|
||||
dev_server
|
||||
.fs()
|
||||
.insert_tree(
|
||||
"/remote",
|
||||
json!({
|
||||
"1.txt": "remote\nremote\nremote",
|
||||
"2.js": "function two() { return 2; }",
|
||||
"3.rs": "mod test",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
store
|
||||
.update(cx, |store, cx| {
|
||||
store.create_dev_server_project(
|
||||
client::DevServerId(resp.dev_server_id),
|
||||
"/remote".to_string(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
let remote_workspace = store
|
||||
.update(cx, |store, cx| {
|
||||
let projects = store.dev_server_projects();
|
||||
assert_eq!(projects.len(), 1);
|
||||
assert_eq!(projects[0].paths, vec!["/remote"]);
|
||||
workspace::join_dev_server_project(
|
||||
projects[0].id,
|
||||
projects[0].project_id.unwrap(),
|
||||
client.app_state.clone(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
let cx = VisualTestContext::from_window(remote_workspace.into(), cx).as_mut();
|
||||
cx.simulate_keystrokes("cmd-p 1 enter");
|
||||
|
||||
let editor = remote_workspace
|
||||
.update(cx, |ws, cx| {
|
||||
ws.active_item_as::<Editor>(cx).unwrap().clone()
|
||||
})
|
||||
.unwrap();
|
||||
editor.update(cx, |ed, cx| {
|
||||
assert_eq!(ed.text(cx).to_string(), "remote\nremote\nremote");
|
||||
});
|
||||
cx.simulate_input("wow!");
|
||||
cx.simulate_keystrokes("cmd-s");
|
||||
|
||||
let content = dev_server
|
||||
.fs()
|
||||
.load(Path::new("/remote/1.txt"))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(content, "wow!remote\nremote\nremote\n");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_env_files(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let cx1 = VisualTestContext::from_window(remote_workspace.into(), cx1).as_mut();
|
||||
cx1.simulate_keystrokes("cmd-p . e enter");
|
||||
|
||||
let editor = remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
ws.active_item_as::<Editor>(cx).unwrap().clone()
|
||||
})
|
||||
.unwrap();
|
||||
editor.update(cx1, |ed, cx| {
|
||||
assert_eq!(ed.text(cx).to_string(), "SECRET");
|
||||
});
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
channel_id,
|
||||
client1.app_state.clone(),
|
||||
Some(remote_workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
assert!(ws.project().read(cx).is_shared());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
join_channel(channel_id, &client2, cx2).await.unwrap();
|
||||
cx2.executor().run_until_parked();
|
||||
|
||||
let (workspace2, cx2) = client2.active_workspace(cx2);
|
||||
let editor = workspace2.update(cx2, |ws, cx| {
|
||||
ws.active_item_as::<Editor>(cx).unwrap().clone()
|
||||
});
|
||||
// TODO: it'd be nice to hide .env files from other people
|
||||
editor.update(cx2, |ed, cx| {
|
||||
assert_eq!(ed.text(cx).to_string(), "SECRET");
|
||||
});
|
||||
}
|
||||
|
||||
async fn create_dev_server_project(
|
||||
server: &TestServer,
|
||||
client_app_state: Arc<AppState>,
|
||||
cx: &mut TestAppContext,
|
||||
cx_devserver: &mut TestAppContext,
|
||||
) -> (TestClient, WindowHandle<Workspace>) {
|
||||
let store = cx.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
let resp = store
|
||||
.update(cx, |store, cx| {
|
||||
store.create_dev_server("server-1".to_string(), None, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let dev_server = server
|
||||
.create_dev_server(resp.access_token, cx_devserver)
|
||||
.await;
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
dev_server
|
||||
.fs()
|
||||
.insert_tree(
|
||||
"/remote",
|
||||
json!({
|
||||
"1.txt": "remote\nremote\nremote",
|
||||
".env": "SECRET",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
store
|
||||
.update(cx, |store, cx| {
|
||||
store.create_dev_server_project(
|
||||
client::DevServerId(resp.dev_server_id),
|
||||
"/remote".to_string(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
let workspace = store
|
||||
.update(cx, |store, cx| {
|
||||
let projects = store.dev_server_projects();
|
||||
assert_eq!(projects.len(), 1);
|
||||
assert_eq!(projects[0].paths, vec!["/remote"]);
|
||||
workspace::join_dev_server_project(
|
||||
projects[0].id,
|
||||
projects[0].project_id.unwrap(),
|
||||
client_app_state,
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
(dev_server, workspace)
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_leave_room(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
channel_id,
|
||||
client1.app_state.clone(),
|
||||
Some(remote_workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
assert!(ws.project().read(cx).is_shared());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
join_channel(channel_id, &client2, cx2).await.unwrap();
|
||||
cx2.executor().run_until_parked();
|
||||
|
||||
cx1.update(|cx| ActiveCall::global(cx).update(cx, |active_call, cx| active_call.hang_up(cx)))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let (workspace, cx2) = client2.active_workspace(cx2);
|
||||
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected(cx)));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_delete(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
channel_id,
|
||||
client1.app_state.clone(),
|
||||
Some(remote_workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
assert!(ws.project().read(cx).is_shared());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
join_channel(channel_id, &client2, cx2).await.unwrap();
|
||||
cx2.executor().run_until_parked();
|
||||
|
||||
cx1.update(|cx| {
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, cx| {
|
||||
store.delete_dev_server_project(store.dev_server_projects().first().unwrap().id, cx)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let (workspace, cx2) = client2.active_workspace(cx2);
|
||||
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected(cx)));
|
||||
|
||||
cx1.update(|cx| {
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, _| {
|
||||
assert_eq!(store.dev_server_projects().len(), 0);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_rename(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
channel_id,
|
||||
client1.app_state.clone(),
|
||||
Some(remote_workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
assert!(ws.project().read(cx).is_shared());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
join_channel(channel_id, &client2, cx2).await.unwrap();
|
||||
cx2.executor().run_until_parked();
|
||||
|
||||
cx1.update(|cx| {
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, cx| {
|
||||
store.rename_dev_server(
|
||||
store.dev_servers().first().unwrap().id,
|
||||
"name-edited".to_string(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
cx1.update(|cx| {
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, _| {
|
||||
assert_eq!(store.dev_servers().first().unwrap().name, "name-edited");
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_refresh_access_token(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
cx4: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
channel_id,
|
||||
client1.app_state.clone(),
|
||||
Some(remote_workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
assert!(ws.project().read(cx).is_shared());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
join_channel(channel_id, &client2, cx2).await.unwrap();
|
||||
cx2.executor().run_until_parked();
|
||||
|
||||
// Regenerate the access token
|
||||
let new_token_response = cx1
|
||||
.update(|cx| {
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, cx| {
|
||||
store.regenerate_dev_server_token(store.dev_servers().first().unwrap().id, cx)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
// Assert that the other client was disconnected
|
||||
let (workspace, cx2) = client2.active_workspace(cx2);
|
||||
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected(cx)));
|
||||
|
||||
// Assert that the owner of the dev server does not see the dev server as online anymore
|
||||
let (workspace, cx1) = client1.active_workspace(cx1);
|
||||
cx1.update(|cx| {
|
||||
assert!(workspace.read(cx).project().read(cx).is_disconnected(cx));
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, _| {
|
||||
assert_eq!(
|
||||
store.dev_servers().first().unwrap().status,
|
||||
DevServerStatus::Offline
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
// Reconnect the dev server with the new token
|
||||
let _dev_server = server
|
||||
.create_dev_server(new_token_response.access_token, cx4)
|
||||
.await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
// Assert that the dev server is online again
|
||||
cx1.update(|cx| {
|
||||
dev_server_projects::Store::global(cx).update(cx, |store, _| {
|
||||
assert_eq!(store.dev_servers().len(), 1);
|
||||
assert_eq!(
|
||||
store.dev_servers().first().unwrap().status,
|
||||
DevServerStatus::Online
|
||||
);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_reconnect(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (mut server, client1) = TestServer::start1(cx1).await;
|
||||
let channel_id = server
|
||||
.make_channel("test", None, (&client1, cx1), &mut [])
|
||||
.await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
channel_id,
|
||||
client1.app_state.clone(),
|
||||
Some(remote_workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
remote_workspace
|
||||
.update(cx1, |ws, cx| {
|
||||
assert!(ws.project().read(cx).is_shared());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
drop(client1);
|
||||
|
||||
let client2 = server.create_client(cx2, "user_a").await;
|
||||
|
||||
let store = cx2.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
store
|
||||
.update(cx2, |store, cx| {
|
||||
let projects = store.dev_server_projects();
|
||||
workspace::join_dev_server_project(
|
||||
projects[0].id,
|
||||
projects[0].project_id.unwrap(),
|
||||
client2.app_state.clone(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dev_server_restart(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext) {
|
||||
let (server, client1) = TestServer::start1(cx1).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
let cx = VisualTestContext::from_window(remote_workspace.into(), cx1).as_mut();
|
||||
|
||||
server.reset().await;
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.simulate_keystrokes("cmd-p 1 enter");
|
||||
remote_workspace
|
||||
.update(cx, |ws, cx| {
|
||||
ws.active_item_as::<Editor>(cx)
|
||||
.unwrap()
|
||||
.update(cx, |ed, cx| {
|
||||
assert_eq!(ed.text(cx).to_string(), "remote\nremote\nremote");
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_create_dev_server_project_path_validation(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
) {
|
||||
let (server, client1) = TestServer::start1(cx1).await;
|
||||
let _channel_id = server
|
||||
.make_channel("test", None, (&client1, cx1), &mut [])
|
||||
.await;
|
||||
|
||||
// Creating a project with a path that does exist should not fail
|
||||
let (_dev_server, _) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let store = cx1.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
let resp = store
|
||||
.update(cx1, |store, cx| {
|
||||
store.create_dev_server("server-2".to_string(), None, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let _dev_server = server.create_dev_server(resp.access_token, cx3).await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
// Creating a remote project with a path that does not exist should fail
|
||||
let result = store
|
||||
.update(cx1, |store, cx| {
|
||||
store.create_dev_server_project(
|
||||
client::DevServerId(resp.dev_server_id),
|
||||
"/notfound".to_string(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let error = result.unwrap_err();
|
||||
assert!(matches!(
|
||||
error.error_code(),
|
||||
ErrorCode::DevServerProjectPathDoesNotExist
|
||||
));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_save_as_remote(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext) {
|
||||
let (server, client1) = TestServer::start1(cx1).await;
|
||||
|
||||
// Creating a project with a path that does exist should not fail
|
||||
let (dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
|
||||
let mut cx = VisualTestContext::from_window(remote_workspace.into(), cx1);
|
||||
|
||||
cx.simulate_keystrokes("cmd-p 1 enter");
|
||||
cx.simulate_keystrokes("cmd-shift-s");
|
||||
cx.simulate_input("2.txt");
|
||||
cx.simulate_keystrokes("enter");
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
let title = remote_workspace
|
||||
.update(&mut cx, |ws, cx| {
|
||||
let active_item = ws.active_item(cx).unwrap();
|
||||
active_item.tab_description(0, cx).unwrap()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(title, "2.txt");
|
||||
|
||||
let path = Path::new("/remote/2.txt");
|
||||
assert_eq!(
|
||||
dev_server.fs().load(path).await.unwrap(),
|
||||
"remote\nremote\nremote"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_new_file_remote(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext) {
|
||||
let (server, client1) = TestServer::start1(cx1).await;
|
||||
|
||||
// Creating a project with a path that does exist should not fail
|
||||
let (dev_server, remote_workspace) =
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
|
||||
let mut cx = VisualTestContext::from_window(remote_workspace.into(), cx1);
|
||||
|
||||
cx.simulate_keystrokes("cmd-n");
|
||||
cx.simulate_input("new!");
|
||||
cx.simulate_keystrokes("cmd-shift-s");
|
||||
cx.simulate_input("2.txt");
|
||||
cx.simulate_keystrokes("enter");
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
let title = remote_workspace
|
||||
.update(&mut cx, |ws, cx| {
|
||||
ws.active_item(cx).unwrap().tab_description(0, cx).unwrap()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(title, "2.txt");
|
||||
|
||||
let path = Path::new("/remote/2.txt");
|
||||
assert_eq!(dev_server.fs().load(path).await.unwrap(), "new!");
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{
|
||||
auth::split_dev_server_token,
|
||||
db::{tests::TestDb, NewUserParams, UserId},
|
||||
executor::Executor,
|
||||
rpc::{Principal, Server, ZedVersion, CLEANUP_TIMEOUT, RECONNECT_TIMEOUT},
|
||||
|
@ -204,7 +203,7 @@ impl TestServer {
|
|||
.override_authenticate(move |cx| {
|
||||
cx.spawn(|_| async move {
|
||||
let access_token = "the-token".to_string();
|
||||
Ok(Credentials::User {
|
||||
Ok(Credentials {
|
||||
user_id: user_id.to_proto(),
|
||||
access_token,
|
||||
})
|
||||
|
@ -213,7 +212,7 @@ impl TestServer {
|
|||
.override_establish_connection(move |credentials, cx| {
|
||||
assert_eq!(
|
||||
credentials,
|
||||
&Credentials::User {
|
||||
&Credentials {
|
||||
user_id: user_id.0 as u64,
|
||||
access_token: "the-token".into()
|
||||
}
|
||||
|
@ -297,7 +296,6 @@ impl TestServer {
|
|||
collab_ui::init(&app_state, cx);
|
||||
file_finder::init(cx);
|
||||
menu::init();
|
||||
dev_server_projects::init(client.clone(), cx);
|
||||
settings::KeymapFile::load_asset(os_keymap, cx).unwrap();
|
||||
language_model::LanguageModelRegistry::test(cx);
|
||||
assistant::context_store::init(&client.clone().into());
|
||||
|
@ -319,135 +317,6 @@ impl TestServer {
|
|||
client
|
||||
}
|
||||
|
||||
pub async fn create_dev_server(
|
||||
&self,
|
||||
access_token: String,
|
||||
cx: &mut TestAppContext,
|
||||
) -> TestClient {
|
||||
cx.update(|cx| {
|
||||
if cx.has_global::<SettingsStore>() {
|
||||
panic!("Same cx used to create two test clients")
|
||||
}
|
||||
let settings = SettingsStore::test(cx);
|
||||
cx.set_global(settings);
|
||||
release_channel::init(SemanticVersion::default(), cx);
|
||||
client::init_settings(cx);
|
||||
});
|
||||
let (dev_server_id, _) = split_dev_server_token(&access_token).unwrap();
|
||||
|
||||
let clock = Arc::new(FakeSystemClock::default());
|
||||
let http = FakeHttpClient::with_404_response();
|
||||
let mut client = cx.update(|cx| Client::new(clock, http.clone(), cx));
|
||||
let server = self.server.clone();
|
||||
let db = self.app_state.db.clone();
|
||||
let connection_killers = self.connection_killers.clone();
|
||||
let forbid_connections = self.forbid_connections.clone();
|
||||
Arc::get_mut(&mut client)
|
||||
.unwrap()
|
||||
.set_id(1)
|
||||
.set_dev_server_token(client::DevServerToken(access_token.clone()))
|
||||
.override_establish_connection(move |credentials, cx| {
|
||||
assert_eq!(
|
||||
credentials,
|
||||
&Credentials::DevServer {
|
||||
token: client::DevServerToken(access_token.to_string())
|
||||
}
|
||||
);
|
||||
|
||||
let server = server.clone();
|
||||
let db = db.clone();
|
||||
let connection_killers = connection_killers.clone();
|
||||
let forbid_connections = forbid_connections.clone();
|
||||
cx.spawn(move |cx| async move {
|
||||
if forbid_connections.load(SeqCst) {
|
||||
Err(EstablishConnectionError::other(anyhow!(
|
||||
"server is forbidding connections"
|
||||
)))
|
||||
} else {
|
||||
let (client_conn, server_conn, killed) =
|
||||
Connection::in_memory(cx.background_executor().clone());
|
||||
let (connection_id_tx, connection_id_rx) = oneshot::channel();
|
||||
let dev_server = db
|
||||
.get_dev_server(dev_server_id)
|
||||
.await
|
||||
.expect("retrieving dev_server failed");
|
||||
cx.background_executor()
|
||||
.spawn(server.handle_connection(
|
||||
server_conn,
|
||||
"dev-server".to_string(),
|
||||
Principal::DevServer(dev_server),
|
||||
ZedVersion(SemanticVersion::new(1, 0, 0)),
|
||||
None,
|
||||
Some(connection_id_tx),
|
||||
Executor::Deterministic(cx.background_executor().clone()),
|
||||
))
|
||||
.detach();
|
||||
let connection_id = connection_id_rx.await.map_err(|e| {
|
||||
EstablishConnectionError::Other(anyhow!(
|
||||
"{} (is server shutting down?)",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
connection_killers
|
||||
.lock()
|
||||
.insert(connection_id.into(), killed);
|
||||
Ok(client_conn)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
|
||||
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||
let language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||
let session = cx.new_model(|cx| AppSession::new(Session::test(), cx));
|
||||
let app_state = Arc::new(workspace::AppState {
|
||||
client: client.clone(),
|
||||
user_store: user_store.clone(),
|
||||
workspace_store,
|
||||
languages: language_registry,
|
||||
fs: fs.clone(),
|
||||
build_window_options: |_, _| Default::default(),
|
||||
node_runtime: NodeRuntime::unavailable(),
|
||||
session,
|
||||
});
|
||||
|
||||
cx.update(|cx| {
|
||||
theme::init(theme::LoadThemes::JustBase, cx);
|
||||
Project::init(&client, cx);
|
||||
client::init(&client, cx);
|
||||
language::init(cx);
|
||||
editor::init(cx);
|
||||
workspace::init(app_state.clone(), cx);
|
||||
call::init(client.clone(), user_store.clone(), cx);
|
||||
channel::init(&client, user_store.clone(), cx);
|
||||
notifications::init(client.clone(), user_store, cx);
|
||||
collab_ui::init(&app_state, cx);
|
||||
file_finder::init(cx);
|
||||
menu::init();
|
||||
headless::init(
|
||||
client.clone(),
|
||||
headless::AppState {
|
||||
languages: app_state.languages.clone(),
|
||||
user_store: app_state.user_store.clone(),
|
||||
fs: fs.clone(),
|
||||
node_runtime: app_state.node_runtime.clone(),
|
||||
},
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
TestClient {
|
||||
app_state,
|
||||
username: "dev-server".to_string(),
|
||||
channel_store: cx.read(ChannelStore::global).clone(),
|
||||
notification_store: cx.read(NotificationStore::global).clone(),
|
||||
state: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disconnect_client(&self, peer_id: PeerId) {
|
||||
self.connection_killers
|
||||
.lock()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue