1
0

diffing.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. //! Diffing Tests
  2. //! -------------
  3. //!
  4. //! These should always compile and run, but the result is not validat root: (), m: () ed for each test.
  5. //! TODO: Validate the results beyond visual inspection.
  6. use bumpalo::Bump;
  7. use anyhow::{Context, Result};
  8. use dioxus::{
  9. arena::SharedResources, diff::DiffMachine, prelude::*, DiffInstruction, DomEdit, MountType,
  10. };
  11. use dioxus_core as dioxus;
  12. use dioxus_html as dioxus_elements;
  13. use futures_util::FutureExt;
  14. mod test_logging;
  15. use DomEdit::*;
  16. // logging is wired up to the test harness
  17. // feel free to enable while debugging
  18. const IS_LOGGING_ENABLED: bool = true;
  19. struct TestDom {
  20. bump: Bump,
  21. resources: SharedResources,
  22. }
  23. impl TestDom {
  24. fn new() -> TestDom {
  25. if IS_LOGGING_ENABLED {
  26. test_logging::set_up_logging();
  27. }
  28. let bump = Bump::new();
  29. let resources = SharedResources::new();
  30. TestDom { bump, resources }
  31. }
  32. fn new_factory<'a>(&'a self) -> NodeFactory<'a> {
  33. NodeFactory::new(&self.bump)
  34. }
  35. fn render<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> VNode<'a>
  36. where
  37. F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
  38. {
  39. use dioxus_core::nodes::{IntoVNode, IntoVNodeList};
  40. lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
  41. }
  42. fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Mutations<'a> {
  43. // let mut edits = Vec::new();
  44. let mut machine = DiffMachine::new_headless(&self.resources);
  45. machine.stack.push(DiffInstruction::DiffNode { new, old });
  46. machine.mutations
  47. }
  48. fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
  49. where
  50. F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
  51. {
  52. let old = self.bump.alloc(self.render(left));
  53. let mut machine = DiffMachine::new_headless(&self.resources);
  54. machine.stack.create_node(old, MountType::Append);
  55. work_sync(&mut machine);
  56. machine.mutations
  57. }
  58. fn lazy_diff<'a, F1, F2>(
  59. &'a self,
  60. left: LazyNodes<'a, F1>,
  61. right: LazyNodes<'a, F2>,
  62. ) -> (Mutations<'a>, Mutations<'a>)
  63. where
  64. F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
  65. F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
  66. {
  67. let old = self.bump.alloc(self.render(left));
  68. let new = self.bump.alloc(self.render(right));
  69. // let mut create_edits = Vec::new();
  70. let mut machine = DiffMachine::new_headless(&self.resources);
  71. machine.stack.create_node(old, MountType::Append);
  72. work_sync(&mut machine);
  73. let create_edits = machine.mutations;
  74. let mut machine = DiffMachine::new_headless(&self.resources);
  75. machine.stack.push(DiffInstruction::DiffNode { old, new });
  76. work_sync(&mut machine);
  77. let edits = machine.mutations;
  78. (create_edits, edits)
  79. }
  80. }
  81. fn work_sync(machine: &mut DiffMachine) {
  82. let mut fut = machine.work().boxed_local();
  83. while let None = (&mut fut).now_or_never() {
  84. //
  85. }
  86. }
  87. #[test]
  88. fn diffing_works() {}
  89. /// Should push the text node onto the stack and modify it
  90. #[test]
  91. fn html_and_rsx_generate_the_same_output() {
  92. let dom = TestDom::new();
  93. let (create, change) = dom.lazy_diff(
  94. rsx! ( div { "Hello world" } ),
  95. rsx! ( div { "Goodbye world" } ),
  96. );
  97. assert_eq!(
  98. create.edits,
  99. [
  100. CreateElement { id: 0, tag: "div" },
  101. CreateTextNode {
  102. id: 1,
  103. text: "Hello world"
  104. },
  105. AppendChildren { many: 1 },
  106. AppendChildren { many: 1 },
  107. ]
  108. );
  109. assert_eq!(
  110. change.edits,
  111. [
  112. PushRoot { id: 1 },
  113. SetText {
  114. text: "Goodbye world"
  115. },
  116. PopRoot
  117. ]
  118. );
  119. }
  120. /// Should result in 3 elements on the stack
  121. #[test]
  122. fn fragments_create_properly() {
  123. let dom = TestDom::new();
  124. let create = dom.create(rsx! {
  125. div { "Hello a" }
  126. div { "Hello b" }
  127. div { "Hello c" }
  128. });
  129. assert_eq!(
  130. create.edits,
  131. [
  132. CreateElement { id: 0, tag: "div" },
  133. CreateTextNode {
  134. id: 1,
  135. text: "Hello a"
  136. },
  137. AppendChildren { many: 1 },
  138. CreateElement { id: 2, tag: "div" },
  139. CreateTextNode {
  140. id: 3,
  141. text: "Hello b"
  142. },
  143. AppendChildren { many: 1 },
  144. CreateElement { id: 4, tag: "div" },
  145. CreateTextNode {
  146. id: 5,
  147. text: "Hello c"
  148. },
  149. AppendChildren { many: 1 },
  150. AppendChildren { many: 3 },
  151. ]
  152. );
  153. }
  154. /// Should result in the creation of an anchor (placeholder) and then a replacewith
  155. #[test]
  156. fn empty_fragments_create_anchors() {
  157. let dom = TestDom::new();
  158. let left = rsx!({ (0..0).map(|f| rsx! { div {}}) });
  159. let right = rsx!({ (0..1).map(|f| rsx! { div {}}) });
  160. let (create, change) = dom.lazy_diff(left, right);
  161. assert_eq!(
  162. create.edits,
  163. [CreatePlaceholder { id: 0 }, AppendChildren { many: 1 }]
  164. );
  165. assert_eq!(
  166. change.edits,
  167. [
  168. CreateElement { id: 1, tag: "div" },
  169. ReplaceWith { m: 1, root: 0 }
  170. ]
  171. );
  172. }
  173. /// Should result in the creation of an anchor (placeholder) and then a replacewith m=5
  174. #[test]
  175. fn empty_fragments_create_many_anchors() {
  176. let dom = TestDom::new();
  177. let left = rsx!({ (0..0).map(|f| rsx! { div {}}) });
  178. let right = rsx!({ (0..5).map(|f| rsx! { div {}}) });
  179. let (create, change) = dom.lazy_diff(left, right);
  180. assert_eq!(
  181. create.edits,
  182. [CreatePlaceholder { id: 0 }, AppendChildren { many: 1 }]
  183. );
  184. assert_eq!(
  185. change.edits,
  186. [
  187. CreateElement { id: 1, tag: "div" },
  188. CreateElement { id: 2, tag: "div" },
  189. CreateElement { id: 3, tag: "div" },
  190. CreateElement { id: 4, tag: "div" },
  191. CreateElement { id: 5, tag: "div" },
  192. ReplaceWith { m: 5, root: 0 }
  193. ]
  194. );
  195. }
  196. /// Should result in the creation of an anchor (placeholder) and then a replacewith
  197. /// Includes child nodes inside the fragment
  198. #[test]
  199. fn empty_fragments_create_anchors_with_many_children() {
  200. let dom = TestDom::new();
  201. let left = rsx!({ (0..0).map(|f| rsx! { div {} }) });
  202. let right = rsx!({
  203. (0..3).map(|f| {
  204. rsx! { div { "hello: {f}" }}
  205. })
  206. });
  207. let (create, change) = dom.lazy_diff(left, right);
  208. assert_eq!(
  209. create.edits,
  210. [CreatePlaceholder { id: 0 }, AppendChildren { many: 1 }]
  211. );
  212. assert_eq!(
  213. change.edits,
  214. [
  215. CreateElement { id: 1, tag: "div" },
  216. CreateTextNode {
  217. text: "hello: 0",
  218. id: 2
  219. },
  220. AppendChildren { many: 1 },
  221. CreateElement { id: 3, tag: "div" },
  222. CreateTextNode {
  223. text: "hello: 1",
  224. id: 4
  225. },
  226. AppendChildren { many: 1 },
  227. CreateElement { id: 5, tag: "div" },
  228. CreateTextNode {
  229. text: "hello: 2",
  230. id: 6
  231. },
  232. AppendChildren { many: 1 },
  233. ReplaceWith { m: 3, root: 0 }
  234. ]
  235. );
  236. }
  237. /// Should result in every node being pushed and then replaced with an anchor
  238. #[test]
  239. fn many_items_become_fragment() {
  240. let dom = TestDom::new();
  241. let left = rsx!({
  242. (0..2).map(|f| {
  243. rsx! { div { "hello" }}
  244. })
  245. });
  246. let right = rsx!({ (0..0).map(|f| rsx! { div {} }) });
  247. let (create, change) = dom.lazy_diff(left, right);
  248. assert_eq!(
  249. create.edits,
  250. [
  251. CreateElement { id: 0, tag: "div" },
  252. CreateTextNode {
  253. text: "hello",
  254. id: 1
  255. },
  256. AppendChildren { many: 1 },
  257. CreateElement { id: 2, tag: "div" },
  258. CreateTextNode {
  259. text: "hello",
  260. id: 3
  261. },
  262. AppendChildren { many: 1 },
  263. AppendChildren { many: 2 },
  264. ]
  265. );
  266. // hmmmmmmmmm worried about reusing IDs that we shouldnt be
  267. assert_eq!(
  268. change.edits,
  269. [
  270. Remove { root: 2 },
  271. CreatePlaceholder { id: 4 },
  272. ReplaceWith { root: 0, m: 1 },
  273. ]
  274. );
  275. }
  276. /// Should result in no edits
  277. #[test]
  278. fn two_equal_fragments_are_equal() {
  279. let dom = TestDom::new();
  280. let left = rsx!({
  281. (0..2).map(|f| {
  282. rsx! { div { "hello" }}
  283. })
  284. });
  285. let right = rsx!({
  286. (0..2).map(|f| {
  287. rsx! { div { "hello" }}
  288. })
  289. });
  290. let (create, change) = dom.lazy_diff(left, right);
  291. assert!(change.edits.is_empty());
  292. }
  293. /// Should result the creation of more nodes appended after the old last node
  294. #[test]
  295. fn two_fragments_with_differrent_elements_are_differet() {
  296. let dom = TestDom::new();
  297. let left = rsx!(
  298. { (0..2).map(|f| rsx! { div { }} ) }
  299. p {}
  300. );
  301. let right = rsx!(
  302. { (0..5).map(|f| rsx! (h1 { }) ) }
  303. p {}
  304. );
  305. let edits = dom.lazy_diff(left, right);
  306. log::debug!("{:#?}", &edits);
  307. }
  308. /// Should result in multiple nodes destroyed - with changes to the first nodes
  309. #[test]
  310. fn two_fragments_with_differrent_elements_are_differet_shorter() {
  311. let dom = TestDom::new();
  312. let left = rsx!(
  313. {(0..5).map(|f| {rsx! { div { }}})}
  314. p {}
  315. );
  316. let right = rsx!(
  317. {(0..2).map(|f| {rsx! { h1 { }}})}
  318. p {}
  319. );
  320. let (create, change) = dom.lazy_diff(left, right);
  321. assert_eq!(
  322. create.edits,
  323. [
  324. CreateElement { id: 0, tag: "div" },
  325. CreateElement { id: 1, tag: "div" },
  326. CreateElement { id: 2, tag: "div" },
  327. CreateElement { id: 3, tag: "div" },
  328. CreateElement { id: 4, tag: "div" },
  329. CreateElement { id: 5, tag: "p" },
  330. AppendChildren { many: 6 },
  331. ]
  332. );
  333. assert_eq!(
  334. change.edits,
  335. [
  336. Remove { root: 2 },
  337. Remove { root: 3 },
  338. Remove { root: 4 },
  339. CreateElement { id: 6, tag: "h1" },
  340. ReplaceWith { root: 0, m: 1 },
  341. CreateElement { id: 7, tag: "h1" },
  342. ReplaceWith { root: 1, m: 1 },
  343. ]
  344. );
  345. }
  346. /// Should result in multiple nodes destroyed - with no changes
  347. #[test]
  348. fn two_fragments_with_same_elements_are_differet() {
  349. let dom = TestDom::new();
  350. let left = rsx!(
  351. {(0..2).map(|f| {rsx! { div { }}})}
  352. p {}
  353. );
  354. let right = rsx!(
  355. {(0..5).map(|f| {rsx! { div { }}})}
  356. p {}
  357. );
  358. let (create, change) = dom.lazy_diff(left, right);
  359. assert_eq!(
  360. create.edits,
  361. [
  362. CreateElement { id: 0, tag: "div" },
  363. CreateElement { id: 1, tag: "div" },
  364. CreateElement { id: 2, tag: "p" },
  365. AppendChildren { many: 3 },
  366. ]
  367. );
  368. assert_eq!(
  369. change.edits,
  370. [
  371. CreateElement { id: 3, tag: "div" },
  372. CreateElement { id: 4, tag: "div" },
  373. CreateElement { id: 5, tag: "div" },
  374. InsertAfter { root: 1, n: 3 },
  375. ]
  376. );
  377. }
  378. /// should result in the removal of elements
  379. #[test]
  380. fn keyed_diffing_order() {
  381. let dom = TestDom::new();
  382. let left = rsx!(
  383. {(0..5).map(|f| {rsx! { div { key: "{f}" }}})}
  384. p {"e"}
  385. );
  386. let right = rsx!(
  387. {(0..2).map(|f| {rsx! { div { key: "{f}" }}})}
  388. p {"e"}
  389. );
  390. let (create, change) = dom.lazy_diff(left, right);
  391. assert_eq!(
  392. change.edits,
  393. [Remove { root: 2 }, Remove { root: 3 }, Remove { root: 4 },]
  394. );
  395. }
  396. #[test]
  397. fn fragment_keys() {
  398. let r = 1;
  399. let p = rsx! {
  400. Fragment { key: "asd {r}" }
  401. };
  402. }
  403. /// Should result in moves, but not removals or additions
  404. #[test]
  405. fn keyed_diffing_out_of_order() {
  406. let dom = TestDom::new();
  407. let left = rsx!({
  408. [0, 1, 2, 3, /**/ 4, 5, 6, /**/ 7, 8, 9].iter().map(|f| {
  409. rsx! { div { key: "{f}" }}
  410. })
  411. });
  412. let right = rsx!({
  413. [0, 1, 2, 3, /**/ 6, 4, 5, /**/ 7, 8, 9].iter().map(|f| {
  414. rsx! { div { key: "{f}" }}
  415. })
  416. });
  417. let edits = dom.lazy_diff(left, right);
  418. log::debug!("{:?}", &edits.1);
  419. }
  420. /// Should result in moves only
  421. #[test]
  422. fn keyed_diffing_out_of_order_adds() {
  423. let dom = TestDom::new();
  424. let left = rsx!({
  425. [/**/ 4, 5, 6, 7, 8 /**/].iter().map(|f| {
  426. rsx! { div { key: "{f}" }}
  427. })
  428. });
  429. let right = rsx!({
  430. [/**/ 8, 7, 4, 5, 6 /**/].iter().map(|f| {
  431. rsx! { div { key: "{f}" }}
  432. })
  433. });
  434. let (_, change) = dom.lazy_diff(left, right);
  435. assert_eq!(
  436. change.edits,
  437. [
  438. PushRoot { id: 4 },
  439. PushRoot { id: 3 },
  440. InsertBefore { n: 2, root: 0 }
  441. ]
  442. );
  443. }
  444. /// Should result in moves onl
  445. #[test]
  446. fn keyed_diffing_out_of_order_adds_2() {
  447. let dom = TestDom::new();
  448. let left = rsx!({
  449. [/**/ 4, 5, 6, 7, 8 /**/].iter().map(|f| {
  450. rsx! { div { key: "{f}" }}
  451. })
  452. });
  453. let right = rsx!({
  454. [/**/ 7, 8, 4, 5, 6 /**/].iter().map(|f| {
  455. rsx! { div { key: "{f}" }}
  456. })
  457. });
  458. let (_, change) = dom.lazy_diff(left, right);
  459. assert_eq!(
  460. change.edits,
  461. [
  462. PushRoot { id: 3 },
  463. PushRoot { id: 4 },
  464. InsertBefore { n: 2, root: 0 }
  465. ]
  466. );
  467. }
  468. /// Should result in moves onl
  469. #[test]
  470. fn keyed_diffing_out_of_order_adds_3() {
  471. let dom = TestDom::new();
  472. let left = rsx!({
  473. [/**/ 4, 5, 6, 7, 8 /**/].iter().map(|f| {
  474. rsx! { div { key: "{f}" }}
  475. })
  476. });
  477. let right = rsx!({
  478. [/**/ 4, 8, 7, 5, 6 /**/].iter().map(|f| {
  479. rsx! { div { key: "{f}" }}
  480. })
  481. });
  482. let (_, change) = dom.lazy_diff(left, right);
  483. assert_eq!(
  484. change.edits,
  485. [
  486. PushRoot { id: 4 },
  487. PushRoot { id: 3 },
  488. InsertBefore { n: 2, root: 1 }
  489. ]
  490. );
  491. }
  492. /// Should result in moves onl
  493. #[test]
  494. fn keyed_diffing_out_of_order_adds_4() {
  495. let dom = TestDom::new();
  496. let left = rsx!({
  497. [/**/ 4, 5, 6, 7, 8 /**/].iter().map(|f| {
  498. rsx! { div { key: "{f}" }}
  499. })
  500. });
  501. let right = rsx!({
  502. [/**/ 4, 5, 8, 7, 6 /**/].iter().map(|f| {
  503. rsx! { div { key: "{f}" }}
  504. })
  505. });
  506. let (_, change) = dom.lazy_diff(left, right);
  507. assert_eq!(
  508. change.edits,
  509. [
  510. PushRoot { id: 4 },
  511. PushRoot { id: 3 },
  512. InsertBefore { n: 2, root: 2 }
  513. ]
  514. );
  515. }
  516. /// Should result in moves onl
  517. #[test]
  518. fn keyed_diffing_out_of_order_adds_5() {
  519. let dom = TestDom::new();
  520. let left = rsx!({
  521. [/**/ 4, 5, 6, 7, 8 /**/].iter().map(|f| {
  522. rsx! { div { key: "{f}" }}
  523. })
  524. });
  525. let right = rsx!({
  526. [/**/ 4, 5, 6, 8, 7 /**/].iter().map(|f| {
  527. rsx! { div { key: "{f}" }}
  528. })
  529. });
  530. let (_, change) = dom.lazy_diff(left, right);
  531. assert_eq!(
  532. change.edits,
  533. [PushRoot { id: 4 }, InsertBefore { n: 1, root: 3 }]
  534. );
  535. }
  536. #[test]
  537. fn keyed_diffing_additions() {
  538. let dom = TestDom::new();
  539. let left = rsx!({
  540. [/**/ 4, 5, 6, 7, 8 /**/].iter().map(|f| {
  541. rsx! { div { key: "{f}" }}
  542. })
  543. });
  544. let right = rsx!({
  545. [/**/ 4, 5, 6, 7, 8, 9, 10 /**/].iter().map(|f| {
  546. rsx! { div { key: "{f}" }}
  547. })
  548. });
  549. let (_, change) = dom.lazy_diff(left, right);
  550. assert_eq!(
  551. change.edits,
  552. [
  553. CreateElement { id: 5, tag: "div" },
  554. CreateElement { id: 6, tag: "div" },
  555. InsertAfter { n: 2, root: 4 }
  556. ]
  557. );
  558. }
  559. #[test]
  560. fn keyed_diffing_additions_and_moves_on_ends() {
  561. let dom = TestDom::new();
  562. let left = rsx!({
  563. [/**/ 4, 5, 6, 7 /**/].iter().map(|f| {
  564. rsx! { div { key: "{f}" }}
  565. })
  566. });
  567. let right = rsx!({
  568. [/**/ 7, 4, 5, 6, 11, 12 /**/].iter().map(|f| {
  569. // [/**/ 8, 7, 4, 5, 6, 9, 10 /**/].iter().map(|f| {
  570. rsx! { div { key: "{f}" }}
  571. })
  572. });
  573. let (_, change) = dom.lazy_diff(left, right);
  574. log::debug!("{:?}", change);
  575. // assert_eq!(
  576. // change.edits,
  577. // [
  578. // CreateElement { id: 5, tag: "div" },
  579. // CreateElement { id: 6, tag: "div" },
  580. // InsertAfter { n: 2, root: 4 }
  581. // ]
  582. // );
  583. }
  584. #[test]
  585. fn keyed_diffing_additions_and_moves_in_middle() {
  586. let dom = TestDom::new();
  587. let left = rsx!({
  588. [/**/ 4, 5, 6, 7 /**/].iter().map(|f| {
  589. rsx! { div { key: "{f}" }}
  590. })
  591. });
  592. let right = rsx!({
  593. [/**/ 7, 4, 13, 17, 5, 11, 12, 6 /**/].iter().map(|f| {
  594. rsx! { div { key: "{f}" }}
  595. })
  596. });
  597. let (_, change) = dom.lazy_diff(left, right);
  598. log::debug!("{:?}", change);
  599. // assert_eq!(
  600. // change.edits,
  601. // [
  602. // CreateElement { id: 5, tag: "div" },
  603. // CreateElement { id: 6, tag: "div" },
  604. // InsertAfter { n: 2, root: 4 }
  605. // ]
  606. // );
  607. }
  608. #[test]
  609. fn controlled_keyed_diffing_out_of_order() {
  610. let dom = TestDom::new();
  611. let left = rsx!({
  612. [4, 5, 6, 7].iter().map(|f| {
  613. rsx! { div { key: "{f}" }}
  614. })
  615. });
  616. let right = rsx!({
  617. [0, 5, 9, 6, 4].iter().map(|f| {
  618. rsx! { div { key: "{f}" }}
  619. })
  620. });
  621. // LIS: 5, 6
  622. let (_, changes) = dom.lazy_diff(left, right);
  623. log::debug!("{:#?}", &changes);
  624. assert_eq!(
  625. changes.edits,
  626. [
  627. // move 4 to after 6
  628. PushRoot { id: 0 },
  629. InsertAfter { n: 1, root: 2 },
  630. // remove 7
  631. // create 9 and insert before 6
  632. CreateElement { id: 4, tag: "div" },
  633. InsertBefore { n: 1, root: 2 },
  634. // create 0 and insert before 5
  635. CreateElement { id: 5, tag: "div" },
  636. InsertBefore { n: 1, root: 1 },
  637. ]
  638. );
  639. }
  640. #[test]
  641. fn controlled_keyed_diffing_out_of_order_max_test() {
  642. let dom = TestDom::new();
  643. let left = rsx!({
  644. [0, 1, 2, 3, 4].iter().map(|f| {
  645. rsx! { div { key: "{f}" }}
  646. })
  647. });
  648. let right = rsx!({
  649. [3, 0, 1, 10, 2].iter().map(|f| {
  650. rsx! { div { key: "{f}" }}
  651. })
  652. });
  653. let (_, changes) = dom.lazy_diff(left, right);
  654. log::debug!("{:#?}", &changes);
  655. assert_eq!(
  656. changes.edits,
  657. [
  658. CreateElement { id: 5, tag: "div" },
  659. InsertBefore { n: 1, root: 2 },
  660. PushRoot { id: 3 },
  661. InsertBefore { n: 1, root: 0 },
  662. ]
  663. );
  664. }