test_context_is_readable.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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("taipy.gui_core._context.core_get_submission", side_effect=mock_core_get):
  125. mockget.reset_mock()
  126. gui_core_context = _GuiCoreContext(Mock())
  127. def sub_cb():
  128. return True
  129. gui_core_context.client_submission[a_submission.id] = _SubmissionDetails("client_id", "", sub_cb, a_submission)
  130. gui_core_context.scenario_status_callback(a_submission.id)
  131. mockget.assert_called()
  132. found = False
  133. for call in mockget.call_args_list:
  134. if call.args[0] == a_scenario.id:
  135. found = True
  136. break
  137. assert found is True
  138. mockget.reset_mock()
  139. with patch("taipy.gui_core._context.is_readable_submission", side_effect=mock_is_readable_false):
  140. gui_core_context.scenario_status_callback(a_submission.id)
  141. mockget.assert_not_called()
  142. def test_data_node_adapter(self):
  143. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  144. gui_core_context = _GuiCoreContext(Mock())
  145. outcome = gui_core_context.data_node_adapter(a_datanode)
  146. assert isinstance(outcome, tuple)
  147. assert outcome[0] == a_datanode.id
  148. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  149. outcome = gui_core_context.data_node_adapter(a_datanode)
  150. assert outcome is None
  151. def test_job_adapter(self):
  152. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  153. gui_core_context = _GuiCoreContext(Mock())
  154. outcome = gui_core_context.job_adapter(a_job)
  155. assert isinstance(outcome, tuple)
  156. assert outcome[0] == a_job.id
  157. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  158. outcome = gui_core_context.job_adapter(a_job)
  159. assert outcome is None
  160. def test_act_on_jobs(self):
  161. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get), patch(
  162. "taipy.gui_core._context.is_deletable", side_effect=mock_is_true
  163. ):
  164. gui_core_context = _GuiCoreContext(Mock())
  165. assign = Mock()
  166. gui_core_context.act_on_jobs(
  167. MockState(assign=assign),
  168. "",
  169. {
  170. "args": [
  171. {"id": [a_job.id], "action": "delete"},
  172. ]
  173. },
  174. )
  175. assign.assert_called_once()
  176. assert assign.call_args.args[0] == "gui_core_js_error"
  177. assert str(assign.call_args.args[1]).find("is not readable.") == -1
  178. assign.reset_mock()
  179. gui_core_context.act_on_jobs(
  180. MockState(assign=assign),
  181. "",
  182. {
  183. "args": [
  184. {"id": [a_job.id], "action": "cancel"},
  185. ]
  186. },
  187. )
  188. assign.assert_called_once()
  189. assert assign.call_args.args[0] == "gui_core_js_error"
  190. assert str(assign.call_args.args[1]).find("is not readable.") == -1
  191. assign.reset_mock()
  192. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  193. gui_core_context.act_on_jobs(
  194. MockState(assign=assign),
  195. "",
  196. {
  197. "args": [
  198. {"id": [a_job.id], "action": "delete"},
  199. ]
  200. },
  201. )
  202. assign.assert_called_once()
  203. assert assign.call_args.args[0] == "gui_core_js_error"
  204. assert str(assign.call_args.args[1]).endswith("is not readable.")
  205. assign.reset_mock()
  206. gui_core_context.act_on_jobs(
  207. MockState(assign=assign),
  208. "",
  209. {
  210. "args": [
  211. {"id": [a_job.id], "action": "cancel"},
  212. ]
  213. },
  214. )
  215. assign.assert_called_once()
  216. assert assign.call_args.args[0] == "gui_core_js_error"
  217. assert str(assign.call_args.args[1]).endswith("is not readable.")
  218. def test_edit_data_node(self):
  219. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  220. gui_core_context = _GuiCoreContext(Mock())
  221. assign = Mock()
  222. gui_core_context.edit_data_node(
  223. MockState(assign=assign),
  224. "",
  225. {
  226. "args": [
  227. {"id": a_datanode.id},
  228. ]
  229. },
  230. )
  231. assign.assert_called_once()
  232. assert assign.call_args.args[0] == "gui_core_dv_error"
  233. assert assign.call_args.args[1] == ""
  234. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  235. assign.reset_mock()
  236. gui_core_context.edit_data_node(
  237. MockState(assign=assign),
  238. "",
  239. {
  240. "args": [
  241. {"id": a_datanode.id},
  242. ]
  243. },
  244. )
  245. assign.assert_called_once()
  246. assert assign.call_args.args[0] == "gui_core_dv_error"
  247. assert str(assign.call_args.args[1]).endswith("is not readable.")
  248. def test_lock_datanode_for_edit(self):
  249. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  250. mockGui = Mock(Gui)
  251. mockGui._get_client_id = lambda: "a_client_id"
  252. gui_core_context = _GuiCoreContext(mockGui)
  253. assign = Mock()
  254. gui_core_context.lock_datanode_for_edit(
  255. MockState(assign=assign),
  256. "",
  257. {
  258. "args": [
  259. {"id": a_datanode.id},
  260. ]
  261. },
  262. )
  263. assign.assert_called_once()
  264. assert assign.call_args.args[0] == "gui_core_dv_error"
  265. assert assign.call_args.args[1] == ""
  266. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  267. assign.reset_mock()
  268. gui_core_context.lock_datanode_for_edit(
  269. MockState(assign=assign),
  270. "",
  271. {
  272. "args": [
  273. {"id": a_datanode.id},
  274. ]
  275. },
  276. )
  277. assign.assert_called_once()
  278. assert assign.call_args.args[0] == "gui_core_dv_error"
  279. assert str(assign.call_args.args[1]).endswith("is not readable.")
  280. def test_get_scenarios_for_owner(self):
  281. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  282. gui_core_context = _GuiCoreContext(Mock())
  283. gui_core_context.get_scenarios_for_owner(a_scenario.id)
  284. mockget.assert_called_once()
  285. mockget.reset_mock()
  286. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  287. gui_core_context.scenario_status_callback(a_scenario.id)
  288. mockget.assert_not_called()
  289. def test_update_data(self):
  290. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  291. mockGui = Mock(Gui)
  292. mockGui._get_client_id = lambda: "a_client_id"
  293. gui_core_context = _GuiCoreContext(mockGui)
  294. assign = Mock()
  295. gui_core_context.update_data(
  296. MockState(assign=assign),
  297. "",
  298. {
  299. "args": [
  300. {"id": a_datanode.id},
  301. ]
  302. },
  303. )
  304. assign.assert_called()
  305. assert assign.call_args_list[0].args[0] == "gui_core_dv_error"
  306. assert assign.call_args_list[0].args[1] == ""
  307. assign.reset_mock()
  308. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  309. gui_core_context.update_data(
  310. MockState(assign=assign),
  311. "",
  312. {
  313. "args": [
  314. {"id": a_datanode.id},
  315. ]
  316. },
  317. )
  318. assign.assert_called_once()
  319. assert assign.call_args.args[0] == "gui_core_dv_error"
  320. assert str(assign.call_args.args[1]).endswith("is not readable.")
  321. def test_tabular_data_edit(self):
  322. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  323. mockGui = Mock(Gui)
  324. mockGui._get_client_id = lambda: "a_client_id"
  325. gui_core_context = _GuiCoreContext(mockGui)
  326. assign = Mock()
  327. gui_core_context.tabular_data_edit(
  328. MockState(assign=assign),
  329. "",
  330. {
  331. "user_data": {"dn_id": a_datanode.id},
  332. },
  333. )
  334. assign.assert_called_once()
  335. assert assign.call_args_list[0].args[0] == "gui_core_dv_error"
  336. assert (
  337. assign.call_args_list[0].args[1]
  338. == "Error updating Datanode tabular value: type does not support at[] indexer."
  339. )
  340. assign.reset_mock()
  341. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  342. gui_core_context.tabular_data_edit(
  343. MockState(assign=assign),
  344. "",
  345. {
  346. "user_data": {"dn_id": a_datanode.id},
  347. },
  348. )
  349. assign.assert_called_once()
  350. assert assign.call_args.args[0] == "gui_core_dv_error"
  351. assert str(assign.call_args.args[1]).endswith("is not readable.")
  352. def test_get_data_node_tabular_data(self):
  353. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  354. gui_core_context = _GuiCoreContext(Mock())
  355. gui_core_context.get_data_node_tabular_data(a_datanode, a_datanode.id)
  356. mockget.assert_called_once()
  357. mockget.reset_mock()
  358. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  359. gui_core_context.get_data_node_tabular_data(a_datanode, a_datanode.id)
  360. mockget.assert_not_called()
  361. def test_get_data_node_tabular_columns(self):
  362. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  363. gui_core_context = _GuiCoreContext(Mock())
  364. gui_core_context.get_data_node_tabular_columns(a_datanode, a_datanode.id)
  365. mockget.assert_called_once()
  366. mockget.reset_mock()
  367. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  368. gui_core_context.get_data_node_tabular_columns(a_datanode, a_datanode.id)
  369. mockget.assert_not_called()
  370. def test_get_data_node_chart_config(self):
  371. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
  372. gui_core_context = _GuiCoreContext(Mock())
  373. gui_core_context.get_data_node_chart_config(a_datanode, a_datanode.id)
  374. mockget.assert_called_once()
  375. mockget.reset_mock()
  376. with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
  377. gui_core_context.get_data_node_chart_config(a_datanode, a_datanode.id)
  378. mockget.assert_not_called()