ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
AbstractFactoryTest.php
Go to the documentation of this file.
1<?php
2
3require_once("libs/composer/vendor/autoload.php");
4
7
18
19 const COMPONENT = 1;
20 const FACTORY = 2;
21
22 /* kitchensink info test configuration:
23 * true = should be there, check
24 * false = may be there, don't check
25 * Notice, some properties (MUST/MUST NOT) will always be checked.
26 */
28 = array('description'
29 => true
30 ,'background'
31 => false
32 ,'context'
33 => true
34 ,'featurewiki'
35 => false
36 ,'javascript'
37 => false
38 ,'rules'
39 => true);
40
41 /* You can overwrite these settings per factory method when using this test
42 * by writing $kitchensink_info_settings. See GlyphFactoryTest for an example.
43 */
44
45
46 // Definitions and Helpers:
47
49 array('purpose', 'composition', 'effect', 'rival');
50
52 array('usage', 'interaction', 'wording', 'style', 'ordering', 'responsiveness',
53 'composition','accessibility');
54
55 final protected function returnsFactory($docstring_data) {
56 return $this->isFactoryName($docstring_data["namespace"]);
57 }
58
59 final protected function returnsComponent($docstring_data) {
60 $reflection = new ReflectionClass($docstring_data["namespace"]);
61 return in_array("ILIAS\\UI\\Component\\Component", $reflection->getInterfaceNames());
62 }
63
64 final protected function isFactoryName($name) {
65 return preg_match("#^(\\\\)?ILIAS\\\\UI\\\\Component\\\\([a-zA-Z]+\\\\)*Factory$#", $name) === 1;
66 }
67
68 final public function buildFactoryReflection() {
69 return new ReflectionClass($this->factory_title);
70 }
71
72 final public function methods_provider() {
73 $reflection = $this->buildFactoryReflection();
74 return array_map(function($element) {
75 return array($element, $element->getName());
76 }, $reflection->getMethods());
77 }
78
79 // Setup
80
81 public function setUp() {
82 $this->yaml_parser = new Crawler\EntriesYamlParser();
83 $this->reflection = $this->buildFactoryReflection();
84 }
85
86 public function test_proper_namespace() {
87 $message = "TODO: Put your factory into the proper namespace.";
88 $this->assertRegExp
89 ( "#^ILIAS\\\\UI\\\\Component.#"
90 , $this->reflection->getNamespaceName()
91 , $message
92 );
93 }
94
95 public function test_proper_name() {
96 $name = $this->reflection->getName();
97 $message = "TODO: Give your factory a proper name.";
98 $this->assertTrue
99 ( $this->isFactoryName($name)
100 , $message
101 );
102 }
103
109 final public function test_check_yaml_extraction($method_reflection, $name) {
110 try {
111 //Todo (TA) this is not pretty. We should think about using only reflection in the parser as well.
112 $function_name_string = "\n public function ".$method_reflection->getName()."()";
113 $docstring_data = $this->yaml_parser->parseArrayFromString(
114 $method_reflection->getDocComment().$function_name_string);
115 $this->assertTrue(true);
116 }
118 $message = "TODO ($name): fix parse error in kitchen sink yaml: ".$e->getMessage();
119 $this->assertTrue(false, $message);
120 }
121 $this->assertCount(1, $docstring_data);
122 return $docstring_data[0];
123 }
124
130 final public function test_return_type($method_reflection, $name) {
131 $message = "TODO ($name): fix return type, it must be a factory or a component.";
132 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
133 if ($this->returnsFactory($docstring_data)) {
134 $this->assertTrue(true);
135 }
136 elseif ($this->returnsComponent($docstring_data)) {
137 $this->assertTrue(true);
138 }
139 else {
140 $this->assertTrue(false, $message);
141 }
142 }
143
149 final public function test_factory_method_name_compatible_docstring($method_reflection, $name) {
150 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
151 $this->test_return_type($method_reflection, $name);
152
153 $return_doc = $docstring_data["namespace"];
154 $name_uppercase = ucwords($name);
155 $regex_factory_namespace = $this->get_regex_factory_namespace();
156 $regex_head = "#^(\\\\?)$regex_factory_namespace";
157
158 $message = "TODO ($name): fix @return, it does not match the method name.";
159 if ($this->returnsFactory($docstring_data)) {
160 $this->assertRegExp
161 ( "$regex_head\\\\$name_uppercase\\\\Factory$#"
162 , $return_doc
163 , $message
164 );
165 }
166 else { // returnsComponent
167 // Every component MUST be described by a single interface, where the name of
168 // the interface corresponds to the name of the component.
169 $standard_pattern = "$regex_head\\\\$name_uppercase#";
170 $standard_case = preg_match($standard_pattern, $return_doc);
171
172 // unless they only differ in a type and share a common prefix to their pathes.
173 $namespace_parts = explode("\\", $this->reflection->getNamespaceName());
174 $typediff_only_pattern = "$regex_head\\\\".array_pop($namespace_parts)."#";
175 $typediff_only_case = preg_match($typediff_only_pattern, $return_doc);
176
177 $this->assertTrue($standard_case || $typediff_only_case, $message);
178 }
179 }
180
181 protected function get_regex_factory_namespace() {
182 return str_replace("\\", "\\\\", $this->reflection->getNamespaceName());
183 }
184
190 final public function test_method_params($method_reflection, $name) {
191 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
192 if($this->returnsFactory($docstring_data)) {
193 $message = "TODO ($name): remove params from method that returns Factory.";
194 $this->assertEquals(0, $method_reflection->getNumberOfParameters(), $message);
195 }
196 }
197
198 // Common rules for all factory methods, regardless whether they return other
199 // factories or components.
200
204 final public function test_kitchensink_info_description($method_reflection, $name) {
205 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
206 $kitchensink_info_settings = $this->kitchensink_info_settings_merged_with_defaults($name);
207
208 if($kitchensink_info_settings['description']) {
209 $message = "TODO ($name): add a description.";
210 $this->assertArrayHasKey('description', $docstring_data, $message);
211
212 $desc_fields = implode(", ", $this->description_categories);
213 $message = "TODO ($name): the description field should at least contain one of these: $desc_fields.";
214 $existing_keys = array_keys($docstring_data["description"]);
215 $existing_expected_keys = array_intersect($this->description_categories, $existing_keys);
216 $this->assertGreaterThanOrEqual
217 ( 1
218 , $existing_expected_keys
219 , $message
220 );
221 }
222 }
223
227 final public function test_kitchensink_info_background($method_reflection, $name) {
228 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
229 $kitchensink_info_settings = $this->kitchensink_info_settings_merged_with_defaults($name);
230
231 if($kitchensink_info_settings['background']) {
232 $message = "TODO ($name): add a background field.";
233 $this->assertArrayHasKey('background', $docstring_data, $message);
234 }
235 }
236
240 final public function test_kitchensink_info_featurewiki($method_reflection, $name) {
241 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
242 $kitchensink_info_settings = $this->kitchensink_info_settings_merged_with_defaults($name);
243
244 if($kitchensink_info_settings['featurewiki']) {
245 $message = "TODO ($name): add a featurewiki field.";
246 $this->assertArrayHasKey('featurewiki', $docstring_data, $message);
247 }
248 }
249
253 final public function test_kitchensink_info_javascript($method_reflection, $name) {
254 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
255 $kitchensink_info_settings = $this->kitchensink_info_settings_merged_with_defaults($name);
256
257 if($kitchensink_info_settings['javascript']) {
258 $message = "TODO ($name): add a javascript field.";
259 $this->assertArrayHasKey('javascript' ,$docstring_data, $message);
260 }
261 }
262
266 final public function test_kitchensink_info_rules($method_reflection, $name) {
267 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
268 $kitchensink_info_settings = $this->kitchensink_info_settings_merged_with_defaults($name);
269
270 if($kitchensink_info_settings['rules']) {
271 $message = "TODO ($name): add a rules field.";
272 $this->assertArrayHasKey('rules', $docstring_data, $message);
273
274 $rules_fields = implode(", ", $this->rules_categories);
275 $message = "TODO ($name): the rules field should at least contain one of these: $rules_fields.";
276 $existing_keys = array_keys($docstring_data["rules"]);
277 $existing_expected_keys = array_intersect($this->rules_categories, $existing_keys);
278 $this->assertGreaterThanOrEqual
279 ( 1
280 , $existing_expected_keys
281 , $message
282 );
283 }
284 }
285
289 final public function test_kitchensink_info_context($method_reflection, $name) {
290 $docstring_data = $this->test_check_yaml_extraction($method_reflection, $name);
291 $kitchensink_info_settings = $this->kitchensink_info_settings_merged_with_defaults($name);
292
293 // Special rules for factory methods:
294 if ($this->returnsFactory($docstring_data)) {
295 $message = "TODO ($name): remove 'context' field, method returns a factory.";
296 $this->assertArrayNotHasKey("context", $docstring_data, $message);
297 }
298 else { // returnsComponent
299 if ($kitchensink_info_settings["context"]) {
300 $message = "TODO ($name): factory method returning component should have context field. Add it.";
301 $this->assertArrayHasKey("context", $docstring_data, $message);
302 }
303 }
304 }
305
307 if (array_key_exists($name, $this->kitchensink_info_settings)) {
308 return array_merge
309 ( $this->kitchensink_info_settings_default
310 , $this->kitchensink_info_settings[$name]
311 );
312 }
313 else {
315 }
316 }
317}
Defines tests every SHOULD pass UI-factory.
test_kitchensink_info_javascript($method_reflection, $name)
@dataProvider methods_provider
test_return_type($method_reflection, $name)
Tests whether the method either returns a factory or a component.
test_kitchensink_info_background($method_reflection, $name)
@dataProvider methods_provider
returnsFactory($docstring_data)
test_factory_method_name_compatible_docstring($method_reflection, $name)
Tests whether the method name matches the.
test_kitchensink_info_context($method_reflection, $name)
@dataProvider methods_provider
test_check_yaml_extraction($method_reflection, $name)
Tests whether the YAML Kitchen Sink info can be parsed.
test_kitchensink_info_rules($method_reflection, $name)
@dataProvider methods_provider
test_kitchensink_info_featurewiki($method_reflection, $name)
@dataProvider methods_provider
kitchensink_info_settings_merged_with_defaults($name)
returnsComponent($docstring_data)
test_kitchensink_info_description($method_reflection, $name)
@dataProvider methods_provider
test_method_params($method_reflection, $name)
Tests whether methods returning factories have no parameters.
An exception for terminatinating execution or to throw for unit testing.