From 0f682a0c319cde9aefe268deb97e97816c1b387a Mon Sep 17 00:00:00 2001 From: jonasongg <120372506+jonasongg@users.noreply.github.com> Date: Wed, 31 Jan 2024 21:59:17 +0800 Subject: [PATCH] [#2016] Remove hash symbol from URL when decoding hash (#2086) Fix bug where some params were not retained after refresh The issue pertains to breakdown of file types disappearing after a refresh, but it seems to apply to all params that were last in the URL due to symbols not being filtered out correctly. Let's fix this issue to make sure the state of the report stays the same when refreshing. --- .../codeView/codeView_renderFilterHash.cy.js | 156 ++++++++++++++++++ frontend/src/utils/api.ts | 4 +- 2 files changed, 159 insertions(+), 1 deletion(-) diff --git a/frontend/cypress/tests/codeView/codeView_renderFilterHash.cy.js b/frontend/cypress/tests/codeView/codeView_renderFilterHash.cy.js index 10cc717b0c..ec2c91e869 100644 --- a/frontend/cypress/tests/codeView/codeView_renderFilterHash.cy.js +++ b/frontend/cypress/tests/codeView/codeView_renderFilterHash.cy.js @@ -306,9 +306,13 @@ describe('render filter hash', () => { cy.get('#summary label.filter-breakdown input:visible') .should('not.be.checked'); + // Assumption: gradle is the first file type and yml is the last file type to appear in the list cy.url() .should('not.contain', 'gradle'); + cy.url() + .should('not.contain', 'yml'); + cy.get('#summary label.filter-breakdown input:visible') .check() .should('be.checked'); @@ -316,14 +320,29 @@ describe('render filter hash', () => { cy.get('#summary div.fileTypes input[id="gradle"]') .should('be.checked'); + cy.get('#summary div.fileTypes input[id="yml"]') + .should('be.checked'); + cy.url() .should('contain', 'gradle'); + cy.url() + .should('contain', 'yml'); + cy.reload(); + cy.get('#summary div.fileTypes input[id="gradle"]') + .should('be.checked'); + + cy.get('#summary div.fileTypes input[id="yml"]') + .should('be.checked'); + cy.url() .should('contain', 'gradle'); + cy.url() + .should('contain', 'yml'); + cy.get('#summary div.fileTypes input[id="gradle"]') .uncheck() .should('not.be.checked'); @@ -331,9 +350,146 @@ describe('render filter hash', () => { cy.url() .should('not.contain', 'gradle'); + cy.url() + .should('contain', 'yml'); + cy.reload(); + cy.get('#summary div.fileTypes input[id="gradle"]') + .should('not.be.checked'); + + cy.get('#summary div.fileTypes input[id="yml"]') + .should('be.checked'); + cy.url() .should('not.contain', 'gradle'); + + cy.url() + .should('contain', 'yml'); + }); + + it('code panel: sort by: url params should persist after change and reload', () => { + // open the code panel + cy.get('.icon-button.fa-code') + .should('be.visible') + .first() + .click(); + + cy.get('div.mui-select.sort-by > select:visible') + .invoke('val') + .should('eq', 'linesOfCode'); + + cy.url() + .should('not.contain', 'authorshipSortBy'); + + /* Select file name and test URL before and after reload */ + cy.get('div.mui-select.sort-by > select:visible') + .select('fileName'); + + cy.url() + .should('contain', 'authorshipSortBy=fileName'); + + cy.reload(); + + cy.url() + .should('not.contain', '%23%2F'); + + cy.url() + .should('contain', 'authorshipSortBy=fileName'); + + /* Select file type and test URL before and after reload */ + cy.get('div.mui-select.sort-by > select:visible') + .select('fileType'); + + cy.url() + .should('contain', 'authorshipSortBy=fileType'); + + cy.reload(); + + cy.url() + .should('not.contain', '%23%2F'); + + cy.url() + .should('contain', 'authorshipSortBy=fileType'); + }); + + it('code panel: order: url params should persist after change and reload', () => { + // open the code panel + cy.get('.icon-button.fa-code') + .should('be.visible') + .first() + .click(); + + cy.get('div.mui-select.sort-order > select:visible') + .invoke('val') + .should('eq', 'true'); // true is Descending + + cy.url() + .should('not.contain', 'reverseAuthorshipOrder'); + + /* Select ascending and test URL before and after reload */ + cy.get('div.mui-select.sort-order > select:visible') + .select('false'); + + cy.url() + .should('contain', 'reverseAuthorshipOrder=false'); + + cy.reload(); + + cy.url() + .should('not.contain', '%23%2F'); + + cy.url() + .should('contain', 'reverseAuthorshipOrder=false'); + + /* Select descending and test URL before and after reload */ + + cy.get('div.mui-select.sort-order > select:visible') + .select('true'); + + cy.url() + .should('contain', 'reverseAuthorshipOrder=true'); + + cy.reload(); + + cy.url() + .should('not.contain', '%23%2F'); + + cy.url() + .should('contain', 'reverseAuthorshipOrder=true'); + }); + + it('code panel: filter by glob: url params should persist after change and reload', () => { + // open the code panel + cy.get('.icon-button.fa-code') + .should('be.visible') + .first() + .click(); + + // click on filter glob radio button + cy.get('.radio-button--search') + .should('be.visible') + .click(); + + // enter some input + cy.get('#search') + .type('README.md'); + + // submit + cy.get('#search') + .type('{enter}'); + + cy.url() + .should('contain', 'authorshipFilesGlob=README.md'); + + // Some bugs appear after two reloads, so reload twice here + cy.reload(); + cy.reload(); + + cy.url() + .should('not.contain', '%23%2F'); + + cy.url() + .should('contain', 'authorshipFilesGlob=README.md'); }); }); diff --git a/frontend/src/utils/api.ts b/frontend/src/utils/api.ts index d3bb73e50a..1ac4d3c96b 100644 --- a/frontend/src/utils/api.ts +++ b/frontend/src/utils/api.ts @@ -70,7 +70,9 @@ window.decodeHash = function decodeHash() { const hashParams: { [key: string]: string } = {}; const hashIndex = window.location.href.indexOf(HASH_ANCHOR); - const parameterString = hashIndex === -1 ? '' : window.location.href.slice(hashIndex + 1); + + // split by # to remove "#/" string at the end of URLs generated by Vue Hash Router + const parameterString = hashIndex === -1 ? '' : window.location.href.slice(hashIndex + 1).split('#')[0]; parameterString.split('&') .forEach((param) => {