diff --git a/cypress/integration/code-highlighting.spec.js b/cypress/integration/code-highlighting.spec.js index 691ee6fd..abafc7a3 100644 --- a/cypress/integration/code-highlighting.spec.js +++ b/cypress/integration/code-highlighting.spec.js @@ -1,104 +1,95 @@ /** * Copyright (C) 2019 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 origin = 'https://github.com/memononen/libtess2'; -const contentPath = 'Source/tess.h'; -const lineStart = 32; -const lineEnd = 42; +import {random} from '../utils'; const $ = Cypress.$; +let origin; +const lineStart = 32; +const lineEnd = 42; + let url; describe('Code highlighting tests', function() { - before(function() { - url = this.Urls.browse_origin_content(origin, contentPath); + origin = this.origin[0]; + url = this.Urls.browse_origin_content(origin.url, origin.content[0].path); }); it('should highlight source code and add line numbers', function() { cy.visit(url); cy.get('.hljs-ln-numbers').then(lnNumbers => { cy.get('.hljs-ln-code').then(lnCode => { assert.equal(lnNumbers.length, lnCode.length); }); }); }); it('should emphasize source code lines based on url fragment', function() { - cy.visit(`${url}/#L${lineStart}-L${lineEnd}`); cy.get('.hljs-ln-line').then(lines => { for (let line of lines) { - let lineElt = $(line); - let lineNumber = parseInt(lineElt.data('line-number')); + const lineElt = $(line); + const lineNumber = parseInt(lineElt.data('line-number')); if (lineNumber >= lineStart && lineNumber <= lineEnd) { assert.notEqual(lineElt.css('background-color'), 'rgba(0, 0, 0, 0)'); } else { assert.equal(lineElt.css('background-color'), 'rgba(0, 0, 0, 0)'); } } }); }); it('should emphasize a line by clicking on its number', function() { cy.visit(url); cy.get('.hljs-ln-numbers').then(lnNumbers => { - let lnNumber = lnNumbers[Math.floor(Math.random() * lnNumbers.length)]; - let lnNumberElt = $(lnNumber); + const lnNumber = lnNumbers[random(0, lnNumbers.length)]; + const lnNumberElt = $(lnNumber); assert.equal(lnNumberElt.css('background-color'), 'rgba(0, 0, 0, 0)'); - let line = parseInt(lnNumberElt.data('line-number')); + const line = parseInt(lnNumberElt.data('line-number')); cy.get(`.hljs-ln-numbers[data-line-number="${line}"]`) - .scrollIntoView() .click() .then(() => { assert.notEqual(lnNumberElt.css('background-color'), 'rgba(0, 0, 0, 0)'); }); }); }); it('should emphasize a range of lines by clicking on two line numbers and holding shift', function() { cy.visit(url); cy.get(`.hljs-ln-numbers[data-line-number="${lineStart}"]`) - .scrollIntoView() .click() .get(`body`) .type(`{shift}`, { release: false }) .get(`.hljs-ln-numbers[data-line-number="${lineEnd}"]`) - .scrollIntoView() .click() .get('.hljs-ln-line') .then(lines => { for (let line of lines) { - let lineElt = $(line); - let lineNumber = parseInt(lineElt.data('line-number')); + const lineElt = $(line); + const lineNumber = parseInt(lineElt.data('line-number')); if (lineNumber >= lineStart && lineNumber <= lineEnd) { assert.notEqual(lineElt.css('background-color'), 'rgba(0, 0, 0, 0)'); } else { assert.equal(lineElt.css('background-color'), 'rgba(0, 0, 0, 0)'); } } }); }); it('should remove emphasized lines when clicking anywhere in code', function() { cy.visit(`${url}/#L${lineStart}-L${lineEnd}`); cy.get(`.hljs-ln-code[data-line-number="1"]`) - .scrollIntoView() .click() .get('.hljs-ln-line') - .then(lines => { - for (let line of lines) { - let lineElt = $(line); - assert.equal(lineElt.css('background-color'), 'rgba(0, 0, 0, 0)'); - } - }); + .should('have.css', 'background-color', 'rgba(0, 0, 0, 0)'); }); }); diff --git a/cypress/integration/content-display.spec.js b/cypress/integration/content-display.spec.js index 293fc429..2cc882e1 100644 --- a/cypress/integration/content-display.spec.js +++ b/cypress/integration/content-display.spec.js @@ -1,91 +1,66 @@ /** * Copyright (C) 2019 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 origin = 'https://github.com/memononen/libtess2'; -const contentPath = 'Source/tess.h'; - -let fileName, filePath, sha1git, rawFilePath, numberLines, originUrl; - +let origin; let url; describe('Test File Rendering', function() { before(function() { - url = this.Urls.browse_origin_content(origin, contentPath); - - cy.visit(url); - cy.window().then(async win => { - const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); - - fileName = metadata.filename; - filePath = metadata.path; - originUrl = metadata['origin url']; - sha1git = metadata.sha1_git; - rawFilePath = this.Urls.browse_content_raw(`sha1_git:${sha1git}`) + - `?filename=${encodeURIComponent(fileName)}`; - - cy.request(rawFilePath) - .then((response) => { - const fileText = response.body; - const fileLines = fileText.split('\n'); - numberLines = fileLines.length; - - // If last line is empty its not shown - if (!fileLines[numberLines - 1]) numberLines -= 1; - }); - }); + origin = this.origin[0]; + url = this.Urls.browse_origin_content(origin.url, 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', fileName) + .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', numberLines) + .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 = filePath.slice(1, -1).slice('/'); + 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(originUrl); + const rootDirUrl = this.Urls.browse_origin_directory(origin.url); cy.get(`a[href='${rootDirUrl}']`) .should('be.visible'); - let splittedPath = filePath.split('/'); + 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(originUrl, subDirPath); + const subDirUrl = this.Urls.browse_origin_directory(origin.url, subDirPath); cy.get(`a[href='${subDirUrl}']`) .should('be.visible'); } }); it('should have correct url to raw file', function() { - cy.get(`a[href='${rawFilePath}']`) + cy.get(`a[href='${origin.content[0].rawFilePath}']`) .should('be.visible'); }); }); diff --git a/cypress/integration/content-rendering.spec.js b/cypress/integration/content-rendering.spec.js index 1e05411f..4bd949c0 100644 --- a/cypress/integration/content-rendering.spec.js +++ b/cypress/integration/content-rendering.spec.js @@ -1,102 +1,99 @@ /** * Copyright (C) 2019 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 {checkLanguageHighlighting} from '../utils'; describe('Code highlighting tests', function() { const extensions = require('../fixtures/source-file-extensions.json'); extensions.forEach(ext => { it(`should highlight source files with extension ${ext}`, function() { cy.request(this.Urls.tests_content_code_extension(ext)).then(response => { - let data = response.body; + const data = response.body; cy.visit(`${this.Urls.browse_content(data.sha1)}?path=file.${ext}`); checkLanguageHighlighting(data.language); }); }); }); const filenames = require('../fixtures/source-file-names.json'); filenames.forEach(filename => { it(`should highlight source files with filenames ${filename}`, function() { cy.request(this.Urls.tests_content_code_filename(filename)).then(response => { - let data = response.body; + const data = response.body; cy.visit(`${this.Urls.browse_content(data.sha1)}?path=${filename}`); checkLanguageHighlighting(data.language); }); }); }); }); describe('Image rendering tests', function() { const imgExtensions = ['gif', 'jpeg', 'png', 'webp']; imgExtensions.forEach(ext => { it(`should render image with extension ${ext}`, function() { cy.request(this.Urls.tests_content_other_extension(ext)).then(response => { - let data = response.body; + const data = response.body; cy.visit(`${this.Urls.browse_content(data.sha1)}?path=file.${ext}`); cy.get('.swh-content img') - .then(img => { - assert.notEqual(img[0].width, 0); - assert.notEqual(img[0].height, 0); - }); + .should('be.visible'); }); }); }); }); describe('PDF rendering test', function() { function sum(previousValue, currentValue) { return previousValue + currentValue; } it(`should render a PDF file`, function() { cy.request(this.Urls.tests_content_other_extension('pdf')).then(response => { - let data = response.body; + const data = response.body; cy.visit(`${this.Urls.browse_content(data.sha1)}?path=file.pdf`); cy.get('.swh-content canvas') .wait(2000) .then(canvas => { let width = canvas[0].width; let height = canvas[0].height; let context = canvas[0].getContext('2d'); let imgData = context.getImageData(0, 0, width, height); assert.notEqual(imgData.data.reduce(sum), 0); }); }); }); }); describe('Jupyter notebook rendering test', function() { it(`should render a notebook file to HTML`, function() { cy.request(this.Urls.tests_content_other_extension('ipynb')).then(response => { - let data = response.body; + const data = response.body; cy.visit(`${this.Urls.browse_content(data.sha1)}?path=file.ipynb`); cy.get('.nb-notebook') .should('be.visible') .and('not.be.empty'); cy.get('.nb-cell.nb-markdown-cell') .should('be.visible') .and('not.be.empty'); cy.get('.nb-cell.nb-code-cell') .should('be.visible') .and('not.be.empty'); cy.get('.MathJax') .should('be.visible') .and('not.be.empty'); }); }); }); diff --git a/cypress/integration/directory.spec.js b/cypress/integration/directory.spec.js index 79badd53..67e0f02d 100644 --- a/cypress/integration/directory.spec.js +++ b/cypress/integration/directory.spec.js @@ -1,79 +1,77 @@ /** * Copyright (C) 2019 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 {httpGetJson} from '../utils'; -const origin = 'https://github.com/memononen/libtess2'; const $ = Cypress.$; -let url, dirs, files; +let origin; -describe('Directory Tests', function() { +let url; +let dirs = []; +let files = []; +describe('Directory Tests', function() { before(function() { - url = this.Urls.browse_origin_directory(origin); - cy.visit(url).window().then(async win => { - const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); - const apiUrl = Cypress.config().baseUrl + this.Urls.api_1_directory(metadata.directory); - let dirContent = await httpGetJson(apiUrl); - files = []; - dirs = []; - for (let entry of dirContent) { - if (entry.type === 'file') { - files.push(entry); - } else { - dirs.push(entry); - } + origin = this.origin[0]; + + url = this.Urls.browse_origin_directory(origin.url); + + for (let entry of origin.dirContent) { + if (entry.type === 'file') { + files.push(entry); + } else { + dirs.push(entry); } - }); + } }); beforeEach(function() { cy.visit(url); }); it('should display all files and directories', function() { cy.get('.swh-directory') .should('have.length', dirs.length) .and('be.visible'); cy.get('.swh-content') .should('have.length', files.length) .and('be.visible'); }); it('should display sizes for files', function() { cy.get('.swh-content') .parent('tr') .then((rows) => { for (let row of rows) { let text = $(row).children('td').eq(2).text(); expect(text.trim()).to.not.be.empty; } }); }); it('should display readme when it is present', function() { cy.get('#readme-panel > .card-body') .should('be.visible') .and('have.class', 'swh-showdown') .and('not.be.empty') .and('not.contain', 'Readme bytes are not available'); }); it('should open subdirectory when clicked', function() { cy.get('.swh-directory') .first() .children('a') .click(); cy.url() .should('include', url + dirs[0]['name']); cy.get('.swh-directory-table') .should('be.visible'); }); }); diff --git a/cypress/integration/errors.spec.js b/cypress/integration/errors.spec.js index 20bb74bc..0b7bba06 100644 --- a/cypress/integration/errors.spec.js +++ b/cypress/integration/errors.spec.js @@ -1,165 +1,150 @@ /** * Copyright (C) 2019 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 {httpGetJson} from '../utils'; -const unarchivedRepo = { - url: 'https://github.com/SoftwareHeritage/swh-web', - revisionSha1git: '7bf1b2f489f16253527807baead7957ca9e8adde', - snapshotSha1git: 'd9829223095de4bb529790de8ba4e4813e38672d', - rootDirSha1git: '7d887d96c0047a77e2e8c4ee9bb1528463677663', - readmeSha1git: 'b203ec39300e5b7e97b6e20986183cbd0b797859' -}; - -const archivedRepo = { - url: 'https://github.com/memononen/libtess2', - invalidSubDir: 'Source1' -}; +let origin; const invalidChecksum = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; const invalidPageUrl = '/invalidPath'; function urlShouldShowError(url, error) { cy.visit(url, { failOnStatusCode: false }); cy.get('.swh-http-error') .should('be.visible'); cy.get('.swh-http-error-code') .should('contain', error.code); cy.get('.swh-http-error-desc') .should('contain', error.msg); } describe('Test Errors', function() { + before(function() { + origin = this.origin[0]; + }); + it('should show navigation buttons on error page', function() { cy.visit(invalidPageUrl, { failOnStatusCode: false }); cy.get('a[onclick="window.history.back();"]') .should('be.visible'); cy.get('a[href="/"') .should('be.visible'); }); context('For unarchived repositories', function() { it('should display NotFoundExc for unarchived repo', function() { - const url = this.Urls.browse_origin_directory(unarchivedRepo.url); + const url = this.Urls.browse_origin_directory(this.unarchivedRepo.url); urlShouldShowError(url, { code: '404', - msg: 'NotFoundExc: Origin with url ' + unarchivedRepo.url + ' not found!' + msg: 'NotFoundExc: Origin with url ' + this.unarchivedRepo.url + ' not found!' }); }); it('should display NotFoundExc for unarchived content', function() { - const url = this.Urls.browse_content(`sha1_git:${unarchivedRepo.readmeSha1git}`); + const url = this.Urls.browse_content(`sha1_git:${this.unarchivedRepo.content[0].sha1git}`); urlShouldShowError(url, { code: '404', - msg: 'NotFoundExc: Content with sha1_git checksum equals to ' + unarchivedRepo.readmeSha1git + ' not found!' + msg: 'NotFoundExc: Content with sha1_git checksum equals to ' + this.unarchivedRepo.content[0].sha1git + ' not found!' }); }); it('should display NotFoundExc for unarchived directory sha1git', function() { - const url = this.Urls.browse_directory(unarchivedRepo.rootDirSha1git); + const url = this.Urls.browse_directory(this.unarchivedRepo.rootDirectory); urlShouldShowError(url, { code: '404', - msg: 'NotFoundExc: Directory with sha1_git ' + unarchivedRepo.rootDirSha1git + ' not found' + msg: 'NotFoundExc: Directory with sha1_git ' + this.unarchivedRepo.rootDirectory + ' not found' }); }); it('should display NotFoundExc for unarchived revision sha1git', function() { - const url = this.Urls.browse_revision(unarchivedRepo.revisionSha1git); + const url = this.Urls.browse_revision(this.unarchivedRepo.revision); urlShouldShowError(url, { code: '404', - msg: 'NotFoundExc: Revision with sha1_git ' + unarchivedRepo.revisionSha1git + ' not found.' + msg: 'NotFoundExc: Revision with sha1_git ' + this.unarchivedRepo.revision + ' not found.' }); }); it('should display NotFoundExc for unarchived snapshot sha1git', function() { - const url = this.Urls.browse_snapshot(unarchivedRepo.snapshotSha1git); + const url = this.Urls.browse_snapshot(this.unarchivedRepo.snapshot); urlShouldShowError(url, { code: '404', - msg: 'Snapshot with id ' + unarchivedRepo.snapshotSha1git + ' not found!' + msg: 'Snapshot with id ' + this.unarchivedRepo.snapshot + ' not found!' }); }); }); context('For archived repositories', function() { before(function() { - const url = this.Urls.browse_origin_directory(archivedRepo.url); + const url = this.Urls.browse_origin_directory(origin.url); cy.visit(url); - cy.window().then(async win => { - const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); - const apiUrl = Cypress.config().baseUrl + this.Urls.api_1_directory(metadata.directory); - const dirContent = await httpGetJson(apiUrl); - - archivedRepo.contentSha1git = dirContent.find(x => x.type === 'file').checksums.sha1_git; - archivedRepo.directorySha1git = metadata.directory; - }); }); it('should display NotFoundExc for invalid directory from archived repo', function() { - const rootDir = this.Urls.browse_origin_directory(archivedRepo.url); - const subDir = rootDir + archivedRepo.invalidSubDir; + const rootDir = this.Urls.browse_origin_directory(origin.url); + const subDir = rootDir + origin.invalidSubDir; urlShouldShowError(subDir, { code: '404', msg: 'NotFoundExc: Directory entry with path ' + - archivedRepo.invalidSubDir + ' from ' + - archivedRepo.directorySha1git + ' not found' + origin.invalidSubDir + ' from ' + + origin.rootDirectory + ' not found' }); }); it(`should display NotFoundExc for incorrect origin_url with correct content hash`, function() { - const url = this.Urls.browse_content(`sha1_git:${archivedRepo.contentSha1git}`) + - `?origin_url=${unarchivedRepo.url}`; + const url = this.Urls.browse_content(`sha1_git:${origin.content[0].sha1git}`) + + `?origin_url=${this.unarchivedRepo.url}`; urlShouldShowError(url, { code: '404', msg: 'The Software Heritage archive has a content ' + 'with the hash you provided but the origin ' + 'mentioned in your request appears broken: ' + - unarchivedRepo.url + '. ' + + this.unarchivedRepo.url + '. ' + 'Please check the URL and try again.\n\n' + 'Nevertheless, you can still browse the content ' + 'without origin information: ' + '/browse/content/sha1_git:' + - archivedRepo.contentSha1git + '/' + origin.content[0].sha1git + '/' }); }); }); context('For invalid data', function() { it(`should display 400 for invalid checksum for directory, snapshot, revision, content`, function() { const types = ['directory', 'snapshot', 'revision', 'content']; for (let type of types) { const url = this.Urls[`browse_${type}`](invalidChecksum); urlShouldShowError(url, { code: '400', msg: 'BadInputExc: Invalid checksum query string ' + invalidChecksum }); } }); it('should show 404 error for invalid path', function() { urlShouldShowError(invalidPageUrl, { code: '404', msg: 'The resource ' + invalidPageUrl + ' could not be found on the server.' }); }); }); }); diff --git a/cypress/integration/home.spec.js b/cypress/integration/home.spec.js index f71183a2..d34244a0 100644 --- a/cypress/integration/home.spec.js +++ b/cypress/integration/home.spec.js @@ -1,25 +1,25 @@ /** * Copyright (C) 2019 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 url = '/'; - const $ = Cypress.$; +const url = '/'; + describe('Home Page Tests', function() { it('should display positive stats for each category', function() { cy.visit(url) .wait(3000) // wait counters request result .get('.swh-counter') .then((counters) => { for (let counter of counters) { let innerText = $(counter).text(); const value = parseInt(innerText.replace(/,/g, '')); assert.isAbove(value, 0); } }); }); }); diff --git a/cypress/integration/language-select.spec.js b/cypress/integration/language-select.spec.js index a526a0e9..39d90c13 100644 --- a/cypress/integration/language-select.spec.js +++ b/cypress/integration/language-select.spec.js @@ -1,90 +1,73 @@ /** * Copyright (C) 2019 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 {random, checkLanguageHighlighting} from '../utils'; -const origin = { - url: 'https://github.com/memononen/libtess2', - content: { - path: 'premake4.lua' - } -}; - -let contentWithLanguageInfo, contentWithoutLanguageInfo; +const $ = Cypress.$; -let languages = []; +let origin; -const $ = Cypress.$; +let contentWithLanguageInfo, contentWithoutLanguageInfo; +const languageSelect = 'python'; describe('Test Content Language Select', function() { before(function() { - contentWithLanguageInfo = this.Urls.browse_origin_content(origin.url, origin.content.path); - - cy.visit(contentWithLanguageInfo); - cy.window().then(win => { - const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); - - origin.content.name = metadata.filename; - origin.content.sha1git = metadata.sha1_git; - contentWithoutLanguageInfo = this.Urls.browse_content(`sha1_git:${origin.content.sha1git}`); - $('.language-select option').each(function() { - languages.push(this.value); - }); - }); + origin = this.origin[0]; + contentWithLanguageInfo = this.Urls.browse_origin_content(origin.url, origin.content[1].path); + contentWithoutLanguageInfo = this.Urls.browse_content(`sha1_git:${origin.content[1].sha1git}`); }); context('When Language is detected', function() { it('should display correct language in dropdown', function() { cy.visit(contentWithLanguageInfo) .then(() => { cy.get(`code.${$('.language-select').val()}`) .should('exist'); }); }); }); context('When Language is not detected', function() { it('should have no selected language in dropdown', function() { cy.visit(contentWithoutLanguageInfo).then(() => { assert.strictEqual($('.language-select').val(), null); }); }); }); context('When language is switched from dropdown', function() { before(function() { cy.visit(contentWithLanguageInfo); - let languageSelect = languages[random(0, languages.length)]; - cy.get('.chosen-container') .click() .get('.chosen-results > li') - .contains(languageSelect) - .click() - .then(() => { - assert.strictEqual($('.language-select').val(), languageSelect); + .its('length') + .then(numOptions => { + const languageIndex = random(0, numOptions); + cy.get('.chosen-results > li') + .eq(languageIndex) + .click(); }); }); it('should contain argument with language in url', function() { cy.location('search') .should('contain', `language=${$('.language-select').val()}`); }); it('should highlight according to new language', function() { checkLanguageHighlighting($('.language-select').val()); }); }); it('should highlight according to the language passed as argument in url', function() { - const languageSelect = languages[random(0, languages.length)]; cy.visit(`${contentWithLanguageInfo}?language=${languageSelect}`); checkLanguageHighlighting(languageSelect); }); }); diff --git a/cypress/integration/origin-search.spec.js b/cypress/integration/origin-search.spec.js index 4c8b99bc..bf55bef7 100644 --- a/cypress/integration/origin-search.spec.js +++ b/cypress/integration/origin-search.spec.js @@ -1,152 +1,129 @@ /** * Copyright (C) 2019 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 unarchivedRepo = { - url: 'https://github.com/SoftwareHeritage/swh-web', - revision: '7bf1b2f489f16253527807baead7957ca9e8adde', - snapshot: 'd9829223095de4bb529790de8ba4e4813e38672d', - rootDirectory: '7d887d96c0047a77e2e8c4ee9bb1528463677663', - readmeSha1git: 'b203ec39300e5b7e97b6e20986183cbd0b797859' -}; - -const archivedRepo = { - url: 'https://github.com/memononen/libtess2', - readme: { - path: 'README.md' - } -}; - const nonExistentText = 'NoMatchExists'; +let origin; let url; function searchShouldRedirect(searchText, redirectUrl) { cy.get('#origins-url-patterns') .type(searchText); cy.get('.swh-search-icon') .click(); cy.location('pathname') .should('equal', redirectUrl); } function searchShouldShowNotFound(searchText, msg) { cy.get('#origins-url-patterns') .type(searchText); cy.get('.swh-search-icon') .click(); cy.get('#swh-no-result') .should('be.visible') .and('contain', msg); } describe('Test origin-search', function() { before(function() { + origin = this.origin[0]; url = this.Urls.browse_search(); - - cy.visit(this.Urls.browse_origin_content(archivedRepo.url, archivedRepo.readme.path)); - cy.window().then(win => { - const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); - - archivedRepo.revision = metadata.revision; - archivedRepo.snapshot = metadata.snapshot; - archivedRepo.readme.directory = metadata.directory; - archivedRepo.readme.sha1git = metadata.sha1_git; - }); }); beforeEach(function() { cy.visit(url); }); it('should show in result for any url substring', function() { // Randomly select substring of origin url - const startIndex = Math.floor(Math.random() * archivedRepo.url.length); - const length = Math.floor(Math.random() * (archivedRepo.url.length - startIndex - 1)) + 1; - const originSubstring = archivedRepo.url.substr(startIndex, length); + const startIndex = Math.floor(Math.random() * origin.url.length); + const length = Math.floor(Math.random() * (origin.url.length - startIndex - 1)) + 1; + const originSubstring = origin.url.substr(startIndex, length); cy.get('#origins-url-patterns') .type(originSubstring); cy.get('.swh-search-icon') .click(); cy.get('#origin-search-results') .should('be.visible'); - cy.contains('tr', archivedRepo.url) + cy.contains('tr', origin.url) .should('be.visible') .find('.swh-visit-status') .find('i') .should('have.class', 'fa-check') .and('have.attr', 'title', 'Origin has at least one full visit by Software Heritage'); }); it('should show not found message when no repo matches', function() { searchShouldShowNotFound(nonExistentText, 'No origins matching the search criteria were found.'); }); context('Test valid persistent ids', function() { it('should resolve directory', function() { - const redirectUrl = this.Urls.browse_directory(archivedRepo.readme.directory); - const persistentId = `swh:1:dir:${archivedRepo.readme.directory}`; + const redirectUrl = this.Urls.browse_directory(origin.content[0].directory); + const persistentId = `swh:1:dir:${origin.content[0].directory}`; searchShouldRedirect(persistentId, redirectUrl); }); it('should resolve revision', function() { - const redirectUrl = this.Urls.browse_revision(archivedRepo.revision); - const persistentId = `swh:1:rev:${archivedRepo.revision}`; + const redirectUrl = this.Urls.browse_revision(origin.revision); + const persistentId = `swh:1:rev:${origin.revision}`; searchShouldRedirect(persistentId, redirectUrl); }); it('should resolve snapshot', function() { - const redirectUrl = this.Urls.browse_snapshot_directory(archivedRepo.snapshot); - const persistentId = `swh:1:snp:${archivedRepo.snapshot}`; + const redirectUrl = this.Urls.browse_snapshot_directory(origin.snapshot); + const persistentId = `swh:1:snp:${origin.snapshot}`; searchShouldRedirect(persistentId, redirectUrl); }); it('should resolve content', function() { - const redirectUrl = this.Urls.browse_content(`sha1_git:${archivedRepo.readme.sha1git}`); - const persistentId = `swh:1:cnt:${archivedRepo.readme.sha1git}`; + const redirectUrl = this.Urls.browse_content(`sha1_git:${origin.content[0].sha1git}`); + const persistentId = `swh:1:cnt:${origin.content[0].sha1git}`; searchShouldRedirect(persistentId, redirectUrl); }); }); context('Test invalid persistent ids', function() { it('should show not found for directory', function() { - const persistentId = `swh:1:dir:${unarchivedRepo.rootDirectory}`; - const msg = `Directory with sha1_git ${unarchivedRepo.rootDirectory} not found`; + const persistentId = `swh:1:dir:${this.unarchivedRepo.rootDirectory}`; + const msg = `Directory with sha1_git ${this.unarchivedRepo.rootDirectory} not found`; searchShouldShowNotFound(persistentId, msg); }); it('should show not found for snapshot', function() { - const persistentId = `swh:1:snp:${unarchivedRepo.snapshot}`; - const msg = `Snapshot with id ${unarchivedRepo.snapshot} not found!`; + const persistentId = `swh:1:snp:${this.unarchivedRepo.snapshot}`; + const msg = `Snapshot with id ${this.unarchivedRepo.snapshot} not found!`; searchShouldShowNotFound(persistentId, msg); }); it('should show not found for revision', function() { - const persistentId = `swh:1:rev:${unarchivedRepo.revision}`; - const msg = `Revision with sha1_git ${unarchivedRepo.revision} not found.`; + const persistentId = `swh:1:rev:${this.unarchivedRepo.revision}`; + const msg = `Revision with sha1_git ${this.unarchivedRepo.revision} not found.`; searchShouldShowNotFound(persistentId, msg); }); it('should show not found for content', function() { - const persistentId = `swh:1:cnt:${unarchivedRepo.readmeSha1git}`; - const msg = `Content with sha1_git checksum equals to ${unarchivedRepo.readmeSha1git} not found!`; + const persistentId = `swh:1:cnt:${this.unarchivedRepo.content[0].sha1git}`; + const msg = `Content with sha1_git checksum equals to ${this.unarchivedRepo.content[0].sha1git} not found!`; searchShouldShowNotFound(persistentId, msg); }); }); }); diff --git a/cypress/integration/origin-visits.spec.js b/cypress/integration/origin-visits.spec.js index d3a738be..53b486ec 100644 --- a/cypress/integration/origin-visits.spec.js +++ b/cypress/integration/origin-visits.spec.js @@ -1,72 +1,76 @@ /** * Copyright (C) 2019 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 {getTime} from '../utils'; -const origin = 'https://github.com/wcoder/highlightjs-line-numbers.js'; +let origin; function checkTimeLink(element) { expect(element.text()).not.to.be.empty; const timeStringLink = element.attr('href').split('visit/')[1].split('/')[0]; // time in link should be equal to that in text assert.deepEqual(getTime(timeStringLink), getTime(element.text())); } function searchInCalendar(date) { cy.contains('label', 'Show all visits') .click(); cy.get(`.year${date.year}`) .click({force: true}); cy.contains('.month', date.monthName) .find('.day-content') .eq(date.date - 1) .trigger('mouseenter') .get('.popover-body') .should('be.visible') .and('contain', `${date.hours}:${date.minutes} UTC`); } describe('Visits tests', function() { + before(function() { + origin = this.origin[1]; + }); + beforeEach(function() { - cy.visit(this.Urls.browse_origin_visits(origin)); + cy.visit(this.Urls.browse_origin_visits(origin.url)); }); it('should display first full visit time', function() { cy.get('#swh-first-full-visit > .swh-visit-full') .then(($el) => { checkTimeLink($el); searchInCalendar(getTime($el.text())); }); }); it('should display last full visit time', function() { cy.get('#swh-last-full-visit > .swh-visit-full') .then(($el) => { checkTimeLink($el); searchInCalendar(getTime($el.text())); }); }); it('should display last visit time', function() { cy.get('#swh-last-visit > .swh-visit-full') .then(($el) => { checkTimeLink($el); searchInCalendar(getTime($el.text())); }); }); it('should display list of visits and mark them on calendar', function() { cy.get('.swh-visits-list-row .swh-visit-full') .should('be.visible') .each(($el) => { checkTimeLink($el); searchInCalendar(getTime($el.text())); }); }); }); diff --git a/cypress/support/index.js b/cypress/support/index.js index 9c349f0b..3e21fa2a 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -1,18 +1,82 @@ /** * Copyright (C) 2019 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/code-coverage/support'; +import {httpGetJson} from '../utils'; + Cypress.Screenshot.defaults({ screenshotOnRunFailure: false }); before(function() { + this.unarchivedRepo = { + url: 'https://github.com/SoftwareHeritage/swh-web', + revision: '7bf1b2f489f16253527807baead7957ca9e8adde', + snapshot: 'd9829223095de4bb529790de8ba4e4813e38672d', + rootDirectory: '7d887d96c0047a77e2e8c4ee9bb1528463677663', + content: [{ + sha1git: 'b203ec39300e5b7e97b6e20986183cbd0b797859' + }] + }; + + this.origin = [{ + url: 'https://github.com/memononen/libtess2', + content: [{ + path: 'Source/tess.h' + }, { + path: 'premake4.lua' + }], + invalidSubDir: 'Source1' + }, { + url: 'https://github.com/wcoder/highlightjs-line-numbers.js', + content: [] + }]; + cy.visit('/').window().then(win => { this.Urls = win.Urls; + + for (let origin of this.origin) { + cy.visit(this.Urls.browse_origin_directory(origin.url)) + .window().then(async win => { + const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); + + const apiUrl = Cypress.config().baseUrl + this.Urls.api_1_directory(metadata.directory); + origin.dirContent = await httpGetJson(apiUrl); + + origin.rootDirectory = metadata.directory; + origin.revision = metadata.revision; + origin.snapshot = metadata.snapshot; + }); + + for (let content of origin.content) { + cy.visit(this.Urls.browse_origin_content(origin.url, content.path)) + .window().then(win => { + const metadata = win.swh.webapp.getBrowsedSwhObjectMetadata(); + + content.name = metadata.filename; + content.sha1git = metadata.sha1_git; + content.directory = metadata.directory; + + 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; + }); + }); + } + + } }); });