undo_redo_test.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. pub mod helper;
  2. use crate::helper::{TestOp::*, *};
  3. use flowy_ot::{
  4. client::{FlowyDoc, PlainDoc, RECORD_THRESHOLD},
  5. core::{Interval, NEW_LINE, WHITESPACE},
  6. };
  7. #[test]
  8. fn history_insert_undo() {
  9. let ops = vec![Insert(0, "123", 0), Undo(0), AssertOpsJson(0, r#"[{"insert":"\n"}]"#)];
  10. TestBuilder::new().run_script::<FlowyDoc>(ops);
  11. }
  12. #[test]
  13. fn history_insert_undo_with_lagging() {
  14. let ops = vec![
  15. Insert(0, "123", 0),
  16. Wait(RECORD_THRESHOLD),
  17. Insert(0, "456", 0),
  18. Undo(0),
  19. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  20. Undo(0),
  21. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  22. ];
  23. TestBuilder::new().run_script::<FlowyDoc>(ops);
  24. }
  25. #[test]
  26. fn history_insert_redo() {
  27. let ops = vec![
  28. Insert(0, "123", 0),
  29. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  30. Undo(0),
  31. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  32. Redo(0),
  33. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  34. ];
  35. TestBuilder::new().run_script::<FlowyDoc>(ops);
  36. }
  37. #[test]
  38. fn history_insert_redo_with_lagging() {
  39. let ops = vec![
  40. Insert(0, "123", 0),
  41. Wait(RECORD_THRESHOLD),
  42. Insert(0, "456", 3),
  43. Wait(RECORD_THRESHOLD),
  44. AssertStr(0, "123456\n"),
  45. AssertOpsJson(0, r#"[{"insert":"123456\n"}]"#),
  46. Undo(0),
  47. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  48. Redo(0),
  49. AssertOpsJson(0, r#"[{"insert":"123456\n"}]"#),
  50. Undo(0),
  51. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  52. ];
  53. TestBuilder::new().run_script::<FlowyDoc>(ops);
  54. }
  55. #[test]
  56. fn history_bold_undo() {
  57. let ops = vec![
  58. Insert(0, "123", 0),
  59. Bold(0, Interval::new(0, 3), true),
  60. Undo(0),
  61. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  62. ];
  63. TestBuilder::new().run_script::<FlowyDoc>(ops);
  64. }
  65. #[test]
  66. fn history_bold_undo_with_lagging() {
  67. let ops = vec![
  68. Insert(0, "123", 0),
  69. Wait(RECORD_THRESHOLD),
  70. Bold(0, Interval::new(0, 3), true),
  71. Undo(0),
  72. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  73. ];
  74. TestBuilder::new().run_script::<FlowyDoc>(ops);
  75. }
  76. #[test]
  77. fn history_bold_redo() {
  78. let ops = vec![
  79. Insert(0, "123", 0),
  80. Bold(0, Interval::new(0, 3), true),
  81. Undo(0),
  82. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  83. Redo(0),
  84. AssertOpsJson(0, r#" [{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
  85. ];
  86. TestBuilder::new().run_script::<FlowyDoc>(ops);
  87. }
  88. #[test]
  89. fn history_bold_redo_with_lagging() {
  90. let ops = vec![
  91. Insert(0, "123", 0),
  92. Wait(RECORD_THRESHOLD),
  93. Bold(0, Interval::new(0, 3), true),
  94. Undo(0),
  95. AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
  96. Redo(0),
  97. AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
  98. ];
  99. TestBuilder::new().run_script::<FlowyDoc>(ops);
  100. }
  101. #[test]
  102. fn history_delete_undo() {
  103. let ops = vec![
  104. Insert(0, "123", 0),
  105. AssertOpsJson(0, r#"[{"insert":"123"}]"#),
  106. Delete(0, Interval::new(0, 3)),
  107. AssertOpsJson(0, r#"[]"#),
  108. Undo(0),
  109. AssertOpsJson(0, r#"[{"insert":"123"}]"#),
  110. ];
  111. TestBuilder::new().run_script::<PlainDoc>(ops);
  112. }
  113. #[test]
  114. fn history_delete_undo_2() {
  115. let ops = vec![
  116. Insert(0, "123", 0),
  117. Bold(0, Interval::new(0, 3), true),
  118. Delete(0, Interval::new(0, 1)),
  119. AssertOpsJson(
  120. 0,
  121. r#"[
  122. {"insert":"23","attributes":{"bold":"true"}},
  123. {"insert":"\n"}]
  124. "#,
  125. ),
  126. Undo(0),
  127. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  128. ];
  129. TestBuilder::new().run_script::<FlowyDoc>(ops);
  130. }
  131. #[test]
  132. fn history_delete_undo_with_lagging() {
  133. let ops = vec![
  134. Insert(0, "123", 0),
  135. Wait(RECORD_THRESHOLD),
  136. Bold(0, Interval::new(0, 3), true),
  137. Wait(RECORD_THRESHOLD),
  138. Delete(0, Interval::new(0, 1)),
  139. AssertOpsJson(
  140. 0,
  141. r#"[
  142. {"insert":"23","attributes":{"bold":"true"}},
  143. {"insert":"\n"}]
  144. "#,
  145. ),
  146. Undo(0),
  147. AssertOpsJson(
  148. 0,
  149. r#"[
  150. {"insert":"123","attributes":{"bold":"true"}},
  151. {"insert":"\n"}]
  152. "#,
  153. ),
  154. ];
  155. TestBuilder::new().run_script::<FlowyDoc>(ops);
  156. }
  157. #[test]
  158. fn history_delete_redo() {
  159. let ops = vec![
  160. Insert(0, "123", 0),
  161. Wait(RECORD_THRESHOLD),
  162. Delete(0, Interval::new(0, 3)),
  163. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  164. Undo(0),
  165. Redo(0),
  166. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  167. ];
  168. TestBuilder::new().run_script::<FlowyDoc>(ops);
  169. }
  170. #[test]
  171. fn history_replace_undo() {
  172. let ops = vec![
  173. Insert(0, "123", 0),
  174. Bold(0, Interval::new(0, 3), true),
  175. Replace(0, Interval::new(0, 2), "ab"),
  176. AssertOpsJson(
  177. 0,
  178. r#"[
  179. {"insert":"ab"},
  180. {"insert":"3","attributes":{"bold":"true"}},{"insert":"\n"}]
  181. "#,
  182. ),
  183. Undo(0),
  184. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  185. ];
  186. TestBuilder::new().run_script::<FlowyDoc>(ops);
  187. }
  188. #[test]
  189. fn history_replace_undo_with_lagging() {
  190. let ops = vec![
  191. Insert(0, "123", 0),
  192. Wait(RECORD_THRESHOLD),
  193. Bold(0, Interval::new(0, 3), true),
  194. Wait(RECORD_THRESHOLD),
  195. Replace(0, Interval::new(0, 2), "ab"),
  196. AssertOpsJson(
  197. 0,
  198. r#"[
  199. {"insert":"ab"},
  200. {"insert":"3","attributes":{"bold":"true"}},{"insert":"\n"}]
  201. "#,
  202. ),
  203. Undo(0),
  204. AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
  205. ];
  206. TestBuilder::new().run_script::<FlowyDoc>(ops);
  207. }
  208. #[test]
  209. fn history_replace_redo() {
  210. let ops = vec![
  211. Insert(0, "123", 0),
  212. Bold(0, Interval::new(0, 3), true),
  213. Replace(0, Interval::new(0, 2), "ab"),
  214. Undo(0),
  215. Redo(0),
  216. AssertOpsJson(
  217. 0,
  218. r#"[
  219. {"insert":"ab"},
  220. {"insert":"3","attributes":{"bold":"true"}},{"insert":"\n"}]
  221. "#,
  222. ),
  223. ];
  224. TestBuilder::new().run_script::<FlowyDoc>(ops);
  225. }
  226. #[test]
  227. fn history_header_added_undo() {
  228. let ops = vec![
  229. Insert(0, "123456", 0),
  230. Header(0, Interval::new(0, 6), 1),
  231. Insert(0, "\n", 3),
  232. Insert(0, "\n", 4),
  233. Undo(0),
  234. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  235. Redo(0),
  236. AssertOpsJson(
  237. 0,
  238. r#"[{"insert":"123"},{"insert":"\n\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
  239. ),
  240. ];
  241. TestBuilder::new().run_script::<FlowyDoc>(ops);
  242. }
  243. #[test]
  244. fn history_link_added_undo() {
  245. let site = "https://appflowy.io";
  246. let ops = vec![
  247. Insert(0, site, 0),
  248. Wait(RECORD_THRESHOLD),
  249. Link(0, Interval::new(0, site.len()), site),
  250. Undo(0),
  251. AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
  252. Redo(0),
  253. AssertOpsJson(
  254. 0,
  255. r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  256. ),
  257. ];
  258. TestBuilder::new().run_script::<FlowyDoc>(ops);
  259. }
  260. #[test]
  261. fn history_link_auto_format_undo_with_lagging() {
  262. let site = "https://appflowy.io";
  263. let ops = vec![
  264. Insert(0, site, 0),
  265. AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
  266. Wait(RECORD_THRESHOLD),
  267. Insert(0, WHITESPACE, site.len()),
  268. AssertOpsJson(
  269. 0,
  270. r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
  271. ),
  272. Undo(0),
  273. AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
  274. ];
  275. TestBuilder::new().run_script::<FlowyDoc>(ops);
  276. }
  277. #[test]
  278. fn history_bullet_undo() {
  279. let ops = vec![
  280. Insert(0, "1", 0),
  281. Bullet(0, Interval::new(0, 1), true),
  282. Insert(0, NEW_LINE, 1),
  283. Insert(0, "2", 2),
  284. AssertOpsJson(
  285. 0,
  286. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  287. ),
  288. Undo(0),
  289. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  290. Redo(0),
  291. AssertOpsJson(
  292. 0,
  293. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  294. ),
  295. ];
  296. TestBuilder::new().run_script::<FlowyDoc>(ops);
  297. }
  298. #[test]
  299. fn history_bullet_undo_with_lagging() {
  300. let ops = vec![
  301. Insert(0, "1", 0),
  302. Bullet(0, Interval::new(0, 1), true),
  303. Wait(RECORD_THRESHOLD),
  304. Insert(0, NEW_LINE, 1),
  305. Insert(0, "2", 2),
  306. Wait(RECORD_THRESHOLD),
  307. AssertOpsJson(
  308. 0,
  309. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  310. ),
  311. Undo(0),
  312. AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
  313. Undo(0),
  314. AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
  315. Redo(0),
  316. Redo(0),
  317. AssertOpsJson(
  318. 0,
  319. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  320. ),
  321. ];
  322. TestBuilder::new().run_script::<FlowyDoc>(ops);
  323. }
  324. #[test]
  325. fn history_undo_attribute_on_merge_between_line() {
  326. let ops = vec![
  327. Insert(0, "123456", 0),
  328. Bullet(0, Interval::new(0, 6), true),
  329. Wait(RECORD_THRESHOLD),
  330. Insert(0, NEW_LINE, 3),
  331. Wait(RECORD_THRESHOLD),
  332. AssertOpsJson(
  333. 0,
  334. r#"[{"insert":"123"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  335. ),
  336. Delete(0, Interval::new(3, 4)), // delete the newline
  337. AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
  338. Undo(0),
  339. AssertOpsJson(
  340. 0,
  341. r#"[{"insert":"123"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  342. ),
  343. ];
  344. TestBuilder::new().run_script::<FlowyDoc>(ops);
  345. }