Showing
14 changed files
with
282 additions
and
27 deletions
| 1 | <?php namespace BookStack; | 1 | <?php namespace BookStack; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | -abstract class Entity extends Ownable | 4 | +class Entity extends Ownable |
| 5 | { | 5 | { |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| ... | @@ -200,11 +200,5 @@ abstract class Entity extends Ownable | ... | @@ -200,11 +200,5 @@ abstract class Entity extends Ownable |
| 200 | 200 | ||
| 201 | return $search->orderBy('title_relevance', 'desc'); | 201 | return $search->orderBy('title_relevance', 'desc'); |
| 202 | } | 202 | } |
| 203 | - | 203 | + |
| 204 | - /** | ||
| 205 | - * Get the url for this item. | ||
| 206 | - * @return string | ||
| 207 | - */ | ||
| 208 | - abstract public function getUrl(); | ||
| 209 | - | ||
| 210 | } | 204 | } | ... | ... |
| ... | @@ -2,7 +2,6 @@ | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | ||
| 3 | use BookStack\Repos\AttributeRepo; | 3 | use BookStack\Repos\AttributeRepo; |
| 4 | use Illuminate\Http\Request; | 4 | use Illuminate\Http\Request; |
| 5 | - | ||
| 6 | use BookStack\Http\Requests; | 5 | use BookStack\Http\Requests; |
| 7 | 6 | ||
| 8 | class AttributeController extends Controller | 7 | class AttributeController extends Controller |
| ... | @@ -19,7 +18,6 @@ class AttributeController extends Controller | ... | @@ -19,7 +18,6 @@ class AttributeController extends Controller |
| 19 | $this->attributeRepo = $attributeRepo; | 18 | $this->attributeRepo = $attributeRepo; |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | - | ||
| 23 | /** | 21 | /** |
| 24 | * Get all the Attributes for a particular entity | 22 | * Get all the Attributes for a particular entity |
| 25 | * @param $entityType | 23 | * @param $entityType |
| ... | @@ -27,6 +25,43 @@ class AttributeController extends Controller | ... | @@ -27,6 +25,43 @@ class AttributeController extends Controller |
| 27 | */ | 25 | */ |
| 28 | public function getForEntity($entityType, $entityId) | 26 | public function getForEntity($entityType, $entityId) |
| 29 | { | 27 | { |
| 30 | - | 28 | + $attributes = $this->attributeRepo->getForEntity($entityType, $entityId); |
| 29 | + return response()->json($attributes); | ||
| 31 | } | 30 | } |
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * Update the attributes for a particular entity. | ||
| 34 | + * @param $entityType | ||
| 35 | + * @param $entityId | ||
| 36 | + * @param Request $request | ||
| 37 | + * @return mixed | ||
| 38 | + */ | ||
| 39 | + public function updateForEntity($entityType, $entityId, Request $request) | ||
| 40 | + { | ||
| 41 | + | ||
| 42 | + $this->validate($request, [ | ||
| 43 | + 'attributes.*.name' => 'required|min:3|max:250', | ||
| 44 | + 'attributes.*.value' => 'max:250' | ||
| 45 | + ]); | ||
| 46 | + | ||
| 47 | + $entity = $this->attributeRepo->getEntity($entityType, $entityId, 'update'); | ||
| 48 | + if ($entity === null) return $this->jsonError("Entity not found", 404); | ||
| 49 | + | ||
| 50 | + $inputAttributes = $request->input('attributes'); | ||
| 51 | + $attributes = $this->attributeRepo->saveAttributesToEntity($entity, $inputAttributes); | ||
| 52 | + return response()->json($attributes); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * Get attribute name suggestions from a given search term. | ||
| 57 | + * @param Request $request | ||
| 58 | + */ | ||
| 59 | + public function getNameSuggestions(Request $request) | ||
| 60 | + { | ||
| 61 | + $searchTerm = $request->get('search'); | ||
| 62 | + $suggestions = $this->attributeRepo->getNameSuggestions($searchTerm); | ||
| 63 | + return response()->json($suggestions); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + | ||
| 32 | } | 67 | } | ... | ... |
| ... | @@ -110,4 +110,15 @@ abstract class Controller extends BaseController | ... | @@ -110,4 +110,15 @@ abstract class Controller extends BaseController |
| 110 | return true; | 110 | return true; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | + /** | ||
| 114 | + * Send back a json error message. | ||
| 115 | + * @param string $messageText | ||
| 116 | + * @param int $statusCode | ||
| 117 | + * @return mixed | ||
| 118 | + */ | ||
| 119 | + protected function jsonError($messageText = "", $statusCode = 500) | ||
| 120 | + { | ||
| 121 | + return response()->json(['message' => $messageText], $statusCode); | ||
| 122 | + } | ||
| 123 | + | ||
| 113 | } | 124 | } | ... | ... |
| ... | @@ -88,6 +88,8 @@ Route::group(['middleware' => 'auth'], function () { | ... | @@ -88,6 +88,8 @@ Route::group(['middleware' => 'auth'], function () { |
| 88 | // Attribute routes (AJAX) | 88 | // Attribute routes (AJAX) |
| 89 | Route::group(['prefix' => 'ajax/attributes'], function() { | 89 | Route::group(['prefix' => 'ajax/attributes'], function() { |
| 90 | Route::get('/get/{entityType}/{entityId}', 'AttributeController@getForEntity'); | 90 | Route::get('/get/{entityType}/{entityId}', 'AttributeController@getForEntity'); |
| 91 | + Route::get('/suggest', 'AttributeController@getNameSuggestions'); | ||
| 92 | + Route::post('/update/{entityType}/{entityId}', 'AttributeController@updateForEntity'); | ||
| 91 | }); | 93 | }); |
| 92 | 94 | ||
| 93 | // Links | 95 | // Links | ... | ... |
| ... | @@ -28,5 +28,76 @@ class AttributeRepo | ... | @@ -28,5 +28,76 @@ class AttributeRepo |
| 28 | $this->permissionService = $ps; | 28 | $this->permissionService = $ps; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | + /** | ||
| 32 | + * Get an entity instance of its particular type. | ||
| 33 | + * @param $entityType | ||
| 34 | + * @param $entityId | ||
| 35 | + * @param string $action | ||
| 36 | + */ | ||
| 37 | + public function getEntity($entityType, $entityId, $action = 'view') | ||
| 38 | + { | ||
| 39 | + $entityInstance = $this->entity->getEntityInstance($entityType); | ||
| 40 | + $searchQuery = $entityInstance->where('id', '=', $entityId)->with('attributes'); | ||
| 41 | + $searchQuery = $this->permissionService->enforceEntityRestrictions($searchQuery, $action); | ||
| 42 | + return $searchQuery->first(); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * Get all attributes for a particular entity. | ||
| 47 | + * @param string $entityType | ||
| 48 | + * @param int $entityId | ||
| 49 | + * @return mixed | ||
| 50 | + */ | ||
| 51 | + public function getForEntity($entityType, $entityId) | ||
| 52 | + { | ||
| 53 | + $entity = $this->getEntity($entityType, $entityId); | ||
| 54 | + if ($entity === null) return collect(); | ||
| 55 | + | ||
| 56 | + return $entity->attributes; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * Get attribute name suggestions from scanning existing attribute names. | ||
| 61 | + * @param $searchTerm | ||
| 62 | + * @return array | ||
| 63 | + */ | ||
| 64 | + public function getNameSuggestions($searchTerm) | ||
| 65 | + { | ||
| 66 | + if ($searchTerm === '') return []; | ||
| 67 | + $query = $this->attribute->where('name', 'LIKE', $searchTerm . '%')->groupBy('name')->orderBy('name', 'desc'); | ||
| 68 | + $query = $this->permissionService->filterRestrictedEntityRelations($query, 'attributes', 'entity_id', 'entity_type'); | ||
| 69 | + return $query->get(['name'])->pluck('name'); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * Save an array of attributes to an entity | ||
| 74 | + * @param Entity $entity | ||
| 75 | + * @param array $attributes | ||
| 76 | + * @return array|\Illuminate\Database\Eloquent\Collection | ||
| 77 | + */ | ||
| 78 | + public function saveAttributesToEntity(Entity $entity, $attributes = []) | ||
| 79 | + { | ||
| 80 | + $entity->attributes()->delete(); | ||
| 81 | + $newAttributes = []; | ||
| 82 | + foreach ($attributes as $attribute) { | ||
| 83 | + $newAttributes[] = $this->newInstanceFromInput($attribute); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + return $entity->attributes()->saveMany($newAttributes); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * Create a new Attribute instance from user input. | ||
| 91 | + * @param $input | ||
| 92 | + * @return static | ||
| 93 | + */ | ||
| 94 | + protected function newInstanceFromInput($input) | ||
| 95 | + { | ||
| 96 | + $name = trim($input['name']); | ||
| 97 | + $value = isset($input['value']) ? trim($input['value']) : ''; | ||
| 98 | + // Any other modification or cleanup required can go here | ||
| 99 | + $values = ['name' => $name, 'value' => $value]; | ||
| 100 | + return $this->attribute->newInstance($values); | ||
| 101 | + } | ||
| 31 | 102 | ||
| 32 | } | 103 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -582,6 +582,7 @@ class PageRepo extends EntityRepo | ... | @@ -582,6 +582,7 @@ class PageRepo extends EntityRepo |
| 582 | { | 582 | { |
| 583 | Activity::removeEntity($page); | 583 | Activity::removeEntity($page); |
| 584 | $page->views()->delete(); | 584 | $page->views()->delete(); |
| 585 | + $page->attributes()->delete(); | ||
| 585 | $page->revisions()->delete(); | 586 | $page->revisions()->delete(); |
| 586 | $page->permissions()->delete(); | 587 | $page->permissions()->delete(); |
| 587 | $this->permissionService->deleteJointPermissionsForEntity($page); | 588 | $this->permissionService->deleteJointPermissionsForEntity($page); | ... | ... |
| ... | @@ -52,4 +52,11 @@ $factory->define(BookStack\Role::class, function ($faker) { | ... | @@ -52,4 +52,11 @@ $factory->define(BookStack\Role::class, function ($faker) { |
| 52 | 'display_name' => $faker->sentence(3), | 52 | 'display_name' => $faker->sentence(3), |
| 53 | 'description' => $faker->sentence(10) | 53 | 'description' => $faker->sentence(10) |
| 54 | ]; | 54 | ]; |
| 55 | +}); | ||
| 56 | + | ||
| 57 | +$factory->define(BookStack\Attribute::class, function ($faker) { | ||
| 58 | + return [ | ||
| 59 | + 'name' => $faker->city, | ||
| 60 | + 'value' => $faker->sentence(3) | ||
| 61 | + ]; | ||
| 55 | }); | 62 | }); |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -181,7 +181,7 @@ class AuthTest extends TestCase | ... | @@ -181,7 +181,7 @@ class AuthTest extends TestCase |
| 181 | public function test_user_deletion() | 181 | public function test_user_deletion() |
| 182 | { | 182 | { |
| 183 | $userDetails = factory(\BookStack\User::class)->make(); | 183 | $userDetails = factory(\BookStack\User::class)->make(); |
| 184 | - $user = $this->getNewUser($userDetails->toArray()); | 184 | + $user = $this->getEditor($userDetails->toArray()); |
| 185 | 185 | ||
| 186 | $this->asAdmin() | 186 | $this->asAdmin() |
| 187 | ->visit('/settings/users/' . $user->id) | 187 | ->visit('/settings/users/' . $user->id) | ... | ... |
tests/Entity/AttributeTests.php
0 → 100644
| 1 | +<?php namespace Entity; | ||
| 2 | + | ||
| 3 | +use BookStack\Attribute; | ||
| 4 | +use BookStack\Page; | ||
| 5 | +use BookStack\Services\PermissionService; | ||
| 6 | + | ||
| 7 | +class AttributeTests extends \TestCase | ||
| 8 | +{ | ||
| 9 | + | ||
| 10 | + protected $defaultAttrCount = 20; | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * Get an instance of a page that has many attributes. | ||
| 14 | + * @param Attribute[]|bool $attributes | ||
| 15 | + * @return mixed | ||
| 16 | + */ | ||
| 17 | + protected function getPageWithAttributes($attributes = false) | ||
| 18 | + { | ||
| 19 | + $page = Page::first(); | ||
| 20 | + | ||
| 21 | + if (!$attributes) { | ||
| 22 | + $attributes = factory(Attribute::class, $this->defaultAttrCount)->make(); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + $page->attributes()->saveMany($attributes); | ||
| 26 | + return $page; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + public function test_get_page_attributes() | ||
| 30 | + { | ||
| 31 | + $page = $this->getPageWithAttributes(); | ||
| 32 | + | ||
| 33 | + // Add some other attributes to check they don't interfere | ||
| 34 | + factory(Attribute::class, $this->defaultAttrCount)->create(); | ||
| 35 | + | ||
| 36 | + $this->asAdmin()->get("/ajax/attributes/get/page/" . $page->id) | ||
| 37 | + ->shouldReturnJson(); | ||
| 38 | + | ||
| 39 | + $json = json_decode($this->response->getContent()); | ||
| 40 | + $this->assertTrue(count($json) === $this->defaultAttrCount, "Returned JSON item count is not as expected"); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + public function test_attribute_name_suggestions() | ||
| 44 | + { | ||
| 45 | + // Create some attributes with similar names to test with | ||
| 46 | + $attrs = collect(); | ||
| 47 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'country'])); | ||
| 48 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'color'])); | ||
| 49 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'city'])); | ||
| 50 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'county'])); | ||
| 51 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'planet'])); | ||
| 52 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'plans'])); | ||
| 53 | + $page = $this->getPageWithAttributes($attrs); | ||
| 54 | + | ||
| 55 | + $this->asAdmin()->get('/ajax/attributes/suggest?search=dog')->seeJsonEquals([]); | ||
| 56 | + $this->get('/ajax/attributes/suggest?search=co')->seeJsonEquals(['color', 'country', 'county']); | ||
| 57 | + $this->get('/ajax/attributes/suggest?search=cou')->seeJsonEquals(['country', 'county']); | ||
| 58 | + $this->get('/ajax/attributes/suggest?search=pla')->seeJsonEquals(['planet', 'plans']); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + public function test_entity_permissions_effect_attribute_suggestions() | ||
| 62 | + { | ||
| 63 | + $permissionService = $this->app->make(PermissionService::class); | ||
| 64 | + | ||
| 65 | + // Create some attributes with similar names to test with and save to a page | ||
| 66 | + $attrs = collect(); | ||
| 67 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'country'])); | ||
| 68 | + $attrs = $attrs->merge(factory(Attribute::class, 5)->make(['name' => 'color'])); | ||
| 69 | + $page = $this->getPageWithAttributes($attrs); | ||
| 70 | + | ||
| 71 | + $this->asAdmin()->get('/ajax/attributes/suggest?search=co')->seeJsonEquals(['color', 'country']); | ||
| 72 | + $this->asEditor()->get('/ajax/attributes/suggest?search=co')->seeJsonEquals(['color', 'country']); | ||
| 73 | + | ||
| 74 | + // Set restricted permission the page | ||
| 75 | + $page->restricted = true; | ||
| 76 | + $page->save(); | ||
| 77 | + $permissionService->buildJointPermissionsForEntity($page); | ||
| 78 | + | ||
| 79 | + $this->asAdmin()->get('/ajax/attributes/suggest?search=co')->seeJsonEquals(['color', 'country']); | ||
| 80 | + $this->asEditor()->get('/ajax/attributes/suggest?search=co')->seeJsonEquals([]); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + public function test_entity_attribute_updating() | ||
| 84 | + { | ||
| 85 | + $page = $this->getPageWithAttributes(); | ||
| 86 | + | ||
| 87 | + $testJsonData = [ | ||
| 88 | + ['name' => 'color', 'value' => 'red'], | ||
| 89 | + ['name' => 'color', 'value' => ' blue '], | ||
| 90 | + ['name' => 'city', 'value' => 'London '], | ||
| 91 | + ['name' => 'country', 'value' => ' England'], | ||
| 92 | + ]; | ||
| 93 | + $testResponseJsonData = [ | ||
| 94 | + ['name' => 'color', 'value' => 'red'], | ||
| 95 | + ['name' => 'color', 'value' => 'blue'], | ||
| 96 | + ['name' => 'city', 'value' => 'London'], | ||
| 97 | + ['name' => 'country', 'value' => 'England'], | ||
| 98 | + ]; | ||
| 99 | + | ||
| 100 | + $this->asAdmin()->json("POST", "/ajax/attributes/update/page/" . $page->id, ['attributes' => $testJsonData]); | ||
| 101 | + $this->asAdmin()->get("/ajax/attributes/get/page/" . $page->id); | ||
| 102 | + $jsonData = json_decode($this->response->getContent()); | ||
| 103 | + // Check counts | ||
| 104 | + $this->assertTrue(count($jsonData) === count($testJsonData), "The received attribute count is incorrect"); | ||
| 105 | + // Check data is correct | ||
| 106 | + $testDataCorrect = true; | ||
| 107 | + foreach ($jsonData as $data) { | ||
| 108 | + $testItem = ['name' => $data->name, 'value' => $data->value]; | ||
| 109 | + if (!in_array($testItem, $testResponseJsonData)) $testDataCorrect = false; | ||
| 110 | + } | ||
| 111 | + $testMessage = "Expected data was not found in the response.\nExpected Data: %s\nRecieved Data: %s"; | ||
| 112 | + $this->assertTrue($testDataCorrect, sprintf($testMessage, json_encode($testResponseJsonData), json_encode($jsonData))); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | +} |
| ... | @@ -161,8 +161,8 @@ class EntityTest extends TestCase | ... | @@ -161,8 +161,8 @@ class EntityTest extends TestCase |
| 161 | public function test_entities_viewable_after_creator_deletion() | 161 | public function test_entities_viewable_after_creator_deletion() |
| 162 | { | 162 | { |
| 163 | // Create required assets and revisions | 163 | // Create required assets and revisions |
| 164 | - $creator = $this->getNewUser(); | 164 | + $creator = $this->getEditor(); |
| 165 | - $updater = $this->getNewUser(); | 165 | + $updater = $this->getEditor(); |
| 166 | $entities = $this->createEntityChainBelongingToUser($creator, $updater); | 166 | $entities = $this->createEntityChainBelongingToUser($creator, $updater); |
| 167 | $this->actingAs($creator); | 167 | $this->actingAs($creator); |
| 168 | app('BookStack\Repos\UserRepo')->destroy($creator); | 168 | app('BookStack\Repos\UserRepo')->destroy($creator); |
| ... | @@ -174,8 +174,8 @@ class EntityTest extends TestCase | ... | @@ -174,8 +174,8 @@ class EntityTest extends TestCase |
| 174 | public function test_entities_viewable_after_updater_deletion() | 174 | public function test_entities_viewable_after_updater_deletion() |
| 175 | { | 175 | { |
| 176 | // Create required assets and revisions | 176 | // Create required assets and revisions |
| 177 | - $creator = $this->getNewUser(); | 177 | + $creator = $this->getEditor(); |
| 178 | - $updater = $this->getNewUser(); | 178 | + $updater = $this->getEditor(); |
| 179 | $entities = $this->createEntityChainBelongingToUser($creator, $updater); | 179 | $entities = $this->createEntityChainBelongingToUser($creator, $updater); |
| 180 | $this->actingAs($updater); | 180 | $this->actingAs($updater); |
| 181 | app('BookStack\Repos\UserRepo')->destroy($updater); | 181 | app('BookStack\Repos\UserRepo')->destroy($updater); |
| ... | @@ -198,7 +198,7 @@ class EntityTest extends TestCase | ... | @@ -198,7 +198,7 @@ class EntityTest extends TestCase |
| 198 | 198 | ||
| 199 | public function test_recently_created_pages_view() | 199 | public function test_recently_created_pages_view() |
| 200 | { | 200 | { |
| 201 | - $user = $this->getNewUser(); | 201 | + $user = $this->getEditor(); |
| 202 | $content = $this->createEntityChainBelongingToUser($user); | 202 | $content = $this->createEntityChainBelongingToUser($user); |
| 203 | 203 | ||
| 204 | $this->asAdmin()->visit('/pages/recently-created') | 204 | $this->asAdmin()->visit('/pages/recently-created') |
| ... | @@ -207,7 +207,7 @@ class EntityTest extends TestCase | ... | @@ -207,7 +207,7 @@ class EntityTest extends TestCase |
| 207 | 207 | ||
| 208 | public function test_recently_updated_pages_view() | 208 | public function test_recently_updated_pages_view() |
| 209 | { | 209 | { |
| 210 | - $user = $this->getNewUser(); | 210 | + $user = $this->getEditor(); |
| 211 | $content = $this->createEntityChainBelongingToUser($user); | 211 | $content = $this->createEntityChainBelongingToUser($user); |
| 212 | 212 | ||
| 213 | $this->asAdmin()->visit('/pages/recently-updated') | 213 | $this->asAdmin()->visit('/pages/recently-updated') |
| ... | @@ -241,7 +241,7 @@ class EntityTest extends TestCase | ... | @@ -241,7 +241,7 @@ class EntityTest extends TestCase |
| 241 | 241 | ||
| 242 | public function test_recently_created_pages_on_home() | 242 | public function test_recently_created_pages_on_home() |
| 243 | { | 243 | { |
| 244 | - $entityChain = $this->createEntityChainBelongingToUser($this->getNewUser()); | 244 | + $entityChain = $this->createEntityChainBelongingToUser($this->getEditor()); |
| 245 | $this->asAdmin()->visit('/') | 245 | $this->asAdmin()->visit('/') |
| 246 | ->seeInElement('#recently-created-pages', $entityChain['page']->name); | 246 | ->seeInElement('#recently-created-pages', $entityChain['page']->name); |
| 247 | } | 247 | } | ... | ... |
| ... | @@ -32,7 +32,7 @@ class PageDraftTest extends TestCase | ... | @@ -32,7 +32,7 @@ class PageDraftTest extends TestCase |
| 32 | ->dontSeeInField('html', $addedContent); | 32 | ->dontSeeInField('html', $addedContent); |
| 33 | 33 | ||
| 34 | $newContent = $this->page->html . $addedContent; | 34 | $newContent = $this->page->html . $addedContent; |
| 35 | - $newUser = $this->getNewUser(); | 35 | + $newUser = $this->getEditor(); |
| 36 | $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); | 36 | $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); |
| 37 | $this->actingAs($newUser)->visit($this->page->getUrl() . '/edit') | 37 | $this->actingAs($newUser)->visit($this->page->getUrl() . '/edit') |
| 38 | ->dontSeeInField('html', $newContent); | 38 | ->dontSeeInField('html', $newContent); |
| ... | @@ -54,7 +54,7 @@ class PageDraftTest extends TestCase | ... | @@ -54,7 +54,7 @@ class PageDraftTest extends TestCase |
| 54 | ->dontSeeInField('html', $addedContent); | 54 | ->dontSeeInField('html', $addedContent); |
| 55 | 55 | ||
| 56 | $newContent = $this->page->html . $addedContent; | 56 | $newContent = $this->page->html . $addedContent; |
| 57 | - $newUser = $this->getNewUser(); | 57 | + $newUser = $this->getEditor(); |
| 58 | $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); | 58 | $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); |
| 59 | 59 | ||
| 60 | $this->actingAs($newUser) | 60 | $this->actingAs($newUser) |
| ... | @@ -79,7 +79,7 @@ class PageDraftTest extends TestCase | ... | @@ -79,7 +79,7 @@ class PageDraftTest extends TestCase |
| 79 | { | 79 | { |
| 80 | $book = \BookStack\Book::first(); | 80 | $book = \BookStack\Book::first(); |
| 81 | $chapter = $book->chapters->first(); | 81 | $chapter = $book->chapters->first(); |
| 82 | - $newUser = $this->getNewUser(); | 82 | + $newUser = $this->getEditor(); |
| 83 | 83 | ||
| 84 | $this->actingAs($newUser)->visit('/') | 84 | $this->actingAs($newUser)->visit('/') |
| 85 | ->visit($book->getUrl() . '/page/create') | 85 | ->visit($book->getUrl() . '/page/create') | ... | ... |
| ... | @@ -9,7 +9,7 @@ class RestrictionsTest extends TestCase | ... | @@ -9,7 +9,7 @@ class RestrictionsTest extends TestCase |
| 9 | public function setUp() | 9 | public function setUp() |
| 10 | { | 10 | { |
| 11 | parent::setUp(); | 11 | parent::setUp(); |
| 12 | - $this->user = $this->getNewUser(); | 12 | + $this->user = $this->getEditor(); |
| 13 | $this->viewer = $this->getViewer(); | 13 | $this->viewer = $this->getViewer(); |
| 14 | $this->restrictionService = $this->app[\BookStack\Services\PermissionService::class]; | 14 | $this->restrictionService = $this->app[\BookStack\Services\PermissionService::class]; |
| 15 | } | 15 | } | ... | ... |
| ... | @@ -14,7 +14,10 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase | ... | @@ -14,7 +14,10 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase |
| 14 | * @var string | 14 | * @var string |
| 15 | */ | 15 | */ |
| 16 | protected $baseUrl = 'http://localhost'; | 16 | protected $baseUrl = 'http://localhost'; |
| 17 | + | ||
| 18 | + // Local user instances | ||
| 17 | private $admin; | 19 | private $admin; |
| 20 | + private $editor; | ||
| 18 | 21 | ||
| 19 | /** | 22 | /** |
| 20 | * Creates the application. | 23 | * Creates the application. |
| ... | @@ -30,6 +33,10 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase | ... | @@ -30,6 +33,10 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase |
| 30 | return $app; | 33 | return $app; |
| 31 | } | 34 | } |
| 32 | 35 | ||
| 36 | + /** | ||
| 37 | + * Set the current user context to be an admin. | ||
| 38 | + * @return $this | ||
| 39 | + */ | ||
| 33 | public function asAdmin() | 40 | public function asAdmin() |
| 34 | { | 41 | { |
| 35 | if($this->admin === null) { | 42 | if($this->admin === null) { |
| ... | @@ -40,6 +47,18 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase | ... | @@ -40,6 +47,18 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase |
| 40 | } | 47 | } |
| 41 | 48 | ||
| 42 | /** | 49 | /** |
| 50 | + * Set the current editor context to be an editor. | ||
| 51 | + * @return $this | ||
| 52 | + */ | ||
| 53 | + public function asEditor() | ||
| 54 | + { | ||
| 55 | + if($this->editor === null) { | ||
| 56 | + $this->editor = $this->getEditor(); | ||
| 57 | + } | ||
| 58 | + return $this->actingAs($this->editor); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 43 | * Quickly sets an array of settings. | 62 | * Quickly sets an array of settings. |
| 44 | * @param $settingsArray | 63 | * @param $settingsArray |
| 45 | */ | 64 | */ |
| ... | @@ -79,7 +98,7 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase | ... | @@ -79,7 +98,7 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase |
| 79 | * @param array $attributes | 98 | * @param array $attributes |
| 80 | * @return mixed | 99 | * @return mixed |
| 81 | */ | 100 | */ |
| 82 | - protected function getNewUser($attributes = []) | 101 | + protected function getEditor($attributes = []) |
| 83 | { | 102 | { |
| 84 | $user = factory(\BookStack\User::class)->create($attributes); | 103 | $user = factory(\BookStack\User::class)->create($attributes); |
| 85 | $role = \BookStack\Role::getRole('editor'); | 104 | $role = \BookStack\Role::getRole('editor'); | ... | ... |
| ... | @@ -33,7 +33,7 @@ class UserProfileTest extends TestCase | ... | @@ -33,7 +33,7 @@ class UserProfileTest extends TestCase |
| 33 | 33 | ||
| 34 | public function test_profile_page_shows_created_content_counts() | 34 | public function test_profile_page_shows_created_content_counts() |
| 35 | { | 35 | { |
| 36 | - $newUser = $this->getNewUser(); | 36 | + $newUser = $this->getEditor(); |
| 37 | 37 | ||
| 38 | $this->asAdmin()->visit('/user/' . $newUser->id) | 38 | $this->asAdmin()->visit('/user/' . $newUser->id) |
| 39 | ->see($newUser->name) | 39 | ->see($newUser->name) |
| ... | @@ -52,7 +52,7 @@ class UserProfileTest extends TestCase | ... | @@ -52,7 +52,7 @@ class UserProfileTest extends TestCase |
| 52 | 52 | ||
| 53 | public function test_profile_page_shows_recent_activity() | 53 | public function test_profile_page_shows_recent_activity() |
| 54 | { | 54 | { |
| 55 | - $newUser = $this->getNewUser(); | 55 | + $newUser = $this->getEditor(); |
| 56 | $this->actingAs($newUser); | 56 | $this->actingAs($newUser); |
| 57 | $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); | 57 | $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); |
| 58 | Activity::add($entities['book'], 'book_update', $entities['book']->id); | 58 | Activity::add($entities['book'], 'book_update', $entities['book']->id); |
| ... | @@ -66,7 +66,7 @@ class UserProfileTest extends TestCase | ... | @@ -66,7 +66,7 @@ class UserProfileTest extends TestCase |
| 66 | 66 | ||
| 67 | public function test_clicking_user_name_in_activity_leads_to_profile_page() | 67 | public function test_clicking_user_name_in_activity_leads_to_profile_page() |
| 68 | { | 68 | { |
| 69 | - $newUser = $this->getNewUser(); | 69 | + $newUser = $this->getEditor(); |
| 70 | $this->actingAs($newUser); | 70 | $this->actingAs($newUser); |
| 71 | $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); | 71 | $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); |
| 72 | Activity::add($entities['book'], 'book_update', $entities['book']->id); | 72 | Activity::add($entities['book'], 'book_update', $entities['book']->id); | ... | ... |
-
Please register or sign in to post a comment