diff --git a/.github/workflows/flarum-approval-backend.yml b/.github/workflows/flarum-approval-backend.yml index 4dc308f87..fec282a69 100644 --- a/.github/workflows/flarum-approval-backend.yml +++ b/.github/workflows/flarum-approval-backend.yml @@ -6,6 +6,6 @@ jobs: run: uses: ./.github/workflows/REUSABLE_backend.yml with: - enable_backend_testing: false + enable_backend_testing: true backend_directory: ./extensions/approval diff --git a/extensions/approval/composer.json b/extensions/approval/composer.json index 42d5750f3..ba792cc28 100644 --- a/extensions/approval/composer.json +++ b/extensions/approval/composer.json @@ -52,7 +52,7 @@ "prettier": true, "typescript": false, "bundlewatch": false, - "backendTesting": false, + "backendTesting": true, "editorConfig": true, "styleci": true } @@ -65,5 +65,28 @@ } ], "minimum-stability": "dev", - "prefer-stable": true + "prefer-stable": true, + "autoload-dev": { + "psr-4": { + "Flarum\\Approval\\Tests\\": "tests/" + } + }, + "scripts": { + "test": [ + "@test:unit", + "@test:integration" + ], + "test:unit": "phpunit -c tests/phpunit.unit.xml", + "test:integration": "phpunit -c tests/phpunit.integration.xml", + "test:setup": "@php tests/integration/setup.php" + }, + "scripts-descriptions": { + "test": "Runs all tests.", + "test:unit": "Runs all unit tests.", + "test:integration": "Runs all integration tests.", + "test:setup": "Sets up a database for use with integration tests. Execute this only once." + }, + "require-dev": { + "flarum/testing": "^1.0.0" + } } diff --git a/extensions/approval/tests/fixtures/.gitkeep b/extensions/approval/tests/fixtures/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/extensions/approval/tests/integration/InteractsWithUnapprovedContent.php b/extensions/approval/tests/integration/InteractsWithUnapprovedContent.php new file mode 100644 index 000000000..3f33097a6 --- /dev/null +++ b/extensions/approval/tests/integration/InteractsWithUnapprovedContent.php @@ -0,0 +1,75 @@ +prepareDatabase([ + 'users' => [ + ['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1], + $this->normalUser(), + ['id' => 3, 'username' => 'acme', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1], + ['id' => 4, 'username' => 'luceos', 'email' => 'luceos@machine.local', 'is_email_confirmed' => 1], + ], + 'discussions' => [ + ['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 1, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0], + ['id' => 2, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 2, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1], + ['id' => 3, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 3, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1], + ['id' => 4, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 4, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0], + ['id' => 5, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 5, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0], + ['id' => 6, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 6, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1], + ['id' => 7, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 7, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0], + ], + 'posts' => [ + ['id' => 1, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + ['id' => 2, 'discussion_id' => 2, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + ['id' => 3, 'discussion_id' => 3, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + ['id' => 4, 'discussion_id' => 4, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + ['id' => 5, 'discussion_id' => 5, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + ['id' => 6, 'discussion_id' => 6, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + ['id' => 7, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 1], + + ['id' => 8, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 2], + ['id' => 9, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 1, 'is_approved' => 0, 'number' => 3], + ['id' => 10, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 0, 'is_approved' => 1, 'number' => 4], + ['id' => 11, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '

Text

', 'is_private' => 1, 'is_approved' => 0, 'number' => 5], + ], + 'groups' => [ + ['id' => 4, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0] + ], + 'group_user' => [ + ['user_id' => 3, 'group_id' => 4] + ], + 'group_permission' => [ + ['permission' => 'discussion.approvePosts', 'group_id' => 4] + ] + ]); + } + + /** + * null: Guest, 2: Normal User. + */ + public function unallowedUsers(): array + { + return [[null], [2]]; + } + + /** + * 1: Admin, 3: Permission Given, 4: Discussions Author. + */ + public function allowedUsers(): array + { + return [[1], [3], [4]]; + } +} diff --git a/extensions/approval/tests/integration/api/ListDiscussionsTest.php b/extensions/approval/tests/integration/api/ListDiscussionsTest.php new file mode 100644 index 000000000..2ebb63951 --- /dev/null +++ b/extensions/approval/tests/integration/api/ListDiscussionsTest.php @@ -0,0 +1,62 @@ +extension('flarum-approval'); + + $this->prepareUnapprovedDatabaseContent(); + } + + /** + * @dataProvider unallowedUsers + * @test + */ + public function can_only_see_approved_if_not_allowed_to_approve(?int $authenticatedAs) + { + $response = $this->send( + $this->request('GET', '/api/discussions', compact('authenticatedAs')) + ); + + $body = json_decode($response->getBody()->getContents(), true); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEqualsCanonicalizing([1, 4, 5, 7], Arr::pluck($body['data'], 'id')); + } + + /** + * @dataProvider allowedUsers + * @test + */ + public function can_see_unapproved_if_allowed_to_approve(int $authenticatedAs) + { + $response = $this->send( + $this->request('GET', '/api/discussions', compact('authenticatedAs')) + ); + + $body = json_decode($response->getBody()->getContents(), true); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEqualsCanonicalizing([1, 2, 3, 4, 5, 6, 7], Arr::pluck($body['data'], 'id')); + } +} diff --git a/extensions/approval/tests/integration/api/ListPostsTest.php b/extensions/approval/tests/integration/api/ListPostsTest.php new file mode 100644 index 000000000..844d0f796 --- /dev/null +++ b/extensions/approval/tests/integration/api/ListPostsTest.php @@ -0,0 +1,74 @@ +extension('flarum-approval'); + + $this->prepareUnapprovedDatabaseContent(); + } + + /** + * @dataProvider unallowedUsers + * @test + */ + public function can_only_see_approved_if_not_allowed_to_approve(?int $authenticatedAs) + { + $response = $this->send( + $this + ->request('GET', '/api/posts', compact('authenticatedAs')) + ->withQueryParams([ + 'filter' => [ + 'discussion' => 7 + ] + ]) + ); + + $body = json_decode($response->getBody()->getContents(), true); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEqualsCanonicalizing([7, 8, 10], Arr::pluck($body['data'], 'id')); + } + + /** + * @dataProvider allowedUsers + * @test + */ + public function can_see_unapproved_if_allowed_to_approve(int $authenticatedAs) + { + $response = $this->send( + $this + ->request('GET', '/api/posts', compact('authenticatedAs')) + ->withQueryParams([ + 'filter' => [ + 'discussion' => 7 + ] + ]) + ); + + $body = json_decode($response->getBody()->getContents(), true); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEqualsCanonicalizing([7, 8, 9, 10, 11], Arr::pluck($body['data'], 'id')); + } +} diff --git a/extensions/approval/tests/integration/setup.php b/extensions/approval/tests/integration/setup.php new file mode 100644 index 000000000..67039c083 --- /dev/null +++ b/extensions/approval/tests/integration/setup.php @@ -0,0 +1,16 @@ +run(); diff --git a/extensions/approval/tests/phpunit.integration.xml b/extensions/approval/tests/phpunit.integration.xml new file mode 100644 index 000000000..90fbbff37 --- /dev/null +++ b/extensions/approval/tests/phpunit.integration.xml @@ -0,0 +1,25 @@ + + + + + ../src/ + + + + + ./integration + ./integration/tmp + + + diff --git a/extensions/approval/tests/phpunit.unit.xml b/extensions/approval/tests/phpunit.unit.xml new file mode 100644 index 000000000..d3a4a3e3d --- /dev/null +++ b/extensions/approval/tests/phpunit.unit.xml @@ -0,0 +1,27 @@ + + + + + ../src/ + + + + + ./unit + + + + + + diff --git a/extensions/approval/tests/unit/.gitkeep b/extensions/approval/tests/unit/.gitkeep new file mode 100644 index 000000000..e69de29bb