test_context_is_readable.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. # Copyright 2023 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. from unittest.mock import Mock, patch
  12. import pytest
  13. import typing as t
  14. from taipy.config.common.scope import Scope
  15. from taipy.core import Job, JobId, Scenario, Task
  16. from taipy.core.data.pickle import PickleDataNode
  17. from taipy.core.submission.submission import Submission
  18. from taipy.gui import Gui
  19. from taipy.gui_core._context import _GuiCoreContext, _SubmissionDetails
  20. a_scenario = Scenario("scenario_config_id", [], {}, sequences={"sequence": {}})
  21. a_task = Task("task_config_id", {}, print)
  22. a_job = Job(t.cast(JobId, "JOB_job_id"), a_task, "submit_id", a_scenario.id)
  23. a_job.isfinished = lambda s: True
  24. a_datanode = PickleDataNode("data_node_config_id", Scope.SCENARIO)
  25. a_submission = Submission(a_scenario.id, "Scenario", a_scenario.config_id)
  26. def mock_is_readable_false(entity_id):
  27. return False
  28. def mock_is_true(entity_id):
  29. return True
  30. def mock_core_get(entity_id):
  31. if entity_id == a_scenario.id:
  32. return a_scenario
  33. if entity_id == a_job.id:
  34. return a_job
  35. if entity_id == a_datanode.id:
  36. return a_datanode
  37. if entity_id == a_submission.id:
  38. return a_submission
  39. return a_task
  40. class MockState:
  41. def __init__(self, **kwargs) -> None:
  42. self.assign = kwargs.get("assign")
  43. class TestGuiCoreContext_is_readable:
  44. def test_scenario_adapter(self):
  45. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  46. gui_core_context = _GuiCoreContext(Mock())
  47. outcome = gui_core_context.scenario_adapter(a_scenario)
  48. assert isinstance(outcome, tuple)
  49. assert outcome[0] == a_scenario.id
  50. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  51. outcome = gui_core_context.scenario_adapter(a_scenario)
  52. assert outcome is None
  53. def test_get_scenario_by_id(self):
  54. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  55. gui_core_context = _GuiCoreContext(Mock())
  56. outcome = gui_core_context.get_scenario_by_id(a_scenario.id)
  57. assert outcome is not None
  58. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  59. outcome = gui_core_context.get_scenario_by_id(a_scenario.id)
  60. assert outcome is None
  61. def test_crud_scenario(self):
  62. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  63. gui_core_context = _GuiCoreContext(Mock())
  64. assign = Mock()
  65. gui_core_context.crud_scenario(
  66. MockState(assign=assign),
  67. "",
  68. {
  69. "args": [
  70. True,
  71. False,
  72. {"name": "name", "id": a_scenario.id},
  73. ]
  74. },
  75. )
  76. assign.assert_not_called()
  77. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  78. assign.reset_mock()
  79. gui_core_context.crud_scenario(
  80. MockState(assign=assign),
  81. "",
  82. {
  83. "args": [
  84. True,
  85. False,
  86. {"name": "name", "id": a_scenario.id},
  87. ]
  88. },
  89. )
  90. assign.assert_called_once()
  91. assert assign.call_args.args[0] == "gui_core_sc_error"
  92. assert str(assign.call_args.args[1]).endswith("is not readable.")
  93. def test_edit_entity(self):
  94. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  95. gui_core_context = _GuiCoreContext(Mock())
  96. assign = Mock()
  97. gui_core_context.edit_entity(
  98. MockState(assign=assign),
  99. "",
  100. {
  101. "args": [
  102. {"name": "name", "id": a_scenario.id},
  103. ]
  104. },
  105. )
  106. assign.assert_called_once()
  107. assert assign.call_args.args[0] == "gui_core_sv_error"
  108. assert assign.call_args.args[1] == ""
  109. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  110. assign.reset_mock()
  111. gui_core_context.edit_entity(
  112. MockState(assign=assign),
  113. "",
  114. {
  115. "args": [
  116. {"name": "name", "id": a_scenario.id},
  117. ]
  118. },
  119. )
  120. assign.assert_called_once()
  121. assert assign.call_args.args[0] == "gui_core_sv_error"
  122. assert str(assign.call_args.args[1]).endswith("is not readable.")
  123. def test_scenario_status_callback(self):
  124. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget, patch(
  125. "taipy.gui_core._context.core_get_submission", side_effect=mock_core_get
  126. ):
  127. mockget.reset_mock()
  128. gui_core_context = _GuiCoreContext(Mock())
  129. def sub_cb():
  130. return True
  131. gui_core_context.client_submission[a_submission.id] = _SubmissionDetails(
  132. "client_id", "", sub_cb, a_submission
  133. )
  134. gui_core_context.scenario_status_callback(a_submission.id)
  135. mockget.assert_called()
  136. found = False
  137. for call in mockget.call_args_list:
  138. if call.args[0] == a_scenario.id:
  139. found = True
  140. break
  141. assert found is True
  142. mockget.reset_mock()
  143. with patch("taipy.gui_core._context.is_readable_submission", side_effect=mock_is_readable_false):
  144. gui_core_context.scenario_status_callback(a_submission.id)
  145. mockget.assert_not_called()
  146. def test_data_node_adapter(self):
  147. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  148. gui_core_context = _GuiCoreContext(Mock())
  149. outcome = gui_core_context.data_node_adapter(a_datanode)
  150. assert isinstance(outcome, tuple)
  151. assert outcome[0] == a_datanode.id
  152. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  153. outcome = gui_core_context.data_node_adapter(a_datanode)
  154. assert outcome is None
  155. def test_job_adapter(self):
  156. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  157. gui_core_context = _GuiCoreContext(Mock())
  158. outcome = gui_core_context.job_adapter(a_job)
  159. assert isinstance(outcome, tuple)
  160. assert outcome[0] == a_job.id
  161. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  162. outcome = gui_core_context.job_adapter(a_job)
  163. assert outcome is None
  164. def test_act_on_jobs(self):
  165. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get), patch(
  166. "taipy.gui_core._context.is_deletable", side_effect=mock_is_true
  167. ):
  168. gui_core_context = _GuiCoreContext(Mock())
  169. assign = Mock()
  170. gui_core_context.act_on_jobs(
  171. MockState(assign=assign),
  172. "",
  173. {
  174. "args": [
  175. {"id": [a_job.id], "action": "delete"},
  176. ]
  177. },
  178. )
  179. assign.assert_called_once()
  180. assert assign.call_args.args[0] == "gui_core_js_error"
  181. assert str(assign.call_args.args[1]).find("is not readable.") == -1
  182. assign.reset_mock()
  183. gui_core_context.act_on_jobs(
  184. MockState(assign=assign),
  185. "",
  186. {
  187. "args": [
  188. {"id": [a_job.id], "action": "cancel"},
  189. ]
  190. },
  191. )
  192. assign.assert_called_once()
  193. assert assign.call_args.args[0] == "gui_core_js_error"
  194. assert str(assign.call_args.args[1]).find("is not readable.") == -1
  195. assign.reset_mock()
  196. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  197. gui_core_context.act_on_jobs(
  198. MockState(assign=assign),
  199. "",
  200. {
  201. "args": [
  202. {"id": [a_job.id], "action": "delete"},
  203. ]
  204. },
  205. )
  206. assign.assert_called_once()
  207. assert assign.call_args.args[0] == "gui_core_js_error"
  208. assert str(assign.call_args.args[1]).endswith("is not readable.")
  209. assign.reset_mock()
  210. gui_core_context.act_on_jobs(
  211. MockState(assign=assign),
  212. "",
  213. {
  214. "args": [
  215. {"id": [a_job.id], "action": "cancel"},
  216. ]
  217. },
  218. )
  219. assign.assert_called_once()
  220. assert assign.call_args.args[0] == "gui_core_js_error"
  221. assert str(assign.call_args.args[1]).endswith("is not readable.")
  222. def test_edit_data_node(self):
  223. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  224. gui_core_context = _GuiCoreContext(Mock())
  225. assign = Mock()
  226. gui_core_context.edit_data_node(
  227. MockState(assign=assign),
  228. "",
  229. {
  230. "args": [
  231. {"id": a_datanode.id},
  232. ]
  233. },
  234. )
  235. assign.assert_called_once()
  236. assert assign.call_args.args[0] == "gui_core_dv_error"
  237. assert assign.call_args.args[1] == ""
  238. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  239. assign.reset_mock()
  240. gui_core_context.edit_data_node(
  241. MockState(assign=assign),
  242. "",
  243. {
  244. "args": [
  245. {"id": a_datanode.id},
  246. ]
  247. },
  248. )
  249. assign.assert_called_once()
  250. assert assign.call_args.args[0] == "gui_core_dv_error"
  251. assert str(assign.call_args.args[1]).endswith("is not readable.")
  252. def test_lock_datanode_for_edit(self):
  253. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  254. mockGui = Mock(Gui)
  255. mockGui._get_client_id = lambda: "a_client_id"
  256. gui_core_context = _GuiCoreContext(mockGui)
  257. assign = Mock()
  258. gui_core_context.lock_datanode_for_edit(
  259. MockState(assign=assign),
  260. "",
  261. {
  262. "args": [
  263. {"id": a_datanode.id},
  264. ]
  265. },
  266. )
  267. assign.assert_called_once()
  268. assert assign.call_args.args[0] == "gui_core_dv_error"
  269. assert assign.call_args.args[1] == ""
  270. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  271. assign.reset_mock()
  272. gui_core_context.lock_datanode_for_edit(
  273. MockState(assign=assign),
  274. "",
  275. {
  276. "args": [
  277. {"id": a_datanode.id},
  278. ]
  279. },
  280. )
  281. assign.assert_called_once()
  282. assert assign.call_args.args[0] == "gui_core_dv_error"
  283. assert str(assign.call_args.args[1]).endswith("is not readable.")
  284. def test_get_scenarios_for_owner(self):
  285. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  286. gui_core_context = _GuiCoreContext(Mock())
  287. gui_core_context.get_scenarios_for_owner(a_scenario.id)
  288. mockget.assert_called_once()
  289. mockget.reset_mock()
  290. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  291. gui_core_context.scenario_status_callback(a_scenario.id)
  292. mockget.assert_not_called()
  293. def test_update_data(self):
  294. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  295. mockGui = Mock(Gui)
  296. mockGui._get_client_id = lambda: "a_client_id"
  297. gui_core_context = _GuiCoreContext(mockGui)
  298. assign = Mock()
  299. gui_core_context.update_data(
  300. MockState(assign=assign),
  301. "",
  302. {
  303. "args": [
  304. {"id": a_datanode.id},
  305. ]
  306. },
  307. )
  308. assign.assert_called()
  309. assert assign.call_args_list[0].args[0] == "gui_core_dv_error"
  310. assert assign.call_args_list[0].args[1] == ""
  311. assign.reset_mock()
  312. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  313. gui_core_context.update_data(
  314. MockState(assign=assign),
  315. "",
  316. {
  317. "args": [
  318. {"id": a_datanode.id},
  319. ]
  320. },
  321. )
  322. assign.assert_called_once()
  323. assert assign.call_args.args[0] == "gui_core_dv_error"
  324. assert str(assign.call_args.args[1]).endswith("is not readable.")
  325. def test_tabular_data_edit(self):
  326. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  327. mockGui = Mock(Gui)
  328. mockGui._get_client_id = lambda: "a_client_id"
  329. gui_core_context = _GuiCoreContext(mockGui)
  330. assign = Mock()
  331. gui_core_context.tabular_data_edit(
  332. MockState(assign=assign),
  333. "",
  334. {
  335. "user_data": {"dn_id": a_datanode.id},
  336. },
  337. )
  338. assign.assert_called_once()
  339. assert assign.call_args_list[0].args[0] == "gui_core_dv_error"
  340. assert (
  341. assign.call_args_list[0].args[1]
  342. == "Error updating Datanode tabular value: type does not support at[] indexer."
  343. )
  344. assign.reset_mock()
  345. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  346. gui_core_context.tabular_data_edit(
  347. MockState(assign=assign),
  348. "",
  349. {
  350. "user_data": {"dn_id": a_datanode.id},
  351. },
  352. )
  353. assign.assert_called_once()
  354. assert assign.call_args.args[0] == "gui_core_dv_error"
  355. assert str(assign.call_args.args[1]).endswith("is not readable.")
  356. def test_get_data_node_tabular_data(self):
  357. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  358. gui_core_context = _GuiCoreContext(Mock())
  359. gui_core_context.get_data_node_tabular_data(a_datanode, a_datanode.id)
  360. mockget.assert_called_once()
  361. mockget.reset_mock()
  362. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  363. gui_core_context.get_data_node_tabular_data(a_datanode, a_datanode.id)
  364. mockget.assert_not_called()
  365. def test_get_data_node_tabular_columns(self):
  366. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  367. gui_core_context = _GuiCoreContext(Mock())
  368. gui_core_context.get_data_node_tabular_columns(a_datanode, a_datanode.id)
  369. mockget.assert_called_once()
  370. mockget.reset_mock()
  371. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  372. gui_core_context.get_data_node_tabular_columns(a_datanode, a_datanode.id)
  373. mockget.assert_not_called()
  374. def test_get_data_node_chart_config(self):
  375. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  376. gui_core_context = _GuiCoreContext(Mock())
  377. gui_core_context.get_data_node_chart_config(a_datanode, a_datanode.id)
  378. mockget.assert_called_once()
  379. mockget.reset_mock()
  380. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  381. gui_core_context.get_data_node_chart_config(a_datanode, a_datanode.id)
  382. mockget.assert_not_called()