link.rs 6.7 KB

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