sdui-python 1.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bin/component-cli.js +94 -0
- bin/serialize-cli.js +91 -0
- bin/type-check-cli.js +103 -0
- examples/__init__.py +0 -0
- examples/basic_usage.py +124 -0
- examples/variant_driven_examples.py +260 -0
- sdui_python/__init__.py +296 -0
- sdui_python/cli.py +87 -0
- sdui_python-1.0.7.dist-info/METADATA +693 -0
- sdui_python-1.0.7.dist-info/RECORD +29 -0
- sdui_python-1.0.7.dist-info/WHEEL +5 -0
- sdui_python-1.0.7.dist-info/entry_points.txt +4 -0
- sdui_python-1.0.7.dist-info/top_level.txt +4 -0
- tests/README.md +29 -0
- tests/__init__.py +0 -0
- tests/test_action_serialization.py +184 -0
- tests/test_action_state_validation.py +139 -0
- tests/test_all.py +238 -0
- tests/test_common_properties.py +43 -0
- tests/test_component_registry.py +167 -0
- tests/test_component_types.py +359 -0
- tests/test_direct_validation.py +212 -0
- tests/test_error_handling.py +244 -0
- tests/test_functionality.py +257 -0
- tests/test_integration_scenarios.py +721 -0
- tests/test_property_rendering.py +171 -0
- tests/test_sdui_toggle.py +161 -0
- tests/test_template_expressions.py +249 -0
- tests/test_todo_app.py +95 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Comprehensive functionality tests for the SDUI Python package
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import unittest
|
|
7
|
+
import json
|
|
8
|
+
from sdui_python import (
|
|
9
|
+
get_available_components,
|
|
10
|
+
validate_from_source,
|
|
11
|
+
serialize_from_source,
|
|
12
|
+
validate_and_serialize,
|
|
13
|
+
get_all_common_properties
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
class TestComponentRegistryFunctionality(unittest.TestCase):
|
|
17
|
+
"""Test component registry functionality"""
|
|
18
|
+
|
|
19
|
+
def test_get_available_components(self):
|
|
20
|
+
"""Test getting available components with their properties"""
|
|
21
|
+
components = get_available_components()
|
|
22
|
+
self.assertIsInstance(components, list)
|
|
23
|
+
self.assertGreater(len(components), 0)
|
|
24
|
+
|
|
25
|
+
# Check that each component has the required structure
|
|
26
|
+
for component in components:
|
|
27
|
+
self.assertIn("name", component)
|
|
28
|
+
self.assertIn("props", component)
|
|
29
|
+
|
|
30
|
+
# Check that props is a dictionary of property info objects
|
|
31
|
+
self.assertIsInstance(component["props"], dict)
|
|
32
|
+
|
|
33
|
+
# Check for specific components
|
|
34
|
+
if component["name"] == "SduiButton":
|
|
35
|
+
self.assertIn("text", component["props"])
|
|
36
|
+
# Check that each property has type info
|
|
37
|
+
self.assertIn("type", component["props"]["text"])
|
|
38
|
+
# Check for disabled property (it's optional, so just check if it exists)
|
|
39
|
+
# Note: disabled property is in the extends array, not in props directly
|
|
40
|
+
elif component["name"] == "SduiText":
|
|
41
|
+
self.assertIn("text", component["props"])
|
|
42
|
+
# Check that each property has type info
|
|
43
|
+
self.assertIn("type", component["props"]["text"])
|
|
44
|
+
# Check for font property (it's in the extends array, not in props directly)
|
|
45
|
+
|
|
46
|
+
def test_validate_from_source(self):
|
|
47
|
+
"""Test component structure validation"""
|
|
48
|
+
# Valid component
|
|
49
|
+
valid_component = """
|
|
50
|
+
function MyComponent() {
|
|
51
|
+
return <SduiText text="Hello World" />;
|
|
52
|
+
}
|
|
53
|
+
"""
|
|
54
|
+
result = validate_from_source(valid_component)
|
|
55
|
+
self.assertTrue(result["isValid"])
|
|
56
|
+
self.assertEqual(len(result["errors"]), 0)
|
|
57
|
+
|
|
58
|
+
# Invalid component
|
|
59
|
+
invalid_component = """
|
|
60
|
+
function MyComponent() {
|
|
61
|
+
return <SduiUnknownComponent />;
|
|
62
|
+
}
|
|
63
|
+
"""
|
|
64
|
+
result = validate_from_source(invalid_component)
|
|
65
|
+
self.assertFalse(result["isValid"])
|
|
66
|
+
self.assertGreater(len(result["errors"]), 0)
|
|
67
|
+
|
|
68
|
+
class TestComponentValidationFunctionality(unittest.TestCase):
|
|
69
|
+
"""Test component validation functionality"""
|
|
70
|
+
|
|
71
|
+
def test_validate_from_source_complex(self):
|
|
72
|
+
"""Test component structure validation with complex components"""
|
|
73
|
+
# Valid complex component
|
|
74
|
+
complex_component = """
|
|
75
|
+
function MyComponent() {
|
|
76
|
+
return (
|
|
77
|
+
<SduiVStack spacing={16}>
|
|
78
|
+
<SduiText text="Hello" />
|
|
79
|
+
<SduiButton text="Click" />
|
|
80
|
+
</SduiVStack>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
"""
|
|
84
|
+
result = validate_from_source(complex_component)
|
|
85
|
+
self.assertTrue(result["isValid"])
|
|
86
|
+
self.assertEqual(len(result["errors"]), 0)
|
|
87
|
+
|
|
88
|
+
# Component with nested children
|
|
89
|
+
nested_component = """
|
|
90
|
+
function MyComponent() {
|
|
91
|
+
return (
|
|
92
|
+
<SduiVStack spacing={16}>
|
|
93
|
+
<SduiHStack spacing={8}>
|
|
94
|
+
<SduiButton text="Save" />
|
|
95
|
+
<SduiButton text="Cancel" />
|
|
96
|
+
</SduiHStack>
|
|
97
|
+
</SduiVStack>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
"""
|
|
101
|
+
result = validate_from_source(nested_component)
|
|
102
|
+
self.assertTrue(result["isValid"])
|
|
103
|
+
self.assertEqual(len(result["errors"]), 0)
|
|
104
|
+
|
|
105
|
+
class TestSerializationFunctionality(unittest.TestCase):
|
|
106
|
+
"""Test serialization functionality"""
|
|
107
|
+
|
|
108
|
+
def test_serialize_from_source_simple(self):
|
|
109
|
+
"""Test serialize_from_source with a simple component"""
|
|
110
|
+
source_code = """
|
|
111
|
+
function MyComponent() {
|
|
112
|
+
return <SduiText text="Hello World" font="headline" />;
|
|
113
|
+
}
|
|
114
|
+
"""
|
|
115
|
+
result = serialize_from_source(source_code)
|
|
116
|
+
self.assertIsInstance(result, dict)
|
|
117
|
+
self.assertIn("type", result)
|
|
118
|
+
self.assertEqual(result["type"], "SduiText")
|
|
119
|
+
self.assertIn("props", result)
|
|
120
|
+
self.assertIn("text", result["props"])
|
|
121
|
+
self.assertEqual(result["props"]["text"], "Hello World")
|
|
122
|
+
# Note: font is a common property that is applied via modifiers, not directly in props
|
|
123
|
+
|
|
124
|
+
def test_serialize_from_source_complex(self):
|
|
125
|
+
"""Test serialize_from_source with a complex component"""
|
|
126
|
+
source_code = """
|
|
127
|
+
function ComplexComponent() {
|
|
128
|
+
return (
|
|
129
|
+
<SduiVStack spacing={16}>
|
|
130
|
+
<SduiText text="Welcome" font="headline" />
|
|
131
|
+
<SduiHStack spacing={8}>
|
|
132
|
+
<SduiButton text="Save" />
|
|
133
|
+
<SduiButton text="Cancel" />
|
|
134
|
+
</SduiHStack>
|
|
135
|
+
</SduiVStack>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
"""
|
|
139
|
+
result = serialize_from_source(source_code)
|
|
140
|
+
self.assertIsInstance(result, dict)
|
|
141
|
+
self.assertIn("type", result)
|
|
142
|
+
self.assertEqual(result["type"], "SduiVStack")
|
|
143
|
+
self.assertIn("props", result)
|
|
144
|
+
self.assertIn("spacing", result["props"])
|
|
145
|
+
self.assertEqual(result["props"]["spacing"], 16)
|
|
146
|
+
self.assertIn("children", result)
|
|
147
|
+
self.assertIsInstance(result["children"], list)
|
|
148
|
+
self.assertEqual(len(result["children"]), 2)
|
|
149
|
+
|
|
150
|
+
# Check first child (SduiText)
|
|
151
|
+
text_child = result["children"][0]
|
|
152
|
+
self.assertEqual(text_child["type"], "SduiText")
|
|
153
|
+
self.assertEqual(text_child["props"]["text"], "Welcome")
|
|
154
|
+
|
|
155
|
+
# Check second child (SduiHStack)
|
|
156
|
+
hstack_child = result["children"][1]
|
|
157
|
+
self.assertEqual(hstack_child["type"], "SduiHStack")
|
|
158
|
+
self.assertEqual(hstack_child["props"]["spacing"], 8)
|
|
159
|
+
self.assertIn("children", hstack_child)
|
|
160
|
+
self.assertEqual(len(hstack_child["children"]), 2)
|
|
161
|
+
|
|
162
|
+
# Check buttons in HStack
|
|
163
|
+
button1 = hstack_child["children"][0]
|
|
164
|
+
button2 = hstack_child["children"][1]
|
|
165
|
+
self.assertEqual(button1["type"], "SduiButton")
|
|
166
|
+
self.assertEqual(button1["props"]["text"], "Save")
|
|
167
|
+
self.assertEqual(button2["type"], "SduiButton")
|
|
168
|
+
self.assertEqual(button2["props"]["text"], "Cancel")
|
|
169
|
+
|
|
170
|
+
def test_serialize_from_source_empty_source(self):
|
|
171
|
+
"""Test serialize_from_source with empty source code"""
|
|
172
|
+
result = serialize_from_source("")
|
|
173
|
+
self.assertIsNone(result)
|
|
174
|
+
|
|
175
|
+
result = serialize_from_source(" ")
|
|
176
|
+
self.assertIsNone(result)
|
|
177
|
+
|
|
178
|
+
class TestValidateAndSerializeFunctionality(unittest.TestCase):
|
|
179
|
+
"""Test validate and serialize functionality"""
|
|
180
|
+
|
|
181
|
+
def test_validate_and_serialize_valid(self):
|
|
182
|
+
"""Test validate_and_serialize with a valid component"""
|
|
183
|
+
component = """
|
|
184
|
+
function MyComponent() {
|
|
185
|
+
return <SduiText text="Hello World" />;
|
|
186
|
+
}
|
|
187
|
+
"""
|
|
188
|
+
result = validate_and_serialize(component)
|
|
189
|
+
self.assertIsInstance(result, dict)
|
|
190
|
+
self.assertIn("isValid", result)
|
|
191
|
+
self.assertTrue(result["isValid"])
|
|
192
|
+
self.assertIn("errors", result)
|
|
193
|
+
self.assertEqual(len(result["errors"]), 0)
|
|
194
|
+
self.assertIn("serialized", result)
|
|
195
|
+
self.assertIsInstance(result["serialized"], dict)
|
|
196
|
+
self.assertEqual(result["serialized"]["type"], "SduiText")
|
|
197
|
+
self.assertEqual(result["serialized"]["props"]["text"], "Hello World")
|
|
198
|
+
|
|
199
|
+
# Test with an invalid component
|
|
200
|
+
component = """
|
|
201
|
+
function MyComponent() {
|
|
202
|
+
return <UnknownComponent />;
|
|
203
|
+
}
|
|
204
|
+
"""
|
|
205
|
+
result = validate_and_serialize(component)
|
|
206
|
+
self.assertIsInstance(result, dict)
|
|
207
|
+
self.assertIn("isValid", result)
|
|
208
|
+
self.assertFalse(result["isValid"])
|
|
209
|
+
self.assertIn("errors", result)
|
|
210
|
+
self.assertGreater(len(result["errors"]), 0)
|
|
211
|
+
self.assertIn("serialized", result)
|
|
212
|
+
self.assertIsNone(result["serialized"])
|
|
213
|
+
|
|
214
|
+
def test_validate_and_serialize_type_error(self):
|
|
215
|
+
"""Test validate_and_serialize with incorrect input type"""
|
|
216
|
+
result = validate_and_serialize({"type": "SduiText", "props": {"text": "Hello"}})
|
|
217
|
+
self.assertIsInstance(result, dict)
|
|
218
|
+
self.assertIn("isValid", result)
|
|
219
|
+
self.assertFalse(result["isValid"])
|
|
220
|
+
self.assertIn("errors", result)
|
|
221
|
+
self.assertGreater(len(result["errors"]), 0)
|
|
222
|
+
self.assertIn("serialized", result)
|
|
223
|
+
self.assertIsNone(result["serialized"])
|
|
224
|
+
|
|
225
|
+
class TestCommonPropertiesFunctionality(unittest.TestCase):
|
|
226
|
+
"""Test common properties functionality"""
|
|
227
|
+
|
|
228
|
+
def test_get_all_common_properties(self):
|
|
229
|
+
"""Test getting all common properties"""
|
|
230
|
+
common_properties = get_all_common_properties()
|
|
231
|
+
self.assertIsInstance(common_properties, dict)
|
|
232
|
+
self.assertGreater(len(common_properties), 0)
|
|
233
|
+
|
|
234
|
+
# Check for some expected common properties
|
|
235
|
+
self.assertIn("padding", common_properties)
|
|
236
|
+
self.assertIn("frame", common_properties)
|
|
237
|
+
self.assertIn("background", common_properties)
|
|
238
|
+
self.assertIn("foregroundColor", common_properties)
|
|
239
|
+
self.assertIn("font", common_properties)
|
|
240
|
+
self.assertIn("fontWeight", common_properties)
|
|
241
|
+
|
|
242
|
+
# Check that each property has the required structure
|
|
243
|
+
for prop_name, prop_info in common_properties.items():
|
|
244
|
+
self.assertIsInstance(prop_info, dict)
|
|
245
|
+
self.assertIn("type", prop_info)
|
|
246
|
+
self.assertIn("description", prop_info)
|
|
247
|
+
# Optional fields
|
|
248
|
+
if "optional" in prop_info:
|
|
249
|
+
self.assertIsInstance(prop_info["optional"], bool)
|
|
250
|
+
if "defaultValue" in prop_info:
|
|
251
|
+
# defaultValue can be any type
|
|
252
|
+
pass
|
|
253
|
+
if "enumValues" in prop_info:
|
|
254
|
+
self.assertIsInstance(prop_info["enumValues"], list)
|
|
255
|
+
|
|
256
|
+
if __name__ == "__main__":
|
|
257
|
+
unittest.main()
|