From 027bab6616e566c1999399c00d340816961b148e Mon Sep 17 00:00:00 2001 From: Yuvinscria Werdxz Date: Mon, 21 Apr 2025 11:13:44 -0700 Subject: [PATCH 1/4] added integrated tests for server --- .github/workflows/server-integrated-test.yml | 28 ++++ test/server/doc.hurl | 5 + test/server/user-profile.hurl | 73 ++++++++++ test/server/user-tags.hurl | 145 +++++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 .github/workflows/server-integrated-test.yml create mode 100644 test/server/doc.hurl create mode 100644 test/server/user-profile.hurl create mode 100644 test/server/user-tags.hurl diff --git a/.github/workflows/server-integrated-test.yml b/.github/workflows/server-integrated-test.yml new file mode 100644 index 0000000..11350e5 --- /dev/null +++ b/.github/workflows/server-integrated-test.yml @@ -0,0 +1,28 @@ +name: Server Integrated Test +on: + pull_request: + branches: + - main + paths: + - '**/*.rs' + - 'Cargo.toml' + - 'Cargo.lock' + +jobs: + docker-compose: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + continue-on-error: false + + - name: Run docker compose + uses: hoverkraft-tech/compose-action@v2.0.1 + with: + compose-file: "docker-compose.yml" + + - name: Integration test + run: | + curl --location --remote-name https://github.com/Orange-OpenSource/hurl/releases/download/4.0.0/hurl_4.0.0_amd64.deb + sudo dpkg -i hurl_4.0.0_amd64.deb + hurl test/server/*.hurl http://localhost:3000 diff --git a/test/server/doc.hurl b/test/server/doc.hurl new file mode 100644 index 0000000..dbc722d --- /dev/null +++ b/test/server/doc.hurl @@ -0,0 +1,5 @@ +GET {{host}}/api-docs/openapi.json +HTTP 200 + +GET {{host}}/swagger-ui/ +HTTP 200 diff --git a/test/server/user-profile.hurl b/test/server/user-profile.hurl new file mode 100644 index 0000000..c1ba459 --- /dev/null +++ b/test/server/user-profile.hurl @@ -0,0 +1,73 @@ +# Check authorization +GET {{host}}/api/v1/user/me + +HTTP 401 + +# Check create user profile if not exists +GET {{host}}/api/v1/user/me +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Captures] +response: body +[Asserts] +jsonpath "$.id" == "user-profile-test-user1" + +# Check not found user profile +GET {{host}}/api/v1/user/user-profile-test-user2 +Authorization: Bearer user-profile-test-user2 +HTTP 404 + +# Check created user profile +GET {{host}}/api/v1/user/user-profile-test-user1 +Authorization: Bearer user-profile-test-user2 +HTTP 200 +[Asserts] +body == {{response}} + +# Update user profile +PUT {{host}}/api/v1/user/me +Authorization: Bearer user-profile-test-user1 +{ + "username": "user-profile-test-user1", + "display_name": "user1", + "bio": "This is a test bio for user1" +} +HTTP 200 +[Asserts] +jsonpath "$.id" == "user-profile-test-user1" +jsonpath "$.display_name" == "user1" +jsonpath "$.username" == "user-profile-test-user1" +jsonpath "$.bio" == "This is a test bio for user1" + +# Update user avatar (without changing username) +PUT {{host}}/api/v1/user/me +Authorization: Bearer user-profile-test-user1 +{ + "avatar_url": "https://example.com/avatar.jpg" +} +HTTP 200 +[Asserts] +jsonpath "$.id" == "user-profile-test-user1" +jsonpath "$.avatar_url" == "https://example.com/avatar.jpg" + +# Test updating user profile with invalid data (empty username) +PUT {{host}}/api/v1/user/me +Authorization: Bearer user-profile-test-user1 +{ + "username": "", + "display_name": "user1" +} +HTTP 400 +[Asserts] +jsonpath "$.Validation.field" == "username" + +# Test clearing display_name with null (null wouldn't change anything, acting same as undefined) +PUT {{host}}/api/v1/user/me +Authorization: Bearer user-profile-test-user1 +{ + "display_name": null +} +HTTP 200 +[Asserts] +jsonpath "$.id" == "user-profile-test-user1" +jsonpath "$.display_name" == "user1" diff --git a/test/server/user-tags.hurl b/test/server/user-tags.hurl new file mode 100644 index 0000000..35d31f3 --- /dev/null +++ b/test/server/user-tags.hurl @@ -0,0 +1,145 @@ +# First, ensure we have access to the API +GET {{host}}/api-docs/openapi.json +HTTP 200 + +# 1. Test authenticating as a test user +# We'll use dummy auth for testing + +# Create or get current user +GET {{host}}/api/v1/user/me +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Captures] +user_id: jsonpath "$.id" +username: jsonpath "$.username" + +# 2. Test getting all tags (should work even if empty at first) +GET {{host}}/api/v1/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*]" isCollection + +# 3. Test getting current user's tags (should be empty initially) +GET {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$" count == 0 + +# 4. Test adding a tag to the current user +POST {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +{ + "tag_name": "introvert" +} +HTTP 200 +[Asserts] +jsonpath "$.tag_name" == "introvert" +jsonpath "$.user_id" == {{user_id}} +[Captures] +first_tag_id: jsonpath "$.id" + +# 5. Add another tag +POST {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +{ + "tag_name": "coffee-lover" +} +HTTP 200 +[Asserts] +jsonpath "$.tag_name" == "coffee-lover" +jsonpath "$.user_id" == {{user_id}} +[Captures] +second_tag_id: jsonpath "$.id" + +# 6. Verify both tags appear in user's tags list +GET {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$" count == 2 +jsonpath "$[*].tag_name" contains "introvert" +jsonpath "$[*].tag_name" contains "coffee-lover" + +# 7. Verify tags are in the global tags list +GET {{host}}/api/v1/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*].tag_name" contains "introvert" +jsonpath "$[*].tag_name" contains "coffee-lover" + +# 8. Try to add an empty tag (should fail) +POST {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +{ + "tag_name": "" +} +HTTP 400 +[Asserts] +jsonpath "$.field" == "tag_name" + +# 9. Find nemesis tags for "introvert" +GET {{host}}/api/v1/tags/introvert/nemesis +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*]" isCollection + +# 10. Test getting another user's tags +# First, get our user ID +GET {{host}}/api/v1/user/{{user_id}}/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*]" isCollection +jsonpath "$" count == 2 + +# 11. Remove one tag +DELETE {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +["introvert"] +HTTP 204 + +# 12. Verify one tag was removed +GET {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*]" isCollection +jsonpath "$" count == 2 +jsonpath "$[0].tag_name" == "coffee-lover" +jsonpath "$[*].tag_name" not contains "introvert" + +# 13. Add a tag that already exists (should work, but be idempotent) +POST {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +{ + "tag_name": "coffee-lover" +} +HTTP 200 +[Asserts] +jsonpath "$.tag_name" == "coffee-lover" + +# 14. Verify we still have only one tag (no duplication) +GET {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*]" isCollection +jsonpath "$" count == 2 + +# 15. Remove all remaining tags +DELETE {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +["coffee-lover"] +HTTP 204 + +# 16. Verify all tags are removed +GET {{host}}/api/v1/user/me/tags +Authorization: Bearer user-profile-test-user1 +HTTP 200 +[Asserts] +jsonpath "$[*]" isCollection +jsonpath "$" count == 0 From 3dbdb629d2a5315f132f52ddcf90d1dcd6494955 Mon Sep 17 00:00:00 2001 From: Yuvinscria Werdxz Date: Mon, 21 Apr 2025 12:50:16 -0700 Subject: [PATCH 2/4] fix server into_response recursion --- src/types/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index 58a9a98..c3cbb1e 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,4 +1,5 @@ use axum::extract::FromRef; +use axum::Json; use axum::{http::StatusCode, response::IntoResponse}; use firebase_auth::FirebaseAuthState; use serde::{Deserialize, Serialize}; @@ -78,6 +79,6 @@ impl IntoResponse for Error { Self::Unknown { .. } => StatusCode::INTERNAL_SERVER_ERROR, }; - (status_code, self).into_response() + (status_code, Json(self)).into_response() } } From 6885c73b3d0b155387862fd3be6d272bb07e4cc5 Mon Sep 17 00:00:00 2001 From: Yuvinscria Werdxz Date: Mon, 21 Apr 2025 13:25:04 -0700 Subject: [PATCH 3/4] fixed compose file path in actions --- .github/workflows/server-integrated-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/server-integrated-test.yml b/.github/workflows/server-integrated-test.yml index 11350e5..4053ed8 100644 --- a/.github/workflows/server-integrated-test.yml +++ b/.github/workflows/server-integrated-test.yml @@ -19,7 +19,7 @@ jobs: - name: Run docker compose uses: hoverkraft-tech/compose-action@v2.0.1 with: - compose-file: "docker-compose.yml" + compose-file: "compose.yml" - name: Integration test run: | From dfb95b735adf4dde698f153d5b0a1d62ca5187d8 Mon Sep 17 00:00:00 2001 From: Yuvinscria Werdxz Date: Wed, 23 Apr 2025 12:32:28 -0700 Subject: [PATCH 4/4] fixed testing --- .github/workflows/server-integrated-test.yml | 2 +- test/server/user-tags.hurl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/server-integrated-test.yml b/.github/workflows/server-integrated-test.yml index 4053ed8..e7b47ee 100644 --- a/.github/workflows/server-integrated-test.yml +++ b/.github/workflows/server-integrated-test.yml @@ -25,4 +25,4 @@ jobs: run: | curl --location --remote-name https://github.com/Orange-OpenSource/hurl/releases/download/4.0.0/hurl_4.0.0_amd64.deb sudo dpkg -i hurl_4.0.0_amd64.deb - hurl test/server/*.hurl http://localhost:3000 + hurl test/server/*.hurl --variable host=http://localhost:3000 diff --git a/test/server/user-tags.hurl b/test/server/user-tags.hurl index 35d31f3..4a6bc19 100644 --- a/test/server/user-tags.hurl +++ b/test/server/user-tags.hurl @@ -78,7 +78,7 @@ Authorization: Bearer user-profile-test-user1 } HTTP 400 [Asserts] -jsonpath "$.field" == "tag_name" +jsonpath "$.Validation.field" == "tag_name" # 9. Find nemesis tags for "introvert" GET {{host}}/api/v1/tags/introvert/nemesis @@ -108,7 +108,7 @@ Authorization: Bearer user-profile-test-user1 HTTP 200 [Asserts] jsonpath "$[*]" isCollection -jsonpath "$" count == 2 +jsonpath "$" count == 1 jsonpath "$[0].tag_name" == "coffee-lover" jsonpath "$[*].tag_name" not contains "introvert" @@ -128,7 +128,7 @@ Authorization: Bearer user-profile-test-user1 HTTP 200 [Asserts] jsonpath "$[*]" isCollection -jsonpath "$" count == 2 +jsonpath "$" count == 1 # 15. Remove all remaining tags DELETE {{host}}/api/v1/user/me/tags