test_var_operations.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. """Integration tests for var operations."""
  2. from typing import Generator
  3. import pytest
  4. from selenium.webdriver.common.by import By
  5. from reflex.testing import AppHarness
  6. # pyright: reportOptionalMemberAccess=false, reportGeneralTypeIssues=false, reportUnknownMemberType=false
  7. def VarOperations():
  8. """App with var operations."""
  9. from typing import Dict, List
  10. import reflex as rx
  11. class VarOperationState(rx.State):
  12. int_var1: int = 10
  13. int_var2: int = 5
  14. int_var3: int = 7
  15. float_var1: float = 10.5
  16. float_var2: float = 5.5
  17. list1: List = [1, 2]
  18. list2: List = [3, 4]
  19. list3: List = ["first", "second", "third"]
  20. str_var1: str = "first"
  21. str_var2: str = "second"
  22. str_var3: str = "ThIrD"
  23. str_var4: str = "a long string"
  24. dict1: Dict = {1: 2}
  25. dict2: Dict = {3: 4}
  26. html_str: str = "<div>hello</div>"
  27. app = rx.App(state=rx.State)
  28. @rx.memo
  29. def memo_comp(list1: List[int], int_var1: int, id: str):
  30. return rx.text(list1, int_var1, id=id)
  31. @rx.memo
  32. def memo_comp_nested(int_var2: int, id: str):
  33. return memo_comp(list1=[3, 4], int_var1=int_var2, id=id)
  34. @app.add_page
  35. def index():
  36. return rx.vstack(
  37. rx.el.input(
  38. id="token",
  39. value=VarOperationState.router.session.client_token,
  40. is_read_only=True,
  41. ),
  42. # INT INT
  43. rx.text(
  44. VarOperationState.int_var1 + VarOperationState.int_var2,
  45. id="int_add_int",
  46. ),
  47. rx.text(
  48. VarOperationState.int_var1 * VarOperationState.int_var2,
  49. id="int_mult_int",
  50. ),
  51. rx.text(
  52. VarOperationState.int_var1 - VarOperationState.int_var2,
  53. id="int_sub_int",
  54. ),
  55. rx.text(
  56. VarOperationState.int_var1**VarOperationState.int_var2,
  57. id="int_exp_int",
  58. ),
  59. rx.text(
  60. VarOperationState.int_var1 / VarOperationState.int_var2,
  61. id="int_div_int",
  62. ),
  63. rx.text(
  64. VarOperationState.int_var1 // VarOperationState.int_var3,
  65. id="int_floor_int",
  66. ),
  67. rx.text(
  68. VarOperationState.int_var1 % VarOperationState.int_var2,
  69. id="int_mod_int",
  70. ),
  71. rx.text(
  72. VarOperationState.int_var1 | VarOperationState.int_var2,
  73. id="int_or_int",
  74. ),
  75. rx.text(
  76. (VarOperationState.int_var1 > VarOperationState.int_var2).to_string(),
  77. id="int_gt_int",
  78. ),
  79. rx.text(
  80. (VarOperationState.int_var1 < VarOperationState.int_var2).to_string(),
  81. id="int_lt_int",
  82. ),
  83. rx.text(
  84. (VarOperationState.int_var1 >= VarOperationState.int_var2).to_string(),
  85. id="int_gte_int",
  86. ),
  87. rx.text(
  88. (VarOperationState.int_var1 <= VarOperationState.int_var2).to_string(),
  89. id="int_lte_int",
  90. ),
  91. rx.text(
  92. VarOperationState.int_var1 & VarOperationState.int_var2,
  93. id="int_and_int",
  94. ),
  95. rx.text(
  96. (VarOperationState.int_var1 | VarOperationState.int_var2).to_string(),
  97. id="int_or_int",
  98. ),
  99. rx.text(
  100. (VarOperationState.int_var1 == VarOperationState.int_var2).to_string(),
  101. id="int_eq_int",
  102. ),
  103. rx.text(
  104. (VarOperationState.int_var1 != VarOperationState.int_var2).to_string(),
  105. id="int_neq_int",
  106. ),
  107. # INT FLOAT OR FLOAT INT
  108. rx.text(
  109. VarOperationState.float_var1 + VarOperationState.int_var2,
  110. id="float_add_int",
  111. ),
  112. rx.text(
  113. VarOperationState.float_var1 * VarOperationState.int_var2,
  114. id="float_mult_int",
  115. ),
  116. rx.text(
  117. VarOperationState.float_var1 - VarOperationState.int_var2,
  118. id="float_sub_int",
  119. ),
  120. rx.text(
  121. VarOperationState.float_var1**VarOperationState.int_var2,
  122. id="float_exp_int",
  123. ),
  124. rx.text(
  125. VarOperationState.float_var1 / VarOperationState.int_var2,
  126. id="float_div_int",
  127. ),
  128. rx.text(
  129. VarOperationState.float_var1 // VarOperationState.int_var3,
  130. id="float_floor_int",
  131. ),
  132. rx.text(
  133. VarOperationState.float_var1 % VarOperationState.int_var2,
  134. id="float_mod_int",
  135. ),
  136. rx.text(
  137. (VarOperationState.float_var1 > VarOperationState.int_var2).to_string(),
  138. id="float_gt_int",
  139. ),
  140. rx.text(
  141. (VarOperationState.float_var1 < VarOperationState.int_var2).to_string(),
  142. id="float_lt_int",
  143. ),
  144. rx.text(
  145. (
  146. VarOperationState.float_var1 >= VarOperationState.int_var2
  147. ).to_string(),
  148. id="float_gte_int",
  149. ),
  150. rx.text(
  151. (
  152. VarOperationState.float_var1 <= VarOperationState.int_var2
  153. ).to_string(),
  154. id="float_lte_int",
  155. ),
  156. rx.text(
  157. (
  158. VarOperationState.float_var1 == VarOperationState.int_var2
  159. ).to_string(),
  160. id="float_eq_int",
  161. ),
  162. rx.text(
  163. (
  164. VarOperationState.float_var1 != VarOperationState.int_var2
  165. ).to_string(),
  166. id="float_neq_int",
  167. ),
  168. rx.text(
  169. (VarOperationState.float_var1 & VarOperationState.int_var2).to_string(),
  170. id="float_and_int",
  171. ),
  172. rx.text(
  173. (VarOperationState.float_var1 | VarOperationState.int_var2).to_string(),
  174. id="float_or_int",
  175. ),
  176. # INT, DICT
  177. rx.text(
  178. (VarOperationState.int_var1 | VarOperationState.dict1).to_string(),
  179. id="int_or_dict",
  180. ),
  181. rx.text(
  182. (VarOperationState.int_var1 & VarOperationState.dict1).to_string(),
  183. id="int_and_dict",
  184. ),
  185. rx.text(
  186. (VarOperationState.int_var1 == VarOperationState.dict1).to_string(),
  187. id="int_eq_dict",
  188. ),
  189. rx.text(
  190. (VarOperationState.int_var1 != VarOperationState.dict1).to_string(),
  191. id="int_neq_dict",
  192. ),
  193. # FLOAT FLOAT
  194. rx.text(
  195. VarOperationState.float_var1 + VarOperationState.float_var2,
  196. id="float_add_float",
  197. ),
  198. rx.text(
  199. VarOperationState.float_var1 * VarOperationState.float_var2,
  200. id="float_mult_float",
  201. ),
  202. rx.text(
  203. VarOperationState.float_var1 - VarOperationState.float_var2,
  204. id="float_sub_float",
  205. ),
  206. rx.text(
  207. VarOperationState.float_var1**VarOperationState.float_var2,
  208. id="float_exp_float",
  209. ),
  210. rx.text(
  211. VarOperationState.float_var1 / VarOperationState.float_var2,
  212. id="float_div_float",
  213. ),
  214. rx.text(
  215. VarOperationState.float_var1 // VarOperationState.float_var2,
  216. id="float_floor_float",
  217. ),
  218. rx.text(
  219. VarOperationState.float_var1 % VarOperationState.float_var2,
  220. id="float_mod_float",
  221. ),
  222. rx.text(
  223. (
  224. VarOperationState.float_var1 > VarOperationState.float_var2
  225. ).to_string(),
  226. id="float_gt_float",
  227. ),
  228. rx.text(
  229. (
  230. VarOperationState.float_var1 < VarOperationState.float_var2
  231. ).to_string(),
  232. id="float_lt_float",
  233. ),
  234. rx.text(
  235. (
  236. VarOperationState.float_var1 >= VarOperationState.float_var2
  237. ).to_string(),
  238. id="float_gte_float",
  239. ),
  240. rx.text(
  241. (
  242. VarOperationState.float_var1 <= VarOperationState.float_var2
  243. ).to_string(),
  244. id="float_lte_float",
  245. ),
  246. rx.text(
  247. (
  248. VarOperationState.float_var1 == VarOperationState.float_var2
  249. ).to_string(),
  250. id="float_eq_float",
  251. ),
  252. rx.text(
  253. (
  254. VarOperationState.float_var1 != VarOperationState.float_var2
  255. ).to_string(),
  256. id="float_neq_float",
  257. ),
  258. rx.text(
  259. (
  260. VarOperationState.float_var1 & VarOperationState.float_var2
  261. ).to_string(),
  262. id="float_and_float",
  263. ),
  264. rx.text(
  265. (
  266. VarOperationState.float_var1 | VarOperationState.float_var2
  267. ).to_string(),
  268. id="float_or_float",
  269. ),
  270. # FLOAT STR
  271. rx.text(
  272. VarOperationState.float_var1 | VarOperationState.str_var1,
  273. id="float_or_str",
  274. ),
  275. rx.text(
  276. VarOperationState.float_var1 & VarOperationState.str_var1,
  277. id="float_and_str",
  278. ),
  279. rx.text(
  280. (
  281. VarOperationState.float_var1 == VarOperationState.str_var1
  282. ).to_string(),
  283. id="float_eq_str",
  284. ),
  285. rx.text(
  286. (
  287. VarOperationState.float_var1 != VarOperationState.str_var1
  288. ).to_string(),
  289. id="float_neq_str",
  290. ),
  291. # FLOAT LIST
  292. rx.text(
  293. (VarOperationState.float_var1 | VarOperationState.list1).to_string(),
  294. id="float_or_list",
  295. ),
  296. rx.text(
  297. (VarOperationState.float_var1 & VarOperationState.list1).to_string(),
  298. id="float_and_list",
  299. ),
  300. rx.text(
  301. (VarOperationState.float_var1 == VarOperationState.list1).to_string(),
  302. id="float_eq_list",
  303. ),
  304. rx.text(
  305. (VarOperationState.float_var1 != VarOperationState.list1).to_string(),
  306. id="float_neq_list",
  307. ),
  308. # FLOAT DICT
  309. rx.text(
  310. (VarOperationState.float_var1 | VarOperationState.dict1).to_string(),
  311. id="float_or_dict",
  312. ),
  313. rx.text(
  314. (VarOperationState.float_var1 & VarOperationState.dict1).to_string(),
  315. id="float_and_dict",
  316. ),
  317. rx.text(
  318. (VarOperationState.float_var1 == VarOperationState.dict1).to_string(),
  319. id="float_eq_dict",
  320. ),
  321. rx.text(
  322. (VarOperationState.float_var1 != VarOperationState.dict1).to_string(),
  323. id="float_neq_dict",
  324. ),
  325. # STR STR
  326. rx.text(
  327. VarOperationState.str_var1 + VarOperationState.str_var2,
  328. id="str_add_str",
  329. ),
  330. rx.text(
  331. (VarOperationState.str_var1 > VarOperationState.str_var2).to_string(),
  332. id="str_gt_str",
  333. ),
  334. rx.text(
  335. (VarOperationState.str_var1 < VarOperationState.str_var2).to_string(),
  336. id="str_lt_str",
  337. ),
  338. rx.text(
  339. (VarOperationState.str_var1 >= VarOperationState.str_var2).to_string(),
  340. id="str_gte_str",
  341. ),
  342. rx.text(
  343. (VarOperationState.str_var1 <= VarOperationState.str_var2).to_string(),
  344. id="str_lte_str",
  345. ),
  346. rx.text(
  347. (
  348. VarOperationState.float_var1 == VarOperationState.float_var2
  349. ).to_string(),
  350. id="str_eq_str",
  351. ),
  352. rx.text(
  353. (
  354. VarOperationState.float_var1 != VarOperationState.float_var2
  355. ).to_string(),
  356. id="str_neq_str",
  357. ),
  358. rx.text(
  359. VarOperationState.str_var1.contains("fir").to_string(),
  360. id="str_contains",
  361. ),
  362. rx.text(
  363. VarOperationState.str_var1 | VarOperationState.str_var1, id="str_or_str"
  364. ),
  365. rx.text(
  366. VarOperationState.str_var1 & VarOperationState.str_var2,
  367. id="str_and_str",
  368. ),
  369. # STR, INT
  370. rx.text(
  371. VarOperationState.str_var1 * VarOperationState.int_var2,
  372. id="str_mult_int",
  373. ),
  374. rx.text(
  375. VarOperationState.str_var1 & VarOperationState.int_var2,
  376. id="str_and_int",
  377. ),
  378. rx.text(
  379. VarOperationState.str_var1 | VarOperationState.int_var2, id="str_or_int"
  380. ),
  381. rx.text(
  382. (VarOperationState.str_var1 == VarOperationState.int_var1).to_string(),
  383. id="str_eq_int",
  384. ),
  385. rx.text(
  386. (VarOperationState.str_var1 != VarOperationState.int_var1).to_string(),
  387. id="str_neq_int",
  388. ),
  389. # STR, LIST
  390. rx.text(
  391. VarOperationState.str_var1 | VarOperationState.list1, id="str_or_list"
  392. ),
  393. rx.text(
  394. (VarOperationState.str_var1 & VarOperationState.list1).to_string(),
  395. id="str_and_list",
  396. ),
  397. rx.text(
  398. (VarOperationState.str_var1 == VarOperationState.list1).to_string(),
  399. id="str_eq_list",
  400. ),
  401. rx.text(
  402. (VarOperationState.str_var1 != VarOperationState.list1).to_string(),
  403. id="str_neq_list",
  404. ),
  405. # STR, DICT
  406. rx.text(
  407. VarOperationState.str_var1 | VarOperationState.dict1, id="str_or_dict"
  408. ),
  409. rx.text(
  410. (VarOperationState.str_var1 & VarOperationState.dict1).to_string(),
  411. id="str_and_dict",
  412. ),
  413. rx.text(
  414. (VarOperationState.str_var1 == VarOperationState.dict1).to_string(),
  415. id="str_eq_dict",
  416. ),
  417. rx.text(
  418. (VarOperationState.str_var1 != VarOperationState.dict1).to_string(),
  419. id="str_neq_dict",
  420. ),
  421. # LIST, LIST
  422. rx.text(
  423. (VarOperationState.list1 + VarOperationState.list2).to_string(),
  424. id="list_add_list",
  425. ),
  426. rx.text(
  427. (VarOperationState.list1 & VarOperationState.list2).to_string(),
  428. id="list_and_list",
  429. ),
  430. rx.text(
  431. (VarOperationState.list1 | VarOperationState.list2).to_string(),
  432. id="list_or_list",
  433. ),
  434. rx.text(
  435. (VarOperationState.list1 > VarOperationState.list2).to_string(),
  436. id="list_gt_list",
  437. ),
  438. rx.text(
  439. (VarOperationState.list1 < VarOperationState.list2).to_string(),
  440. id="list_lt_list",
  441. ),
  442. rx.text(
  443. (VarOperationState.list1 >= VarOperationState.list2).to_string(),
  444. id="list_gte_list",
  445. ),
  446. rx.text(
  447. (VarOperationState.list1 <= VarOperationState.list2).to_string(),
  448. id="list_lte_list",
  449. ),
  450. rx.text(
  451. (VarOperationState.list1 == VarOperationState.list2).to_string(),
  452. id="list_eq_list",
  453. ),
  454. rx.text(
  455. (VarOperationState.list1 != VarOperationState.list2).to_string(),
  456. id="list_neq_list",
  457. ),
  458. rx.text(
  459. VarOperationState.list1.contains(1).to_string(), id="list_contains"
  460. ),
  461. rx.text(VarOperationState.list1.reverse().to_string(), id="list_reverse"),
  462. # LIST, INT
  463. rx.text(
  464. (VarOperationState.list1 * VarOperationState.int_var2).to_string(),
  465. id="list_mult_int",
  466. ),
  467. rx.text(
  468. (VarOperationState.list1 | VarOperationState.int_var1).to_string(),
  469. id="list_or_int",
  470. ),
  471. rx.text(
  472. (VarOperationState.list1 & VarOperationState.int_var1).to_string(),
  473. id="list_and_int",
  474. ),
  475. rx.text(
  476. (VarOperationState.list1 == VarOperationState.int_var1).to_string(),
  477. id="list_eq_int",
  478. ),
  479. rx.text(
  480. (VarOperationState.list1 != VarOperationState.int_var1).to_string(),
  481. id="list_neq_int",
  482. ),
  483. # LIST, DICT
  484. rx.text(
  485. (VarOperationState.list1 | VarOperationState.dict1).to_string(),
  486. id="list_or_dict",
  487. ),
  488. rx.text(
  489. (VarOperationState.list1 & VarOperationState.dict1).to_string(),
  490. id="list_and_dict",
  491. ),
  492. rx.text(
  493. (VarOperationState.list1 == VarOperationState.dict1).to_string(),
  494. id="list_eq_dict",
  495. ),
  496. rx.text(
  497. (VarOperationState.list1 != VarOperationState.dict1).to_string(),
  498. id="list_neq_dict",
  499. ),
  500. # DICT, DICT
  501. rx.text(
  502. (VarOperationState.dict1 | VarOperationState.dict2).to_string(),
  503. id="dict_or_dict",
  504. ),
  505. rx.text(
  506. (VarOperationState.dict1 & VarOperationState.dict2).to_string(),
  507. id="dict_and_dict",
  508. ),
  509. rx.text(
  510. (VarOperationState.dict1 == VarOperationState.dict2).to_string(),
  511. id="dict_eq_dict",
  512. ),
  513. rx.text(
  514. (VarOperationState.dict1 != VarOperationState.dict2).to_string(),
  515. id="dict_neq_dict",
  516. ),
  517. rx.text(
  518. VarOperationState.dict1.contains(1).to_string(), id="dict_contains"
  519. ),
  520. rx.text(VarOperationState.str_var3.lower(), id="str_lower"),
  521. rx.text(VarOperationState.str_var3.upper(), id="str_upper"),
  522. rx.text(VarOperationState.str_var4.split(" ").to_string(), id="str_split"),
  523. rx.text(VarOperationState.list3.join(""), id="list_join"),
  524. rx.text(VarOperationState.list3.join(","), id="list_join_comma"),
  525. # Index from an op var
  526. rx.text(
  527. VarOperationState.list3[VarOperationState.int_var1 % 3],
  528. id="list_index_mod",
  529. ),
  530. rx.html(
  531. VarOperationState.html_str,
  532. id="html_str",
  533. ),
  534. rx.chakra.highlight(
  535. "second",
  536. query=[VarOperationState.str_var2],
  537. ),
  538. rx.text(rx.Var.range(2, 5).join(","), id="list_join_range1"),
  539. rx.text(rx.Var.range(2, 10, 2).join(","), id="list_join_range2"),
  540. rx.text(rx.Var.range(5, 0, -1).join(","), id="list_join_range3"),
  541. rx.text(rx.Var.range(0, 3).join(","), id="list_join_range4"),
  542. rx.box(
  543. rx.foreach(
  544. rx.Var.range(0, 2),
  545. lambda x: rx.text(VarOperationState.list1[x], as_="p"),
  546. ),
  547. id="foreach_list_arg",
  548. ),
  549. rx.box(
  550. rx.foreach(
  551. rx.Var.range(0, 2),
  552. lambda x, ix: rx.text(VarOperationState.list1[ix], as_="p"),
  553. ),
  554. id="foreach_list_ix",
  555. ),
  556. rx.box(
  557. rx.foreach(
  558. rx.Var.create_safe(list(range(0, 3))).to(List[int]),
  559. lambda x: rx.foreach(
  560. rx.Var.range(x),
  561. lambda y: rx.text(VarOperationState.list1[y], as_="p"),
  562. ),
  563. ),
  564. id="foreach_list_nested",
  565. ),
  566. memo_comp(
  567. list1=VarOperationState.list1,
  568. int_var1=VarOperationState.int_var1,
  569. id="memo_comp",
  570. ),
  571. memo_comp_nested(
  572. int_var2=VarOperationState.int_var2,
  573. id="memo_comp_nested",
  574. ),
  575. )
  576. @pytest.fixture(scope="module")
  577. def var_operations(tmp_path_factory) -> Generator[AppHarness, None, None]:
  578. """Start VarOperations app at tmp_path via AppHarness.
  579. Args:
  580. tmp_path_factory: pytest tmp_path_factory fixture
  581. Yields:
  582. running AppHarness instance
  583. """
  584. with AppHarness.create(
  585. root=tmp_path_factory.mktemp("var_operations"),
  586. app_source=VarOperations, # type: ignore
  587. ) as harness:
  588. assert harness.app_instance is not None, "app is not running"
  589. yield harness
  590. @pytest.fixture
  591. def driver(var_operations: AppHarness):
  592. """Get an instance of the browser open to the var operations app.
  593. Args:
  594. var_operations: harness for VarOperations app
  595. Yields:
  596. WebDriver instance.
  597. """
  598. driver = var_operations.frontend()
  599. try:
  600. token_input = driver.find_element(By.ID, "token")
  601. assert token_input
  602. # wait for the backend connection to send the token
  603. token = var_operations.poll_for_value(token_input)
  604. assert token is not None
  605. yield driver
  606. finally:
  607. driver.quit()
  608. def test_var_operations(driver, var_operations: AppHarness):
  609. """Test that the var operations produce the right results.
  610. Args:
  611. driver: selenium WebDriver open to the app
  612. var_operations: AppHarness for the var operations app
  613. """
  614. tests = [
  615. # int, int
  616. ("int_add_int", "15"),
  617. ("int_mult_int", "50"),
  618. ("int_sub_int", "5"),
  619. ("int_exp_int", "100000"),
  620. ("int_div_int", "2"),
  621. ("int_floor_int", "1"),
  622. ("int_mod_int", "0"),
  623. ("int_gt_int", "true"),
  624. ("int_lt_int", "false"),
  625. ("int_gte_int", "true"),
  626. ("int_lte_int", "false"),
  627. ("int_and_int", "5"),
  628. ("int_or_int", "10"),
  629. ("int_eq_int", "false"),
  630. ("int_neq_int", "true"),
  631. # int, float
  632. ("float_add_int", "15.5"),
  633. ("float_mult_int", "52.5"),
  634. ("float_sub_int", "5.5"),
  635. ("float_exp_int", "127628.15625"),
  636. ("float_div_int", "2.1"),
  637. ("float_floor_int", "1"),
  638. ("float_mod_int", "0.5"),
  639. ("float_gt_int", "true"),
  640. ("float_lt_int", "false"),
  641. ("float_gte_int", "true"),
  642. ("float_lte_int", "false"),
  643. ("float_eq_int", "false"),
  644. ("float_neq_int", "true"),
  645. ("float_and_int", "5"),
  646. ("float_or_int", "10.5"),
  647. # int, dict
  648. ("int_or_dict", "10"),
  649. ("int_and_dict", '{"1":2}'),
  650. ("int_eq_dict", "false"),
  651. ("int_neq_dict", "true"),
  652. # float, float
  653. ("float_add_float", "16"),
  654. ("float_mult_float", "57.75"),
  655. ("float_sub_float", "5"),
  656. ("float_exp_float", "413562.49323606625"),
  657. ("float_div_float", "1.9090909090909092"),
  658. ("float_floor_float", "1"),
  659. ("float_mod_float", "5"),
  660. ("float_gt_float", "true"),
  661. ("float_lt_float", "false"),
  662. ("float_gte_float", "true"),
  663. ("float_lte_float", "false"),
  664. ("float_eq_float", "false"),
  665. ("float_neq_float", "true"),
  666. ("float_and_float", "5.5"),
  667. ("float_or_float", "10.5"),
  668. # float, str
  669. ("float_or_str", "10.5"),
  670. ("float_and_str", "first"),
  671. ("float_eq_str", "false"),
  672. ("float_neq_str", "true"),
  673. # float, list
  674. ("float_or_list", "10.5"),
  675. ("float_and_list", "[1,2]"),
  676. ("float_eq_list", "false"),
  677. ("float_neq_list", "true"),
  678. # float, dict
  679. ("float_or_dict", "10.5"),
  680. ("float_and_dict", '{"1":2}'),
  681. ("float_eq_dict", "false"),
  682. ("float_neq_dict", "true"),
  683. # str, str
  684. ("str_add_str", "firstsecond"),
  685. ("str_gt_str", "false"),
  686. ("str_lt_str", "true"),
  687. ("str_gte_str", "false"),
  688. ("str_lte_str", "true"),
  689. ("str_eq_str", "false"),
  690. ("str_neq_str", "true"),
  691. ("str_and_str", "second"),
  692. ("str_or_str", "first"),
  693. ("str_contains", "true"),
  694. ("str_lower", "third"),
  695. ("str_upper", "THIRD"),
  696. ("str_split", '["a","long","string"]'),
  697. # str, int
  698. ("str_mult_int", "firstfirstfirstfirstfirst"),
  699. ("str_and_int", "5"),
  700. ("str_or_int", "first"),
  701. ("str_eq_int", "false"),
  702. ("str_neq_int", "true"),
  703. # str, list
  704. ("str_and_list", "[1,2]"),
  705. ("str_or_list", "first"),
  706. ("str_eq_list", "false"),
  707. ("str_neq_list", "true"),
  708. # str, dict
  709. ("str_or_dict", "first"),
  710. ("str_and_dict", '{"1":2}'),
  711. ("str_eq_dict", "false"),
  712. ("str_neq_dict", "true"),
  713. # list, list
  714. ("list_add_list", "[1,2,3,4]"),
  715. ("list_gt_list", "false"),
  716. ("list_lt_list", "true"),
  717. ("list_gte_list", "false"),
  718. ("list_lte_list", "true"),
  719. ("list_eq_list", "false"),
  720. ("list_neq_list", "true"),
  721. ("list_and_list", "[3,4]"),
  722. ("list_or_list", "[1,2]"),
  723. ("list_contains", "true"),
  724. ("list_reverse", "[2,1]"),
  725. ("list_join", "firstsecondthird"),
  726. ("list_join_comma", "first,second,third"),
  727. ("list_join_range1", "2,3,4"),
  728. ("list_join_range2", "2,4,6,8"),
  729. ("list_join_range3", "5,4,3,2,1"),
  730. ("list_join_range4", "0,1,2"),
  731. # list, int
  732. ("list_mult_int", "[1,2,1,2,1,2,1,2,1,2]"),
  733. ("list_or_int", "[1,2]"),
  734. ("list_and_int", "10"),
  735. ("list_eq_int", "false"),
  736. ("list_neq_int", "true"),
  737. # list, dict
  738. ("list_and_dict", '{"1":2}'),
  739. ("list_or_dict", "[1,2]"),
  740. ("list_eq_dict", "false"),
  741. ("list_neq_dict", "true"),
  742. # dict, dict
  743. ("dict_or_dict", '{"1":2}'),
  744. ("dict_and_dict", '{"3":4}'),
  745. ("dict_eq_dict", "false"),
  746. ("dict_neq_dict", "true"),
  747. ("dict_contains", "true"),
  748. # index from an op var
  749. ("list_index_mod", "second"),
  750. # html component with var
  751. ("html_str", "hello"),
  752. # index into list with foreach
  753. ("foreach_list_arg", "1\n2"),
  754. ("foreach_list_ix", "1\n2"),
  755. ("foreach_list_nested", "1\n1\n2"),
  756. # rx.memo component with state
  757. ("memo_comp", "1210"),
  758. ("memo_comp_nested", "345"),
  759. ]
  760. for tag, expected in tests:
  761. assert driver.find_element(By.ID, tag).text == expected
  762. # Highlight component with var query (does not plumb ID)
  763. assert driver.find_element(By.TAG_NAME, "mark").text == "second"