diff --git a/frontend/cypress/tests/chartView/chartView_scrollToActiveRepo.cy.js b/frontend/cypress/tests/chartView/chartView_scrollToActiveRepo.cy.js new file mode 100644 index 0000000000..97afc7b1ea --- /dev/null +++ b/frontend/cypress/tests/chartView/chartView_scrollToActiveRepo.cy.js @@ -0,0 +1,62 @@ +describe('scroll to active repo', () => { + // need to set scrollBehavior to false because the default behavior is to scroll the element into view + it('selecting a visible repo should not scroll', { scrollBehavior: false }, () => { + // close the error message box + cy.get('.error-message-box') + .should('be.visible'); + + cy.get('#summary-wrapper > #summary > .error-message-box > .error-message-box__close-button') + .click(); + + cy.get('.error-message-box') + .should('not.be.visible'); + + cy.get('.icon-button.fa-code') + .should('exist') + .first(); + + let scrollTopOriginal = 0; + cy.get('#summary-wrapper') + .first() + .then(($el) => { + scrollTopOriginal = $el.prop('scrollTop'); + }); + + cy.get('.icon-button.fa-code') + .should('exist') + .first() + .click(); + + cy.get('#summary-wrapper') + .first() + .then(($el) => { + const scrollTop = $el.prop('scrollTop'); + expect(scrollTop).to.equal(scrollTopOriginal); + }); + }); + + it('selecting a non-visible repo should scroll', () => { + cy.get('.icon-button.fa-code') + .should('exist') + .last() + .click(); + + cy.get('#summary-wrapper') + .first() + .then(($el) => { + const scrollTop = $el.prop('scrollTop'); + expect(scrollTop).to.not.equal(0); + }); + + cy.url() + .should('contain', 'tabAuthor=yong24s') + .should('contain', 'tabRepo=reposense%2FRepoSense%5Bcypress%5D'); + + cy.reload(); + + cy.get('.icon-button.fa-code') + .should('exist') + .last() + .should('be.visible'); + }); +}); diff --git a/frontend/cypress/tests/codeView/codeView_codeHighlighting.cy.js b/frontend/cypress/tests/codeView/codeView_codeHighlighting.cy.js new file mode 100644 index 0000000000..adbd9c338c --- /dev/null +++ b/frontend/cypress/tests/codeView/codeView_codeHighlighting.cy.js @@ -0,0 +1,67 @@ +// Assumes: RepoSense repo from 03/05/2018 to current date +describe('code highlighting works properly', () => { + it('should highlight code when there is a single author', () => { + // open the code panel + cy.get('.icon-button.fa-code') + .should('exist') + .first() + .click(); + + cy.get('#tab-authorship .files', { timeout: 90000 }) + .should('be.visible'); + + cy.get('.hljs-comment').contains('* Represents a Git Author.') + .parent() // .line-content + .parent() // .code + .should('have.css', 'background-color', 'rgb(230, 255, 237)'); // #e6ffed + }); + + it('should highlight code when multiple authors are merged in a repo group', () => { + cy.get('div.mui-select.grouping > select:visible') + .select('groupByRepos'); + + cy.get('#summary label.merge-group > input:visible') + .should('be.visible') + .check() + .should('be.checked'); + + // open the code panel + cy.get('.icon-button.fa-code') + .should('exist') + .first() + .click(); + + cy.get('#tab-authorship .files', { timeout: 90000 }) + .should('be.visible'); + + cy.get('.hljs-comment').contains('* MUI Colors module') // eugenepeh + .parent() // .line-content + .parent() // .code + .should('have.css', 'background-color', 'rgba(30, 144, 255, 0.19)') // #1e90ff, transparencyValue 30 + .then((firstAuthorColor) => { + // eslint-disable-next-line quotes + cy.get('.line-content').contains("'red': (") // jamessspanggg + .parent() // .code + // #f08080, transparencyValue 30 + .should('have.css', 'background-color', 'rgba(240, 128, 128, 0.19)') + .and('not.eq', firstAuthorColor); + }); + }); + + it('should not highlight non-attributed lines', () => { + // open the code panel + cy.get('.icon-button.fa-code') + .should('exist') + .first() + .click(); + + cy.get('#tab-authorship .files', { timeout: 90000 }) + .should('be.visible'); + + cy.get('.hljs-title').contains('Author') + .parent() // .hljs-class + .parent() // .line-content + .parent() // .code + .should('have.css', 'background-color', 'rgb(255, 255, 255)'); // #ffffff + }); +}); diff --git a/frontend/src/components/c-summary-charts.vue b/frontend/src/components/c-summary-charts.vue index e017ec6045..7ebe313ddf 100644 --- a/frontend/src/components/c-summary-charts.vue +++ b/frontend/src/components/c-summary-charts.vue @@ -153,7 +153,8 @@ .summary-chart( v-for="(user, j) in getRepo(repo)", v-bind:style="isChartGroupWidgetMode && j === getRepo(repo).length - 1 ? {'marginBottom': 0} : {}", - v-bind:ref="'summary-chart-' + j" + v-bind:ref="'summary-chart-' + j", + v-bind:id="user.name === activeUser && user.repoName === activeRepo ? 'selectedChart' : null" ) .summary-chart__title( v-if="!isGroupMerged(getGroupName(repo))", @@ -428,6 +429,15 @@ export default defineComponent({ this.removeSelectedTab(); } }, + + // watching so highlighted only when summary charts are rendered + filteredRepos() { + this.$nextTick(() => { + if (this.activeRepo !== null && this.activeUser !== null) { + this.scrollToActiveRepo(); + } + }); + }, }, created(): void { this.retrieveSelectedTabHash(); @@ -829,6 +839,8 @@ export default defineComponent({ this.activeTabType = tabType; window.encodeHash(); + + this.$nextTick(() => this.scrollToActiveRepo()); }, removeSelectedTab(): void { @@ -881,6 +893,13 @@ export default defineComponent({ return totalContribution / totalCommits; }, + + scrollToActiveRepo(): void { + const chart = document.getElementById('selectedChart'); + if (chart) { + chart.scrollIntoView({ block: 'nearest' }); + } + }, }, });