diff --git a/cypress/integration/content-display.spec.js b/cypress/integration/content-display.spec.js index 36e51341..bd70939a 100644 --- a/cypress/integration/content-display.spec.js +++ b/cypress/integration/content-display.spec.js @@ -1,66 +1,69 @@ /** - * Copyright (C) 2019-2020 The Software Heritage developers + * Copyright (C) 2019-2022 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ let origin; let url; describe('Test File Rendering', function() { before(function() { origin = this.origin[0]; url = `${this.Urls.browse_origin_content()}?origin_url=${origin.url}&path=${origin.content[0].path}`; }); beforeEach(function() { cy.visit(url); }); it('should display correct file name', function() { cy.get('.swh-content-filename') .should('be.visible') .and('contain', origin.content[0].name) .and('have.css', 'background-color', 'rgb(242, 244, 245)'); }); it('should display all lines', function() { cy.get('.hljs-ln-code') .should('have.length', origin.content[0].numberLines) .and('be.visible') .and('have.css', 'background-color', 'rgba(0, 0, 0, 0)'); }); it('should show correct path', function() { // Array containing names of all the ancestor directories of the file const filePathArr = origin.content[0].path.slice(1, -1).slice('/'); filePathArr.split('/').forEach(dirName => { cy.get('.swh-browse-bread-crumbs') .should('contain', dirName); }); }); it('should have links to all ancestor directories', function() { const rootDirUrl = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}`; cy.get(`a[href='${rootDirUrl}']`) .should('be.visible'); const splittedPath = origin.content[0].path.split('/'); for (let i = 2; i < splittedPath.length; ++i) { const subDirPath = splittedPath.slice(1, i).join('/'); const subDirUrl = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}&path=${subDirPath}`; cy.get(`a[href='${subDirUrl}']`) .should('be.visible'); } }); it('should have correct url to raw file', function() { - cy.get(`a[href='${origin.content[0].rawFilePath}']`) + const content = origin.content[0]; + const rawFileUrl = this.Urls.browse_content_raw(`sha1_git:${content.sha1git}`) + + `?filename=${encodeURIComponent(content.name)}`; + cy.get(`a[href='${rawFileUrl}']`) .should('be.visible'); }); }); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index f21d0d0f..7cd36c78 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -1,27 +1,130 @@ /** - * Copyright (C) 2019 The Software Heritage developers + * Copyright (C) 2019-2022 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ const axios = require('axios'); const fs = require('fs'); +async function httpGet(url) { + const response = await axios.get(url); + return response.data; +} + +async function getMetadataForOrigin(originUrl, baseUrl) { + const originVisitsApiUrl = `${baseUrl}/api/1/origin/${originUrl}/visits`; + const originVisits = await httpGet(originVisitsApiUrl); + const lastVisit = originVisits[0]; + const snapshotApiUrl = `${baseUrl}/api/1/snapshot/${lastVisit.snapshot}`; + const lastOriginSnapshot = await httpGet(snapshotApiUrl); + let revision = lastOriginSnapshot.branches.HEAD.target; + if (lastOriginSnapshot.branches.HEAD.target_type === 'alias') { + revision = lastOriginSnapshot.branches[revision].target; + } + const revisionApiUrl = `${baseUrl}/api/1/revision/${revision}`; + const lastOriginHeadRevision = await httpGet(revisionApiUrl); + return { + 'directory': lastOriginHeadRevision.directory, + 'revision': lastOriginHeadRevision.id, + 'snapshot': lastOriginSnapshot.id + }; +}; + module.exports = (on, config) => { require('@cypress/code-coverage/task')(on, config); // produce JSON files prior launching browser in order to dynamically generate tests on('before:browser:launch', function(browser, launchOptions) { return new Promise((resolve) => { const p1 = axios.get(`${config.baseUrl}/tests/data/content/code/extensions/`); const p2 = axios.get(`${config.baseUrl}/tests/data/content/code/filenames/`); Promise.all([p1, p2]) .then(function(responses) { fs.writeFileSync('cypress/fixtures/source-file-extensions.json', JSON.stringify(responses[0].data)); fs.writeFileSync('cypress/fixtures/source-file-names.json', JSON.stringify(responses[1].data)); resolve(); }); }); }); + on('task', { + getSwhTestsData: async() => { + if (!global.swhTestsData) { + const swhTestsData = {}; + swhTestsData.unarchivedRepo = { + url: 'https://github.com/SoftwareHeritage/swh-web', + type: 'git', + revision: '7bf1b2f489f16253527807baead7957ca9e8adde', + snapshot: 'd9829223095de4bb529790de8ba4e4813e38672d', + rootDirectory: '7d887d96c0047a77e2e8c4ee9bb1528463677663', + content: [{ + sha1git: 'b203ec39300e5b7e97b6e20986183cbd0b797859' + }] + }; + + swhTestsData.origin = [{ + url: 'https://github.com/memononen/libtess2', + type: 'git', + content: [{ + path: 'Source/tess.h' + }, { + path: 'premake4.lua' + }], + directory: [{ + path: 'Source', + id: 'cd19126d815470b28919d64b2a8e6a3e37f900dd' + }], + revisions: [], + invalidSubDir: 'Source1' + }, { + url: 'https://github.com/wcoder/highlightjs-line-numbers.js', + type: 'git', + content: [{ + path: 'src/highlightjs-line-numbers.js' + }], + directory: [], + revisions: ['1c480a4573d2a003fc2630c21c2b25829de49972'], + release: { + name: 'v2.6.0', + id: '6877028d6e5412780517d0bfa81f07f6c51abb41', + directory: '5b61d50ef35ca9a4618a3572bde947b8cccf71ad' + } + }]; + + for (const origin of swhTestsData.origin) { + + const metadata = await getMetadataForOrigin(origin.url, config.baseUrl); + const directoryApiUrl = `${config.baseUrl}/api/1/directory/${metadata.directory}`; + + origin.dirContent = await httpGet(directoryApiUrl); + origin.rootDirectory = metadata.directory; + origin.revisions.push(metadata.revision); + origin.snapshot = metadata.snapshot; + + for (const content of origin.content) { + + const contentPathApiUrl = `${config.baseUrl}/api/1/directory/${origin.rootDirectory}/${content.path}`; + const contentMetaData = await httpGet(contentPathApiUrl); + + content.name = contentMetaData.name.split('/').slice(-1)[0]; + content.sha1git = contentMetaData.target; + content.directory = contentMetaData.dir_id; + + const rawFileUrl = `${config.baseUrl}/browse/content/sha1_git:${content.sha1git}/raw/?filename=${content.name}`; + const fileText = await httpGet(rawFileUrl); + const fileLines = fileText.split('\n'); + content.numberLines = fileLines.length; + + if (!fileLines[content.numberLines - 1]) { + // If last line is empty its not shown + content.numberLines -= 1; + } + } + } + global.swhTestsData = swhTestsData; + } + return global.swhTestsData; + } + }); return config; }; diff --git a/cypress/support/index.js b/cypress/support/index.js index 7b72ebfa..b52d6d0d 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -1,181 +1,91 @@ /** - * Copyright (C) 2019-2020 The Software Heritage developers + * Copyright (C) 2019-2022 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ import 'cypress-hmr-restarter'; import '@cypress/code-coverage/support'; -import {httpGetJson} from '../utils'; - Cypress.Screenshot.defaults({ screenshotOnRunFailure: false }); Cypress.Commands.add('xhrShouldBeCalled', (alias, timesCalled) => { const testRoutes = cy.state('routes'); const aliasRoute = Cypress._.find(testRoutes, {alias}); expect(Object.keys(aliasRoute.requests || {})).to.have.length(timesCalled); }); function loginUser(username, password) { const url = '/admin/login/'; return cy.request({ url: url, method: 'GET' }).then(() => { cy.getCookie('sessionid').should('not.exist'); cy.getCookie('csrftoken').its('value').then((token) => { cy.request({ url: url, method: 'POST', form: true, followRedirect: false, body: { username: username, password: password, csrfmiddlewaretoken: token } }).then(() => { cy.getCookie('sessionid').should('exist'); return cy.getCookie('csrftoken').its('value'); }); }); }); } Cypress.Commands.add('adminLogin', () => { return loginUser('admin', 'admin'); }); Cypress.Commands.add('userLogin', () => { return loginUser('user', 'user'); }); Cypress.Commands.add('ambassadorLogin', () => { return loginUser('ambassador', 'ambassador'); }); function mockSwhStatusRequest() { cy.intercept('https://status.softwareheritage.org/**', { body: { 'result': { 'status': [ { 'id': '5f7c4c567f50b304c1e7bd5f', 'name': 'Save Code Now', 'updated': '2020-11-30T13:51:21.151Z', 'status': 'Operational', 'status_code': 100 } ] } }}).as('swhPlatformStatus'); } before(function() { - this.unarchivedRepo = { - url: 'https://github.com/SoftwareHeritage/swh-web', - type: 'git', - revision: '7bf1b2f489f16253527807baead7957ca9e8adde', - snapshot: 'd9829223095de4bb529790de8ba4e4813e38672d', - rootDirectory: '7d887d96c0047a77e2e8c4ee9bb1528463677663', - content: [{ - sha1git: 'b203ec39300e5b7e97b6e20986183cbd0b797859' - }] - }; - - this.origin = [{ - url: 'https://github.com/memononen/libtess2', - type: 'git', - content: [{ - path: 'Source/tess.h' - }, { - path: 'premake4.lua' - }], - directory: [{ - path: 'Source', - id: 'cd19126d815470b28919d64b2a8e6a3e37f900dd' - }], - revisions: [], - invalidSubDir: 'Source1' - }, { - url: 'https://github.com/wcoder/highlightjs-line-numbers.js', - type: 'git', - content: [{ - path: 'src/highlightjs-line-numbers.js' - }], - directory: [], - revisions: ['1c480a4573d2a003fc2630c21c2b25829de49972'], - release: { - name: 'v2.6.0', - id: '6877028d6e5412780517d0bfa81f07f6c51abb41', - directory: '5b61d50ef35ca9a4618a3572bde947b8cccf71ad' - } - }]; mockSwhStatusRequest(); - const getMetadataForOrigin = async originUrl => { - const originVisitsApiUrl = this.Urls.api_1_origin_visits(originUrl); - const originVisits = await httpGetJson(originVisitsApiUrl); - const lastVisit = originVisits[0]; - const snapshotApiUrl = this.Urls.api_1_snapshot(lastVisit.snapshot); - const lastOriginSnapshot = await httpGetJson(snapshotApiUrl); - let revision = lastOriginSnapshot.branches.HEAD.target; - if (lastOriginSnapshot.branches.HEAD.target_type === 'alias') { - revision = lastOriginSnapshot.branches[revision].target; - } - const revisionApiUrl = this.Urls.api_1_revision(revision); - const lastOriginHeadRevision = await httpGetJson(revisionApiUrl); - return { - 'directory': lastOriginHeadRevision.directory, - 'revision': lastOriginHeadRevision.id, - 'snapshot': lastOriginSnapshot.id - }; - }; + cy.task('getSwhTestsData').then(testsData => { + Object.assign(this, testsData); + }); cy.visit('/').window().then(async win => { this.Urls = win.Urls; - - for (const origin of this.origin) { - - const metadata = await getMetadataForOrigin(origin.url); - const directoryApiUrl = this.Urls.api_1_directory(metadata.directory); - origin.dirContent = await httpGetJson(directoryApiUrl); - origin.rootDirectory = metadata.directory; - origin.revisions.push(metadata.revision); - origin.snapshot = metadata.snapshot; - - for (const content of origin.content) { - - const contentPathApiUrl = this.Urls.api_1_directory(origin.rootDirectory, content.path); - const contentMetaData = await httpGetJson(contentPathApiUrl); - - content.name = contentMetaData.name.split('/').slice(-1)[0]; - content.sha1git = contentMetaData.target; - content.directory = contentMetaData.dir_id; - - content.rawFilePath = this.Urls.browse_content_raw(`sha1_git:${content.sha1git}`) + - `?filename=${encodeURIComponent(content.name)}`; - - cy.request(content.rawFilePath) - .then((response) => { - const fileText = response.body; - const fileLines = fileText.split('\n'); - content.numberLines = fileLines.length; - - // If last line is empty its not shown - if (!fileLines[content.numberLines - 1]) content.numberLines -= 1; - }); - } - - } }); }); beforeEach(function() { mockSwhStatusRequest(); }); diff --git a/cypress/utils/index.js b/cypress/utils/index.js index 44c1064d..063100b7 100644 --- a/cypress/utils/index.js +++ b/cypress/utils/index.js @@ -1,54 +1,47 @@ /** - * Copyright (C) 2019 The Software Heritage developers + * Copyright (C) 2019-2022 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ -import axios from 'axios'; - -export async function httpGetJson(url) { - const response = await axios.get(url); - return response.data; -} - /** * Converts string with Time information * to an object with Time information */ export function getTime(text) { const date = new Date(text); function pad(n) { return n < 10 ? '0' + n : n; } const time = { date: date.getUTCDate(), month: date.getUTCMonth(), monthName: date.toLocaleString('en', {month: 'long'}), year: date.getUTCFullYear(), hours: pad(date.getUTCHours()), minutes: pad(date.getUTCMinutes()) }; return time; } export function checkLanguageHighlighting(language) { cy.get('code') .should('be.visible') .and('have.class', 'hljs') .and('have.class', language) .and('not.be.empty') .find('table.hljs-ln') .should('be.visible') .and('not.be.empty'); } export function random(start, end) { const range = end - start; return Math.floor(Math.random() * range) + start; } export const describeSlowTests = Cypress.env('SKIP_SLOW_TESTS') === 1 ? describe.skip : describe;