ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
AbstractFactoryTest.php
Go to the documentation of this file.
1 <?php
2 
3 require_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 
306  final public function kitchensink_info_settings_merged_with_defaults($name) {
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 }
test_method_params($method_reflection, $name)
Tests whether methods returning factories have no parameters.
test_return_type($method_reflection, $name)
Tests whether the method either returns a factory or a component.
test_kitchensink_info_context($method_reflection, $name)
methods_provider
test_kitchensink_info_description($method_reflection, $name)
methods_provider
test_check_yaml_extraction($method_reflection, $name)
Tests whether the YAML Kitchen Sink info can be parsed.
test_kitchensink_info_featurewiki($method_reflection, $name)
methods_provider
test_kitchensink_info_javascript($method_reflection, $name)
methods_provider
returnsFactory($docstring_data)
test_factory_method_name_compatible_docstring($method_reflection, $name)
Tests whether the method name matches the.
Defines tests every SHOULD pass UI-factory.
test_kitchensink_info_background($method_reflection, $name)
methods_provider
kitchensink_info_settings_merged_with_defaults($name)
Create styles array
The data for the language used.
test_kitchensink_info_rules($method_reflection, $name)
methods_provider
returnsComponent($docstring_data)