test.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. use flowy_folder2::entities::*;
  2. use flowy_test::event_builder::EventBuilder;
  3. use flowy_test::FlowyCoreTest;
  4. use flowy_user::errors::ErrorCode;
  5. #[tokio::test]
  6. async fn create_workspace_event_test() {
  7. let test = FlowyCoreTest::new_with_user().await;
  8. let request = CreateWorkspacePayloadPB {
  9. name: "my second workspace".to_owned(),
  10. desc: "".to_owned(),
  11. };
  12. let resp = EventBuilder::new(test)
  13. .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
  14. .payload(request)
  15. .async_send()
  16. .await
  17. .parse::<flowy_folder2::entities::WorkspacePB>();
  18. assert_eq!(resp.name, "my second workspace");
  19. }
  20. #[tokio::test]
  21. async fn open_workspace_event_test() {
  22. let test = FlowyCoreTest::new_with_user().await;
  23. let payload = CreateWorkspacePayloadPB {
  24. name: "my second workspace".to_owned(),
  25. desc: "".to_owned(),
  26. };
  27. // create a workspace
  28. let resp_1 = EventBuilder::new(test.clone())
  29. .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
  30. .payload(payload)
  31. .async_send()
  32. .await
  33. .parse::<flowy_folder2::entities::WorkspacePB>();
  34. // open the workspace
  35. let payload = WorkspaceIdPB {
  36. value: Some(resp_1.id.clone()),
  37. };
  38. let resp_2 = EventBuilder::new(test)
  39. .event(flowy_folder2::event_map::FolderEvent::OpenWorkspace)
  40. .payload(payload)
  41. .async_send()
  42. .await
  43. .parse::<flowy_folder2::entities::WorkspacePB>();
  44. assert_eq!(resp_1.id, resp_2.id);
  45. assert_eq!(resp_1.name, resp_2.name);
  46. }
  47. #[tokio::test]
  48. async fn create_view_event_test() {
  49. let test = FlowyCoreTest::new_with_user().await;
  50. let current_workspace = test.get_current_workspace().await.workspace;
  51. let view = test
  52. .create_view(&current_workspace.id, "My first view".to_string())
  53. .await;
  54. assert_eq!(view.parent_view_id, current_workspace.id);
  55. assert_eq!(view.name, "My first view");
  56. assert_eq!(view.layout, ViewLayoutPB::Document);
  57. }
  58. #[tokio::test]
  59. async fn update_view_event_with_name_test() {
  60. let test = FlowyCoreTest::new_with_user().await;
  61. let current_workspace = test.get_current_workspace().await.workspace;
  62. let view = test
  63. .create_view(&current_workspace.id, "My first view".to_string())
  64. .await;
  65. let error = test
  66. .update_view(UpdateViewPayloadPB {
  67. view_id: view.id.clone(),
  68. name: Some("My second view".to_string()),
  69. ..Default::default()
  70. })
  71. .await;
  72. assert!(error.is_none());
  73. let view = test.get_view(&view.id).await;
  74. assert_eq!(view.name, "My second view");
  75. }
  76. #[tokio::test]
  77. async fn update_view_event_with_icon_url_test() {
  78. let test = FlowyCoreTest::new_with_user().await;
  79. let current_workspace = test.get_current_workspace().await.workspace;
  80. let view = test
  81. .create_view(&current_workspace.id, "My first view".to_string())
  82. .await;
  83. let error = test
  84. .update_view(UpdateViewPayloadPB {
  85. view_id: view.id.clone(),
  86. icon_url: Some("appflowy.io".to_string()),
  87. ..Default::default()
  88. })
  89. .await;
  90. assert!(error.is_none());
  91. let view = test.get_view(&view.id).await;
  92. assert_eq!(view.icon_url.unwrap(), "appflowy.io");
  93. }
  94. #[tokio::test]
  95. async fn update_view_event_with_cover_url_test() {
  96. let test = FlowyCoreTest::new_with_user().await;
  97. let current_workspace = test.get_current_workspace().await.workspace;
  98. let view = test
  99. .create_view(&current_workspace.id, "My first view".to_string())
  100. .await;
  101. let error = test
  102. .update_view(UpdateViewPayloadPB {
  103. view_id: view.id.clone(),
  104. cover_url: Some("appflowy.io".to_string()),
  105. ..Default::default()
  106. })
  107. .await;
  108. assert!(error.is_none());
  109. let view = test.get_view(&view.id).await;
  110. assert_eq!(view.cover_url.unwrap(), "appflowy.io");
  111. }
  112. #[tokio::test]
  113. async fn delete_view_event_test() {
  114. let test = FlowyCoreTest::new_with_user().await;
  115. let current_workspace = test.get_current_workspace().await.workspace;
  116. let view = test
  117. .create_view(&current_workspace.id, "My first view".to_string())
  118. .await;
  119. test.delete_view(&view.id).await;
  120. // Try the read the view
  121. let payload = ViewIdPB {
  122. value: view.id.clone(),
  123. };
  124. let error = EventBuilder::new(test.clone())
  125. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  126. .payload(payload)
  127. .async_send()
  128. .await
  129. .error()
  130. .unwrap();
  131. assert_eq!(error.code, ErrorCode::RecordNotFound.value());
  132. }
  133. #[tokio::test]
  134. async fn put_back_trash_event_test() {
  135. let test = FlowyCoreTest::new_with_user().await;
  136. let current_workspace = test.get_current_workspace().await.workspace;
  137. let view = test
  138. .create_view(&current_workspace.id, "My first view".to_string())
  139. .await;
  140. test.delete_view(&view.id).await;
  141. // After delete view, the view will be moved to trash
  142. let payload = ViewIdPB {
  143. value: view.id.clone(),
  144. };
  145. let error = EventBuilder::new(test.clone())
  146. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  147. .payload(payload)
  148. .async_send()
  149. .await
  150. .error()
  151. .unwrap();
  152. assert_eq!(error.code, ErrorCode::RecordNotFound.value());
  153. let payload = TrashIdPB {
  154. id: view.id.clone(),
  155. };
  156. EventBuilder::new(test.clone())
  157. .event(flowy_folder2::event_map::FolderEvent::PutbackTrash)
  158. .payload(payload)
  159. .async_send()
  160. .await;
  161. let payload = ViewIdPB {
  162. value: view.id.clone(),
  163. };
  164. let error = EventBuilder::new(test.clone())
  165. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  166. .payload(payload)
  167. .async_send()
  168. .await
  169. .error();
  170. assert!(error.is_none());
  171. }
  172. #[tokio::test]
  173. async fn delete_view_permanently_event_test() {
  174. let test = FlowyCoreTest::new_with_user().await;
  175. let current_workspace = test.get_current_workspace().await.workspace;
  176. let view = test
  177. .create_view(&current_workspace.id, "My first view".to_string())
  178. .await;
  179. let payload = RepeatedViewIdPB {
  180. items: vec![view.id.clone()],
  181. };
  182. // delete the view. the view will be moved to trash
  183. EventBuilder::new(test.clone())
  184. .event(flowy_folder2::event_map::FolderEvent::DeleteView)
  185. .payload(payload)
  186. .async_send()
  187. .await;
  188. let trash = EventBuilder::new(test.clone())
  189. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  190. .async_send()
  191. .await
  192. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  193. .items;
  194. assert_eq!(trash.len(), 1);
  195. assert_eq!(trash[0].id, view.id);
  196. // delete the view from trash
  197. let payload = RepeatedTrashIdPB {
  198. items: vec![TrashIdPB {
  199. id: view.id.clone(),
  200. }],
  201. };
  202. EventBuilder::new(test.clone())
  203. .event(flowy_folder2::event_map::FolderEvent::DeleteTrash)
  204. .payload(payload)
  205. .async_send()
  206. .await;
  207. // After delete the last view, the trash should be empty
  208. let trash = EventBuilder::new(test.clone())
  209. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  210. .async_send()
  211. .await
  212. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  213. .items;
  214. assert!(trash.is_empty());
  215. }
  216. #[tokio::test]
  217. async fn delete_all_trash_test() {
  218. let test = FlowyCoreTest::new_with_user().await;
  219. let current_workspace = test.get_current_workspace().await.workspace;
  220. for i in 0..3 {
  221. let view = test
  222. .create_view(&current_workspace.id, format!("My {} view", i))
  223. .await;
  224. let payload = RepeatedViewIdPB {
  225. items: vec![view.id.clone()],
  226. };
  227. // delete the view. the view will be moved to trash
  228. EventBuilder::new(test.clone())
  229. .event(flowy_folder2::event_map::FolderEvent::DeleteView)
  230. .payload(payload)
  231. .async_send()
  232. .await;
  233. }
  234. let trash = EventBuilder::new(test.clone())
  235. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  236. .async_send()
  237. .await
  238. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  239. .items;
  240. assert_eq!(trash.len(), 3);
  241. // Delete all the trash
  242. EventBuilder::new(test.clone())
  243. .event(flowy_folder2::event_map::FolderEvent::DeleteAllTrash)
  244. .async_send()
  245. .await;
  246. // After delete the last view, the trash should be empty
  247. let trash = EventBuilder::new(test.clone())
  248. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  249. .async_send()
  250. .await
  251. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  252. .items;
  253. assert!(trash.is_empty());
  254. }
  255. #[tokio::test]
  256. async fn multiple_hierarchy_view_test() {
  257. let test = FlowyCoreTest::new_with_user().await;
  258. let current_workspace = test.get_current_workspace().await.workspace;
  259. for i in 1..4 {
  260. let parent = test
  261. .create_view(&current_workspace.id, format!("My {} view", i))
  262. .await;
  263. for j in 1..3 {
  264. let child = test
  265. .create_view(&parent.id, format!("My {}-{} view", i, j))
  266. .await;
  267. for k in 1..2 {
  268. let _sub_child = test
  269. .create_view(&child.id, format!("My {}-{}-{} view", i, j, k))
  270. .await;
  271. }
  272. }
  273. }
  274. let mut views = test.get_all_workspace_views().await;
  275. // There will be one default view when AppFlowy is initialized. So there will be 4 views in total
  276. assert_eq!(views.len(), 4);
  277. views.remove(0);
  278. // workspace
  279. // - view1
  280. // - view1-1
  281. // - view1-1-1
  282. // - view1-2
  283. // - view1-2-1
  284. // - view2
  285. // - view2-1
  286. // - view2-1-1
  287. // - view2-2
  288. // - view2-2-1
  289. // - view3
  290. // - view3-1
  291. // - view3-1-1
  292. // - view3-2
  293. // - view3-2-1
  294. assert_eq!(views[0].name, "My 1 view");
  295. assert_eq!(views[1].name, "My 2 view");
  296. assert_eq!(views[2].name, "My 3 view");
  297. assert_eq!(views[0].child_views.len(), 2);
  298. // By default only the first level of child views will be loaded
  299. assert!(views[0].child_views[0].child_views.is_empty());
  300. for (i, view) in views.into_iter().enumerate() {
  301. for (j, child_view) in view.child_views.into_iter().enumerate() {
  302. let payload = ViewIdPB {
  303. value: child_view.id.clone(),
  304. };
  305. let child = EventBuilder::new(test.clone())
  306. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  307. .payload(payload)
  308. .async_send()
  309. .await
  310. .parse::<flowy_folder2::entities::ViewPB>();
  311. assert_eq!(child.name, format!("My {}-{} view", i + 1, j + 1));
  312. assert_eq!(child.child_views.len(), 1);
  313. // By default only the first level of child views will be loaded
  314. assert!(child.child_views[0].child_views.is_empty());
  315. for (k, _child_view) in child_view.child_views.into_iter().enumerate() {
  316. // Get the last level view
  317. let sub_child = test.get_view(&child.id).await;
  318. assert_eq!(child.name, format!("My {}-{}-{} view", i + 1, j + 1, k + 1));
  319. assert!(sub_child.child_views.is_empty());
  320. }
  321. }
  322. }
  323. }
  324. #[tokio::test]
  325. async fn move_view_event_test() {
  326. let test = FlowyCoreTest::new_with_user().await;
  327. let current_workspace = test.get_current_workspace().await.workspace;
  328. for i in 1..4 {
  329. let parent = test
  330. .create_view(&current_workspace.id, format!("My {} view", i))
  331. .await;
  332. for j in 1..3 {
  333. let _ = test
  334. .create_view(&parent.id, format!("My {}-{} view", i, j))
  335. .await;
  336. }
  337. }
  338. let views = test.get_all_workspace_views().await;
  339. // There will be one default view when AppFlowy is initialized. So there will be 4 views in total
  340. assert_eq!(views.len(), 4);
  341. assert_eq!(views[1].name, "My 1 view");
  342. assert_eq!(views[2].name, "My 2 view");
  343. assert_eq!(views[3].name, "My 3 view");
  344. let payload = MoveViewPayloadPB {
  345. view_id: views[1].id.clone(),
  346. from: 1,
  347. to: 2,
  348. };
  349. let _ = EventBuilder::new(test.clone())
  350. .event(flowy_folder2::event_map::FolderEvent::MoveView)
  351. .payload(payload)
  352. .async_send()
  353. .await;
  354. let views = test.get_all_workspace_views().await;
  355. assert_eq!(views[1].name, "My 2 view");
  356. assert_eq!(views[2].name, "My 1 view");
  357. assert_eq!(views[3].name, "My 3 view");
  358. }
  359. #[tokio::test]
  360. async fn move_view_event_after_delete_view_test() {
  361. let test = FlowyCoreTest::new_with_user().await;
  362. let current_workspace = test.get_current_workspace().await.workspace;
  363. for i in 1..6 {
  364. let _ = test
  365. .create_view(&current_workspace.id, format!("My {} view", i))
  366. .await;
  367. }
  368. let views = test.get_all_workspace_views().await;
  369. assert_eq!(views[1].name, "My 1 view");
  370. assert_eq!(views[2].name, "My 2 view");
  371. assert_eq!(views[3].name, "My 3 view");
  372. assert_eq!(views[4].name, "My 4 view");
  373. assert_eq!(views[5].name, "My 5 view");
  374. test.delete_view(&views[3].id).await;
  375. // There will be one default view when AppFlowy is initialized. So there will be 4 views in total
  376. let views = test.get_all_workspace_views().await;
  377. assert_eq!(views[1].name, "My 1 view");
  378. assert_eq!(views[2].name, "My 2 view");
  379. assert_eq!(views[3].name, "My 4 view");
  380. assert_eq!(views[4].name, "My 5 view");
  381. let payload = MoveViewPayloadPB {
  382. view_id: views[1].id.clone(),
  383. from: 1,
  384. to: 3,
  385. };
  386. let _ = EventBuilder::new(test.clone())
  387. .event(flowy_folder2::event_map::FolderEvent::MoveView)
  388. .payload(payload)
  389. .async_send()
  390. .await;
  391. let views = test.get_all_workspace_views().await;
  392. assert_eq!(views[1].name, "My 2 view");
  393. assert_eq!(views[2].name, "My 4 view");
  394. assert_eq!(views[3].name, "My 1 view");
  395. assert_eq!(views[4].name, "My 5 view");
  396. }
  397. #[tokio::test]
  398. async fn move_view_event_after_delete_view_test2() {
  399. let test = FlowyCoreTest::new_with_user().await;
  400. let current_workspace = test.get_current_workspace().await.workspace;
  401. let parent = test
  402. .create_view(&current_workspace.id, "My view".to_string())
  403. .await;
  404. for j in 1..6 {
  405. let _ = test
  406. .create_view(&parent.id, format!("My 1-{} view", j))
  407. .await;
  408. }
  409. let views = test.get_view(&parent.id).await.child_views;
  410. assert_eq!(views.len(), 5);
  411. assert_eq!(views[0].name, "My 1-1 view");
  412. assert_eq!(views[1].name, "My 1-2 view");
  413. assert_eq!(views[2].name, "My 1-3 view");
  414. assert_eq!(views[3].name, "My 1-4 view");
  415. assert_eq!(views[4].name, "My 1-5 view");
  416. test.delete_view(&views[2].id).await;
  417. let payload = MoveViewPayloadPB {
  418. view_id: views[0].id.clone(),
  419. from: 0,
  420. to: 2,
  421. };
  422. let _ = EventBuilder::new(test.clone())
  423. .event(flowy_folder2::event_map::FolderEvent::MoveView)
  424. .payload(payload)
  425. .async_send()
  426. .await;
  427. let views = test.get_view(&parent.id).await.child_views;
  428. assert_eq!(views[0].name, "My 1-2 view");
  429. assert_eq!(views[1].name, "My 1-4 view");
  430. assert_eq!(views[2].name, "My 1-1 view");
  431. assert_eq!(views[3].name, "My 1-5 view");
  432. }
  433. #[tokio::test]
  434. async fn create_parent_view_with_invalid_name() {
  435. for (name, code) in invalid_workspace_name_test_case() {
  436. let sdk = FlowyCoreTest::new();
  437. let request = CreateWorkspacePayloadPB {
  438. name,
  439. desc: "".to_owned(),
  440. };
  441. assert_eq!(
  442. EventBuilder::new(sdk)
  443. .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
  444. .payload(request)
  445. .async_send()
  446. .await
  447. .error()
  448. .unwrap()
  449. .code,
  450. code.value()
  451. )
  452. }
  453. }
  454. fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
  455. vec![
  456. ("".to_owned(), ErrorCode::WorkspaceNameInvalid),
  457. ("1234".repeat(100), ErrorCode::WorkspaceNameTooLong),
  458. ]
  459. }