Skip to content

Équipe 3 – Phase 2 : Persistance MongoDB des définitions de tests API - #55

Merged
Valeeeu merged 10 commits into
devfrom
feature/MongoDB
Mar 13, 2026
Merged

Équipe 3 – Phase 2 : Persistance MongoDB des définitions de tests API#55
Valeeeu merged 10 commits into
devfrom
feature/MongoDB

Conversation

@michelzzw

@michelzzw michelzzw commented Mar 11, 2026

Copy link
Copy Markdown

Équipe 3 - Phase 2 : Persistance MongoDB des définitions de tests API

Summary

This PR delivers a Phase 2 component for Équipe 3 - Persistance MongoDB des définitions de tests API + corrections d'affichage frontend. The objective was to persist API test definitions to MongoDB so that users don't lose their test configurations on page refresh, add edit functionality for existing tests, fix several frontend display bugs, and clean up legacy dead code.

Before this PR, test definitions existed only in frontend memory - refreshing the page or logging out wiped all configured tests. Users had to re-enter every test definition from scratch each session. There was also no way to edit an existing test (only add or delete), and the delete operation had an index-based bug that caused wrong tests to be removed after any prior deletion.

After our changes, test definitions are automatically persisted to MongoDB with per-user isolation (via JWT username). Tests survive page refreshes and logouts. Users can edit existing tests. Delete correctly targets the intended row regardless of prior operations. Legacy scaffolding code (TestController) has been removed.

Note sur le schéma de base de données : La collection api_test_definitions et l'entité ApiTestDefinition constituent un **schéma préliminaire conçu pour répondre aux besoins immédiats du module TestAPI (Équipe 3). Ce schéma est destiné à être intégré et harmonisé avec les schémas des autres équipes (Selenium, Gatling, Performance) lors d'une phase ultérieure de consolidation, afin d'établir un modèle de données unifié pour l'ensemble du framework TAF.

Problems Found & Changes Made

1. Test definitions lost on page refresh – no persistence

Problem: API test definitions lived exclusively in a BehaviorSubject<testModel2[]> in the Angular frontend. There was no backend storage – refreshing the browser, navigating away, or restarting the Docker containers erased all configured tests. This was the most impactful usability issue: users in a testing session could lose dozens of carefully configured test cases.

Changes (Backend – MongoDB persistence):

  • Created ApiTestDefinition.java (entity/ApiTestDefinition.java):

    • MongoDB document entity mapped to collection api_test_definitions
    • Fields: id (ObjectId), username (JWT owner), method, apiUrl, headers, expectedHeaders, input, expectedOutput, statusCode, responseTime, createdAt, updatedAt
    • @Document(collection = "api_test_definitions") with Lombok @Data
  • Created ApiTestDefinitionRepository.java (repository/ApiTestDefinitionRepository.java):

    • Spring Data MongoDB repository with findByUsername(String username) query
    • Per-user isolation: each user only sees their own test definitions
  • Created ApiTestDefinitionController.java (controller/ApiTestDefinitionController.java):

    • Full CRUD REST API at /api/testapi/definitions (JWT-protected)
    • GET / – list all definitions for the authenticated user
    • POST / – create a new definition (username extracted from JWT)
    • PUT /{id} – update (with ownership verification → 403 if not owner)
    • DELETE /{id} – delete (with ownership verification → 403 if not owner)
    • 404 response for non-existent IDs

Changes (Frontend – HTTP persistence):

  • Modified TestApiService (_services/test-api.service.ts):

    • Added DEFINITIONS_API endpoint constant
    • loadDefinitions() – GET from backend, populate listTests and BehaviorSubject
    • addTestOnList() – POST to backend after adding locally, stores returned mongoId
    • updateTest() – PUT to backend when editing
    • deleteTest() – DELETE from backend when removing
    • toBackend() / fromBackend() – conversion between frontend testModel2 and backend DTO
  • Modified testModel2 (models/testmodel2.ts):

    • Added optional mongoId?: string field to track the MongoDB document ID
  • Modified TestApiComponent (test-api.component.ts):

    • ngOnInit() calls loadDefinitions() to restore persisted tests on page load

2. No way to edit an existing test

Problem: Once a test was added to the table, the only options were to delete it and re-create it. There was no edit button or edit flow.

Changes:

  • Modified AddTestDialogComponent (add-test-dialog.component.ts):

    • Added isEditMode flag and editingId tracking
    • When data is passed (edit mode), pre-populates all form fields including headers
    • saveForm() calls updateTest() in edit mode, addTestOnList() in create mode
  • Modified add-test-dialog.component.html:

    • Dialog title changes: "Ajouter un test" vs "Modifier le test"
    • Save button text changes: "Ajouter" vs "Sauvegarder"
  • Modified test-api.component.ts:

    • Added editTest(test) method that opens AddTestDialogComponent with test data
  • Modified test-api.component.html:

    • Added edit button (pencil icon) in the action column of each table row
图片

3. Delete removes wrong test after prior deletions

Problem: deleteTest(id) used id - 1 as the array index (this.listTests.splice(id - 1, 1)). This assumed test IDs always matched their array position. After any deletion, IDs no longer aligned with indices – e.g., after deleting test #2, the remaining tests had IDs [1, 3, 4], so deleting "test #3" would splice index 2 (actually test #4).

Change (test-api.service.ts):

  • Replaced splice(id - 1, 1) with findIndex(t => t.id === id) to locate the correct element
  • Added sequential ID renumbering after each deletion: this.listTests.forEach((t, i) => t.id = i + 1)

4. Dialog close caused subscription leaks and race conditions

Problem: Every dialog close (addTest, editTest, deleteTest) called this.ngOnInit(), which:

  1. Created a new subscription to tests$ each time (subscription leak – never unsubscribed)
  2. Triggered loadDefinitions() which raced with the just-issued POST/PUT/DELETE HTTP call, potentially overwriting the local state with stale server data

Additionally, deleteTest() had a stray this.getTestList() call outside the dialog close callback, executing immediately regardless of user confirmation.

Changes (test-api.component.ts):

  • Removed ngOnInit() calls from all dialog afterClosed() callbacks – the BehaviorSubject already propagates changes reactively
  • Removed the stray getTestList() call outside the delete dialog

5. Gherkin "Appliquer" replaced all tests instead of appending

Problem: When clicking "Appliquer" in Gherkin mode, onGherkinTestsReady() called clearTests() before adding the parsed Gherkin tests. This erased all existing tests (including those loaded from MongoDB) and only kept the newly parsed ones.

Change (test-api.component.ts):

  • Removed clearTests() call – Gherkin tests now append to the existing list

6. Eureka service discovery – intermittent 500 errors in Docker

Problem: The backend registered with Eureka using its Docker container ID as hostname (e.g., 88f36aa23000). The gateway couldn't reliably resolve this hostname via Docker DNS, causing alternating 200/500 responses on consecutive requests to the same endpoint.

Change (docker-compose-local-test.yml):

  • Added EUREKA_INSTANCE_PREFER_IP_ADDRESS: "true" to backend-team2 environment
  • Backend now registers with its IP address instead of container hostname

7. Legacy TestController – dead code removal

Problem: TestController.java contained 3 hardcoded endpoints (/api/test/all, /api/test/user, /api/test/admin) that returned static strings like "User Content.". These were scaffolding endpoints created during initial project setup with no business logic. They also had a dedicated permitAll() rule in WebSecurityConfig for /api/test/**.

Changes:

  • Deleted TestController.java and TestControllerTest.java (3 tests removed)
  • Modified WebSecurityConfig.java: Removed .requestMatchers("/api/test/**").permitAll()
  • Modified WebSecurityConfigTest.java: Removed TestController import, removed from @WebMvcTest, removed /api/test/all test (7 → 6 tests)

8. Logout did not clear test list from screen

Problem: AppComponent.logout() called window.location.reload() which reloaded the current page (e.g. /test-api). After reload, TestApiComponent.ngOnInit() still fired and called loadDefinitions() without a JWT token, triggering a 401 that raced with the page render. The user could briefly see stale test data on the logged-out page.

Changes:

  • app.component.ts: Changed window.location.reload()window.location.href = '/login' – logout now navigates directly to the login page
  • test-api.component.ts: Added TokenStorageService injection and guard if (this.tokenStorage.getToken()) before calling loadDefinitions() – no HTTP request is made when not authenticated

Testing & Validation

All changes validated in local Docker environment (docker-compose-local-test.yml).

Backend Test Results

[INFO] Tests run: 84, Failures: 0, Errors: 0, Skipped: 1
[INFO] BUILD SUCCESS

84 tests (83 passing + 1 skipped contextLoads). Net change: +9 (ApiTestDefinitionController) −3 (TestController) −1 (WebSecurityConfig test all) = +5 from 79.

Frontend Test Results

TOTAL: 80 SUCCESS

80 specs across all frontend test suites. 0 failures. Net change: +4 new tests for persistence and edit functionality.

JaCoCo Coverage (Team Controllers)

Controller Instructions Branches Lines
ApiTestDefinitionController 100% 100% 100%
AuthController 100% 100% 100%
OAuth2Controller 100% n/a 100%
TestApiController 100% 100% 100%

TestController removed – no longer tracked. All remaining team-owned controllers at 100%.

MongoDB Persistence Validation

Step Action Expected Result Actual Result
1 Login, add 3 API tests Tests appear in table ✅ Pass
2 Refresh page (F5) Same 3 tests reloaded from MongoDB ✅ Pass
3 Edit test #2 (change method GET→POST) Test updated in table and MongoDB ✅ Pass
4 Delete test #1 Test removed, remaining IDs renumbered 1,2 ✅ Pass
5 Delete test #2 Only test #1 remains ✅ Pass
6 Login as different user Empty test list (per-user isolation) ✅ Pass
7 Gherkin "Appliquer" with 2 scenarios 2 tests appended to existing list ✅ Pass
8 Restart Docker containers Tests persist across restart ✅ Pass

Eureka DNS Fix Validation

Test Before Fix After Fix
5 consecutive GET requests to gateway Alternating 200/500 5× stable 401 (correct – no JWT)

System Health

Service Status Port
mongodb healthy 27017
registry healthy 8761
gateway running 8080
backend-team2 healthy 8084
testapi-team2 running 8086
frontend-team2 running 4300
mongo-express running 8881

Files Modified

New Files

File Description
backend/src/.../entity/ApiTestDefinition.java MongoDB entity – api_test_definitions collection
backend/src/.../repository/ApiTestDefinitionRepository.java Spring Data repo with per-user query
backend/src/.../controller/ApiTestDefinitionController.java CRUD REST API – /api/testapi/definitions
backend/src/test/.../ApiTestDefinitionControllerTest.java 9 tests – CRUD + ownership + 404/403

Deleted Files

File Reason
backend/src/.../controller/TestController.java Legacy scaffolding – 3 hardcoded string endpoints, no business logic
backend/src/test/.../controller/TestControllerTest.java Tests for deleted controller

Modified Files (Backend)

File Type of Change
backend/src/.../security/WebSecurityConfig.java Removed /api/test/** permitAll rule
backend/src/test/.../security/WebSecurityConfigTest.java Removed TestController ref, updated @WebMvcTest, 7→6 tests

Modified Files (Frontend)

File Type of Change
frontend/src/app/_services/test-api.service.ts Added HTTP persistence (CRUD), fixed deleteTest index bug, added ID renumbering
frontend/src/app/_services/test-api.service.spec.ts +4 tests for persistence, updated delete assertion
frontend/src/app/models/testmodel2.ts Added mongoId?: string field
frontend/src/app/.../test-api/test-api.component.ts Added editTest(), loadDefinitions() on init (guarded by token check), removed subscription leaks, Gherkin append fix
frontend/src/app/.../test-api/test-api.component.html Added edit button in action column
frontend/src/app/.../test-api/test-api.component.spec.ts Updated for removed ngOnInit calls
frontend/src/app/.../add-test-dialog/add-test-dialog.component.ts Added edit mode (pre-populate form, updateTest on save)
frontend/src/app/.../add-test-dialog/add-test-dialog.component.html Dynamic title/button text for add vs edit
frontend/src/app/app.component.ts Logout redirects to /login instead of window.location.reload()

Modified Files (Infrastructure)

File Type of Change
docker-compose-local-test.yml Added EUREKA_INSTANCE_PREFER_IP_ADDRESS: "true" for backend-team2, added mongo-express service (port 8881)

Modified Files (Documentation)

File Type of Change
testapi-Service/README.md Added MongoDB persistence section, updated test count 79→84
testapi-Service/TEST-REPORT.md Added ApiTestDefinitionController, removed TestController, updated counts

Commit History

# Commit Description
1 615f602 feat(frontend): add edit button for existing API tests – 9 files
2 93ab863 feat: persist API test definitions to MongoDB – 9 files, 495 insertions
3 5868c49 fix: Gherkin appliquer now appends instead of replacing all tests – 3 files
4 4fbab10 refactor: remove legacy TestController (unused scaffolding endpoints) – 4 files
5 fda2f13 fix: correct delete/edit display logic in frontend – 4 files
6 4f67677 docs: update README and TEST-REPORT for MongoDB persistence – 2 files
7 8e43659 fix: redirect to /login on logout and guard loadDefinitions – 3 files
8 c27e92b docs: add Mongo Express to verification table in README – 1 file
9 038c013 fix: address Copilot code review findings (PR #55) – 8 files

Modified Files (Code Review Fixes)

File Fix Applied
TestAutomationFrameworkApplicationTests.java Removed unused DisabledIfEnvironmentVariable import
ApiTestDefinitionController.java POST returns 201 Created, DELETE returns 204 No Content, 403 Forbidden for non-owner (instead of 404)
ApiTestDefinitionControllerTest.java Updated test assertions for new HTTP status codes (201, 204, 403)
testapi/Dockerfile Fixed EXPOSE 8090EXPOSE 8082 (actual server port)
application.yml Changed auto-index-creation: falsetrue (enables @Indexed annotations)
UserService.java Removed dead null-check after orElseThrow()
auth.interceptor.ts Added /auth/api/ exclusion to 401 refresh handler
oauth2-callback.component.ts Added base64url padding before atob() to prevent InvalidCharacterError

Architecture Notes

MongoDB Persistence Flow

Frontend Angular                 Backend (8084)                     MongoDB
┌────────────────┐        ┌──────────────────────────┐        ┌──────────────┐
│ TestApiService │─POST──►│ ApiTestDefinitionCtrl    │─save──►│ api_test_    │
│ addTestOnList  │◄──201──│ POST /definitions        │◄───────│ definitions  │
│                │        │                          │        │              │
│ loadDefs()     │─GET───►│ GET /definitions         │─find──►│ {username:   │
│                │◄──200──│ (filtered by JWT user)   │◄───────│  "equipe3"}  │
│                │        │                          │        │              │
│ updateTest()   │─PUT───►│ PUT /definitions/{id}    │─save──►│              │
│                │◄──200──│ (ownership check)        │◄───────│              │
│                │        │                          │        │              │
│ deleteTest()   │─DEL───►│ DELETE /definitions/{id} │─del───►│              │
│                │◄──204──│ (ownership check)        │◄───────│              │
└────────────────┘        └──────────────────────────┘        └──────────────┘

Database Schema (preliminary – api_test_definitions)

{
  "_id": ObjectId("..."),
  "username": "equipe3",          // JWT owner – per-user isolation
  "method": "GET",
  "apiUrl": "https://jsonplaceholder.typicode.com/posts/1",
  "headers": { "Accept": "application/json" },
  "expectedHeaders": {},
  "input": "",
  "expectedOutput": "{\"userId\": 1}",
  "statusCode": 200,
  "responseTime": 5000,
  "createdAt": ISODate("2026-03-11T..."),
  "updatedAt": ISODate("2026-03-11T...")
}

Planned Evolution: This schema is a preliminary design for the TestAPI module's immediate needs. It is intended to be harmonized with the collections of other teams (e.g., Selenium definitions, Gatling scenarios) to create a unified data model covering all test types in the TAF framework. Fields like method, apiUrl, headers could be generalized into a common "test definition" format, and the username field could migrate to a shared project/workspace system.


⚠️ Merge Note for DevOps

If PR #51 (feature/RenewalToken) has already been merged into dev, merging this PR will produce a minor conflict in:

  • testapi-Service/frontend/src/app/oauth2-callback/oauth2-callback.component.ts – both branches add base64url padding restoration before atob(). Keep either version (they are functionally identical).

- Add edit (pencil) icon button in the test table action column
- Reuse AddTestDialogComponent with pre-filled data for editing
- Add updateTest() method to TestApiService
- Add missing input/body field to the test dialog form
- Dialog title and submit button adapt to edit vs add mode
- Add 3 unit tests (79 total, all passing)
- Update README: document edit feature, input field, fix Angular version
- Update TEST-REPORT: branch and date
- Add ApiTestDefinition entity (collection: api_test_definitions)
- Add ApiTestDefinitionRepository with per-user queries
- Add ApiTestDefinitionController (CRUD /api/testapi/definitions)
- Add 9 backend unit tests (88 total, all pass)
- Update frontend TestApiService with HTTP persistence (load/add/update/delete)
- Update TestApiComponent to load definitions on init
- Update frontend tests with HttpTestingController (80 total, all pass)
- Each user's test definitions are isolated by JWT username
- onGherkinTestsReady no longer clears existing tests before adding
- Gherkin-parsed tests are appended to the current list (including DB-loaded ones)
- Fix Eureka DNS issue: add EUREKA_INSTANCE_PREFER_IP_ADDRESS in docker-compose
- 80 frontend tests pass
- Fix deleteTest using id-1 as index (wrong after prior deletions)
- Renumber test IDs sequentially after each deletion
- Remove ngOnInit() calls on dialog close (caused subscription leaks
  and race conditions with backend persistence)
- Remove stray getTestList() outside dialog close in deleteTest
- Update tests to match corrected behavior
- Update test count 79 → 84 (added ApiTestDefinitionController 9 tests,
  removed TestController 3 tests, removed 1 WebSecurityConfig test)
- Add MongoDB persistence API section to README (CRUD endpoints)
- Replace TestController references with ApiTestDefinitionController
- Update WebSecurityConfigTest scenarios (6 tests, no more /api/test/**)
- Note that test definitions persist across page refresh via MongoDB
Copilot AI review requested due to automatic review settings March 11, 2026 13:17
@michelzzw
michelzzw changed the base branch from main to dev March 11, 2026 13:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds MongoDB-backed persistence for API test definitions (per-user), introduces editing support and a Gherkin editor in the Angular UI, and expands auth/security with OAuth2 (Google) + refresh-token support across the stack, alongside various infra/version updates.

Changes:

  • Persist TestAPI definitions in MongoDB with CRUD endpoints and Angular sync (load/add/edit/delete).
  • Add Gherkin editor mode + edit dialog UX improvements; fix delete/indexing and subscription refresh issues.
  • Introduce OAuth2 Google login + refresh-token flow; tighten backend security rules and update Docker/Maven configs.

Reviewed changes

Copilot reviewed 104 out of 106 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
user/src/test/java/ca/etsmtl/taf/user/AuthGatewayApplicationTests.java Fix test package name
user/src/main/java/ca/etsmtl/taf/user/services/UserService.java Update logic + input validation
user/src/main/java/ca/etsmtl/taf/user/services/JwtService.java Remove unused deps/imports
user/src/main/java/ca/etsmtl/taf/user/repository/UserRepository.java Add @NonNull on existsById
user/src/main/java/ca/etsmtl/taf/user/payload/request/PasswordRequest.java Remove unused import
user/src/main/java/ca/etsmtl/taf/user/jwt/JwtUtil.java Remove dead token methods
user/src/main/java/ca/etsmtl/taf/user/jwt/JwtAuthenticationFilter.java Add @NonNull params
user/src/main/java/ca/etsmtl/taf/user/controller/UserController.java Remove unused auth wiring
user/src/main/java/ca/etsmtl/taf/user/AuthGatewayApplication.java Remove unused imports
testapi-Service/testapi/src/main/java/org/requests/payload/request/TestApiRequest.java Migrate validation to jakarta
testapi-Service/testapi/src/main/java/org/requests/TestApiController.java Migrate @Valid to jakarta
testapi-Service/testapi/src/main/java/org/requests/RequestController.java Safer request build + error handling
testapi-Service/testapi/pom.xml Move to Java 17 + Boot mgmt
testapi-Service/testapi/Dockerfile Update builder image + flags
testapi-Service/selenium/src/test/java/ca/etsmtl/selenium/SeleniumApplicationTests.java Remove unused @Test import
testapi-Service/selenium/src/main/java/ca/etsmtl/selenium/requests/UseSelenium.java Selenium 4 API updates
testapi-Service/selenium/src/main/java/ca/etsmtl/selenium/config/DevCorsConfiguration.java Fix package + @NonNull param
testapi-Service/selenium/pom.xml Java 17 + Selenium version bump
testapi-Service/run-tests-testapi.ps1 Add one-click test runner
testapi-Service/pom.xml Parent/BOM updates + CVE override
testapi-Service/gatling/pom.xml Java 17 compiler target
testapi-Service/frontend/yarn.lock Lockfile platform deps adjustments
testapi-Service/frontend/src/environments/environment.ts Local gateway/backend URLs
testapi-Service/frontend/src/environments/environment.prod.ts Add oauth2 backend URL
testapi-Service/frontend/src/app/register/register.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/project/project.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/profile/profile.component.spec.ts Mock TokenStorageService in tests
testapi-Service/frontend/src/app/performance-test-api/gatling-api/gatling-api.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/oauth2-callback/oauth2-callback.component.ts OAuth2 callback token handling
testapi-Service/frontend/src/app/oauth2-callback/oauth2-callback.component.html OAuth2 callback UI
testapi-Service/frontend/src/app/oauth2-callback/oauth2-callback.component.css OAuth2 callback styling
testapi-Service/frontend/src/app/models/testmodel2.ts Add mongoId field
testapi-Service/frontend/src/app/login/login.component.ts Save refresh token + Google login
testapi-Service/frontend/src/app/login/login.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/login/login.component.html Add Google login button
testapi-Service/frontend/src/app/login/login.component.css Add Google button styles
testapi-Service/frontend/src/app/interface-test-api/test-api/test-api.component.ts Load persisted defs + Gherkin mode
testapi-Service/frontend/src/app/interface-test-api/test-api/test-api.component.spec.ts Add tests for Gherkin/edit flows
testapi-Service/frontend/src/app/interface-test-api/test-api/test-api.component.html UI toggle + edit button
testapi-Service/frontend/src/app/interface-test-api/test-api/add-test-dialog/add-test-dialog.component.ts Add edit mode + body input
testapi-Service/frontend/src/app/interface-test-api/test-api/add-test-dialog/add-test-dialog.component.html Dynamic dialog labels + input field
testapi-Service/frontend/src/app/interface-test-api/gherkin-editor/gherkin-editor.component.ts New Gherkin editor component
testapi-Service/frontend/src/app/interface-test-api/gherkin-editor/gherkin-editor.component.spec.ts Unit tests for editor
testapi-Service/frontend/src/app/interface-test-api/gherkin-editor/gherkin-editor.component.html Editor template + preview
testapi-Service/frontend/src/app/interface-test-api/gherkin-editor/gherkin-editor.component.css Editor styling + highlight classes
testapi-Service/frontend/src/app/home/home.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/gatling/gatling.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/board-user/board-user.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/board-admin/board-admin.component.spec.ts Fix test module deps/schemas
testapi-Service/frontend/src/app/app.module.ts Register OAuth2 + Gherkin components
testapi-Service/frontend/src/app/app.component.spec.ts Relax schema + remove brittle title tests
testapi-Service/frontend/src/app/app-routing.module.ts Add /oauth2/callback route
testapi-Service/frontend/src/app/_services/user.service.spec.ts Add HttpClientTestingModule
testapi-Service/frontend/src/app/_services/token-storage.service.ts Add refresh token storage
testapi-Service/frontend/src/app/_services/test-api.service.ts CRUD persistence to backend + fixes
testapi-Service/frontend/src/app/_services/test-api.service.spec.ts Add persistence/edit/delete tests
testapi-Service/frontend/src/app/_services/performance-test-api.service.spec.ts Add HttpClientTestingModule
testapi-Service/frontend/src/app/_services/gherkin-parser.service.ts New lightweight Gherkin parser
testapi-Service/frontend/src/app/_services/auth.service.ts Add refresh-token API call
testapi-Service/frontend/src/app/_services/auth.service.spec.ts Add HttpClientTestingModule
testapi-Service/frontend/src/app/_helpers/auth.interceptor.ts Bearer header + refresh-on-401 logic
testapi-Service/frontend/package.json Formatting-only
testapi-Service/frontend/angular.json Increase build budget thresholds
testapi-Service/documentation/CONVENTIONS.md Document test conventions
testapi-Service/build.sh Fix env var names (DOCKER_*)
testapi-Service/backend/src/test/resources/application.yml New test config + excludes
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/services/UserDetailsServiceImplTest.java New unit tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/services/UserDetailsImplTest.java New unit tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/oauth2/OAuth2LoginSuccessHandlerTest.java OAuth2 handler tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/jwt/JwtUtilsTest.java JWT + refresh token tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/jwt/AuthTokenFilterTest.java Filter behavior tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/jwt/AuthEntryPointJwtTest.java 401 JSON body tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/security/WebSecurityConfigTest.java Security rules tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/payload/response/MessageResponseTest.java DTO tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/payload/response/JwtResponseTest.java DTO tests (refreshToken added)
testapi-Service/backend/src/test/java/ca/etsmtl/taf/entity/UserEntityTest.java Entity tests (provider/googleId)
testapi-Service/backend/src/test/java/ca/etsmtl/taf/entity/RoleTest.java Role tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/controller/TestApiControllerTest.java Controller tests + embedded server
testapi-Service/backend/src/test/java/ca/etsmtl/taf/controller/OAuth2ControllerTest.java OAuth2 controller tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/controller/AuthControllerTest.java Auth + refresh-token tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/controller/ApiTestDefinitionControllerTest.java CRUD persistence controller tests
testapi-Service/backend/src/test/java/ca/etsmtl/taf/TestAutomationFrameworkApplicationTests.java Disable full-context test
testapi-Service/backend/src/main/resources/application.yml OAuth2 + refresh + index config
testapi-Service/backend/src/main/java/ca/etsmtl/taf/security/oauth2/OAuth2LoginSuccessHandler.java OAuth2 success handling + redirect
testapi-Service/backend/src/main/java/ca/etsmtl/taf/security/jwt/JwtUtils.java Add refresh + username helper APIs
testapi-Service/backend/src/main/java/ca/etsmtl/taf/security/WebSecurityConfig.java Tighten routes + OAuth2 login
testapi-Service/backend/src/main/java/ca/etsmtl/taf/repository/UserRepository.java Add findByEmail/findByGoogleId
testapi-Service/backend/src/main/java/ca/etsmtl/taf/repository/ApiTestDefinitionRepository.java New per-user definition queries
testapi-Service/backend/src/main/java/ca/etsmtl/taf/payload/response/JwtResponse.java Add refreshToken field
testapi-Service/backend/src/main/java/ca/etsmtl/taf/payload/request/TestApiRequest.java Swagger schema examples
testapi-Service/backend/src/main/java/ca/etsmtl/taf/payload/request/SignupRequest.java Swagger schema examples
testapi-Service/backend/src/main/java/ca/etsmtl/taf/payload/request/RefreshTokenRequest.java New refresh request DTO
testapi-Service/backend/src/main/java/ca/etsmtl/taf/payload/request/LoginRequest.java Swagger schema examples
testapi-Service/backend/src/main/java/ca/etsmtl/taf/entity/User.java Add provider/googleId + username size
testapi-Service/backend/src/main/java/ca/etsmtl/taf/entity/ApiTestDefinition.java New Mongo document for definitions
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/TestSeleniumController.java Add OpenAPI security requirement
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/TestController.java Removed legacy controller (deleted)
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/TestApiController.java Add OpenAPI security requirement
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/OAuth2Controller.java Add OAuth2 helper endpoint
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/GatlingApiController.java Add OpenAPI security requirement
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/AuthController.java Add refresh-token endpoint
testapi-Service/backend/src/main/java/ca/etsmtl/taf/controller/ApiTestDefinitionController.java New CRUD definitions controller
testapi-Service/backend/src/main/java/ca/etsmtl/taf/config/OpenApiConfig.java Add OpenAPI + bearer scheme
testapi-Service/backend/src/main/java/ca/etsmtl/taf/config/MongoAuditingConfig.java Enable auditing outside main app
testapi-Service/backend/src/main/java/ca/etsmtl/taf/TestAutomationFrameworkApplication.java Move auditing to config class
testapi-Service/backend/pom.xml OAuth2 dep + profiles + JaCoCo
testapi-Service/backend/pom.docker.xml OAuth2 dep for Docker build
testapi-Service/backend/.env Local env tweaks (JWT/Mongo/Eureka)
testapi-Service/TEST-REPORT.md New unit test report doc
testapi-Service/Dockerfile.local Skip tests for Docker packaging
testapi-Service/CONTRIBUTING.md Add backend test instructions
testapi-Service/.env Fix DOCKER_* vars + simplify
testapi-Service/.docker_config.env.old Remove old config file (deleted)
registry/src/test/java/ca/estmtl/taf/registry/RegistryApplicationTests.java Package change in test
gateway/src/main/java/ca/etsmtl/taf/gateway/GatewayApplication.java Remove unused imports
docker-compose-local-test.yml Add testapi-team2 + Eureka IP pref
auth/src/main/java/ca/etsmtl/taf/auth/services/JwtService.java Remove unused imports
auth/src/main/java/ca/etsmtl/taf/auth/services/CustomUserDetailsService.java Remove unused imports
.vscode/settings.json Add Java workspace exclusions
.gitignore Ignore *.py files
Comments suppressed due to low confidence (1)

testapi-Service/testapi/src/main/java/org/requests/RequestController.java:207

  • checkResponseHeaders() does not fail when an expected header is missing: when foundValue == null, the code continues without setting ok = false. This makes tests incorrectly pass when required headers are absent. Set ok = false for missing required headers and ensure the collected details are surfaced in the returned Answer (currently messages here are not added to answer.messages).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test class has an unused import (DisabledIfEnvironmentVariable). In Java, unused imports are compilation errors and will fail the build. Remove the unused import or switch to using that conditional disable annotation instead of @Disabled.

Suggested change
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +37
@PostMapping
public ResponseEntity<ApiTestDefinition> create(@RequestBody ApiTestDefinition def, Authentication auth) {
def.setId(null);
def.setUsername(auth.getName());
return ResponseEntity.ok(repository.save(def));
}

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create/delete endpoints currently return 200 OK. For a CRUD REST API, it’s more conventional to return 201 Created on POST (optionally with a Location header) and 204 No Content on DELETE. Aligning status codes will make the API easier to integrate with and matches the PR description expectations.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to 9
RUN mvn clean install -DskipTests -B

EXPOSE 8090
ENTRYPOINT ["mvn", "spring-boot:run" ] No newline at end of file

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EXPOSE 8090 does not match the service port used elsewhere for this module (the runtime config/compose expects 8082). This mismatch makes the container harder to run/debug and can lead to incorrect port mappings/healthchecks. Update the exposed port to the actual server port (or align the server port configuration to 8090).

Copilot uses AI. Check for mistakes.
@@ -13,6 +13,21 @@ spring:
database: ${DB_NAME}
auto-index-creation: false

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing spring.data.mongodb.auto-index-creation to false disables automatic creation of indexes declared via @Indexed (including unique indexes on User). Unless indexes are created via migrations/scripts, this can silently remove uniqueness guarantees and hurt query performance. Either keep auto-index creation enabled or document/provide a migration step to create the required indexes.

Suggested change
auto-index-creation: false
auto-index-creation: true

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +53
String username = auth.getName();
return repository.findById(id)
.filter(existing -> username.equals(existing.getUsername()))
.map(existing -> {
def.setId(id);
def.setUsername(username);
def.setCreatedAt(existing.getCreatedAt());
return ResponseEntity.ok(repository.save(def));
})
.orElse(ResponseEntity.notFound().build());
}

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ownership check returns 404 Not Found when the definition exists but belongs to another user. The PR description mentions 403 Forbidden for this case; 404 vs 403 has different semantics for API clients. Consider returning 403 for "exists but not owner" (and reserve 404 for truly missing IDs).

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +128
// Redirect to frontend with JWT token, refresh token, and user info
String redirectUrl = frontendRedirectUrl + "/oauth2/callback?token=" + jwtToken + "&refreshToken=" + refreshToken + "&userInfo=" + userInfoBase64;
log.info("Redirecting OAuth2 user to: {}", frontendRedirectUrl + "/oauth2/callback?token=***");

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OAuth2 success handler builds a redirect URL that includes the access token and refresh token as query parameters. Tokens in query params are commonly leaked via browser history, referer headers, and logs/proxies. Consider returning tokens via an HTTP-only secure cookie or at least putting them in the URL fragment (#...) instead of the query string, and avoid logging any part of the token-bearing URL.

Suggested change
// Redirect to frontend with JWT token, refresh token, and user info
String redirectUrl = frontendRedirectUrl + "/oauth2/callback?token=" + jwtToken + "&refreshToken=" + refreshToken + "&userInfo=" + userInfoBase64;
log.info("Redirecting OAuth2 user to: {}", frontendRedirectUrl + "/oauth2/callback?token=***");
// Redirect to frontend with JWT token, refresh token, and user info in the URL fragment
String redirectUrl = frontendRedirectUrl + "/oauth2/callback#token=" + jwtToken + "&refreshToken=" + refreshToken + "&userInfo=" + userInfoBase64;
log.info("Redirecting OAuth2 user to: {}", frontendRedirectUrl + "/oauth2/callback#token=***");

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +46
if(!signUpRequest.getFullName().isEmpty())
user.setFullName(signUpRequest.getFullName());
if(signUpRequest.getEmail().isEmpty())
if(!signUpRequest.getEmail().isEmpty())
user.setEmail(signUpRequest.getEmail());

return userRepository.save(user);
if (user != null) {
return userRepository.save(user);
}
return user;

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user is never null here because orElseThrow() would have already thrown. The extra if (user != null) branch adds dead code and makes the flow harder to read; return userRepository.save(user) directly.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +34
catchError((error: HttpErrorResponse) => {
// Only attempt refresh on 401 errors and if the request is not itself a refresh/auth request
if (error.status === 401 && !req.url.includes('/api/auth/')) {
return this.handle401Error(authReq, next);
}

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refresh-on-401 exclusion only checks for URLs containing "/api/auth/", but the frontend login/signup calls go to ".../auth/api/...". As a result, a 401 from login/signup can incorrectly trigger the refresh-token flow (and possible logout/redirect). Update the exclusion condition to also skip the gateway auth path (or use a more robust allow/deny list for refreshable requests).

Copilot uses AI. Check for mistakes.
Comment on lines 1 to +4
export const environment = {
production: true,
apiUrl: '/my-backend'
apiUrl: '/my-backend',
oauth2BackendUrl: 'http://localhost:8084'

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oauth2BackendUrl is set to a hard-coded localhost URL in the production environment file. This will break OAuth2 redirect/refresh flows in any deployed environment. Consider using a relative URL, the gateway base URL, or injecting the backend URL via deployment-time configuration.

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +45
if (userInfoBase64) {
// Decode base64url user info
const json: string = atob(userInfoBase64.replace(/-/g, '+').replace(/_/g, '/'));
const userInfo: Record<string, unknown> = JSON.parse(json);
this.tokenStorage.saveUser(userInfo);
} else {

Copilot AI Mar 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userInfo is encoded as base64url without padding on the backend, but the frontend decodes with atob() after only replacing '-'/'_'. atob() can throw on unpadded base64 (length not multiple of 4), causing OAuth2 login to fail. Add proper base64 padding before decoding (and keep the try/catch scoped so a decode failure can still fall back to the minimal user object).

Copilot uses AI. Check for mistakes.
- AppComponent.logout() now redirects to /login instead of reloading current page
- TestApiComponent.ngOnInit() only calls loadDefinitions() when JWT token exists
- Add mongo-express service to docker-compose-local-test.yml (port 8881)
- Remove duplicate mongo-express definition
- Remove unused DisabledIfEnvironmentVariable import
- POST /definitions returns 201 Created instead of 200
- DELETE /definitions returns 204 No Content instead of 200
- Return 403 Forbidden (not 404) when user lacks ownership
- Fix testapi Dockerfile EXPOSE 8090 -> 8082 (actual port)
- Enable auto-index-creation for @indexed annotations
- Remove dead null-check in UserService after orElseThrow()
- Add /auth/api/ exclusion in auth.interceptor 401 handler
- Add base64url padding in oauth2-callback before atob()
@michelzzw michelzzw changed the title Équipe 3 — Phase 2 : Persistance MongoDB des définitions de tests API Équipe 3 - Phase 2 : Persistance MongoDB des définitions de tests API Mar 11, 2026
@michelzzw michelzzw changed the title Équipe 3 - Phase 2 : Persistance MongoDB des définitions de tests API Équipe 3 – Phase 2 : Persistance MongoDB des définitions de tests API Mar 11, 2026
@Valeeeu
Valeeeu self-requested a review March 11, 2026 23:54
@Valeeeu
Valeeeu merged commit 7920c87 into dev Mar 13, 2026
2 of 3 checks passed
@Valeeeu
Valeeeu deleted the feature/MongoDB branch March 13, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants