test.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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 delete_view_event_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. test.delete_view(&view.id).await;
  66. // Try the read the view
  67. let payload = ViewIdPB {
  68. value: view.id.clone(),
  69. };
  70. let error = EventBuilder::new(test.clone())
  71. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  72. .payload(payload)
  73. .async_send()
  74. .await
  75. .error()
  76. .unwrap();
  77. assert_eq!(error.code, ErrorCode::RecordNotFound.value());
  78. }
  79. #[tokio::test]
  80. async fn put_back_trash_event_test() {
  81. let test = FlowyCoreTest::new_with_user().await;
  82. let current_workspace = test.get_current_workspace().await.workspace;
  83. let view = test
  84. .create_view(&current_workspace.id, "My first view".to_string())
  85. .await;
  86. test.delete_view(&view.id).await;
  87. // After delete view, the view will be moved to trash
  88. let payload = ViewIdPB {
  89. value: view.id.clone(),
  90. };
  91. let error = EventBuilder::new(test.clone())
  92. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  93. .payload(payload)
  94. .async_send()
  95. .await
  96. .error()
  97. .unwrap();
  98. assert_eq!(error.code, ErrorCode::RecordNotFound.value());
  99. let payload = TrashIdPB {
  100. id: view.id.clone(),
  101. };
  102. EventBuilder::new(test.clone())
  103. .event(flowy_folder2::event_map::FolderEvent::PutbackTrash)
  104. .payload(payload)
  105. .async_send()
  106. .await;
  107. let payload = ViewIdPB {
  108. value: view.id.clone(),
  109. };
  110. let error = EventBuilder::new(test.clone())
  111. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  112. .payload(payload)
  113. .async_send()
  114. .await
  115. .error();
  116. assert!(error.is_none());
  117. }
  118. #[tokio::test]
  119. async fn delete_view_permanently_event_test() {
  120. let test = FlowyCoreTest::new_with_user().await;
  121. let current_workspace = test.get_current_workspace().await.workspace;
  122. let view = test
  123. .create_view(&current_workspace.id, "My first view".to_string())
  124. .await;
  125. let payload = RepeatedViewIdPB {
  126. items: vec![view.id.clone()],
  127. };
  128. // delete the view. the view will be moved to trash
  129. EventBuilder::new(test.clone())
  130. .event(flowy_folder2::event_map::FolderEvent::DeleteView)
  131. .payload(payload)
  132. .async_send()
  133. .await;
  134. let trash = EventBuilder::new(test.clone())
  135. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  136. .async_send()
  137. .await
  138. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  139. .items;
  140. assert_eq!(trash.len(), 1);
  141. assert_eq!(trash[0].id, view.id);
  142. // delete the view from trash
  143. let payload = RepeatedTrashIdPB {
  144. items: vec![TrashIdPB {
  145. id: view.id.clone(),
  146. }],
  147. };
  148. EventBuilder::new(test.clone())
  149. .event(flowy_folder2::event_map::FolderEvent::DeleteTrash)
  150. .payload(payload)
  151. .async_send()
  152. .await;
  153. // After delete the last view, the trash should be empty
  154. let trash = EventBuilder::new(test.clone())
  155. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  156. .async_send()
  157. .await
  158. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  159. .items;
  160. assert!(trash.is_empty());
  161. }
  162. #[tokio::test]
  163. async fn delete_all_trash_test() {
  164. let test = FlowyCoreTest::new_with_user().await;
  165. let current_workspace = test.get_current_workspace().await.workspace;
  166. for i in 0..3 {
  167. let view = test
  168. .create_view(&current_workspace.id, format!("My {} view", i))
  169. .await;
  170. let payload = RepeatedViewIdPB {
  171. items: vec![view.id.clone()],
  172. };
  173. // delete the view. the view will be moved to trash
  174. EventBuilder::new(test.clone())
  175. .event(flowy_folder2::event_map::FolderEvent::DeleteView)
  176. .payload(payload)
  177. .async_send()
  178. .await;
  179. }
  180. let trash = EventBuilder::new(test.clone())
  181. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  182. .async_send()
  183. .await
  184. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  185. .items;
  186. assert_eq!(trash.len(), 3);
  187. // Delete all the trash
  188. EventBuilder::new(test.clone())
  189. .event(flowy_folder2::event_map::FolderEvent::DeleteAllTrash)
  190. .async_send()
  191. .await;
  192. // After delete the last view, the trash should be empty
  193. let trash = EventBuilder::new(test.clone())
  194. .event(flowy_folder2::event_map::FolderEvent::ReadTrash)
  195. .async_send()
  196. .await
  197. .parse::<flowy_folder2::entities::RepeatedTrashPB>()
  198. .items;
  199. assert!(trash.is_empty());
  200. }
  201. #[tokio::test]
  202. async fn multiple_hierarchy_view_test() {
  203. let test = FlowyCoreTest::new_with_user().await;
  204. let current_workspace = test.get_current_workspace().await.workspace;
  205. for i in 1..4 {
  206. let parent = test
  207. .create_view(&current_workspace.id, format!("My {} view", i))
  208. .await;
  209. for j in 1..3 {
  210. let child = test
  211. .create_view(&parent.id, format!("My {}-{} view", i, j))
  212. .await;
  213. for k in 1..2 {
  214. let _sub_child = test
  215. .create_view(&child.id, format!("My {}-{}-{} view", i, j, k))
  216. .await;
  217. }
  218. }
  219. }
  220. let mut views = test.get_all_workspace_views().await;
  221. // There will be one default view when AppFlowy is initialized. So there will be 4 views in total
  222. assert_eq!(views.len(), 4);
  223. views.remove(0);
  224. // workspace
  225. // - view1
  226. // - view1-1
  227. // - view1-1-1
  228. // - view1-2
  229. // - view1-2-1
  230. // - view2
  231. // - view2-1
  232. // - view2-1-1
  233. // - view2-2
  234. // - view2-2-1
  235. // - view3
  236. // - view3-1
  237. // - view3-1-1
  238. // - view3-2
  239. // - view3-2-1
  240. assert_eq!(views[0].name, "My 1 view");
  241. assert_eq!(views[1].name, "My 2 view");
  242. assert_eq!(views[2].name, "My 3 view");
  243. assert_eq!(views[0].child_views.len(), 2);
  244. // By default only the first level of child views will be loaded
  245. assert!(views[0].child_views[0].child_views.is_empty());
  246. for (i, view) in views.into_iter().enumerate() {
  247. for (j, child_view) in view.child_views.into_iter().enumerate() {
  248. let payload = ViewIdPB {
  249. value: child_view.id.clone(),
  250. };
  251. let child = EventBuilder::new(test.clone())
  252. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  253. .payload(payload)
  254. .async_send()
  255. .await
  256. .parse::<flowy_folder2::entities::ViewPB>();
  257. assert_eq!(child.name, format!("My {}-{} view", i + 1, j + 1));
  258. assert_eq!(child.child_views.len(), 1);
  259. // By default only the first level of child views will be loaded
  260. assert!(child.child_views[0].child_views.is_empty());
  261. for (k, _child_view) in child_view.child_views.into_iter().enumerate() {
  262. // Get the last level view
  263. let sub_child = test.get_view(&child.id).await;
  264. assert_eq!(child.name, format!("My {}-{}-{} view", i + 1, j + 1, k + 1));
  265. assert!(sub_child.child_views.is_empty());
  266. }
  267. }
  268. }
  269. }
  270. #[tokio::test]
  271. async fn move_view_event_test() {
  272. let test = FlowyCoreTest::new_with_user().await;
  273. let current_workspace = test.get_current_workspace().await.workspace;
  274. for i in 1..4 {
  275. let parent = test
  276. .create_view(&current_workspace.id, format!("My {} view", i))
  277. .await;
  278. for j in 1..3 {
  279. let _ = test
  280. .create_view(&parent.id, format!("My {}-{} view", i, j))
  281. .await;
  282. }
  283. }
  284. let views = test.get_all_workspace_views().await;
  285. // There will be one default view when AppFlowy is initialized. So there will be 4 views in total
  286. assert_eq!(views.len(), 4);
  287. assert_eq!(views[1].name, "My 1 view");
  288. assert_eq!(views[2].name, "My 2 view");
  289. assert_eq!(views[3].name, "My 3 view");
  290. let payload = MoveViewPayloadPB {
  291. view_id: views[1].id.clone(),
  292. from: 1,
  293. to: 2,
  294. };
  295. let _ = EventBuilder::new(test.clone())
  296. .event(flowy_folder2::event_map::FolderEvent::MoveView)
  297. .payload(payload)
  298. .async_send()
  299. .await;
  300. let views = test.get_all_workspace_views().await;
  301. assert_eq!(views[1].name, "My 2 view");
  302. assert_eq!(views[2].name, "My 1 view");
  303. assert_eq!(views[3].name, "My 3 view");
  304. }
  305. #[tokio::test]
  306. async fn move_view_event_after_delete_view_test() {
  307. let test = FlowyCoreTest::new_with_user().await;
  308. let current_workspace = test.get_current_workspace().await.workspace;
  309. for i in 1..6 {
  310. let _ = test
  311. .create_view(&current_workspace.id, format!("My {} view", i))
  312. .await;
  313. }
  314. let views = test.get_all_workspace_views().await;
  315. assert_eq!(views[1].name, "My 1 view");
  316. assert_eq!(views[2].name, "My 2 view");
  317. assert_eq!(views[3].name, "My 3 view");
  318. assert_eq!(views[4].name, "My 4 view");
  319. assert_eq!(views[5].name, "My 5 view");
  320. test.delete_view(&views[3].id).await;
  321. // There will be one default view when AppFlowy is initialized. So there will be 4 views in total
  322. let views = test.get_all_workspace_views().await;
  323. assert_eq!(views[1].name, "My 1 view");
  324. assert_eq!(views[2].name, "My 2 view");
  325. assert_eq!(views[3].name, "My 4 view");
  326. assert_eq!(views[4].name, "My 5 view");
  327. let payload = MoveViewPayloadPB {
  328. view_id: views[1].id.clone(),
  329. from: 1,
  330. to: 3,
  331. };
  332. let _ = EventBuilder::new(test.clone())
  333. .event(flowy_folder2::event_map::FolderEvent::MoveView)
  334. .payload(payload)
  335. .async_send()
  336. .await;
  337. let views = test.get_all_workspace_views().await;
  338. assert_eq!(views[1].name, "My 2 view");
  339. assert_eq!(views[2].name, "My 4 view");
  340. assert_eq!(views[3].name, "My 1 view");
  341. assert_eq!(views[4].name, "My 5 view");
  342. }
  343. #[tokio::test]
  344. async fn move_view_event_after_delete_view_test2() {
  345. let test = FlowyCoreTest::new_with_user().await;
  346. let current_workspace = test.get_current_workspace().await.workspace;
  347. let parent = test
  348. .create_view(&current_workspace.id, "My view".to_string())
  349. .await;
  350. for j in 1..6 {
  351. let _ = test
  352. .create_view(&parent.id, format!("My 1-{} view", j))
  353. .await;
  354. }
  355. let views = test.get_view(&parent.id).await.child_views;
  356. assert_eq!(views.len(), 5);
  357. assert_eq!(views[0].name, "My 1-1 view");
  358. assert_eq!(views[1].name, "My 1-2 view");
  359. assert_eq!(views[2].name, "My 1-3 view");
  360. assert_eq!(views[3].name, "My 1-4 view");
  361. assert_eq!(views[4].name, "My 1-5 view");
  362. test.delete_view(&views[2].id).await;
  363. let payload = MoveViewPayloadPB {
  364. view_id: views[0].id.clone(),
  365. from: 0,
  366. to: 2,
  367. };
  368. let _ = EventBuilder::new(test.clone())
  369. .event(flowy_folder2::event_map::FolderEvent::MoveView)
  370. .payload(payload)
  371. .async_send()
  372. .await;
  373. let views = test.get_view(&parent.id).await.child_views;
  374. assert_eq!(views[0].name, "My 1-2 view");
  375. assert_eq!(views[1].name, "My 1-4 view");
  376. assert_eq!(views[2].name, "My 1-1 view");
  377. assert_eq!(views[3].name, "My 1-5 view");
  378. }
  379. #[tokio::test]
  380. async fn create_parent_view_with_invalid_name() {
  381. for (name, code) in invalid_workspace_name_test_case() {
  382. let sdk = FlowyCoreTest::new();
  383. let request = CreateWorkspacePayloadPB {
  384. name,
  385. desc: "".to_owned(),
  386. };
  387. assert_eq!(
  388. EventBuilder::new(sdk)
  389. .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
  390. .payload(request)
  391. .async_send()
  392. .await
  393. .error()
  394. .unwrap()
  395. .code,
  396. code.value()
  397. )
  398. }
  399. }
  400. fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
  401. vec![
  402. ("".to_owned(), ErrorCode::WorkspaceNameInvalid),
  403. ("1234".repeat(100), ErrorCode::WorkspaceNameTooLong),
  404. ]
  405. }