]> BookStack Code Mirror - bookstack/blobdiff - tests/Entity/TagTest.php
Merge pull request #4021 from BookStackApp/laravel9
[bookstack] / tests / Entity / TagTest.php
index b1217f9594070062498361755eb3893f57a9d29f..7e667495908d2dbf62e862a77952533841c5d056 100644 (file)
@@ -1,4 +1,6 @@
-<?php namespace Tests\Entity;
+<?php
+
+namespace Tests\Entity;
 
 use BookStack\Actions\Tag;
 use BookStack\Entities\Models\Entity;
@@ -7,7 +9,6 @@ use Tests\TestCase;
 
 class TagTest extends TestCase
 {
-
     protected $defaultTagCount = 20;
 
     /**
@@ -18,10 +19,11 @@ class TagTest extends TestCase
         $entity = $class::first();
 
         if (is_null($tags)) {
-            $tags = factory(Tag::class, $this->defaultTagCount)->make();
+            $tags = Tag::factory()->count($this->defaultTagCount)->make();
         }
 
         $entity->tags()->saveMany($tags);
+
         return $entity;
     }
 
@@ -29,72 +31,185 @@ class TagTest extends TestCase
     {
         // Create some tags with similar names to test with
         $attrs = collect();
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'city']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans']));
-        $page = $this->getEntityWithTags(Page::class, $attrs);
-
-        $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->seeJsonEquals([]);
-        $this->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country', 'county']);
-        $this->get('/ajax/tags/suggest/names?search=cou')->seeJsonEquals(['country', 'county']);
-        $this->get('/ajax/tags/suggest/names?search=pla')->seeJsonEquals(['planet', 'plans']);
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'city']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'county']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'planet']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'plans']));
+        $page = $this->getEntityWithTags(Page::class, $attrs->all());
+
+        $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->assertSimilarJson([]);
+        $this->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country', 'county']);
+        $this->get('/ajax/tags/suggest/names?search=cou')->assertSimilarJson(['country', 'county']);
+        $this->get('/ajax/tags/suggest/names?search=pla')->assertSimilarJson(['planet', 'plans']);
     }
 
     public function test_tag_value_suggestions()
     {
         // Create some tags with similar values to test with
         $attrs = collect();
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country', 'value' => 'cats']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color', 'value' => 'cattery']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'city', 'value' => 'castle']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county', 'value' => 'dog']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet', 'value' => 'catapult']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans', 'value' => 'dodgy']));
-        $page = $this->getEntityWithTags(Page::class, $attrs);
-
-        $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->seeJsonEquals([]);
-        $this->get('/ajax/tags/suggest/values?search=cat')->seeJsonEquals(['cats', 'cattery', 'catapult']);
-        $this->get('/ajax/tags/suggest/values?search=do')->seeJsonEquals(['dog', 'dodgy']);
-        $this->get('/ajax/tags/suggest/values?search=cas')->seeJsonEquals(['castle']);
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country', 'value' => 'cats']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color', 'value' => 'cattery']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'city', 'value' => 'castle']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'county', 'value' => 'dog']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'planet', 'value' => 'catapult']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'plans', 'value' => 'dodgy']));
+        $page = $this->getEntityWithTags(Page::class, $attrs->all());
+
+        $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->assertSimilarJson([]);
+        $this->get('/ajax/tags/suggest/values?search=cat')->assertSimilarJson(['cats', 'cattery', 'catapult']);
+        $this->get('/ajax/tags/suggest/values?search=do')->assertSimilarJson(['dog', 'dodgy']);
+        $this->get('/ajax/tags/suggest/values?search=cas')->assertSimilarJson(['castle']);
     }
 
     public function test_entity_permissions_effect_tag_suggestions()
     {
         // Create some tags with similar names to test with and save to a page
         $attrs = collect();
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country']));
-        $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color']));
-        $page = $this->getEntityWithTags(Page::class, $attrs);
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country']));
+        $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color']));
+        $page = $this->getEntityWithTags(Page::class, $attrs->all());
 
-        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
-        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
+        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
+        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
 
         // Set restricted permission the page
-        $page->restricted = true;
-        $page->save();
-        $page->rebuildPermissions();
+        $this->permissions->setEntityPermissions($page, [], []);
 
-        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']);
-        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals([]);
+        $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
+        $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson([]);
     }
 
     public function test_tags_shown_on_search_listing()
     {
         $tags = [
-            factory(Tag::class)->make(['name' => 'category', 'value' => 'buckets']),
-            factory(Tag::class)->make(['name' => 'color', 'value' => 'red']),
+            Tag::factory()->make(['name' => 'category', 'value' => 'buckets']),
+            Tag::factory()->make(['name' => 'color', 'value' => 'red']),
         ];
 
         $page = $this->getEntityWithTags(Page::class, $tags);
-        $resp = $this->asEditor()->get("/search?term=[category]");
+        $resp = $this->asEditor()->get('/search?term=[category]');
         $resp->assertSee($page->name);
-        $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'category');
-        $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'buckets');
-        $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'color');
-        $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'red');
+        $this->withHtml($resp)->assertElementContains('[href="' . $page->getUrl() . '"]', 'category');
+        $this->withHtml($resp)->assertElementContains('[href="' . $page->getUrl() . '"]', 'buckets');
+        $this->withHtml($resp)->assertElementContains('[href="' . $page->getUrl() . '"]', 'color');
+        $this->withHtml($resp)->assertElementContains('[href="' . $page->getUrl() . '"]', 'red');
+    }
+
+    public function test_tags_index_shows_tag_name_as_expected_with_right_counts()
+    {
+        $page = $this->entities->page();
+        $page->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']);
+        $page->tags()->create(['name' => 'Category', 'value' => 'OtherTestContent']);
+
+        $resp = $this->asEditor()->get('/tags');
+        $resp->assertSee('Category');
+        $html = $this->withHtml($resp);
+        $html->assertElementCount('.tag-item', 1);
+        $resp->assertDontSee('GreatTestContent');
+        $resp->assertDontSee('OtherTestContent');
+        $html->assertElementContains('a[title="Total tag usages"]', '2');
+        $html->assertElementContains('a[title="Assigned to Pages"]', '2');
+        $html->assertElementContains('a[title="Assigned to Books"]', '0');
+        $html->assertElementContains('a[title="Assigned to Chapters"]', '0');
+        $html->assertElementContains('a[title="Assigned to Shelves"]', '0');
+        $html->assertElementContains('a[href$="/tags?name=Category"]', '2 unique values');
+
+        $book = $this->entities->book();
+        $book->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']);
+        $resp = $this->asEditor()->get('/tags');
+        $this->withHtml($resp)->assertElementContains('a[title="Total tag usages"]', '3');
+        $this->withHtml($resp)->assertElementContains('a[title="Assigned to Books"]', '1');
+        $this->withHtml($resp)->assertElementContains('a[href$="/tags?name=Category"]', '2 unique values');
+    }
+
+    public function test_tag_index_can_be_searched()
+    {
+        $page = $this->entities->page();
+        $page->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']);
+
+        $resp = $this->asEditor()->get('/tags?search=cat');
+        $this->withHtml($resp)->assertElementContains('.tag-item .tag-name', 'Category');
+
+        $resp = $this->asEditor()->get('/tags?search=content');
+        $this->withHtml($resp)->assertElementContains('.tag-item .tag-name', 'Category');
+        $this->withHtml($resp)->assertElementContains('.tag-item .tag-value', 'GreatTestContent');
+
+        $resp = $this->asEditor()->get('/tags?search=other');
+        $this->withHtml($resp)->assertElementNotExists('.tag-item .tag-name');
     }
 
+    public function test_tag_index_search_will_show_mulitple_values_of_a_single_tag_name()
+    {
+        $page = $this->entities->page();
+        $page->tags()->create(['name' => 'Animal', 'value' => 'Catfish']);
+        $page->tags()->create(['name' => 'Animal', 'value' => 'Catdog']);
+
+        $resp = $this->asEditor()->get('/tags?search=cat');
+        $this->withHtml($resp)->assertElementContains('.tag-item .tag-value', 'Catfish');
+        $this->withHtml($resp)->assertElementContains('.tag-item .tag-value', 'Catdog');
+    }
+
+    public function test_tag_index_can_be_scoped_to_specific_tag_name()
+    {
+        $page = $this->entities->page();
+        $page->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']);
+        $page->tags()->create(['name' => 'Category', 'value' => 'OtherTestContent']);
+        $page->tags()->create(['name' => 'OtherTagName', 'value' => 'OtherValue']);
+
+        $resp = $this->asEditor()->get('/tags?name=Category');
+        $resp->assertSee('Category');
+        $resp->assertSee('GreatTestContent');
+        $resp->assertSee('OtherTestContent');
+        $resp->assertDontSee('OtherTagName');
+        $resp->assertSee('Active Filter:');
+        $this->withHtml($resp)->assertElementCount('.item-list .tag-item', 2);
+        $this->withHtml($resp)->assertElementContains('form[action$="/tags"]', 'Clear Filter');
+    }
+
+    public function test_tags_index_adheres_to_page_permissions()
+    {
+        $page = $this->entities->page();
+        $page->tags()->create(['name' => 'SuperCategory', 'value' => 'GreatTestContent']);
+
+        $resp = $this->asEditor()->get('/tags');
+        $resp->assertSee('SuperCategory');
+        $resp = $this->get('/tags?name=SuperCategory');
+        $resp->assertSee('GreatTestContent');
+
+        $this->permissions->setEntityPermissions($page, [], []);
+
+        $resp = $this->asEditor()->get('/tags');
+        $resp->assertDontSee('SuperCategory');
+        $resp = $this->get('/tags?name=SuperCategory');
+        $resp->assertDontSee('GreatTestContent');
+    }
+
+    public function test_tag_index_shows_message_on_no_results()
+    {
+        $resp = $this->asEditor()->get('/tags?search=testingval');
+        $resp->assertSee('No items available');
+        $resp->assertSee('Tags can be assigned via the page editor sidebar');
+    }
+
+    public function test_tag_classes_visible_on_entities()
+    {
+        $this->asEditor();
+
+        foreach ($this->entities->all() as $entity) {
+            $entity->tags()->create(['name' => 'My Super Tag Name', 'value' => 'An-awesome-value']);
+            $html = $this->withHtml($this->get($entity->getUrl()));
+            $html->assertElementExists('body.tag-name-mysupertagname.tag-value-anawesomevalue.tag-pair-mysupertagname-anawesomevalue');
+        }
+    }
+
+    public function test_tag_classes_are_escaped()
+    {
+        $page = $this->entities->page();
+        $page->tags()->create(['name' => '<>']);
+        $resp = $this->asEditor()->get($page->getUrl());
+        $resp->assertDontSee('tag-name-<>', false);
+        $resp->assertSee('tag-name-&lt;&gt;', false);
+    }
 }