Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check Tool: 'back' link takes user to referrer page , when arriving via deep link. #584

Merged
merged 7 commits into from
Oct 24, 2024

Conversation

rosado
Copy link
Collaborator

@rosado rosado commented Oct 23, 2024

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

  • Bug Fix

Description

Sets the "back" link on page user arrives at via a deep link to the linked from page (using the referer header when available).

Related Tickets & Documents

QA Instructions, Screenshots, Recordings

Go to a task list of any dataset and click the "check service" link, for example

Then click the "Back" link. It should take you back to the task list page.

image

Also worth checking: the "Back" links on further steps do not take you to the task list page.

Note: there is a limitation/bug where going "back" from the upload type will always take you to the /dataset step. This is a limitation in the wizard library (this behaviour is already present in production).

Added/updated tests?

  • Yes

Summary by CodeRabbit

  • New Features

    • Enhanced session data to include referrer information when valid.
    • Introduced a new method to determine the back link URL based on deep link information.
  • Bug Fixes

    • Improved logic for back link assignment in the PageController, including error handling.
  • Tests

    • Added a test suite for validating back link detection in various scenarios.
    • Enhanced mock request object for more comprehensive testing of HTTP headers.

@rosado rosado added the bug Something isn't working label Oct 23, 2024
@rosado rosado self-assigned this Oct 23, 2024
Copy link

github-actions bot commented Oct 23, 2024

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 62.3% 3539 / 5680
🔵 Statements 62.3% 3539 / 5680
🔵 Functions 65.5% 150 / 229
🔵 Branches 81.08% 420 / 518
File Coverage
File Stmts % Branch % Funcs % Lines Uncovered Lines
Changed Files
src/controllers/deepLinkController.js 85.36% 71.42% 100% 85.36% 22-33
src/controllers/pageController.js 88.13% 76.92% 100% 88.13% 17-18, 49-53
Generated in workflow #85 for commit cd70737 by the Vitest Coverage Report Action

Copy link
Contributor

coderabbitai bot commented Oct 24, 2024

Walkthrough

The changes in this pull request primarily enhance the functionality of the DeepLinkController and PageController classes. The DeepLinkController now validates the presence of a referer header and incorporates it into the session data. The PageController introduces a new method for determining the back link URL based on session data, improving the control flow when navigating back in the wizard. Additionally, new tests have been added to ensure the correct functionality of these changes, particularly regarding the back link logic.

Changes

File Change Summary
src/controllers/deepLinkController.js Modified get method to validate referer header and include it in session data.
src/controllers/pageController.js Added wizardBackLink function and modified locals method to use this function for back link logic.
test/unit/PageController.test.js Introduced new test suite for back link detection, covering various session states and URLs.
test/unit/deepLinkController.test.js Enhanced mockRequestObject to include headers property for more comprehensive testing.

Assessment against linked issues

Objective Addressed Explanation
Back button should take user to the last page they were on (Issue #557)

🐇 In the meadow, I hop and play,
With links that guide the users' way.
A back button now leads to the past,
Where memories of pages hold fast.
So come along, let’s jump with glee,
For deep links and wizards, oh so free! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@rosado rosado marked this pull request as ready for review October 24, 2024 09:50
Copy link
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: 4

🧹 Outside diff range and nitpick comments (1)
src/controllers/deepLinkController.js (1)

37-39: Note HTTP spec uses "referer" spelling

The code correctly uses "referer" when checking headers (as per HTTP spec) but uses "referrer" when storing in session. Whilst this works, it might be worth maintaining consistency with either spelling throughout the codebase.

Consider using consistent spelling:

 if (req.headers.referer) {
-  sessionData.referrer = req.headers.referer
+  sessionData.referer = req.headers.referer
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b10507d and b0b9213.

📒 Files selected for processing (4)
  • src/controllers/deepLinkController.js (1 hunks)
  • src/controllers/pageController.js (2 hunks)
  • test/unit/PageController.test.js (1 hunks)
  • test/unit/deepLinkController.test.js (1 hunks)
🔇 Additional comments (6)
src/controllers/pageController.js (1)

12-24: Verify coverage of all required navigation paths

The implementation handles the upload method step as specified in the PR objectives. However, let's verify if all the required paths are covered.

✅ Verification successful

Based on the search results, I can now generate a final response as we have a clear picture of all the navigation paths in the application.

Back navigation implementation correctly covers the required paths

The implementation in wizardBackLink function appropriately handles the two key scenarios:

  • For tree dataset: returns to referrer from /check/geometry-type
  • For non-tree datasets: returns to referrer from /check/upload-method

The search results confirm these are the only two points where deep-link back navigation needs special handling, as they represent the diverging paths in the wizard flow:

  1. Tree dataset path: /check/dataset -> /check/geometry-type
  2. Non-tree dataset path: /check/dataset -> /check/upload-method

The implementation aligns with the PR objectives and covers all the required navigation paths.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other potential navigation paths in the codebase
echo "Searching for route definitions and navigation paths..."
rg -g '!node_modules' -g '*.{js,jsx}' "'/check/.*'" -A 5

Length of output: 13658

test/unit/deepLinkController.test.js (2)

7-7: LGTM: Addition of headers object to mock request

The addition of the empty headers object to the mock request is necessary to support testing the new referer header functionality.


Line range hint 28-52: Additional test cases needed for referer header functionality

The test suite should include cases that verify the new referer header validation functionality. Consider adding test cases for:

  • Request with valid referer header
  • Request with missing referer header
  • Request with invalid referer header format

Here's a script to verify the implementation of referer header handling in the controller:

src/controllers/deepLinkController.js (1)

36-40: Verify referrer usage across the application

The changes store the referrer in the session, but we should verify how this integrates with the rest of the application.

Let's check how this referrer value is used:

✅ Verification successful

Let me gather more specific information about how the deep link session key is accessed.


Based on the search results, I can now provide a final response about the referrer usage:

The referrer implementation is properly integrated within the application

The referrer storage and usage is well-structured:

  • The referrer is stored in the session under the check-tool-deep-link key in deepLinkController.js
  • It's retrieved in pageController.js along with other deep link information
  • The value is used appropriately for back-link navigation, as evidenced by the test cases

The implementation follows a consistent pattern where:

  1. deepLinkController captures and stores the referrer
  2. pageController retrieves and uses it for navigation purposes
  3. The functionality is properly tested in the test suite
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of referrer/referer in the codebase
echo "Searching for referrer usage:"
rg -i "referr?er" --type js

# Specifically look for session access to this value
echo "\nSearching for session access patterns:"
ast-grep --pattern 'sessionModel.get($PATTERN)' 

Length of output: 1059


Script:

#!/bin/bash
# Search for checkToolDeepLinkSessionKey usage and its value
echo "Searching for deep link session key usage:"
rg "checkToolDeepLinkSessionKey" -B 2 -A 2

# Look for sessionModel.get patterns specifically with the deep link key
echo "\nSearching for deep link session access:"
ast-grep --pattern 'sessionModel.get($KEY)'

# Look for any cleanup or removal of the session data
echo "\nSearching for session cleanup:"
rg "sessionModel\.(unset|delete|remove|clear)" --type js

Length of output: 1851

test/unit/PageController.test.js (2)

58-85: 🛠️ Refactor suggestion

Consider additional test cases for edge cases and security

Whilst the current test coverage is good, consider adding these scenarios:

  1. Invalid or malformed referrer URLs
  2. Security implications of using referrer headers

Add these test cases:

it('sanitises malformed referrer URLs', () => {
  const pageController = new PageController({ route: '/upload-method' })
  const req = makeReq({
    deepLinkData: { referrer: 'javascript:alert(1)' }
  })
  pageController.locals(req, {}, vi.fn())
  expect(req.form.options.lastPage).toBe(undefined)
})

it('handles external referrer URLs securely', () => {
  const pageController = new PageController({ route: '/upload-method' })
  const req = makeReq({
    deepLinkData: { referrer: 'https://malicious-site.com' }
  })
  pageController.locals(req, {}, vi.fn())
  expect(req.form.options.lastPage).toBe(undefined)
})

Let's verify the current security measures:

#!/bin/bash
# Description: Check for URL validation in the codebase
# Expected: Find URL validation logic for referrer headers

# Look for URL validation patterns
rg -A 5 'referrer|referer' 

43-86: Verify test coverage aligns with acceptance criteria

The test suite effectively covers the core functionality, but let's verify it matches all acceptance criteria from issue #557.

✅ Verification successful

Let me gather more context about the acceptance criteria mentioned in issue #557 to properly verify the test coverage.


Based on the gathered context, I can now provide a final response as we have sufficient information about both the implementation and the acceptance criteria.

Test coverage adequately verifies acceptance criteria

The test suite effectively covers the acceptance criteria from issue #557. Specifically:

  • The tests verify that clicking the back button on the 'upload method' step takes users back to their referrer page when deep linking is active
  • The test cases cover all key scenarios:
    • Arriving at the deep link entry point (verifies return to referrer)
    • Arriving at other steps (verifies normal wizard flow)
    • Handling cases with and without deep link session information
    • Preserving existing back link behaviour when needed

The implementation in pageController.js aligns with the tests, showing proper handling of the wizardBackLink logic for both deep linking and standard navigation paths.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify implementation matches acceptance criteria
# Expected: Find related controller logic and route definitions

# Look for upload method route definitions
rg -A 5 "upload-method"

# Look for back link logic in controllers
ast-grep --pattern 'backLink = $$$'

Length of output: 10344


Script:

#!/bin/bash
# Look for issue #557 details
gh issue view 557

# Look for wizard back link implementation
rg -A 5 "wizardBackLink"

# Look for deep link related code
ast-grep --pattern 'deepLink'

Length of output: 1842

src/controllers/pageController.js Outdated Show resolved Hide resolved
src/controllers/pageController.js Show resolved Hide resolved
src/controllers/deepLinkController.js Outdated Show resolved Hide resolved
test/unit/PageController.test.js Show resolved Hide resolved
Copy link
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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b0b9213 and a362b24.

📒 Files selected for processing (2)
  • src/controllers/deepLinkController.js (2 hunks)
  • test/unit/PageController.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/unit/PageController.test.js
🔇 Additional comments (1)
src/controllers/deepLinkController.js (1)

58-60: LGTM! Verify session data handling

The session data handling changes look good. The integration with maybeSetReferrer is clean and maintains the existing flow.

Let's verify the session data handling across the codebase:

✅ Verification successful

Let me gather more information about the maybeSetReferrer function to ensure it's properly integrated.


Session data handling and referrer integration verified successfully

The session data handling is consistent across the codebase:

  • The checkToolDeepLinkSessionKey is properly defined and used in both pageController.js and deepLinkController.js
  • The maybeSetReferrer function correctly validates and sets the referrer URL in the session data
  • The referrer is appropriately used in wizardBackLink function for navigation purposes
  • Test coverage confirms the expected behaviour
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent session data handling
# Look for other places where checkToolDeepLinkSessionKey is used
rg -A 3 "checkToolDeepLinkSessionKey" 

Length of output: 1307


Script:

#!/bin/bash
# Check the implementation of maybeSetReferrer
rg -A 5 "maybeSetReferrer" 

# Also check for any referrer-related session handling
rg -A 3 "referrer" 

Length of output: 3456

src/controllers/deepLinkController.js Show resolved Hide resolved
@eveleighoj eveleighoj temporarily deployed to submit-pr-584 October 24, 2024 11:59 Inactive
Copy link
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

🧹 Outside diff range and nitpick comments (1)
src/controllers/pageController.js (1)

36-52: Consider enhancing error handling specificity

The error handling is good, but could be more specific about what went wrong. Consider adding more context to the log message.

Consider this enhancement:

     } catch (e) {
       logger.warn('PageController.locals(): error setting back link', {
         type: types.App,
-        errorMessage: e.message
+        errorMessage: e.message,
+        currentUrl: req?.originalUrl,
+        sessionId: req?.sessionID,
+        hasDeepLinkInfo: !!req?.sessionModel?.get(this.checkToolDeepLinkSessionKey)
       })
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a362b24 and cd70737.

📒 Files selected for processing (1)
  • src/controllers/pageController.js (2 hunks)
🔇 Additional comments (3)
src/controllers/pageController.js (3)

2-3: LGTM! Appropriate logging imports added.

The addition of logging utilities will help with monitoring and debugging the back link functionality.


6-25: 🛠️ Refactor suggestion

Consider additional edge cases and validation

Whilst the implementation handles the core functionality, there are a few areas for improvement:

  1. The function assumes currentUrl will always match exact strings - consider using URL parsing to handle potential query parameters or trailing slashes
  2. No validation for the structure of deepLinkInfo beyond checking for 'referrer'

Consider this enhancement:

+const VALID_ROUTES = {
+  GEOMETRY_TYPE: '/check/geometry-type',
+  UPLOAD_METHOD: '/check/upload-method'
+};
+
 function wizardBackLink (currentUrl, deepLinkInfo) {
+  // Normalise the URL by removing trailing slash and query params
+  const normalisedUrl = new URL(currentUrl, 'http://base').pathname.replace(/\/$/, '')
+
   if (deepLinkInfo && 'referrer' in deepLinkInfo) {
     const { referrer, dataset } = deepLinkInfo
-    if (dataset === 'tree' && currentUrl === '/check/geometry-type') {
+    if (dataset === 'tree' && normalisedUrl === VALID_ROUTES.GEOMETRY_TYPE) {
       return referrer
     }
-    if (dataset !== 'tree' && currentUrl === '/check/upload-method') {
+    if (dataset !== 'tree' && normalisedUrl === VALID_ROUTES.UPLOAD_METHOD) {
       return referrer
     }
   }
   return undefined
 }

Likely invalid or redundant comment.


38-41: Verify referrer handling across the application

Let's ensure the referrer is being properly set and maintained across the application flow.

✅ Verification successful

Let me gather more specific information about the referrer handling implementation.


Referrer handling implementation is properly structured and verified

The implementation shows a well-structured approach to handling referrers:

  • The DeepLinkController correctly captures and validates the referrer URL from request headers
  • The wizardBackLink function properly handles deep link scenarios for both tree and non-tree datasets
  • The referrer is appropriately stored in and retrieved from the session
  • Test coverage confirms the expected behaviour for deep link entry points

The code changes align with the PR objective of fixing back navigation for deep-linked users, with proper referrer handling across the application flow.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all places where referrer might be set or used
echo "Checking referrer usage across the codebase:"
rg -l 'referrer' --type js

echo "\nChecking deep link session key usage:"
rg -l 'check-tool-deep-link' --type js

echo "\nChecking related controller implementations:"
rg -l 'DeepLinkController' --type js

Length of output: 607


Script:

#!/bin/bash
# Check referrer handling implementation in PageController
echo "Checking referrer handling in PageController:"
rg -A 5 -B 5 'referrer' src/controllers/pageController.js

echo "\nChecking referrer handling in DeepLinkController:"
rg -A 5 -B 5 'referrer' src/controllers/deepLinkController.js

echo "\nChecking wizardBackLink implementation:"
ast-grep --pattern 'function wizardBackLink($$$) { $$$ }'

echo "\nChecking related test cases:"
rg -A 5 -B 5 'referrer' test/unit/PageController.test.js

Length of output: 3619

Copy link
Contributor

@GeorgeGoodall-GovUk GeorgeGoodall-GovUk left a comment

Choose a reason for hiding this comment

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

looks good, shame about the edge case of tree and points/polygons. maybe worth making another ticket in the backlog. on the other hand who knows how hacky the solution would end up being?? do we bother??

@rosado
Copy link
Collaborator Author

rosado commented Oct 24, 2024

Correct solution would require a sane API from the wizard library; what it currently exposes is does not make things like this easy. I'm for not opening a ticket unless someone feels really strongly about this and argues for it in planning.

@rosado rosado merged commit 1148958 into main Oct 24, 2024
5 checks passed
@rosado rosado deleted the rosado/557-check-back-button branch October 24, 2024 13:56
@CharliePatterson
Copy link
Contributor

👋 could we please make sure there's a product and/or design review prior to merging and pushing to production?

What's the edge-case situation?

@coderabbitai coderabbitai bot mentioned this pull request Oct 28, 2024
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Change path of 'back' button in check tool
4 participants