script.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. use bytes::Bytes;
  2. use flowy_grid::services::field::*;
  3. use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor};
  4. use flowy_grid::services::row::CreateRowRevisionPayload;
  5. use flowy_grid_data_model::entities::*;
  6. use flowy_grid_data_model::revision::*;
  7. use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
  8. use flowy_sync::client_grid::GridBuilder;
  9. use flowy_test::helper::ViewTest;
  10. use flowy_test::FlowySDKTest;
  11. use std::collections::HashMap;
  12. use std::sync::Arc;
  13. use std::time::Duration;
  14. use strum::EnumCount;
  15. use tokio::time::sleep;
  16. pub enum EditorScript {
  17. CreateField {
  18. params: InsertFieldParams,
  19. },
  20. UpdateField {
  21. changeset: FieldChangesetParams,
  22. },
  23. DeleteField {
  24. field_rev: FieldRevision,
  25. },
  26. AssertFieldCount(usize),
  27. AssertFieldEqual {
  28. field_index: usize,
  29. field_rev: FieldRevision,
  30. },
  31. CreateBlock {
  32. block: GridBlockRevision,
  33. },
  34. UpdateBlock {
  35. changeset: GridBlockRevisionChangeset,
  36. },
  37. AssertBlockCount(usize),
  38. AssertBlock {
  39. block_index: usize,
  40. row_count: i32,
  41. start_row_index: i32,
  42. },
  43. AssertBlockEqual {
  44. block_index: usize,
  45. block: GridBlockRevision,
  46. },
  47. CreateEmptyRow,
  48. CreateRow {
  49. context: CreateRowRevisionPayload,
  50. },
  51. UpdateRow {
  52. changeset: RowMetaChangeset,
  53. },
  54. AssertRow {
  55. expected_row: RowRevision,
  56. },
  57. DeleteRows {
  58. row_ids: Vec<String>,
  59. },
  60. UpdateCell {
  61. changeset: CellChangeset,
  62. is_err: bool,
  63. },
  64. AssertRowCount(usize),
  65. UpdateGridSetting {
  66. params: GridSettingChangesetParams,
  67. },
  68. AssertGridSetting {
  69. expected_setting: GridSettingRevision,
  70. },
  71. AssertGridRevisionPad,
  72. }
  73. pub struct GridEditorTest {
  74. pub sdk: FlowySDKTest,
  75. pub grid_id: String,
  76. pub editor: Arc<GridRevisionEditor>,
  77. pub field_revs: Vec<FieldRevision>,
  78. pub grid_block_revs: Vec<GridBlockRevision>,
  79. pub row_revs: Vec<Arc<RowRevision>>,
  80. pub field_count: usize,
  81. pub row_order_by_row_id: HashMap<String, RowOrder>,
  82. }
  83. impl GridEditorTest {
  84. pub async fn new() -> Self {
  85. let sdk = FlowySDKTest::default();
  86. let _ = sdk.init_user().await;
  87. let build_context = make_test_grid();
  88. let view_data: Bytes = build_context.into();
  89. let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await;
  90. let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
  91. let field_revs = editor.get_field_revs::<FieldOrder>(None).await.unwrap();
  92. let grid_blocks = editor.get_block_metas().await.unwrap();
  93. let row_revs = editor.grid_block_snapshots(None).await.unwrap().pop().unwrap().row_revs;
  94. assert_eq!(row_revs.len(), 3);
  95. assert_eq!(grid_blocks.len(), 1);
  96. // It seems like you should add the field in the make_test_grid() function.
  97. // Because we assert the initialize count of the fields is equal to FieldType::COUNT.
  98. assert_eq!(field_revs.len(), FieldType::COUNT);
  99. let grid_id = test.view.id;
  100. Self {
  101. sdk,
  102. grid_id,
  103. editor,
  104. field_revs,
  105. grid_block_revs: grid_blocks,
  106. row_revs,
  107. field_count: FieldType::COUNT,
  108. row_order_by_row_id: HashMap::default(),
  109. }
  110. }
  111. pub async fn run_scripts(&mut self, scripts: Vec<EditorScript>) {
  112. for script in scripts {
  113. self.run_script(script).await;
  114. }
  115. }
  116. pub async fn run_script(&mut self, script: EditorScript) {
  117. let grid_manager = self.sdk.grid_manager.clone();
  118. let pool = self.sdk.user_session.db_pool().unwrap();
  119. let rev_manager = self.editor.rev_manager();
  120. let _cache = rev_manager.revision_cache().await;
  121. match script {
  122. EditorScript::CreateField { params } => {
  123. if !self.editor.contain_field(&params.field.id).await {
  124. self.field_count += 1;
  125. }
  126. self.editor.insert_field(params).await.unwrap();
  127. self.field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
  128. assert_eq!(self.field_count, self.field_revs.len());
  129. }
  130. EditorScript::UpdateField { changeset: change } => {
  131. self.editor.update_field(change).await.unwrap();
  132. self.field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
  133. }
  134. EditorScript::DeleteField { field_rev } => {
  135. if self.editor.contain_field(&field_rev.id).await {
  136. self.field_count -= 1;
  137. }
  138. self.editor.delete_field(&field_rev.id).await.unwrap();
  139. self.field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
  140. assert_eq!(self.field_count, self.field_revs.len());
  141. }
  142. EditorScript::AssertFieldCount(count) => {
  143. assert_eq!(
  144. self.editor.get_field_revs::<FieldOrder>(None).await.unwrap().len(),
  145. count
  146. );
  147. }
  148. EditorScript::AssertFieldEqual { field_index, field_rev } => {
  149. let field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
  150. assert_eq!(field_revs[field_index].clone(), field_rev);
  151. }
  152. EditorScript::CreateBlock { block } => {
  153. self.editor.create_block(block).await.unwrap();
  154. self.grid_block_revs = self.editor.get_block_metas().await.unwrap();
  155. }
  156. EditorScript::UpdateBlock { changeset: change } => {
  157. self.editor.update_block(change).await.unwrap();
  158. }
  159. EditorScript::AssertBlockCount(count) => {
  160. assert_eq!(self.editor.get_block_metas().await.unwrap().len(), count);
  161. }
  162. EditorScript::AssertBlock {
  163. block_index,
  164. row_count,
  165. start_row_index,
  166. } => {
  167. assert_eq!(self.grid_block_revs[block_index].row_count, row_count);
  168. assert_eq!(self.grid_block_revs[block_index].start_row_index, start_row_index);
  169. }
  170. EditorScript::AssertBlockEqual { block_index, block } => {
  171. let blocks = self.editor.get_block_metas().await.unwrap();
  172. let compared_block = blocks[block_index].clone();
  173. assert_eq!(compared_block, block);
  174. }
  175. EditorScript::CreateEmptyRow => {
  176. let row_order = self.editor.create_row(None).await.unwrap();
  177. self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
  178. self.row_revs = self.get_row_revs().await;
  179. self.grid_block_revs = self.editor.get_block_metas().await.unwrap();
  180. }
  181. EditorScript::CreateRow { context } => {
  182. let row_orders = self.editor.insert_rows(vec![context]).await.unwrap();
  183. for row_order in row_orders {
  184. self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
  185. }
  186. self.row_revs = self.get_row_revs().await;
  187. self.grid_block_revs = self.editor.get_block_metas().await.unwrap();
  188. }
  189. EditorScript::UpdateRow { changeset: change } => self.editor.update_row(change).await.unwrap(),
  190. EditorScript::DeleteRows { row_ids } => {
  191. let row_orders = row_ids
  192. .into_iter()
  193. .map(|row_id| self.row_order_by_row_id.get(&row_id).unwrap().clone())
  194. .collect::<Vec<RowOrder>>();
  195. self.editor.delete_rows(row_orders).await.unwrap();
  196. self.row_revs = self.get_row_revs().await;
  197. self.grid_block_revs = self.editor.get_block_metas().await.unwrap();
  198. }
  199. EditorScript::AssertRow { expected_row } => {
  200. let row = &*self
  201. .row_revs
  202. .iter()
  203. .find(|row| row.id == expected_row.id)
  204. .cloned()
  205. .unwrap();
  206. assert_eq!(&expected_row, row);
  207. // if let Some(visibility) = changeset.visibility {
  208. // assert_eq!(row.visibility, visibility);
  209. // }
  210. //
  211. // if let Some(height) = changeset.height {
  212. // assert_eq!(row.height, height);
  213. // }
  214. }
  215. EditorScript::UpdateCell { changeset, is_err } => {
  216. let result = self.editor.update_cell(changeset).await;
  217. if is_err {
  218. assert!(result.is_err())
  219. } else {
  220. let _ = result.unwrap();
  221. self.row_revs = self.get_row_revs().await;
  222. }
  223. }
  224. EditorScript::AssertRowCount(expected_row_count) => {
  225. assert_eq!(expected_row_count, self.row_revs.len());
  226. }
  227. EditorScript::UpdateGridSetting { params } => {
  228. let _ = self.editor.update_grid_setting(params).await.unwrap();
  229. }
  230. EditorScript::AssertGridSetting { expected_setting } => {
  231. let setting = self.editor.get_grid_setting().await.unwrap();
  232. assert_eq!(expected_setting, setting);
  233. }
  234. EditorScript::AssertGridRevisionPad => {
  235. sleep(Duration::from_millis(2 * REVISION_WRITE_INTERVAL_IN_MILLIS)).await;
  236. let mut grid_rev_manager = grid_manager.make_grid_rev_manager(&self.grid_id, pool.clone()).unwrap();
  237. let grid_pad = grid_rev_manager.load::<GridPadBuilder>(None).await.unwrap();
  238. println!("{}", grid_pad.delta_str());
  239. }
  240. }
  241. }
  242. async fn get_row_revs(&self) -> Vec<Arc<RowRevision>> {
  243. self.editor
  244. .grid_block_snapshots(None)
  245. .await
  246. .unwrap()
  247. .pop()
  248. .unwrap()
  249. .row_revs
  250. }
  251. }
  252. pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
  253. let field_rev = FieldBuilder::new(RichTextTypeOptionBuilder::default())
  254. .name("Name")
  255. .visibility(true)
  256. .build();
  257. let cloned_field_rev = field_rev.clone();
  258. let type_option_data = field_rev
  259. .get_type_option_entry::<RichTextTypeOption>(&field_rev.field_type)
  260. .unwrap()
  261. .protobuf_bytes()
  262. .to_vec();
  263. let field = Field {
  264. id: field_rev.id,
  265. name: field_rev.name,
  266. desc: field_rev.desc,
  267. field_type: field_rev.field_type,
  268. frozen: field_rev.frozen,
  269. visibility: field_rev.visibility,
  270. width: field_rev.width,
  271. is_primary: false,
  272. };
  273. let params = InsertFieldParams {
  274. grid_id: grid_id.to_owned(),
  275. field,
  276. type_option_data,
  277. start_field_id: None,
  278. };
  279. (params, cloned_field_rev)
  280. }
  281. pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
  282. let single_select = SingleSelectTypeOptionBuilder::default()
  283. .option(SelectOption::new("Done"))
  284. .option(SelectOption::new("Progress"));
  285. let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build();
  286. let cloned_field_rev = field_rev.clone();
  287. let type_option_data = field_rev
  288. .get_type_option_entry::<SingleSelectTypeOption>(&field_rev.field_type)
  289. .unwrap()
  290. .protobuf_bytes()
  291. .to_vec();
  292. let field = Field {
  293. id: field_rev.id,
  294. name: field_rev.name,
  295. desc: field_rev.desc,
  296. field_type: field_rev.field_type,
  297. frozen: field_rev.frozen,
  298. visibility: field_rev.visibility,
  299. width: field_rev.width,
  300. is_primary: false,
  301. };
  302. let params = InsertFieldParams {
  303. grid_id: grid_id.to_owned(),
  304. field,
  305. type_option_data,
  306. start_field_id: None,
  307. };
  308. (params, cloned_field_rev)
  309. }
  310. fn make_test_grid() -> BuildGridContext {
  311. let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
  312. .name("Name")
  313. .visibility(true)
  314. .build();
  315. // Single Select
  316. let single_select = SingleSelectTypeOptionBuilder::default()
  317. .option(SelectOption::new("Live"))
  318. .option(SelectOption::new("Completed"))
  319. .option(SelectOption::new("Planned"))
  320. .option(SelectOption::new("Paused"));
  321. let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
  322. // MultiSelect
  323. let multi_select = MultiSelectTypeOptionBuilder::default()
  324. .option(SelectOption::new("Google"))
  325. .option(SelectOption::new("Facebook"))
  326. .option(SelectOption::new("Twitter"));
  327. let multi_select_field = FieldBuilder::new(multi_select)
  328. .name("Platform")
  329. .visibility(true)
  330. .build();
  331. // Number
  332. let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
  333. let number_field = FieldBuilder::new(number).name("Price").visibility(true).build();
  334. // Date
  335. let date = DateTypeOptionBuilder::default()
  336. .date_format(DateFormat::US)
  337. .time_format(TimeFormat::TwentyFourHour);
  338. let date_field = FieldBuilder::new(date).name("Time").visibility(true).build();
  339. // Checkbox
  340. let checkbox = CheckboxTypeOptionBuilder::default();
  341. let checkbox_field = FieldBuilder::new(checkbox).name("is done").visibility(true).build();
  342. // URL
  343. let url = URLTypeOptionBuilder::default();
  344. let url_field = FieldBuilder::new(url).name("link").visibility(true).build();
  345. GridBuilder::default()
  346. .add_field(text_field)
  347. .add_field(single_select_field)
  348. .add_field(multi_select_field)
  349. .add_field(number_field)
  350. .add_field(date_field)
  351. .add_field(checkbox_field)
  352. .add_field(url_field)
  353. .add_empty_row()
  354. .add_empty_row()
  355. .add_empty_row()
  356. .build()
  357. }
  358. pub fn make_date_cell_string(s: &str) -> String {
  359. serde_json::to_string(&DateCellContentChangeset {
  360. date: Some(s.to_string()),
  361. time: None,
  362. })
  363. .unwrap()
  364. }