Civi\Afform\Symbols - Add unit test. Define behavior for Angular exprs.
authorTim Otten <totten@civicrm.org>
Sat, 19 Oct 2019 01:30:14 +0000 (18:30 -0700)
committerCiviCRM <info@civicrm.org>
Wed, 16 Sep 2020 02:13:19 +0000 (19:13 -0700)
ext/afform/core/Civi/Afform/Symbols.php
ext/afform/core/tests/phpunit/Civi/Afform/SymbolsTest.php [new file with mode: 0644]

index b933afb11f4341686cf5c61519bfea4a29c62b0e..f816a3c18a6e3f9e5b1f5d11a22c8c8d0fdf7e4a 100644 (file)
@@ -50,7 +50,7 @@ class Symbols {
       self::increment($this->attributes, $node->nodeName);
 
       if ($node->nodeName === 'class') {
-        $classes = explode(' ', $node->nodeValue);
+        $classes = $this->parseClasses($node->nodeValue);
         foreach ($classes as $class) {
           self::increment($this->classes, $class);
         }
@@ -58,6 +58,26 @@ class Symbols {
     }
   }
 
+  /**
+   * @param string $expr
+   *   Ex: 'crm-icon fa-mail'
+   * @return array
+   *   Ex: ['crm-icon', 'fa-mail']
+   */
+  protected function parseClasses($expr) {
+    if ($expr === '' || $expr === NULL || $expr === FALSE) {
+      return [];
+    }
+    if (strpos($expr, '{{') === FALSE) {
+      return explode(' ', $expr);
+    }
+    if (preg_match_all(';([a-zA-Z\-_]+|\{\{.*\}\}) ;U', "$expr ", $m)) {
+      return $m[1];
+    }
+    error_log("Failed to parse CSS classes: $expr");
+    return [];
+  }
+
   private static function increment(&$arr, $key) {
     if (!isset($arr[$key])) {
       $arr[$key] = 0;
diff --git a/ext/afform/core/tests/phpunit/Civi/Afform/SymbolsTest.php b/ext/afform/core/tests/phpunit/Civi/Afform/SymbolsTest.php
new file mode 100644 (file)
index 0000000..8074fc4
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+namespace Civi\Afform;
+
+use Civi\Test\HeadlessInterface;
+use Civi\Test\TransactionalInterface;
+
+/**
+ * @group headless
+ */
+class SymbolsTest extends \PHPUnit\Framework\TestCase implements HeadlessInterface, TransactionalInterface {
+
+  /**
+   * Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
+   *
+   * See: https://github.com/civicrm/org.civicrm.testapalooza/blob/master/civi-test.md
+   *
+   * @throws \CRM_Extension_Exception_ParseException
+   */
+  public function setUpHeadless() {
+    return \Civi\Test::headless()->installMe(__DIR__)->apply();
+  }
+
+  public function getExamples() {
+    $exs = [];
+    $exs[] = [
+      '<div/>',
+      [
+        'e' => ['div' => 1, 'body' => 1],
+        'a' => [],
+        'c' => [],
+      ],
+    ];
+    $exs[] = [
+      '<my-tabset><my-tab id="1"/><my-tab id="2">foo</my-tab><my-tab id="3">bar</my-tab></my-tabset>',
+      [
+        'e' => ['my-tabset' => 1, 'my-tab' => 3, 'body' => 1],
+        'a' => ['id' => 3],
+        'c' => [],
+      ],
+    ];
+    $exs[] = [
+      '<div class="my-parent"><div class="my-child"><img class="special" src="foo.png"/></div></div>',
+      [
+        'e' => ['div' => 2, 'img' => 1, 'body' => 1],
+        'a' => ['class' => 3, 'src' => 1],
+        'c' => [
+          'my-parent' => 1,
+          'my-child' => 1,
+          'special' => 1,
+        ],
+      ],
+    ];
+    $exs[] = [
+      '<div class="my-parent foo bar">a<div class="my-child whiz bang {{ghost + stuff}} last">b</div>c</div>',
+      [
+        'e' => ['div' => 2, 'body' => 1],
+        'a' => ['class' => 2],
+        'c' => [
+          'my-parent' => 1,
+          'my-child' => 1,
+          'foo' => 1,
+          'bar' => 1,
+          'whiz' => 1,
+          'bang' => 1,
+          '{{ghost + stuff}}' => 1,
+          'last' => 1,
+        ],
+      ],
+    ];
+    $exs[] = [
+      '<div class="{{make[\'cheese\']}} {{ghost + stuff}} {{a}}_{{b}}"/>',
+      [
+        'e' => ['div' => 1, 'body' => 1],
+        'a' => ['class' => 1],
+        'c' => [
+          '{{ghost + stuff}}' => 1,
+          '{{make[\'cheese\']}}' => 1,
+          '{{a}}_{{b}}' => 1,
+        ],
+      ],
+    ];
+
+    return $exs;
+  }
+
+  /**
+   * @param string $html
+   * @param array $expect
+   *   List of expected symbol counts, by type.
+   *   Types are (e)lement, (a)ttribute, (c)lass
+   * @dataProvider getExamples
+   */
+  public function testSymbols($html, $expect) {
+    $expectDefaults = ['e' => [], 'a' => [], 'c' => []];
+    $expect = array_merge($expectDefaults, $expect);
+    $actual = Symbols::scan($html);
+
+    $this->assertEquals($expect['e'], $actual->elements);
+    $this->assertEquals($expect['a'], $actual->attributes);
+    $this->assertEquals($expect['c'], $actual->classes);
+  }
+
+}