Skip to content

Auto plugin detection#1144

Merged
pooleycodes merged 7 commits into
mainfrom
automatic-plugin-retrieval
Dec 19, 2025
Merged

Auto plugin detection#1144
pooleycodes merged 7 commits into
mainfrom
automatic-plugin-retrieval

Conversation

@pooleycodes
Copy link
Copy Markdown
Contributor

@pooleycodes pooleycodes commented Dec 12, 2025

Description

This branch implements automatic plugin detection and storage for dataset submissions through the check tool, along with improvements to organisation name handling and error display.

  1. Plugin Detection & Storage in Jira Tickets - Changes to Async now allow this.
  2. Organisation Name Parameter, store in parameter such to no longer use outdate session info.
  3. Enhanced Error Display from the Async Failures - No longer just Fetch Failed, or please try again.
  4. Content-Type Validation Removed - No longer is the content-type in the header checked, this will not work with arcgis, wfs as they have format text/html yet are accepted. Furthermore, the content type validations while exhaustive still did not cover URLs we should accept.

What type of PR is this? (check all applicable)

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Related Tickets & Documents

QA Instructions, Screenshots, Recordings

  1. Go to Doncaster LPA, take one of the submitted URL's for one of the datasets, run this through the check tool, previously this would fail as it was a ArcGIS link, now it should work and show check results with no detectable difference.

  2. Also use a URL that causes a error such as SSL, this should now be nicely displayed.

  3. Finally on JIRA ticket creation, a plugin value should now be automatically created in the IMPORT.csv

NOTE** The JIRA ticket needs a quick live test.

Added/updated tests?

We encourage you to keep the code coverage percentage at 80% and above.

  • Yes
  • No, and this is why: Please replace this line with details on why tests have not been included
  • I need help with writing tests

NOTE** The JIRA ticket creation with plugin needs a quick live test.

QA sign off

  • Code has been checked and approved
  • Design has been checked and approved
  • Product and business logic has been checked and proved

Summary by CodeRabbit

  • New Features

    • Background CSV attachment to service requests including dynamic plugin and organisation info; attachments run async so they don't block request creation.
    • Results banner now shows organisation name when available.
  • Bug Fixes

    • Error pages show richer, more specific messages and surface additional error details.
    • POST validation skipped for 405 responses; front-end filetype check removed.
  • Tests

    • Updated tests for plugin-included CSV, SSL/content-type cases and background attachment behaviour.
  • Documentation / Chores

    • Expanded Jira setup guidance; environment variables now load from a .env file; Jira request type config adjusted/removed in some environments.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 12, 2025

Walkthrough

Polls the async request API after creating an async check to retrieve plugin data, builds a CSV including dynamic plugin and organisationName, and attaches it to Jira asynchronously; organisationName propagated into form payloads; ResultData gains getPlugin(); errorDetail support and templates/tests updated.

Changes

Cohort / File(s) Summary
Check answers controller
src/controllers/CheckAnswersController.js
Adds getRequestData usage to poll the async request API for plugin data; adds attachFileToIssue(requestId, data, description, response) to generate a CSV (now with dynamic plugin) and attach it to Jira asynchronously; attachment errors are logged and non‑blocking; post path error message broadened.
Upload & submit controllers
src/controllers/uploadController.js, src/controllers/submitUrlController.js
getBaseFormData includes organisationName from deep-link session; submit URL flow removes front-end filetype check and skips post-validators when HEAD returns 405; retains exists/restricted403/size checks.
Async request API & model
src/services/asyncRequestApi.js, src/models/requestData.js
postFileRequest / postUrlRequest wire organisationName into payloads; getRequestData() added and axios.get uses { timeout: 15000 }; ResultData gains getPlugin() with null-safety and warning logging.
Error handling & views
src/utils/errors.js, src/controllers/resultsController.js, src/views/check/error-redirect.html, src/views/check/results/results.html
MiddlewareError accepts optional errorDetail; resultsController extracts errMsgDetail into errorDetail; error-redirect.html renders specific messages and iterable errorDetail; results view passes organisationName into datasetBanner.
Config & env
config/index.js, config/default.yaml, config/development.yaml, config/staging.yaml
Loads .env via dotenv in config/index.js; jira.requestTypeId changed in config/default.yaml; Jira blocks removed from development and staging YAMLs.
Tests & README
test/unit/checkAnswersController.test.js, test/unit/publishRequestAPI.test.js, test/acceptance/request_check.test.js, readme.md
Unit tests mock and assert getRequestData/getPlugin() and CSV/plugin inclusion; axios.get timeout asserted; acceptance tests updated for SSL/content-type scenarios; README expanded with Jira sandbox/local spinup guidance (duplicated insertion noted).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant Controller as CheckAnswersController
    participant Session
    participant AsyncAPI as asyncRequestApi
    participant AsyncStore as "Async Request Store"
    participant ResultModel as ResultData
    participant Jira as JiraService
    participant View as Results/View

    User->>Controller: submit form
    Controller->>Session: read session org / organisationName
    Session-->>Controller: organisationName

    Controller->>AsyncAPI: postUrlRequest / postFileRequest (includes organisationName)
    AsyncAPI->>AsyncStore: enqueue request -> returns requestId
    AsyncStore-->>AsyncAPI: requestId
    AsyncAPI-->>Controller: response (requestId)

    alt background attachment (async, non-blocking)
        Controller->>AsyncAPI: getRequestData(requestId) (GET, timeout 15s)
        AsyncAPI->>AsyncStore: HTTP GET
        AsyncStore-->>AsyncAPI: request data (includes plugin)
        AsyncAPI-->>Controller: ResultModel
        Controller->>ResultModel: getPlugin()
        ResultModel-->>Controller: plugin or null
        Controller->>Jira: attachFileToIssue(requestId, CSV-with-plugin, description) (async)
        Jira-->>Controller: attach response / errors logged (non-blocking)
    end

    Controller->>View: render/redirect with organisationName
    View-->>User: results (datasetBanner receives organisationName)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect CheckAnswersController: async polling, CSV generation (plugin column), non‑blocking attachment and log changes.
  • Verify ResultData.getPlugin() guards and warning logging.
  • Confirm organisationName propagation into asyncRequestApi payloads and UploadController.
  • Validate resultsController errorDetail extraction and template changes.
  • Review submitUrlController HEAD 405 skip logic and commented validator rationale.
  • Check updated tests for axios.get timeout and CSV/plugin assertions.

Possibly related PRs

Suggested reviewers

  • DilwoarH
  • rosado

Poem

🐰 I nibbled code and found a thread,

Pulled an org name from a session bed,
I chased a plugin through a waiting queue,
Wove it into CSV rows shiny and new,
Left soft logs behind and let the app hop ahead.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title "Auto plugin detection" accurately reflects the main feature being implemented: automatic detection and storage of plugin information for dataset submissions, which is the central objective of this PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch automatic-plugin-retrieval

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Dec 12, 2025

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 66.41% 6705 / 10096
🔵 Statements 66.41% 6705 / 10096
🔵 Functions 64.23% 273 / 425
🔵 Branches 79.89% 902 / 1129
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
config/index.js 100% 33.33% 100% 100%
src/controllers/CheckAnswersController.js 85.78% 74.07% 100% 85.78% 64-67, 71-74, 87-93, 165-171, 178, 195-200
src/controllers/resultsController.js 58.84% 65% 50% 58.84% 20-39, 66-70, 74-83, 91-92, 94-95, 99-100, 139-141, 170-178, 190-191, 228-229, 238-246, 249-252, 255-267, 280-304, 314-315, 342-344, 360-365, 373-388, 395-416, 428-438, 441-443, 452-465, 512-531
src/controllers/submitUrlController.js 90.09% 73.91% 100% 90.09% 41-43, 126-129, 152-154, 164-165, 171-173, 189-191, 206-208
src/controllers/uploadController.js 100% 100% 100% 100%
src/models/requestData.js 94.68% 94.59% 94.11% 94.68% 45-49, 135-140
src/services/asyncRequestApi.js 96.77% 63.63% 100% 96.77% 68-69
src/utils/errors.js 93.75% 40% 100% 93.75% 29-30
Generated in workflow #1316 for commit 4ea2080 by the Vitest Coverage Report Action

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/views/check/error-redirect.html (1)

11-19: Fix broken ErrorSummary anchor when err.errorDetail is present.

The error summary links to #bad-upload, but that id is only rendered in the else branch—so with err.errorDetail, the summary link target disappears.

 {% if err.errorDetail %}
   {% if err.errorDetail is iterable and err.errorDetail is not string %}
     {% for detail in err.errorDetail %}
-      <p class="govuk-body">{{ detail }}</p>
+      <p class="govuk-body"{% if loop.first %} id="bad-upload" tabindex="-1"{% endif %}>{{ detail }}</p>
     {% endfor %}
   {% else %}
-    <p class="govuk-body">{{ err.errorDetail }}</p>
+    <p class="govuk-body" id="bad-upload" tabindex="-1">{{ err.errorDetail }}</p>
   {% endif %}
 {% else %}
   <p class="govuk-body" id="bad-upload" tabindex="-1">
     Error: {{ err.message }}
   </p>
 {% endif %}

Also applies to: 23-35

src/services/asyncRequestApi.js (1)

61-71: Fix getRequestData error status reporting for Axios errors.

error.status is undefined for Axios errors; use error.response.status instead. Line 70 currently logs an undefined status. Since 404 errors are already handled explicitly, simplify the catch block:

 export const getRequestData = async (resultId, opts = undefined) => {
   const url = new URL(`${config.asyncRequestApi.url}/${config.asyncRequestApi.requestsEndpoint}/${resultId}`)
   try {
     const response = await axios.get(url)
     return new ResultData(response.data)
   } catch (error) {
     if (error?.response?.status === 404) {
       throw error
     }
-    throw new Error(`HTTP error! status: ${error.status}: ${error.message}`, { cause: error })
+    const status = error?.response?.status ?? 'unknown'
+    throw new Error(`HTTP error! status: ${status}: ${error?.message ?? 'unknown error'}`, { cause: error })
   }
 }
🧹 Nitpick comments (5)
src/controllers/submitUrlController.js (1)

199-209: Consider removing unused validation function.

Since the filetype validation has been removed from the validation chain, the validateAcceptedFileType function is now dead code. If the filetype check is being permanently removed (as indicated by the TODO comment), consider removing this function as well to reduce maintenance burden.

Alternatively, if you intend to keep it for future reference or potential re-enablement, add a comment explaining why it's preserved.

test/acceptance/request_check.test.js (1)

312-316: Scope error-message matching to the error region to avoid false positives.

page.getByText(errorMessage) can match incidental content; consider scoping to a known container (e.g. .govuk-error-summary / main content) so “foundError” only trips on the rendered error UI.

src/utils/errors.js (1)

17-34: Document options.errorDetail in MiddlewareError JSDoc.

Helps callers know whether this expects string, string[], etc.

src/controllers/resultsController.js (1)

73-83: Tidy error copy + double-check errMsgDetail is safe to show to end-users.

  • Minor: “occured” → “occurred” (Line 79).
  • Please confirm errMsgDetail doesn’t include stack traces/secrets from the async service.
-      return next(new MiddlewareError('An unknown error occured when processing your endpoint', 500, { template: 'check/error-redirect.html' }))
+      return next(new MiddlewareError('An unknown error occurred when processing your endpoint', 500, { template: 'check/error-redirect.html' }))
test/unit/checkAnswersController.test.js (1)

193-237: Make CSV assertions more specific than toContain('plugin')/toContain('wfs').

To reduce false positives, consider asserting the header row includes a plugin column and that the corresponding row contains wfs in that column (e.g. split lines by \n and commas).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f2a0133 and ae71fb6.

📒 Files selected for processing (11)
  • src/controllers/CheckAnswersController.js (3 hunks)
  • src/controllers/resultsController.js (1 hunks)
  • src/controllers/submitUrlController.js (2 hunks)
  • src/controllers/uploadController.js (1 hunks)
  • src/models/requestData.js (1 hunks)
  • src/services/asyncRequestApi.js (2 hunks)
  • src/utils/errors.js (1 hunks)
  • src/views/check/error-redirect.html (1 hunks)
  • src/views/check/results/results.html (1 hunks)
  • test/acceptance/request_check.test.js (1 hunks)
  • test/unit/checkAnswersController.test.js (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-01-30T10:13:37.085Z
Learnt from: rosado
Repo: digital-land/submit PR: 831
File: src/controllers/resultsController.js:67-75
Timestamp: 2025-01-30T10:13:37.085Z
Learning: Express.js async middleware functions require explicit error handling using try/catch blocks to properly handle asynchronous errors and prevent unhandled promise rejections.

Applied to files:

  • src/controllers/resultsController.js
🧬 Code graph analysis (5)
src/controllers/resultsController.js (1)
src/utils/errors.js (1)
  • MiddlewareError (17-35)
src/models/requestData.js (1)
src/utils/logger.js (1)
  • logger (21-28)
src/controllers/CheckAnswersController.js (1)
src/services/asyncRequestApi.js (2)
  • getRequestData (61-72)
  • getRequestData (61-72)
src/services/asyncRequestApi.js (1)
src/utils/logger.js (1)
  • logger (21-28)
test/unit/checkAnswersController.test.js (1)
src/services/asyncRequestApi.js (6)
  • getRequestData (61-72)
  • getRequestData (61-72)
  • postUrlRequest (23-34)
  • postUrlRequest (23-34)
  • response (44-44)
  • response (64-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: run-tests / test
🔇 Additional comments (8)
src/controllers/submitUrlController.js (1)

79-86: LGTM! Sensible handling for servers that don't support HEAD.

The 405 status handling is appropriate, as some servers disallow HEAD requests. Skipping post validators in this scenario is reasonable, and the logging provides good observability.

src/views/check/results/results.html (1)

48-48: Ensure datasetBanner handles missing/empty organisationName.

If options.requestParams.organisationName can be undefined (e.g. older deep-links), confirm the macro gracefully falls back without rendering “undefined”.

src/controllers/uploadController.js (1)

9-17: Verify session key consistency for organisationName.

This reads deep-link-session-key.orgName; please confirm all entrypoints that reach upload have that key populated (or you have a deliberate fallback elsewhere).

src/services/asyncRequestApi.js (1)

9-34: Confirm async API expects organisationName (camelCase) and consider log redaction.

Two things to sanity-check:

  1. If the async API expects snake_case params, organisationName may be silently dropped.
  2. logger.debug('postUrlRequest', { url, ... }) risks logging secrets in querystrings; consider redacting or logging host-only.
test/unit/checkAnswersController.test.js (1)

5-6: Good: test now covers getRequestData integration for plugin retrieval.

Nice to see the controller’s new dependency explicitly imported and mockable in unit tests.

src/models/requestData.js (1)

134-140: LGTM! Consistent implementation.

The getPlugin() method follows the same defensive pattern as existing methods in this class (e.g., getError(), getColumnFieldLog()), with appropriate null checks and logging. The implementation correctly returns null when the response data is unavailable.

src/controllers/CheckAnswersController.js (2)

76-82: LGTM! Organisation name correctly included in API request.

The addition of organisationName to formData correctly passes the organisation context to the async request API, enabling plugin detection to be associated with the organisation. This is distinct from the data.organisationName used for Jira issue creation (line 53).


144-145: Confirm plugin field requirement with Jira integration team.

When requestData is null or getPlugin() returns null, the CSV will contain an empty value for the plugin column. This is standard csv-stringify v6.5.2 behaviour (null/undefined values convert to empty fields). Verify whether the downstream Jira CSV import process requires this field to be populated, or confirm that empty plugin values are acceptable.

Comment thread src/controllers/CheckAnswersController.js Outdated
Comment thread src/controllers/submitUrlController.js
@pooleycodes pooleycodes linked an issue Dec 12, 2025 that may be closed by this pull request
6 tasks
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/views/check/error-redirect.html (1)

41-41: Consider "an HTML" for consistency with standard grammar.

The phrase "a HTML webpage" could be refined to "an HTML webpage" to align with standard British English grammar conventions.

-      <p class="govuk-body" id="bad-upload" tabindex="-1">The URL returns a HTML webpage. This must be a data file.</p>
+      <p class="govuk-body" id="bad-upload" tabindex="-1">The URL returns an HTML webpage. This must be a data file.</p>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 63400b4 and 05c8661.

📒 Files selected for processing (9)
  • config/default.yaml (1 hunks)
  • config/development.yaml (0 hunks)
  • config/index.js (1 hunks)
  • config/staging.yaml (0 hunks)
  • readme.md (1 hunks)
  • src/controllers/CheckAnswersController.js (3 hunks)
  • src/views/check/error-redirect.html (1 hunks)
  • test/acceptance/request_check.test.js (3 hunks)
  • test/unit/checkAnswersController.test.js (5 hunks)
💤 Files with no reviewable changes (2)
  • config/development.yaml
  • config/staging.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/unit/checkAnswersController.test.js
  • test/acceptance/request_check.test.js
🧰 Additional context used
🧬 Code graph analysis (1)
src/controllers/CheckAnswersController.js (2)
src/services/jiraService.js (3)
  • data (22-30)
  • data (60-60)
  • attachFileToIssue (50-92)
src/services/asyncRequestApi.js (4)
  • response (44-44)
  • response (64-64)
  • getRequestData (61-72)
  • getRequestData (61-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: run-tests / test
🔇 Additional comments (8)
src/views/check/error-redirect.html (1)

24-53: Excellent improvement to error messaging.

The specific error messages for SSL certificate failures and file format issues provide much clearer, actionable guidance to users compared to generic error text. The SSL explanation appropriately balances technical detail with accessibility, and the file format guidance correctly lists the accepted formats including ArcGIS and WFS.

config/default.yaml (1)

106-106: Verify that request type ID 28 is correct for the Jira service desk.

The requestTypeId has been changed from 1 to 28 in the default configuration, which is now used consistently across all environments (development, staging, and production). This must correspond to an actual request type configured in your Jira service desk; an incorrect ID would cause all Jira ticket creation to fail. Please confirm with your Jira administrator that this request type ID is valid for the asynchronous attachment workflow.

readme.md (1)

177-179: Helpful clarification for Sandbox setup.

The addition of Sandbox URL guidance and the alternative spinup section improves the onboarding experience for local Jira development.

src/controllers/CheckAnswersController.js (5)

76-82: LGTM!

The addition of organisationName to the form data correctly aligns with the PR objective to store organisation name in parameters rather than relying solely on session data.


128-137: LGTM!

The fire-and-forget pattern with .catch() for error handling is appropriate here. The CSV attachment runs in the background without blocking the user response, and failures are logged but don't affect the main flow.


159-180: Polling logic is sound.

The retry mechanism with a maximum of 6 attempts and 5-second intervals provides reasonable tolerance for the async API response delay. The early exit when isComplete() returns true is correct—no point retrying if the request has finished processing.


184-187: CSV schema update looks good.

The dynamic plugin value and the addition of the licence column align with the PR objectives. Note that if plugin retrieval fails after all retries, csv-stringify will output an empty cell for the plugin field, which provides graceful degradation.


190-200: LGTM!

Error handling for attachment failures is comprehensive with appropriate logging.

Comment thread config/index.js
Comment thread readme.md Outdated
Comment thread src/views/check/error-redirect.html Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
readme.md (3)

177-178: Fix run-on sentence; clarify Sandbox-vs-alternative guidance.

Line 177 contains a comma splice joining two independent clauses. Additionally, the phrase "this only requires the three env parameters for JIRA to be filled in" is unclear about when/whether to use Sandbox versus the alternative spinup below.

Rewrite lines 177–178 to separate the ideas and clarify the choice:

-Ideally use the Jira Sandbox URL, this only requires the three env parameters for JIRA to be filled in, The JIRA_BASIC_AUTH and JIRA_SERVICE_DESK_ID are the same as the production environment, only the URL needs to be changed to use the Sandbox Jira environment.
+For local development, use the Jira Sandbox URL if possible—it requires only the three JIRA environment variables. The JIRA_BASIC_AUTH and JIRA_SERVICE_DESK_ID remain the same as production; only the JIRA_URL changes to the Sandbox environment.
+
+If you prefer to set up your own instance, follow the alternative steps below.

182-182: Standardise quote style in step 2.

The phrase uses both double and single quotes inconsistently: "Create a 'Customer Desk' Project". For readability, use uniform quoting.

-2. Click on Try for free and "Create a 'Customer Desk' Project"
+2. Click on "Try for free" and create a "Customer Desk" Project

183-185: Clarify vague instructions in steps 3–5.

Steps 3–5 reference actions ("Fill in the form", "create a new user", "create a new project") without specifying where these options are located in the Jira UI or what information to enter.

Expand steps 3–5 with clearer UI navigation cues:

-3. Fill in the form and create a test instance
-4. In the "Users" section, create a new user
-5. In the "Projects" section, create a new project
+3. Fill in the form with your details and create your test instance.
+4. Navigate to the admin or user management area and create a new user account; note the email and temporary password.
+5. In the Projects section, create a new project (or verify that a default project exists).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05c8661 and fe80f49.

📒 Files selected for processing (2)
  • readme.md (1 hunks)
  • src/views/check/error-redirect.html (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/views/check/error-redirect.html

eveleighoj
eveleighoj previously approved these changes Dec 19, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/unit/checkAnswersController.test.js (1)

206-249: LGTM! Consider adding edge case coverage.

The test correctly validates that plugin data is retrieved and included in the CSV. The CSV content verification on lines 242-246 is thorough.

Optionally, consider adding test cases for edge scenarios:

  • Plugin remains null after maximum retries
  • getRequestData fails repeatedly
  • isComplete() returns true but plugin is null

These would help ensure robustness of the polling mechanism, but the current test coverage is adequate for the happy path.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe80f49 and 4ea2080.

📒 Files selected for processing (2)
  • src/controllers/CheckAnswersController.js (4 hunks)
  • test/unit/checkAnswersController.test.js (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-14T16:38:49.883Z
Learnt from: rosado
Repo: digital-land/submit PR: 657
File: test/unit/middleware/issueDetails.middleware.test.js:43-43
Timestamp: 2024-11-14T16:38:49.883Z
Learning: In `test/unit/middleware/issueDetails.middleware.test.js`, template params are verified with a schema, so it's acceptable for the test expectations to use primitive values while the test input uses an object for `issueEntitiesCount`.

Applied to files:

  • test/unit/checkAnswersController.test.js
🧬 Code graph analysis (2)
test/unit/checkAnswersController.test.js (2)
src/services/asyncRequestApi.js (6)
  • response (44-44)
  • response (64-64)
  • getRequestData (61-72)
  • getRequestData (61-72)
  • postUrlRequest (23-34)
  • postUrlRequest (23-34)
src/services/jiraService.js (3)
  • data (22-30)
  • data (60-60)
  • attachFileToIssue (50-92)
src/controllers/CheckAnswersController.js (2)
src/services/jiraService.js (3)
  • data (22-30)
  • data (60-60)
  • attachFileToIssue (50-92)
src/services/asyncRequestApi.js (4)
  • response (44-44)
  • response (64-64)
  • getRequestData (61-72)
  • getRequestData (61-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: run-tests / test
🔇 Additional comments (7)
src/controllers/CheckAnswersController.js (4)

7-7: LGTM!

The getRequestData import is correctly added and used in the new attachFileToIssue method for polling plugin data.


76-82: LGTM!

Adding organisationName to the payload aligns with the PR objective to store organisation name in parameters rather than session data.


128-137: LGTM!

The fire-and-forget pattern for CSV attachment improves user experience by not blocking the response. Attachment errors are logged appropriately and won't disrupt the main flow.


183-201: LGTM!

CSV structure correctly updated to include the plugin column per PR objectives. Error handling for the attachment operation is appropriate.

test/unit/checkAnswersController.test.js (3)

5-5: LGTM!

Import correctly updated to include getRequestData for test mocking.


52-52: LGTM!

Error message assertions correctly updated to match the source implementation.

Also applies to: 62-62


69-126: LGTM!

Tests correctly updated to validate the asynchronous attachment flow and non-blocking behaviour. The spy pattern appropriately verifies that attachment is triggered with the correct parameters, and the test on lines 170-171 correctly reflects that attachment failures don't block Jira request creation.

Also applies to: 150-172

Comment thread src/controllers/CheckAnswersController.js
@pooleycodes pooleycodes merged commit 754d15e into main Dec 19, 2025
5 checks passed
@pooleycodes pooleycodes deleted the automatic-plugin-retrieval branch December 19, 2025 16:40
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.

Show Plugins via Check & Endpoint Submission Form

3 participants