diff --git a/cypress/integration/origin-search.spec.js b/cypress/integration/origin-search.spec.js --- a/cypress/integration/origin-search.spec.js +++ b/cypress/integration/origin-search.spec.js @@ -19,18 +19,18 @@ function searchShouldRedirect(searchText, redirectUrl) { doSearch(searchText); - cy.location('pathname') - .should('equal', redirectUrl); + cy.location('pathname').should('equal', redirectUrl); } function searchShouldShowNotFound(searchText, msg) { doSearch(searchText); - cy.get('#swh-no-result') - .should('be.visible') - .and('contain', msg); + cy.get('#swh-no-result').should('be.visible').and('contain', msg); } -function stubOriginVisitLatestRequests(status = 200, response = {type: 'tar'}) { +function stubOriginVisitLatestRequests( + status = 200, + response = {type: 'tar'} +) { cy.server(); cy.route({ method: 'GET', @@ -51,79 +51,95 @@ }); it('should have focus on search form after page load', function() { - cy.get('#swh-origins-url-patterns') - .should('have.attr', 'autofocus'); + cy.get('#swh-origins-url-patterns').should('have.attr', 'autofocus'); // for some reason, autofocus is not honored when running cypress tests // while it is in non controlled browsers // .should('have.focus'); }); + it('should search in origin intrinsic metadata', function() { + cy.intercept('GET', '**/origin/metadata-search/**').as( + 'originMetadataSearch' + ); + cy.get('#swh-search-origins-with-visit') + .check({force: true}) + .get('#swh-filter-empty-visits') + .check({force: true}) + .get('#swh-search-origin-metadata') + .check({force: true}) + .then(() => { + const searchText = 'plugin'; + doSearch(searchText); + console.log(searchText); + cy.wait('@originMetadataSearch').then((req) => { + expect(req.response.body[0].metadata.metadata.description).to.equal( + 'Line numbering plugin for Highlight.js' + ); + }); + }); + }); + it('should show in result when url is searched', function() { - cy.get('#swh-origins-url-patterns') - .type(origin.url); - cy.get('.swh-search-icon') - .click(); + cy.get('#swh-origins-url-patterns').type(origin.url); + cy.get('.swh-search-icon').click(); - cy.get('#origin-search-results') - .should('be.visible'); + cy.get('#origin-search-results').should('be.visible'); cy.contains('tr', origin.url) .should('be.visible') .find('.swh-visit-status') .find('i') .should('have.class', 'mdi-check-bold') - .and('have.attr', 'title', - 'Software origin has been archived by Software Heritage'); - - const browseOriginUrl = `${this.Urls.browse_origin()}?origin_url=${encodeURIComponent(origin.url)}`; - cy.get('tr a') - .should('have.attr', 'href', browseOriginUrl); + .and( + 'have.attr', + 'title', + 'Software origin has been archived by Software Heritage' + ); + + const browseOriginUrl = `${this.Urls.browse_origin()}?origin_url=${encodeURIComponent( + origin.url + )}`; + cy.get('tr a').should('have.attr', 'href', browseOriginUrl); }); it('should remove origin URL with no archived content', function() { stubOriginVisitLatestRequests(404); - cy.get('#swh-origins-url-patterns') - .type(origin.url); - cy.get('.swh-search-icon') - .click(); + cy.get('#swh-origins-url-patterns').type(origin.url); + cy.get('.swh-search-icon').click(); cy.wait('@originVisitLatest'); cy.get('#origin-search-results') .should('be.visible') - .find('tbody tr').should('have.length', 0); + .find('tbody tr') + .should('have.length', 0); stubOriginVisitLatestRequests(200, {}); - cy.get('.swh-search-icon') - .click(); + cy.get('.swh-search-icon').click(); cy.wait('@originVisitLatest'); cy.get('#origin-search-results') .should('be.visible') - .find('tbody tr').should('have.length', 0); - + .find('tbody tr') + .should('have.length', 0); }); it('should filter origins by visit type', function() { cy.intercept('**/visit/latest/**').as('checkOriginVisits'); - cy.get('#swh-origins-url-patterns') - .type('http'); + cy.get('#swh-origins-url-patterns').type('http'); for (let visitType of ['git', 'tar']) { - cy.get('#swh-search-visit-type') - .select(visitType); + cy.get('#swh-search-visit-type').select(visitType); - cy.get('.swh-search-icon') - .click(); + cy.get('.swh-search-icon').click(); cy.wait('@checkOriginVisits'); - cy.get('#origin-search-results') - .should('be.visible'); + cy.get('#origin-search-results').should('be.visible'); - cy.get('tbody tr td.swh-origin-visit-type').then(elts => { + cy.get('tbody tr td.swh-origin-visit-type').then((elts) => { for (let elt of elts) { cy.get(elt).should('have.text', visitType); } @@ -132,8 +148,10 @@ }); it('should show not found message when no repo matches', function() { - searchShouldShowNotFound(nonExistentText, - 'No origins matching the search criteria were found.'); + searchShouldShowNotFound( + nonExistentText, + 'No origins matching the search criteria were found.' + ); }); it('should add appropriate URL parameters', function() { @@ -148,7 +166,7 @@ .then(() => { const searchText = origin.url; doSearch(searchText); - cy.location('search').then(locationSearch => { + cy.location('search').then((locationSearch) => { const urlParams = new URLSearchParams(locationSearch); const query = urlParams.get('q'); const withVisit = urlParams.has('with_visit'); @@ -176,10 +194,8 @@ url: `${this.Urls.api_1_origin_search(origin.url)}**` }).as('searchOrigin'); - cy.get('#swh-origins-url-patterns') - .type(origin.url); - cy.get('.swh-search-icon') - .click(); + cy.get('#swh-origins-url-patterns').type(origin.url); + cy.get('.swh-search-icon').click(); cy.wait('@searchOrigin'); @@ -200,16 +216,21 @@ // Get first page of results doSearch(searchText); - cy.get('.swh-search-result-entry') - .should('have.length', 1); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://github.com/memononen/libtess2'); - - cy.get('#origins-prev-results-button') - .should('have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 1); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://github.com/memononen/libtess2' + ); + + cy.get('#origins-prev-results-button').should( + 'have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'have.class', + 'disabled' + ); }); }); @@ -227,54 +248,73 @@ doSearch(searchText); cy.wait('@originVisitLatest'); - cy.get('.swh-search-result-entry') - .should('have.length', 100); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://many.origins/1'); - cy.get('.swh-search-result-entry#origin-99 td a') - .should('have.text', 'https://many.origins/100'); - - cy.get('#origins-prev-results-button') - .should('have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 100); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://many.origins/1' + ); + cy.get('.swh-search-result-entry#origin-99 td a').should( + 'have.text', + 'https://many.origins/100' + ); + + cy.get('#origins-prev-results-button').should( + 'have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get second page of results - cy.get('#origins-next-results-button a') - .click(); + cy.get('#origins-next-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('.swh-search-result-entry') - .should('have.length', 100); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://many.origins/101'); - cy.get('.swh-search-result-entry#origin-99 td a') - .should('have.text', 'https://many.origins/200'); - - cy.get('#origins-prev-results-button') - .should('not.have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 100); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://many.origins/101' + ); + cy.get('.swh-search-result-entry#origin-99 td a').should( + 'have.text', + 'https://many.origins/200' + ); + + cy.get('#origins-prev-results-button').should( + 'not.have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get third (and last) page of results - cy.get('#origins-next-results-button a') - .click(); + cy.get('#origins-next-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('.swh-search-result-entry') - .should('have.length', 50); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://many.origins/201'); - cy.get('.swh-search-result-entry#origin-49 td a') - .should('have.text', 'https://many.origins/250'); - - cy.get('#origins-prev-results-button') - .should('not.have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 50); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://many.origins/201' + ); + cy.get('.swh-search-result-entry#origin-49 td a').should( + 'have.text', + 'https://many.origins/250' + ); + + cy.get('#origins-prev-results-button').should( + 'not.have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'have.class', + 'disabled' + ); }); }); @@ -292,38 +332,51 @@ doSearch(searchText); cy.wait('@originVisitLatest'); - cy.get('#origins-prev-results-button') - .should('have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('#origins-prev-results-button').should( + 'have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get second page of results - cy.get('#origins-next-results-button a') - .click(); + cy.get('#origins-next-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('#origins-prev-results-button') - .should('not.have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('#origins-prev-results-button').should( + 'not.have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get first page of results again - cy.get('#origins-prev-results-button a') - .click(); + cy.get('#origins-prev-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('.swh-search-result-entry') - .should('have.length', 100); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://many.origins/1'); - cy.get('.swh-search-result-entry#origin-99 td a') - .should('have.text', 'https://many.origins/100'); - - cy.get('#origins-prev-results-button') - .should('have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 100); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://many.origins/1' + ); + cy.get('.swh-search-result-entry#origin-99 td a').should( + 'have.text', + 'https://many.origins/100' + ); + + cy.get('#origins-prev-results-button').should( + 'have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); }); }); @@ -341,72 +394,96 @@ doSearch(searchText); cy.wait('@originVisitLatest'); - cy.get('#origins-prev-results-button') - .should('have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('#origins-prev-results-button').should( + 'have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get second page of results - cy.get('#origins-next-results-button a') - .click(); + cy.get('#origins-next-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('#origins-prev-results-button') - .should('not.have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('#origins-prev-results-button').should( + 'not.have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get third (and last) page of results - cy.get('#origins-next-results-button a') - .click(); + cy.get('#origins-next-results-button a').click(); - cy.get('#origins-prev-results-button') - .should('not.have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('have.class', 'disabled'); + cy.get('#origins-prev-results-button').should( + 'not.have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'have.class', + 'disabled' + ); // Get second page of results again - cy.get('#origins-prev-results-button a') - .click(); + cy.get('#origins-prev-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('.swh-search-result-entry') - .should('have.length', 100); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://many.origins/101'); - cy.get('.swh-search-result-entry#origin-99 td a') - .should('have.text', 'https://many.origins/200'); - - cy.get('#origins-prev-results-button') - .should('not.have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 100); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://many.origins/101' + ); + cy.get('.swh-search-result-entry#origin-99 td a').should( + 'have.text', + 'https://many.origins/200' + ); + + cy.get('#origins-prev-results-button').should( + 'not.have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); // Get first page of results again - cy.get('#origins-prev-results-button a') - .click(); + cy.get('#origins-prev-results-button a').click(); cy.wait('@originVisitLatest'); - cy.get('.swh-search-result-entry') - .should('have.length', 100); - - cy.get('.swh-search-result-entry#origin-0 td a') - .should('have.text', 'https://many.origins/1'); - cy.get('.swh-search-result-entry#origin-99 td a') - .should('have.text', 'https://many.origins/100'); - - cy.get('#origins-prev-results-button') - .should('have.class', 'disabled'); - cy.get('#origins-next-results-button') - .should('not.have.class', 'disabled'); + cy.get('.swh-search-result-entry').should('have.length', 100); + + cy.get('.swh-search-result-entry#origin-0 td a').should( + 'have.text', + 'https://many.origins/1' + ); + cy.get('.swh-search-result-entry#origin-99 td a').should( + 'have.text', + 'https://many.origins/100' + ); + + cy.get('#origins-prev-results-button').should( + 'have.class', + 'disabled' + ); + cy.get('#origins-next-results-button').should( + 'not.have.class', + 'disabled' + ); }); }); }); context('Test valid SWHIDs', function() { it('should resolve directory', function() { - const redirectUrl = this.Urls.browse_directory(origin.content[0].directory); + const redirectUrl = this.Urls.browse_directory( + origin.content[0].directory + ); const swhid = `swh:1:dir:${origin.content[0].directory}`; searchShouldRedirect(swhid, redirectUrl); @@ -427,7 +504,9 @@ }); it('should resolve content', function() { - const redirectUrl = this.Urls.browse_content(`sha1_git:${origin.content[0].sha1git}`); + const redirectUrl = this.Urls.browse_content( + `sha1_git:${origin.content[0].sha1git}` + ); const swhid = `swh:1:cnt:${origin.content[0].sha1git}`; searchShouldRedirect(swhid, redirectUrl); @@ -447,10 +526,8 @@ url: `${this.Urls.api_1_origin_search('').slice(0, -1)}**` }).as('searchOrigin'); - cy.get('#swh-origins-url-patterns') - .type(swhid); - cy.get('.swh-search-icon') - .click(); + cy.get('#swh-origins-url-patterns').type(swhid); + cy.get('.swh-search-icon').click(); cy.wait('@resolveSWHID'); @@ -488,5 +565,4 @@ searchShouldShowNotFound(swhid, msg); }); }); - }); diff --git a/swh/web/tests/api/views/test_origin.py b/swh/web/tests/api/views/test_origin.py --- a/swh/web/tests/api/views/test_origin.py +++ b/swh/web/tests/api/views/test_origin.py @@ -4,6 +4,7 @@ # See top-level LICENSE file for more information from datetime import timedelta +import json from hypothesis import given import pytest @@ -615,14 +616,20 @@ "configuration": INDEXER_TOOL["tool_configuration"], "id": INDEXER_TOOL["id"], }, - "metadata": {ORIGIN_METADATA_KEY: ORIGIN_METADATA_VALUE}, "mappings": [], }, } for origin_url, master_rev in ORIGIN_MASTER_REVISION.items() ] - assert rv.data == expected_data + for i in range(len(expected_data)): + expected = expected_data[i] + response = rv.data[i] + + assert ORIGIN_METADATA_VALUE in json.dumps(response["metadata"]) + + del response["metadata"]["metadata"] + assert response == expected def test_api_origin_metadata_search_limit(api_client, mocker): diff --git a/swh/web/tests/data.py b/swh/web/tests/data.py --- a/swh/web/tests/data.py +++ b/swh/web/tests/data.py @@ -121,11 +121,15 @@ "highlightjs-line-numbers.js.zip", "highlightjs-line-numbers.js_visit2.zip", ], + "metadata": {"description": "Line numbering plugin for Highlight.js",}, }, { "type": "git", "url": "repo_with_submodules", "archives": ["repo_with_submodules.tgz"], + "metadata": { + "description": "This is just a sample repository with submodules", + }, }, ] @@ -229,7 +233,7 @@ content_path = {} # Get all objects loaded into the test archive - metadata = {ORIGIN_METADATA_KEY: ORIGIN_METADATA_VALUE} + common_metadata = {ORIGIN_METADATA_KEY: ORIGIN_METADATA_VALUE} for origin in _TEST_ORIGINS: snp = snapshot_get_latest(storage, origin["url"]) snapshots.add(hash_to_hex(snp.id)) @@ -239,6 +243,8 @@ revisions.add(branch_data.target) if b"master" in branch_name: # Add some origin intrinsic metadata for tests + metadata = common_metadata + metadata.update(origin.get("metadata", {})) origin_metadata = OriginIntrinsicMetadataRow( id=origin["url"], from_revision=branch_data.target,