link.rs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #![allow(non_snake_case)]
  2. use dioxus::prelude::*;
  3. use dioxus_router::prelude::*;
  4. use serde::{de::DeserializeOwned, Deserialize, Serialize};
  5. use std::str::FromStr;
  6. fn prepare<R: Routable + Serialize + DeserializeOwned>() -> String
  7. where
  8. <R as FromStr>::Err: std::fmt::Display,
  9. {
  10. let mut vdom = VirtualDom::new_with_props(
  11. App,
  12. AppProps::<R> {
  13. phantom: std::marker::PhantomData,
  14. },
  15. );
  16. let _ = vdom.rebuild();
  17. return dioxus_ssr::render(&vdom);
  18. #[derive(Props)]
  19. struct AppProps<R: Routable> {
  20. phantom: std::marker::PhantomData<R>,
  21. }
  22. impl<R: Routable> PartialEq for AppProps<R> {
  23. fn eq(&self, _other: &Self) -> bool {
  24. false
  25. }
  26. }
  27. fn App<R: Routable + Serialize + DeserializeOwned>(cx: Scope<AppProps<R>>) -> Element
  28. where
  29. <R as FromStr>::Err: std::fmt::Display,
  30. {
  31. render! {
  32. h1 { "App" }
  33. GenericRouter::<R> {
  34. config: RouterConfiguration {
  35. history: Box::<MemoryHistory::<R>>::default(),
  36. ..Default::default()
  37. }
  38. }
  39. }
  40. }
  41. }
  42. #[test]
  43. fn href_internal() {
  44. #[derive(Routable, Clone, Serialize, Deserialize)]
  45. enum Route {
  46. #[route("/")]
  47. Root {},
  48. #[route("/test")]
  49. Test {},
  50. }
  51. #[inline_props]
  52. fn Test(cx: Scope) -> Element {
  53. todo!()
  54. }
  55. #[inline_props]
  56. fn Root(cx: Scope) -> Element {
  57. render! {
  58. Link {
  59. target: Route::Test {},
  60. "Link"
  61. }
  62. }
  63. }
  64. let expected = format!(
  65. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  66. href = r#"href="/test""#,
  67. default = r#"dioxus-prevent-default="onclick""#,
  68. class = r#"class="""#,
  69. id = r#"id="""#,
  70. rel = r#"rel="""#,
  71. target = r#"target="""#
  72. );
  73. assert_eq!(prepare::<Route>(), expected);
  74. }
  75. #[test]
  76. fn href_external() {
  77. #[derive(Routable, Clone, Serialize, Deserialize)]
  78. enum Route {
  79. #[route("/")]
  80. Root {},
  81. #[route("/test")]
  82. Test {},
  83. }
  84. #[inline_props]
  85. fn Test(cx: Scope) -> Element {
  86. todo!()
  87. }
  88. #[inline_props]
  89. fn Root(cx: Scope) -> Element {
  90. render! {
  91. Link {
  92. target: "https://dioxuslabs.com/",
  93. "Link"
  94. }
  95. }
  96. }
  97. let expected = format!(
  98. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  99. href = r#"href="https://dioxuslabs.com/""#,
  100. default = r#"dioxus-prevent-default="""#,
  101. class = r#"class="""#,
  102. id = r#"id="""#,
  103. rel = r#"rel="noopener noreferrer""#,
  104. target = r#"target="""#
  105. );
  106. assert_eq!(prepare::<Route>(), expected);
  107. }
  108. #[test]
  109. fn with_class() {
  110. #[derive(Routable, Clone, Serialize, Deserialize)]
  111. enum Route {
  112. #[route("/")]
  113. Root {},
  114. #[route("/test")]
  115. Test {},
  116. }
  117. #[inline_props]
  118. fn Test(cx: Scope) -> Element {
  119. todo!()
  120. }
  121. #[inline_props]
  122. fn Root(cx: Scope) -> Element {
  123. render! {
  124. Link {
  125. target: Route::Test {},
  126. class: "test_class",
  127. "Link"
  128. }
  129. }
  130. }
  131. let expected = format!(
  132. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  133. href = r#"href="/test""#,
  134. default = r#"dioxus-prevent-default="onclick""#,
  135. class = r#"class="test_class""#,
  136. id = r#"id="""#,
  137. rel = r#"rel="""#,
  138. target = r#"target="""#
  139. );
  140. assert_eq!(prepare::<Route>(), expected);
  141. }
  142. #[test]
  143. fn with_active_class_active() {
  144. #[derive(Routable, Clone, Serialize, Deserialize)]
  145. enum Route {
  146. #[route("/")]
  147. Root {},
  148. }
  149. #[inline_props]
  150. fn Root(cx: Scope) -> Element {
  151. render! {
  152. Link {
  153. target: "/",
  154. active_class: "active_class",
  155. class: "test_class",
  156. "Link"
  157. }
  158. }
  159. }
  160. let expected = format!(
  161. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  162. href = r#"href="/""#,
  163. default = r#"dioxus-prevent-default="onclick""#,
  164. class = r#"class="test_class active_class""#,
  165. id = r#"id="""#,
  166. rel = r#"rel="""#,
  167. target = r#"target="""#
  168. );
  169. assert_eq!(prepare::<Route>(), expected);
  170. }
  171. #[test]
  172. fn with_active_class_inactive() {
  173. #[derive(Routable, Clone, Serialize, Deserialize)]
  174. enum Route {
  175. #[route("/")]
  176. Root {},
  177. #[route("/test")]
  178. Test {},
  179. }
  180. #[inline_props]
  181. fn Test(cx: Scope) -> Element {
  182. todo!()
  183. }
  184. #[inline_props]
  185. fn Root(cx: Scope) -> Element {
  186. render! {
  187. Link {
  188. target: Route::Test {},
  189. active_class: "active_class",
  190. class: "test_class",
  191. "Link"
  192. }
  193. }
  194. }
  195. let expected = format!(
  196. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  197. href = r#"href="/test""#,
  198. default = r#"dioxus-prevent-default="onclick""#,
  199. class = r#"class="test_class""#,
  200. id = r#"id="""#,
  201. rel = r#"rel="""#,
  202. target = r#"target="""#
  203. );
  204. assert_eq!(prepare::<Route>(), expected);
  205. }
  206. #[test]
  207. fn with_id() {
  208. #[derive(Routable, Clone, Serialize, Deserialize)]
  209. enum Route {
  210. #[route("/")]
  211. Root {},
  212. #[route("/test")]
  213. Test {},
  214. }
  215. #[inline_props]
  216. fn Test(cx: Scope) -> Element {
  217. todo!()
  218. }
  219. #[inline_props]
  220. fn Root(cx: Scope) -> Element {
  221. render! {
  222. Link {
  223. target: Route::Test {},
  224. id: "test_id",
  225. "Link"
  226. }
  227. }
  228. }
  229. let expected = format!(
  230. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  231. href = r#"href="/test""#,
  232. default = r#"dioxus-prevent-default="onclick""#,
  233. class = r#"class="""#,
  234. id = r#"id="test_id""#,
  235. rel = r#"rel="""#,
  236. target = r#"target="""#
  237. );
  238. assert_eq!(prepare::<Route>(), expected);
  239. }
  240. #[test]
  241. fn with_new_tab() {
  242. #[derive(Routable, Clone, Serialize, Deserialize)]
  243. enum Route {
  244. #[route("/")]
  245. Root {},
  246. #[route("/test")]
  247. Test {},
  248. }
  249. #[inline_props]
  250. fn Test(cx: Scope) -> Element {
  251. todo!()
  252. }
  253. #[inline_props]
  254. fn Root(cx: Scope) -> Element {
  255. render! {
  256. Link {
  257. target: Route::Test {},
  258. new_tab: true,
  259. "Link"
  260. }
  261. }
  262. }
  263. let expected = format!(
  264. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  265. href = r#"href="/test""#,
  266. default = r#"dioxus-prevent-default="""#,
  267. class = r#"class="""#,
  268. id = r#"id="""#,
  269. rel = r#"rel="""#,
  270. target = r#"target="_blank""#
  271. );
  272. assert_eq!(prepare::<Route>(), expected);
  273. }
  274. #[test]
  275. fn with_new_tab_external() {
  276. #[derive(Routable, Clone, Serialize, Deserialize)]
  277. enum Route {
  278. #[route("/")]
  279. Root {},
  280. }
  281. #[inline_props]
  282. fn Root(cx: Scope) -> Element {
  283. render! {
  284. Link {
  285. target: "https://dioxuslabs.com/",
  286. new_tab: true,
  287. "Link"
  288. }
  289. }
  290. }
  291. let expected = format!(
  292. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  293. href = r#"href="https://dioxuslabs.com/""#,
  294. default = r#"dioxus-prevent-default="""#,
  295. class = r#"class="""#,
  296. id = r#"id="""#,
  297. rel = r#"rel="noopener noreferrer""#,
  298. target = r#"target="_blank""#
  299. );
  300. assert_eq!(prepare::<Route>(), expected);
  301. }
  302. #[test]
  303. fn with_rel() {
  304. #[derive(Routable, Clone, Serialize, Deserialize)]
  305. enum Route {
  306. #[route("/")]
  307. Root {},
  308. #[route("/test")]
  309. Test {},
  310. }
  311. #[inline_props]
  312. fn Test(cx: Scope) -> Element {
  313. todo!()
  314. }
  315. #[inline_props]
  316. fn Root(cx: Scope) -> Element {
  317. render! {
  318. Link {
  319. target: Route::Test {},
  320. rel: "test_rel",
  321. "Link"
  322. }
  323. }
  324. }
  325. let expected = format!(
  326. "<h1>App</h1><a {href} {default} {class} {id} {rel} {target}>Link</a>",
  327. href = r#"href="/test""#,
  328. default = r#"dioxus-prevent-default="onclick""#,
  329. class = r#"class="""#,
  330. id = r#"id="""#,
  331. rel = r#"rel="test_rel""#,
  332. target = r#"target="""#
  333. );
  334. assert_eq!(prepare::<Route>(), expected);
  335. }