blob: 7b23027fe7ec28ea37f14af94401f0ffe1cd3805 [file] [log] [blame]
Philipp Le4071d912022-04-26 22:02:43 +02001# SPDX-License-Identifier: MPL-2.0
2# Copyright (c) 2022 Philipp Le <philipp@philipple.de>.
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this
5# file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7import unittest
8from typing import List
9from pydantic import conint, confloat
Philipp Lecefab922022-04-26 22:06:33 +020010from tkinter import Tk, ttk
Philipp Le4071d912022-04-26 22:02:43 +020011from enum import IntEnum
Philipp Lecefab922022-04-26 22:06:33 +020012import toml
Philipp Le4071d912022-04-26 22:02:43 +020013
14from dcs.config.store import Store, ConfigObject, ConfigControlFrame
15from dcs.config.ui import ui_create
16
17
18class ExampleSubFrame(ConfigControlFrame):
Philipp Lecefab922022-04-26 22:06:33 +020019 wdg_id: ttk.Spinbox
Philipp Le4071d912022-04-26 22:02:43 +020020
21
22@ui_create
23class ExampleSub(ConfigObject):
24 id: conint(ge=0, lt=10000) = 1
25 title: str = 'test'
26
27 def make_config_widget(self, parent: ttk.Widget) -> ConfigControlFrame:
28 frm = ExampleSubFrame(parent)
Philipp Lecefab922022-04-26 22:06:33 +020029 frm.pack()
30 ttk.Label(frm, text="Id:").grid(row=0, column=0)
31 frm.wdg_id = self.ui_create_id(frm)
32 frm.wdg_id.grid(row=0, column=1)
Philipp Le4071d912022-04-26 22:02:43 +020033 return frm
34
35
36
37class ExampleIntEnum(IntEnum):
38 Option1 = 1
39 Option2 = 2
40
41
42@ui_create
43class ExampleConfig(ConfigObject):
44 _KEY = 'example'
45 id: conint(ge=0, lt=10) = 1
46 name: str = 'Hello'
47 sub: List[ExampleSub] = [
48 ExampleSub(id=1, title='item 1'),
49 ExampleSub(id=2, title='item 2'),
50 ]
51 int_option: ExampleIntEnum = ExampleIntEnum.Option2
52 flt: confloat(ge=0.0, lt=10.0, multiple_of=0.01) = 0.12
53
54
55class UITest(unittest.TestCase):
56 def test_deserialize(self):
57 in_data = {
58 'example': {
59 'id': 0,
60 'name': 'Test1',
61 'sub': [
62 {
63 'id': 0,
64 'title': 'Title1',
65 },
66 {
67 'id': 1,
68 'title': 'Title2',
69 },
70 ]
71 }
72 }
73
74 loaded_store = Store.load_obj(in_data, 'default')
75
76 store = Store.get_instance('default')
77 self.assertEqual(id(loaded_store), id(store))
78
79 cfg: ExampleConfig = store.get_config(ExampleConfig)
80 self.assertIn('ui_create_id', dir(cfg))
Philipp Lecefab922022-04-26 22:06:33 +020081
82
83class UIInteractiveTest(unittest.TestCase):
84 def setUp(self) -> None:
85 self.root = Tk()
86 self.frm = ttk.Frame(self.root, padding=10)
87 self.frm.pack()
88
89 self.store = Store.new('default')
90
91 def _print_cfg(self) -> None:
92 print(repr(self.store.get_config(ExampleConfig)))
93 print(toml.dumps(self.store.dump_obj()))
94 #print(self.store.get_config(ExampleConfig).json())
95
96 def _run_ui(self) -> bool:
97 self.res = False
98
99 def act(ok: bool) -> None:
100 self.root.destroy()
101 self.res = ok
102
103 self.ok_btn = ttk.Button(self.root, text='Test OK', command=lambda: act(True))
104 self.ok_btn.pack()
105 self.ok_fail = ttk.Button(self.root, text='Test Fail', command=lambda: act(False))
106 self.ok_fail.pack()
107
108 self.root.mainloop()
109
110 return self.res
111
112 def test_int_widget(self):
113 cfg = self.store.get_config(ExampleConfig)
114 wdg = cfg.ui_create_id(self.frm)
115 wdg.pack()
116 wdg.listen_change(lambda x, y, z: self._print_cfg())
117
118 self.assertTrue(self._run_ui())
119
120 def test_float_widget(self):
121 cfg = self.store.get_config(ExampleConfig)
122 wdg = cfg.ui_create_flt(self.frm)
123 wdg.pack()
124 wdg.listen_change(lambda x, y, z: self._print_cfg())
125
126 self.assertTrue(self._run_ui())