diff --git a/api/tests/Api/Categories/CreateCategoryTest.php b/api/tests/Api/Categories/CreateCategoryTest.php index 5433282fb1..14a0b76f42 100644 --- a/api/tests/Api/Categories/CreateCategoryTest.php +++ b/api/tests/Api/Categories/CreateCategoryTest.php @@ -99,10 +99,10 @@ public function testCreateCategoryCreatesNewColumnLayoutAsRootContentNode() { $this->assertResponseStatusCodeSame(201); $newestColumnLayout = $this->getEntityManager()->getRepository(ContentNode::class) - ->findBy(['contentType' => static::$fixtures['contentTypeColumnLayout']], ['createTime' => 'DESC'])[0] + ->findBy(['contentType' => static::$fixtures['contentTypeColumnLayout'], 'instanceName' => null], ['createTime' => 'DESC'], 1)[0] ; $this->assertJsonContains(['_links' => [ - 'rootContentNode' => ['href' => '/content_node/column_layouts/'.$newestColumnLayout->getId()], + 'rootContentNode' => ['href' => $this->getIriFor($newestColumnLayout)], ]]); } @@ -456,6 +456,102 @@ public function testCreateCategoryValidatesInvalidNumberingStyle() { ]); } + public function testCreateCategoryFromCopySourceValidatesAccess() { + static::createClientWithCredentials(['email' => static::$fixtures['user8memberOnlyInCamp2']->getEmail()])->request( + 'POST', + '/categories', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp2'), + 'copyCategorySource' => $this->getIriFor('category1'), + ] + )] + ); + + // No Access on category1 -> BadRequest + $this->assertResponseStatusCodeSame(400); + } + + public function testCreateCategoryFromCopySourceWithinSameCamp() { + static::createClientWithCredentials()->request( + 'POST', + '/categories', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp1'), + 'copyCategorySource' => $this->getIriFor('category1'), + ], + )] + ); + + // Category created + $this->assertResponseStatusCodeSame(201); + } + + public function testCreateCategoryFromCopySourceAcrossCamp() { + static::createClientWithCredentials()->request( + 'POST', + '/categories', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp2'), + 'copyCategorySource' => $this->getIriFor('category1'), + ], + )] + ); + + // Category created + $this->assertResponseStatusCodeSame(201); + } + + public function testCreateCategoryFromCopySourceActivityValidatesAccess() { + static::createClientWithCredentials(['email' => static::$fixtures['user8memberOnlyInCamp2']->getEmail()])->request( + 'POST', + '/categories', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp2'), + 'copyCategorySource' => $this->getIriFor('activity1'), + ] + )] + ); + + // No Access on activity1 -> BadRequest + $this->assertResponseStatusCodeSame(400); + } + + public function testCreateCategoryFromCopySourceActivityWithinSameCamp() { + static::createClientWithCredentials()->request( + 'POST', + '/categories', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp1'), + 'copyCategorySource' => $this->getIriFor('activity1'), + ], + )] + ); + + // Category created + $this->assertResponseStatusCodeSame(201); + } + + public function testCreateCategoryFromCopySourceActivityAcrossCamp() { + static::createClientWithCredentials()->request( + 'POST', + '/categories', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp2'), + 'copyCategorySource' => $this->getIriFor('activity1'), + ], + )] + ); + + // Category created + $this->assertResponseStatusCodeSame(201); + } + /** * @throws RedirectionExceptionInterface * @throws DecodingExceptionInterface @@ -488,6 +584,7 @@ public function getExampleWritePayload($attributes = [], $except = []) { Category::class, Post::class, array_merge([ + 'copyCategorySource' => null, 'camp' => $this->getIriFor('camp1'), 'preferredContentTypes' => [$this->getIriFor('contentTypeSafetyConcept')], ], $attributes), diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 60be7ed441..6eeed510f5 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -362,7 +362,7 @@ components: format: iri-reference type: string copyActivitySource: - description: 'Copy Contents from this Source-Activity.' + description: 'Copy contents from this source activity.' example: /activities/1a2b3c4d format: iri-reference type: @@ -1168,7 +1168,7 @@ components: format: iri-reference type: string copyActivitySource: - description: 'Copy Contents from this Source-Activity.' + description: 'Copy contents from this source activity.' example: /activities/1a2b3c4d format: iri-reference type: @@ -1607,7 +1607,7 @@ components: format: iri-reference type: string copyActivitySource: - description: 'Copy Contents from this Source-Activity.' + description: 'Copy contents from this source activity.' example: /activities/1a2b3c4d format: iri-reference type: @@ -7938,6 +7938,13 @@ components: maxLength: 8 pattern: '^(#[0-9a-zA-Z]{6})$' type: string + copyCategorySource: + description: 'Copy contents from this source category or activity.' + example: /categories/1a2b3c4d + format: iri-reference + type: + - 'null' + - string name: description: 'The full name of the category.' example: Lagersport @@ -8690,6 +8697,13 @@ components: maxLength: 8 pattern: '^(#[0-9a-zA-Z]{6})$' type: string + copyCategorySource: + description: 'Copy contents from this source category or activity.' + example: /categories/1a2b3c4d + format: iri-reference + type: + - 'null' + - string name: description: 'The full name of the category.' example: Lagersport @@ -9062,6 +9076,13 @@ components: maxLength: 8 pattern: '^(#[0-9a-zA-Z]{6})$' type: string + copyCategorySource: + description: 'Copy contents from this source category or activity.' + example: /categories/1a2b3c4d + format: iri-reference + type: + - 'null' + - string name: description: 'The full name of the category.' example: Lagersport diff --git a/frontend/src/components/campAdmin/DialogCategoryCreate.vue b/frontend/src/components/campAdmin/DialogCategoryCreate.vue index 5f8f589f5f..3566695929 100644 --- a/frontend/src/components/campAdmin/DialogCategoryCreate.vue +++ b/frontend/src/components/campAdmin/DialogCategoryCreate.vue @@ -19,9 +19,7 @@