test_var_operations.py 28 KB

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