test_var_operations.py 27 KB

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