Page MenuHomeSoftware Heritage

No OneTemporary

diff --git a/cypress/e2e/add-forge-now-request-dashboard.cy.js b/cypress/e2e/add-forge-now-request-dashboard.cy.js
index c546f493..6c62d231 100644
--- a/cypress/e2e/add-forge-now-request-dashboard.cy.js
+++ b/cypress/e2e/add-forge-now-request-dashboard.cy.js
@@ -1,315 +1,312 @@
/**
* Copyright (C) 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 requestId;
let requestForgeDomain;
let requestInboundEmailAddress;
const requestData = {
forge_type: 'bitbucket',
forge_url: 'test.example.com',
forge_contact_email: 'test@example.com',
forge_contact_name: 'test user',
submitter_forward_username: true,
forge_contact_comment: 'test comment'
};
function createDummyRequest(urls) {
cy.task('db:add_forge_now:delete');
cy.userLogin();
return cy.getCookie('csrftoken').its('value').then((token) => {
cy.request({
method: 'POST',
url: urls.api_1_add_forge_request_create(),
body: requestData,
headers: {
'X-CSRFToken': token
}
}).then((response) => {
// setting requestId and forgeDomain from response
requestId = response.body.id;
requestForgeDomain = response.body.forge_domain;
requestInboundEmailAddress = response.body.inbound_email_address;
// logout the user
cy.visit(urls.swh_web_homepage());
cy.contains('a', 'logout').click();
});
});
}
function genEmailSrc() {
return `Message-ID: <d5c43e75-2a11-250a-43e3-37034ae3904b@example.com>
Date: Tue, 19 Apr 2022 14:00:56 +0200
MIME-Version: 1.0
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Thunderbird/91.8.0
To: ${requestData.forge_contact_email}
Cc: ${requestInboundEmailAddress}
Reply-To: ${requestInboundEmailAddress}
Subject: Software Heritage archival notification for test.example.com
Content-Language: en-US
From: Test Admin <admin@example.com>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Dear forge administrator,
The mission of Software Heritage is to collect, preserve and share all
the publicly available source code (see
https://www.softwareheritage.org for more information).
We just received a request to add the forge hosted at <%= forgeUrl %>
to the list of software origins that are archived, and it is our
understanding that you are the contact person for this forge.
In order to archive the forge contents, we will have to periodically
pull the public repositories it contains and clone them into the
Software Heritage archive.
Please let us know if there are any technical issues to consider before
we launch the archival of the public repositories hosted on your
infrastructure.(use "Reply all" to ensure our system will process
your answer properly)
In the absence of an answer to this message, we will start to archive
your forge in the coming weeks (only the publicly accessible
repositories will be archived)
Thank you in advance for your help.
Kind regards,
The Software Heritage team
`;
}
describe('Test add forge now request dashboard load', function() {
- before(function() {
- // Create an add-forge-request object in the DB
- createDummyRequest(this.Urls);
- });
-
beforeEach(function() {
- const url = this.Urls.add_forge_now_request_dashboard(requestId);
- // request dashboard require admin permissions to view
- cy.adminLogin();
- cy.intercept(`${this.Urls.api_1_add_forge_request_get(requestId)}**`).as('forgeRequestGet');
- cy.visit(url);
- cy.get('.swh-add-forge-now-moderation-item')
- .should('have.class', 'active');
+ createDummyRequest(this.Urls).then(() => {
+ const url = this.Urls.add_forge_now_request_dashboard(requestId);
+ // request dashboard require admin permissions to view
+ cy.adminLogin();
+ cy.intercept(`${this.Urls.api_1_add_forge_request_get(requestId)}**`).as('forgeRequestGet');
+ cy.visit(url);
+ cy.get('.swh-add-forge-now-moderation-item')
+ .should('have.class', 'active');
+ });
});
it('should load add forge request details', function() {
cy.wait('@forgeRequestGet');
cy.get('#requestStatus')
.should('contain', 'Pending');
cy.get('#requestType')
.should('contain', 'bitbucket');
cy.get('#requestURL')
.should('contain', 'test.example.com');
cy.get('#requestContactEmail')
.should('contain', 'test@example.com');
cy.get('#requestContactName')
.should('contain', 'test user');
cy.get('#requestContactEmail')
.should('contain', 'test@example.com');
cy.get('#requestContactConsent')
.should('contain', 'true');
cy.get('#submitterMessage')
.should('contain', 'test comment');
});
it('should show send message link', function() {
cy.wait('@forgeRequestGet');
cy.get('#contactForgeAdmin')
.should('have.attr', 'emailto')
.and('include', 'test@example.com');
cy.get('#contactForgeAdmin')
.should('have.attr', 'emailsubject')
.and('include', `Software Heritage archival notification for ${requestForgeDomain}`);
});
it('should not show any error message', function() {
cy.wait('@forgeRequestGet');
cy.get('#fetchError')
.should('have.class', 'd-none');
cy.get('#requestDetails')
.should('not.have.class', 'd-none');
});
it('should show error message for an api error', function() {
// requesting with a non existing request ID
const invalidRequestId = requestId + 10;
const url = this.Urls.add_forge_now_request_dashboard(invalidRequestId);
cy.intercept(`${this.Urls.api_1_add_forge_request_get(invalidRequestId)}**`,
{statusCode: 400}).as('forgeAddInvalidRequest');
cy.visit(url);
cy.wait('@forgeAddInvalidRequest');
cy.get('#fetchError')
.should('not.have.class', 'd-none');
cy.get('#requestDetails')
.should('have.class', 'd-none');
});
it('should load add forge request history', function() {
cy.wait('@forgeRequestGet');
cy.get('#requestHistory')
.children()
.should('have.length', 1);
cy.get('#requestHistory')
.children()
.should('contain', 'New status: Pending');
cy.get('#requestHistory')
.should('contain', 'From user (SUBMITTER)');
});
it('should load possible next status', function() {
cy.wait('@forgeRequestGet');
// 3 possible next status and the comment option
cy.get('#decisionOptions')
.children()
.should('have.length', 4);
});
});
function populateAndSubmitForm() {
cy.get('#decisionOptions').select('WAITING_FOR_FEEDBACK');
cy.get('#updateComment').type('This is an update comment');
cy.get('#updateRequestForm').submit();
}
describe('Test add forge now request update', function() {
beforeEach(function() {
createDummyRequest(this.Urls).then(() => {
this.url = this.Urls.add_forge_now_request_dashboard(requestId);
cy.adminLogin();
// intercept GET API on page load
cy.intercept(`${this.Urls.api_1_add_forge_request_get(requestId)}**`).as('forgeRequestGet');
// intercept update POST API
cy.intercept('POST', `${this.Urls.api_1_add_forge_request_update(requestId)}**`).as('forgeRequestUpdate');
cy.visit(this.url).then(() => {
cy.wait('@forgeRequestGet');
});
});
});
it('should submit correct details', function() {
populateAndSubmitForm();
// Making sure posting the right data
cy.wait('@forgeRequestUpdate').its('request.body')
.should('include', 'new_status')
.should('include', 'text')
.should('include', 'WAITING_FOR_FEEDBACK');
});
it('should show success message', function() {
populateAndSubmitForm();
// Making sure showing the success message
cy.wait('@forgeRequestUpdate');
cy.get('#userMessage')
.should('contain', 'The request status has been updated')
.should('not.have.class', 'badge-danger')
.should('have.class', 'badge-success');
});
it('should update the dashboard after submit', function() {
populateAndSubmitForm();
// Making sure the UI is updated after the submit
cy.wait('@forgeRequestGet');
cy.get('#requestStatus')
.should('contain', 'Waiting for feedback');
cy.get('#requestHistory')
.children()
.should('have.length', 2);
cy.get('#requestHistory')
.children()
.should('contain', 'New status: Waiting for feedback');
cy.get('#requestHistory')
.children()
.should('contain', 'This is an update comment');
cy.get('#requestHistory')
.children()
.should('contain', 'Status changed to: Waiting for feedback');
cy.get('#decisionOptions')
.children()
.should('have.length', 2);
});
it('should update the dashboard after receiving email', function() {
const emailSrc = genEmailSrc();
cy.task('processAddForgeNowInboundEmail', emailSrc);
// Refresh page and wait for the async request to complete
cy.visit(this.url);
cy.wait('@forgeRequestGet');
cy.get('#requestHistory')
.children()
.should('have.length', 2);
cy.get('#historyItem1')
.click()
.should('contain', 'New status: Waiting for feedback');
cy.get('#historyItemBody1')
.find('a')
.should('contain', 'Open original message in email client')
.should('have.prop', 'href').and('contain', '/message-source/').then(function(href) {
cy.request(href).then((response) => {
expect(response.headers['content-type'])
.to.equal('text/email');
expect(response.headers['content-disposition'])
.to.match(/filename="add-forge-now-test.example.com-message\d+.eml"/);
expect(response.body)
.to.equal(emailSrc);
});
});
});
it('should show an error on API failure', function() {
cy.intercept('POST',
`${this.Urls.api_1_add_forge_request_update(requestId)}**`,
{forceNetworkError: true})
.as('updateFailedRequest');
cy.get('#updateComment').type('This is an update comment');
cy.get('#updateRequestForm').submit();
cy.wait('@updateFailedRequest');
cy.get('#userMessage')
.should('contain', 'Sorry; Updating the request failed')
.should('have.class', 'badge-danger')
.should('not.have.class', 'badge-success');
});
});
diff --git a/cypress/e2e/add-forge-now-requests-moderation.cy.js b/cypress/e2e/add-forge-now-requests-moderation.cy.js
index 8ead52d6..0cb5ad42 100644
--- a/cypress/e2e/add-forge-now-requests-moderation.cy.js
+++ b/cypress/e2e/add-forge-now-requests-moderation.cy.js
@@ -1,125 +1,120 @@
/**
* Copyright (C) 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 defaultRedirect = '/login/';
-
-let addForgeModerationUrl;
-let listAddForgeRequestsUrl;
-
function logout() {
cy.contains('a', 'logout')
.click();
}
describe('Test "Add Forge Now" moderation Login/logout', function() {
- before(function() {
- addForgeModerationUrl = this.Urls.add_forge_now_requests_moderation();
+ beforeEach(function() {
+ this.addForgeModerationUrl = this.Urls.add_forge_now_requests_moderation();
});
it('should redirect to default page', function() {
- cy.visit(addForgeModerationUrl)
+ cy.visit(this.addForgeModerationUrl)
.get('input[name="username"]')
.type('admin')
.get('input[name="password"]')
.type('admin')
.get('.container form')
.submit();
cy.location('pathname')
- .should('be.equal', addForgeModerationUrl);
+ .should('be.equal', this.addForgeModerationUrl);
});
it('should redirect to correct page after login', function() {
- cy.visit(addForgeModerationUrl)
+ cy.visit(this.addForgeModerationUrl)
.location('pathname')
- .should('be.equal', defaultRedirect);
+ .should('be.equal', this.Urls.login());
cy.adminLogin();
- cy.visit(addForgeModerationUrl)
+ cy.visit(this.addForgeModerationUrl)
.location('pathname')
- .should('be.equal', addForgeModerationUrl);
+ .should('be.equal', this.addForgeModerationUrl);
logout();
});
it('should not display moderation link in sidebar when anonymous', function() {
- cy.visit(addForgeModerationUrl);
- cy.get(`.sidebar a[href="${addForgeModerationUrl}"]`)
+ cy.visit(this.addForgeModerationUrl);
+ cy.get(`.sidebar a[href="${this.addForgeModerationUrl}"]`)
.should('not.exist');
});
it('should not display moderation link when connected as unprivileged user', function() {
cy.userLogin();
- cy.visit(addForgeModerationUrl);
+ cy.visit(this.addForgeModerationUrl);
- cy.get(`.sidebar a[href="${addForgeModerationUrl}"]`)
+ cy.get(`.sidebar a[href="${this.addForgeModerationUrl}"]`)
.should('not.exist');
});
it('should display moderation link in sidebar when connected as privileged user', function() {
cy.addForgeModeratorLogin();
- cy.visit(addForgeModerationUrl);
+ cy.visit(this.addForgeModerationUrl);
- cy.get(`.sidebar a[href="${addForgeModerationUrl}"]`)
+ cy.get(`.sidebar a[href="${this.addForgeModerationUrl}"]`)
.should('exist');
});
it('should display moderation link in sidebar when connected as staff member', function() {
cy.adminLogin();
- cy.visit(addForgeModerationUrl);
+ cy.visit(this.addForgeModerationUrl);
- cy.get(`.sidebar a[href="${addForgeModerationUrl}"]`)
+ cy.get(`.sidebar a[href="${this.addForgeModerationUrl}"]`)
.should('exist');
});
});
describe('Test "Add Forge Now" moderation listing', function() {
- before(function() {
- addForgeModerationUrl = this.Urls.add_forge_now_requests_moderation();
- listAddForgeRequestsUrl = this.Urls.add_forge_request_list_datatables();
+ beforeEach(function() {
+ this.addForgeModerationUrl = this.Urls.add_forge_now_requests_moderation();
+ this.listAddForgeRequestsUrl = this.Urls.add_forge_request_list_datatables();
});
it('should list add-forge-now requests', function() {
- cy.intercept(`${listAddForgeRequestsUrl}**`, {fixture: 'add-forge-now-requests'}).as('listRequests');
+ cy.intercept(`${this.listAddForgeRequestsUrl}**`, {fixture: 'add-forge-now-requests'}).as('listRequests');
let expectedRequests;
cy.readFile('cypress/fixtures/add-forge-now-requests.json').then((result) => {
expectedRequests = result['data'];
});
cy.addForgeModeratorLogin();
- cy.visit(addForgeModerationUrl);
+ cy.visit(this.addForgeModerationUrl);
cy.get('.swh-add-forge-now-moderation-item')
.should('have.class', 'active');
cy.wait('@listRequests').then((xhr) => {
cy.log('response:', xhr.response);
cy.log(xhr.response.body);
const requests = xhr.response.body.data;
cy.log('Requests: ', requests);
expect(requests.length).to.equal(expectedRequests.length);
cy.get('#swh-add-forge-now-moderation-list').find('tbody > tr').as('rows');
// only 2 entries
cy.get('@rows').each((row, idx, collection) => {
const request = requests[idx];
const expectedRequest = expectedRequests[idx];
assert.isNotNull(request);
assert.isNotNull(expectedRequest);
expect(request.id).to.be.equal(expectedRequest['id']);
expect(request.status).to.be.equal(expectedRequest['status']);
expect(request.submission_date).to.be.equal(expectedRequest['submission_date']);
expect(request.forge_type).to.be.equal(expectedRequest['forge_type']);
expect(request.forge_url).to.be.equal(expectedRequest['forge_url']);
});
});
});
});
diff --git a/cypress/e2e/admin.cy.js b/cypress/e2e/admin.cy.js
index f720d5ea..bbe90d01 100644
--- a/cypress/e2e/admin.cy.js
+++ b/cypress/e2e/admin.cy.js
@@ -1,300 +1,296 @@
/**
* 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 $ = Cypress.$;
-const defaultRedirect = '/';
-
-let url;
-
function logout() {
cy.contains('a', 'logout')
.click();
}
describe('Test Admin Login/logout', function() {
- before(function() {
- url = this.Urls.login();
+ beforeEach(function() {
+ this.url = this.Urls.login();
});
it('should redirect to default page', function() {
- cy.visit(url)
+ cy.visit(this.url)
.get('input[name="username"]')
.type('admin')
.get('input[name="password"]')
.type('admin')
.get('.container form')
.submit();
cy.location('pathname')
- .should('be.equal', defaultRedirect);
+ .should('be.equal', this.Urls.swh_web_homepage());
logout();
});
it('should display admin-origin-save and deposit in sidebar', function() {
cy.adminLogin();
- cy.visit(url);
+ cy.visit(this.url);
cy.get(`.sidebar a[href="${this.Urls.admin_origin_save_requests()}"]`)
.should('be.visible');
cy.get(`.sidebar a[href="${this.Urls.admin_deposit()}"]`)
.should('be.visible');
logout();
});
it('should display username on top-right', function() {
cy.adminLogin();
- cy.visit(url);
+ cy.visit(this.url);
cy.get('.swh-position-right')
.should('contain', 'admin');
logout();
});
it('should get info about a user logged in from javascript', function() {
cy.window().then(win => {
expect(win.swh.webapp.isUserLoggedIn()).to.be.false;
});
cy.adminLogin();
- cy.visit(url);
+ cy.visit(this.url);
cy.window().then(win => {
expect(win.swh.webapp.isUserLoggedIn()).to.be.true;
});
logout();
- cy.visit(url);
+ cy.visit(this.url);
cy.window().then(win => {
expect(win.swh.webapp.isUserLoggedIn()).to.be.false;
});
});
it('should prevent unauthorized access after logout', function() {
cy.visit(this.Urls.admin_origin_save_requests())
.location('pathname')
.should('be.equal', '/login/');
cy.visit(this.Urls.admin_deposit())
.location('pathname')
.should('be.equal', '/login/');
});
it('should redirect to correct page after login', function() {
// mock calls to deposit list api to avoid possible errors
// while running the test
cy.intercept(`${this.Urls.admin_deposit_list()}**`, {
body: {
data: [],
recordsTotal: 0,
recordsFiltered: 0,
draw: 1
}
});
cy.visit(this.Urls.admin_deposit())
.location('search')
.should('contain', `next=${this.Urls.admin_deposit()}`);
cy.adminLogin();
cy.visit(this.Urls.admin_deposit());
cy.location('pathname')
.should('be.equal', this.Urls.admin_deposit());
logout();
});
});
const existingRowToSelect = 'https://bitbucket.org/';
const originUrlListTestData = [
{
listType: 'authorized',
originToAdd: 'git://git.archlinux.org/',
originToRemove: 'https://github.com/'
},
{
listType: 'unauthorized',
originToAdd: 'https://random.org',
originToRemove: 'https://gitlab.com'
}
];
const capitalize = s => s.charAt(0).toUpperCase() + s.slice(1);
describe('Test Admin Origin Save Urls Filtering', function() {
beforeEach(function() {
cy.adminLogin();
cy.visit(this.Urls.admin_origin_save_requests());
cy.contains('a', 'Origin urls filtering')
.click()
.wait(500);
});
it(`should select or unselect a table row by clicking on it`, function() {
cy.contains(`#swh-authorized-origin-urls tr`, existingRowToSelect)
.click()
.should('have.class', 'selected')
.click()
.should('not.have.class', 'selected');
});
originUrlListTestData.forEach(testData => {
it(`should add a new origin url prefix in the ${testData.listType} list`, function() {
const tabName = capitalize(testData.listType) + ' urls';
cy.contains('a', tabName)
.click()
.wait(500);
cy.get(`#swh-${testData.listType}-origin-urls tr`).each(elt => {
if ($(elt).text() === testData.originToAdd) {
cy.get(elt).click();
cy.get(`#swh-remove-${testData.listType}-origin-url`).click();
}
});
cy.get(`#swh-${testData.listType}-url-prefix`)
.type(testData.originToAdd);
cy.get(`#swh-add-${testData.listType}-origin-url`)
.click();
cy.contains(`#swh-${testData.listType}-origin-urls tr`, testData.originToAdd)
.should('be.visible');
cy.contains('.alert-success', `The origin url prefix has been successfully added in the ${testData.listType} list.`)
.should('be.visible');
cy.get(`#swh-add-${testData.listType}-origin-url`)
.click();
cy.contains('.alert-warning', `The provided origin url prefix is already registered in the ${testData.listType} list.`)
.should('be.visible');
});
it(`should remove an origin url prefix from the ${testData.listType} list`, function() {
const tabName = capitalize(testData.listType) + ' urls';
cy.contains('a', tabName)
.click();
let originUrlMissing = true;
cy.get(`#swh-${testData.listType}-origin-urls tr`).each(elt => {
if ($(elt).text() === testData.originToRemove) {
originUrlMissing = false;
}
});
if (originUrlMissing) {
cy.get(`#swh-${testData.listType}-url-prefix`)
.type(testData.originToRemove);
cy.get(`#swh-add-${testData.listType}-origin-url`)
.click();
cy.get('.alert-dismissible button').click();
}
cy.contains(`#swh-${testData.listType}-origin-urls tr`, testData.originToRemove)
.click();
cy.get(`#swh-remove-${testData.listType}-origin-url`).click();
cy.contains(`#swh-${testData.listType}-origin-urls tr`, testData.originToRemove)
.should('not.exist');
});
});
});
describe('Test Admin Origin Save', function() {
it(`should reject a save code now request with note`, function() {
const originUrl = `https://example.org/${Date.now()}`;
const rejectionNote = 'The provided URL does not target a git repository.';
const rejectUrl = this.Urls.admin_origin_save_request_reject('git', originUrl);
cy.intercept('POST', rejectUrl).as('rejectSaveRequest');
// anonymous user creates a request put in pending state
cy.visit(this.Urls.origin_save());
cy.get('#swh-input-origin-url')
.type(originUrl);
cy.get('#swh-input-origin-save-submit')
.click();
// admin user logs in and visits save code now admin page
cy.adminLogin();
cy.visit(this.Urls.admin_origin_save_requests());
// admin rejects the save request and adds a rejection note
cy.contains('#swh-origin-save-pending-requests', originUrl)
.click();
cy.get('#swh-reject-save-origin-request')
.click();
cy.get('#swh-rejection-text')
.then(textarea => {
textarea.val(rejectionNote);
});
cy.get('#swh-rejection-submit')
.click();
cy.get('#swh-web-modal-confirm-ok-btn')
.click();
cy.wait('@rejectSaveRequest');
// checks rejection note has been saved to swh-web database
cy.request(this.Urls.api_1_save_origin('git', originUrl))
.then(response => {
expect(response.body[0]['note']).to.equal(rejectionNote);
});
// check rejection note is displayed by clicking on the info icon
// in requests table from public save code now page
cy.visit(this.Urls.origin_save());
cy.get('#swh-origin-save-requests-list-tab')
.click();
cy.contains('#swh-origin-save-requests tr', originUrl);
cy.get('.swh-save-request-info')
.eq(0)
.click();
cy.get('.popover-body')
.should('have.text', rejectionNote);
// remove rejected request from swh-web database to avoid side effects
// in tests located in origin-save.spec.js
cy.visit(this.Urls.admin_origin_save_requests());
cy.get('#swh-save-requests-rejected-tab')
.click();
cy.contains('#swh-origin-save-rejected-requests', originUrl)
.click();
cy.get('#swh-remove-rejected-save-origin-request')
.click();
cy.get('#swh-web-modal-confirm-ok-btn')
.click();
});
});

File Metadata

Mime Type
text/x-diff
Expires
Jul 4 2025, 6:12 PM (4 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3251336

Event Timeline