diff --git a/assets/src/bundles/vault/vault-ui.js b/assets/src/bundles/vault/vault-ui.js
index 10373703..facf4539 100644
--- a/assets/src/bundles/vault/vault-ui.js
+++ b/assets/src/bundles/vault/vault-ui.js
@@ -1,256 +1,258 @@
/**
* Copyright (C) 2018-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 {handleFetchError, handleFetchErrors, csrfPost} from 'utils/functions';
import vaultTableRowTemplate from './vault-table-row.ejs';
const progress =
`
;`;
const pollingInterval = 5000;
let checkVaultId;
function updateProgressBar(progressBar, cookingTask) {
if (cookingTask.status === 'new') {
progressBar.css('background-color', 'rgba(128, 128, 128, 0.5)');
} else if (cookingTask.status === 'pending') {
progressBar.css('background-color', 'rgba(0, 0, 255, 0.5)');
} else if (cookingTask.status === 'done') {
progressBar.css('background-color', '#5cb85c');
} else if (cookingTask.status === 'failed') {
progressBar.css('background-color', 'rgba(255, 0, 0, 0.5)');
progressBar.css('background-image', 'none');
}
progressBar.text(cookingTask.progress_message || cookingTask.status);
if (cookingTask.status === 'new' || cookingTask.status === 'pending') {
progressBar.addClass('progress-bar-animated');
} else {
progressBar.removeClass('progress-bar-striped');
}
}
let recookTask;
// called when the user wants to download a cooked archive
export async function fetchCookedObject(fetchUrl) {
recookTask = null;
// first, check if the link is still available from the vault
const response = await fetch(fetchUrl);
// link is still alive, proceed to download
if (response.ok) {
$('#vault-fetch-iframe').attr('src', fetchUrl);
// link is dead
} else {
// get the associated cooking task
const vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
for (let i = 0; i < vaultCookingTasks.length; ++i) {
if (vaultCookingTasks[i].fetch_url === fetchUrl) {
recookTask = vaultCookingTasks[i];
break;
}
}
// display a modal asking the user if he wants to recook the archive
$('#vault-recook-object-modal').modal('show');
}
}
// called when the user wants to recook an archive
// for which the download link is not available anymore
export async function recookObject() {
if (recookTask) {
// stop cooking tasks status polling
clearTimeout(checkVaultId);
// build cook request url
let cookingUrl;
if (recookTask.bundle_type === 'flat') {
cookingUrl = Urls.api_1_vault_cook_flat(recookTask.swhid);
} else {
cookingUrl = Urls.api_1_vault_cook_gitfast(recookTask.swhid);
}
if (recookTask.email) {
cookingUrl += '?email=' + recookTask.email;
}
try {
// request archive cooking
const response = await csrfPost(cookingUrl);
handleFetchError(response);
// update task status
recookTask.status = 'new';
const vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
for (let i = 0; i < vaultCookingTasks.length; ++i) {
if (vaultCookingTasks[i].swhid === recookTask.swhid) {
vaultCookingTasks[i] = recookTask;
break;
}
}
// save updated tasks to local storage
localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));
// hide recook archive modal
$('#vault-recook-object-modal').modal('hide');
// restart cooking tasks status polling
await checkVaultCookingTasks();
} catch (_) {
// something went wrong
$('#vault-recook-object-modal').modal('hide');
await checkVaultCookingTasks();
}
}
}
async function checkVaultCookingTasks() {
const vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
if (!vaultCookingTasks || vaultCookingTasks.length === 0) {
$('.swh-vault-table tbody tr').remove();
checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);
return;
}
const cookingTaskRequests = [];
const tasks = {};
const currentObjectIds = [];
for (let i = 0; i < vaultCookingTasks.length; ++i) {
const cookingTask = vaultCookingTasks[i];
if (typeof cookingTask.object_type !== 'undefined') {
// Legacy cooking task, upgrade it to the new schema
if (cookingTask.object_type === 'directory') {
cookingTask.swhid = `swh:1:dir:${cookingTask.object_id}`;
cookingTask.bundle_type = 'flat';
+ cookingTask.fetch_url = Urls.api_1_vault_fetch_flat(cookingTask.swhid);
} else if (cookingTask.object_type === 'revision') {
cookingTask.swhid = `swh:1:rev:${cookingTask.object_id}`;
cookingTask.bundle_type = 'gitfast';
+ cookingTask.fetch_url = Urls.api_1_vault_fetch_gitfast(cookingTask.swhid);
} else {
// Log to the console + Sentry
console.error(`Unexpected cookingTask.object_type: ${cookingTask.object_type}`);
// Ignore it for now and hope a future version will fix it
continue;
}
delete cookingTask.object_type;
delete cookingTask.object_id;
}
currentObjectIds.push(cookingTask.swhid);
tasks[cookingTask.swhid] = cookingTask;
let cookingUrl;
if (cookingTask.bundle_type === 'flat') {
cookingUrl = Urls.api_1_vault_cook_flat(cookingTask.swhid);
} else {
cookingUrl = Urls.api_1_vault_cook_gitfast(cookingTask.swhid);
}
if (cookingTask.status !== 'done' && cookingTask.status !== 'failed') {
cookingTaskRequests.push(fetch(cookingUrl));
}
}
$('.swh-vault-table tbody tr').each((i, row) => {
const swhid = $(row).find('.vault-object-info').data('swhid');
if ($.inArray(swhid, currentObjectIds) === -1) {
$(row).remove();
}
});
try {
const responses = await Promise.all(cookingTaskRequests);
handleFetchErrors(responses);
const cookingTasks = await Promise.all(responses.map(r => r.json()));
const table = $('#vault-cooking-tasks tbody');
for (let i = 0; i < cookingTasks.length; ++i) {
const cookingTask = tasks[cookingTasks[i].swhid];
cookingTask.status = cookingTasks[i].status;
cookingTask.fetch_url = cookingTasks[i].fetch_url;
cookingTask.progress_message = cookingTasks[i].progress_message;
}
for (let i = 0; i < vaultCookingTasks.length; ++i) {
const cookingTask = vaultCookingTasks[i];
const rowTask = $(`#vault-task-${CSS.escape(cookingTask.swhid)}`);
if (!rowTask.length) {
let browseUrl = cookingTask.browse_url;
if (!browseUrl) {
browseUrl = Urls.browse_swhid(cookingTask.swhid);
}
const progressBar = $.parseHTML(progress)[0];
const progressBarContent = $(progressBar).find('.progress-bar');
updateProgressBar(progressBarContent, cookingTask);
table.prepend(vaultTableRowTemplate({
browseUrl: browseUrl,
cookingTask: cookingTask,
progressBar: progressBar,
Urls: Urls,
swh: swh
}));
} else {
const progressBar = rowTask.find('.progress-bar');
updateProgressBar(progressBar, cookingTask);
const downloadLink = rowTask.find('.vault-dl-link');
if (cookingTask.status === 'done') {
downloadLink[0].innerHTML =
'';
} else {
downloadLink[0].innerHTML = '';
}
}
}
localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));
checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);
} catch (error) {
console.log('Error when fetching vault cooking tasks:', error);
}
}
export function removeCookingTaskInfo(tasksToRemove) {
let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));
if (!vaultCookingTasks) {
return;
}
vaultCookingTasks = $.grep(vaultCookingTasks, task => {
return $.inArray(task.swhid, tasksToRemove) === -1;
});
localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));
}
export function initUi() {
$('#vault-tasks-toggle-selection').change(event => {
$('.vault-task-toggle-selection').prop('checked', event.currentTarget.checked);
});
$('#vault-remove-tasks').click(() => {
clearTimeout(checkVaultId);
const tasksToRemove = [];
$('.swh-vault-table tbody tr').each((i, row) => {
const taskSelected = $(row).find('.vault-task-toggle-selection').prop('checked');
if (taskSelected) {
const swhid = $(row).find('.vault-object-info').data('swhid');
tasksToRemove.push(swhid);
$(row).remove();
}
});
removeCookingTaskInfo(tasksToRemove);
$('#vault-tasks-toggle-selection').prop('checked', false);
checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);
});
checkVaultCookingTasks();
window.onfocus = () => {
clearTimeout(checkVaultId);
checkVaultCookingTasks();
};
}
diff --git a/cypress/integration/vault.spec.js b/cypress/integration/vault.spec.js
index f83388d0..9bc5e3f0 100644
--- a/cypress/integration/vault.spec.js
+++ b/cypress/integration/vault.spec.js
@@ -1,547 +1,541 @@
/**
* Copyright (C) 2019-2021 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 progressbarColors = {
'new': 'rgba(128, 128, 128, 0.5)',
'pending': 'rgba(0, 0, 255, 0.5)',
'done': 'rgb(92, 184, 92)'
};
function checkVaultCookingTask(objectType) {
cy.contains('button', 'Download')
.click();
cy.contains('.dropdown-item', objectType)
.click();
cy.wait('@checkVaultCookingTask');
}
function getVaultItemList() {
return JSON.parse(window.localStorage.getItem('swh-vault-cooking-tasks'));
}
-function updateVaultItemList(vaultUrl, vaultItems) {
- cy.visit(vaultUrl)
- .then(() => {
- // Add uncooked task to localStorage
- // which updates it in vault items list
- window.localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultItems));
- });
+function updateVaultItemList(vaultItems) {
+ window.localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultItems));
}
// Mocks API response : /api/1/vault/(:bundleType)/(:swhid)
// bundleType : {'flat', 'gitfast'}
function genVaultCookingResponse(bundleType, swhid, status, message, fetchUrl) {
return {
'bundle_type': bundleType,
'id': 1,
'progress_message': message,
'status': status,
'swhid': swhid,
'fetch_url': fetchUrl
};
};
// Tests progressbar color, status
// And status in localStorage
function testStatus(taskId, color, statusMsg, status) {
cy.get(`.swh-vault-table #vault-task-${CSS.escape(taskId)}`)
.should('be.visible')
.find('.progress-bar')
.should('be.visible')
.and('have.css', 'background-color', color)
.and('contain', statusMsg)
.then(() => {
// Vault item with object_id as taskId should exist in localStorage
const currentVaultItems = getVaultItemList();
const vaultItem = currentVaultItems.find(obj => obj.swhid === taskId);
assert.isNotNull(vaultItem);
assert.strictEqual(vaultItem.status, status);
});
}
describe('Vault Cooking User Interface Tests', function() {
before(function() {
const dirInfo = this.origin[0].directory[0];
this.directory = `swh:1:dir:${dirInfo.id}`;
this.directoryUrl = this.Urls.browse_origin_directory() +
`?origin_url=${this.origin[0].url}&path=${dirInfo.path}`;
this.vaultDirectoryUrl = this.Urls.api_1_vault_cook_flat(this.directory);
this.vaultFetchDirectoryUrl = this.Urls.api_1_vault_fetch_flat(this.directory);
this.revisionId = this.origin[1].revisions[0];
this.revision = `swh:1:rev:${this.revisionId}`;
this.revisionUrl = this.Urls.browse_revision(this.revisionId);
this.vaultRevisionUrl = this.Urls.api_1_vault_cook_gitfast(this.revision);
this.vaultFetchRevisionUrl = this.Urls.api_1_vault_fetch_gitfast(this.revision);
const release = this.origin[1].release;
this.releaseUrl = this.Urls.browse_release(release.id) + `?origin_url=${this.origin[1].url}`;
this.vaultReleaseDirectoryUrl = this.Urls.api_1_vault_cook_flat(`swh:1:dir:${release.directory}`);
});
beforeEach(function() {
// For some reason, this gets reset if we define it in the before() hook,
// so we need to define it here
this.vaultItems = [
{
'bundle_type': 'gitfast',
'swhid': this.revision,
'email': '',
'status': 'done',
'fetch_url': `/api/1/vault/gitfast/${this.revision}/raw/`,
'progress_message': null
}
];
this.legacyVaultItems = [
{
'object_type': 'revision',
'object_id': this.revisionId,
'email': '',
'status': 'done',
'fetch_url': `/api/1/vault/revision/${this.revisionId}/gitfast/raw/`,
'progress_message': null
}
];
this.genVaultDirCookingResponse = (status, message = null) => {
return genVaultCookingResponse('flat', this.directory, status,
message, this.vaultFetchDirectoryUrl);
};
this.genVaultRevCookingResponse = (status, message = null) => {
return genVaultCookingResponse('gitfast', this.revision, status,
message, this.vaultFetchRevisionUrl);
};
});
it('should report an error when vault service is experiencing issues', function() {
// Browse a directory
cy.visit(this.directoryUrl);
// Stub responses when requesting the vault API to simulate
// an internal server error
cy.intercept(this.vaultDirectoryUrl, {
body: {'exception': 'APIError'},
statusCode: 500
}).as('checkVaultCookingTask');
cy.contains('button', 'Download')
.click();
// Check error alert is displayed
cy.get('.alert-danger')
.should('be.visible')
.should('contain', 'Archive cooking service is currently experiencing issues.');
});
it('should report an error when a cooking task creation failed', function() {
// Browse a directory
cy.visit(this.directoryUrl);
// Stub responses when requesting the vault API to simulate
// a task can not be created
cy.intercept('GET', this.vaultDirectoryUrl, {
body: {'exception': 'NotFoundExc'}
}).as('checkVaultCookingTask');
cy.intercept('POST', this.vaultDirectoryUrl, {
body: {'exception': 'ValueError'},
statusCode: 500
}).as('createVaultCookingTask');
cy.contains('button', 'Download')
.click();
// Create a vault cooking task through the GUI
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.click();
cy.wait('@createVaultCookingTask');
// Check error alert is displayed
cy.get('.alert-danger')
.should('be.visible')
.should('contain', 'Archive cooking request submission failed.');
});
it('should display previous cooking tasks', function() {
- updateVaultItemList(this.Urls.browse_vault(), this.vaultItems);
+ updateVaultItemList(this.vaultItems);
cy.visit(this.Urls.browse_vault());
cy.contains(`#vault-task-${CSS.escape(this.revision)} button`, 'Download')
.click();
});
it('should display and upgrade previous cooking tasks from the legacy format', function() {
- updateVaultItemList(this.Urls.browse_vault(), this.legacyVaultItems);
-
- // updateVaultItemList doesn't work in this test?!?!
- window.localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(this.vaultItems));
+ updateVaultItemList(this.legacyVaultItems);
cy.visit(this.Urls.browse_vault());
// Check it is displayed
cy.contains(`#vault-task-${CSS.escape(this.revision)} button`, 'Download')
- .click();
-
- // Check the LocalStorage was upgraded
- expect(getVaultItemList()).to.deep.equal(this.vaultItems);
+ .then(() => {
+ // Check the LocalStorage was upgraded
+ expect(getVaultItemList()).to.deep.equal(this.vaultItems);
+ });
});
it('should create a directory cooking task and report the success', function() {
// Browse a directory
cy.visit(this.directoryUrl);
// Stub response to the vault API to simulate archive download
cy.intercept('GET', this.vaultFetchDirectoryUrl, {
fixture: `${this.directory}.tar.gz`,
headers: {
'Content-disposition': `attachment; filename=${this.directory}.tar.gz`,
'Content-Type': 'application/gzip'
}
}).as('fetchCookedArchive');
// Stub responses when checking vault task status
const checkVaulResponses = [
{'exception': 'NotFoundExc'},
this.genVaultDirCookingResponse('new'),
this.genVaultDirCookingResponse('pending', 'Processing...'),
this.genVaultDirCookingResponse('done')
];
// trick to override the response of an intercepted request
// https://github.com/cypress-io/cypress/issues/9302
cy.intercept('GET', this.vaultDirectoryUrl, req => req.reply(checkVaulResponses.shift()))
.as('checkVaultCookingTask');
// Stub responses when requesting the vault API to simulate
// a task has been created
cy.intercept('POST', this.vaultDirectoryUrl, {
body: this.genVaultDirCookingResponse('new')
}).as('createVaultCookingTask');
cy.contains('button', 'Download')
.click();
cy.window().then(win => {
const swhIdsContext = win.swh.webapp.getSwhIdsContext();
const browseDirectoryUrl = swhIdsContext.directory.swhid_with_context_url;
// Create a vault cooking task through the GUI
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.click();
cy.wait('@createVaultCookingTask');
// Check success alert is displayed
cy.get('.alert-success')
.should('be.visible')
.should('contain', 'Archive cooking request successfully submitted.');
// Go to Downloads page
cy.visit(this.Urls.browse_vault());
cy.wait('@checkVaultCookingTask').then(() => {
testStatus(this.directory, progressbarColors['new'], 'new', 'new');
});
cy.wait('@checkVaultCookingTask').then(() => {
testStatus(this.directory, progressbarColors['pending'], 'Processing...', 'pending');
});
cy.wait('@checkVaultCookingTask').then(() => {
testStatus(this.directory, progressbarColors['done'], 'done', 'done');
});
cy.get(`#vault-task-${CSS.escape(this.directory)} .vault-origin a`)
.should('contain', this.origin[0].url)
.should('have.attr', 'href', `${this.Urls.browse_origin()}?origin_url=${this.origin[0].url}`);
cy.get(`#vault-task-${CSS.escape(this.directory)} .vault-object-info a`)
.should('have.text', this.directory)
.should('have.attr', 'href', browseDirectoryUrl);
cy.get(`#vault-task-${CSS.escape(this.directory)} .vault-dl-link button`)
.click();
cy.wait('@fetchCookedArchive').then((xhr) => {
assert.isNotNull(xhr.response.body);
});
});
});
it('should create a revision cooking task and report its status', function() {
cy.adminLogin();
// Browse a revision
cy.visit(this.revisionUrl);
// Stub response to the vault API indicating to simulate archive download
cy.intercept({url: this.vaultFetchRevisionUrl}, {
fixture: `${this.revision}.gitfast.gz`,
headers: {
'Content-disposition': `attachment; filename=${this.revision}.gitfast.gz`,
'Content-Type': 'application/gzip'
}
}).as('fetchCookedArchive');
// Stub responses when checking vault task status
const checkVaultResponses = [
{'exception': 'NotFoundExc'},
this.genVaultRevCookingResponse('new'),
this.genVaultRevCookingResponse('pending', 'Processing...'),
this.genVaultRevCookingResponse('done')
];
// trick to override the response of an intercepted request
// https://github.com/cypress-io/cypress/issues/9302
cy.intercept('GET', this.vaultRevisionUrl, req => req.reply(checkVaultResponses.shift()))
.as('checkVaultCookingTask');
// Stub responses when requesting the vault API to simulate
// a task has been created
cy.intercept('POST', this.vaultRevisionUrl, {
body: this.genVaultRevCookingResponse('new')
}).as('createVaultCookingTask');
// Create a vault cooking task through the GUI
checkVaultCookingTask('as git');
cy.window().then(win => {
const swhIdsContext = win.swh.webapp.getSwhIdsContext();
const browseRevisionUrl = swhIdsContext.revision.swhid_url;
// Create a vault cooking task through the GUI
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.click();
cy.wait('@createVaultCookingTask');
// Check success alert is displayed
cy.get('.alert-success')
.should('be.visible')
.should('contain', 'Archive cooking request successfully submitted.');
// Go to Downloads page
cy.visit(this.Urls.browse_vault());
cy.wait('@checkVaultCookingTask').then(() => {
testStatus(this.revision, progressbarColors['new'], 'new', 'new');
});
cy.wait('@checkVaultCookingTask').then(() => {
testStatus(this.revision, progressbarColors['pending'], 'Processing...', 'pending');
});
cy.wait('@checkVaultCookingTask').then(() => {
testStatus(this.revision, progressbarColors['done'], 'done', 'done');
});
cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-origin`)
.should('have.text', 'unknown');
cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-object-info a`)
.should('have.text', this.revision)
.should('have.attr', 'href', browseRevisionUrl);
cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-dl-link button`)
.click();
cy.wait('@fetchCookedArchive').then((xhr) => {
assert.isNotNull(xhr.response.body);
});
});
});
it('should create a directory cooking task from the release view', function() {
// Browse a directory
cy.visit(this.releaseUrl);
// Stub responses when checking vault task status
const checkVaultResponses = [
{'exception': 'NotFoundExc'},
this.genVaultDirCookingResponse('new')
];
// trick to override the response of an intercepted request
// https://github.com/cypress-io/cypress/issues/9302
cy.intercept('GET', this.vaultReleaseDirectoryUrl, req => req.reply(checkVaultResponses.shift()))
.as('checkVaultCookingTask');
// Stub responses when requesting the vault API to simulate
// a task has been created
cy.intercept('POST', this.vaultReleaseDirectoryUrl, {
body: this.genVaultDirCookingResponse('new')
}).as('createVaultCookingTask');
cy.contains('button', 'Download')
.click();
// Create a vault cooking task through the GUI
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.click();
cy.wait('@createVaultCookingTask');
// Check success alert is displayed
cy.get('.alert-success')
.should('be.visible')
.should('contain', 'Archive cooking request successfully submitted.');
});
it('should offer to recook an archive if no more available to download', function() {
- updateVaultItemList(this.Urls.browse_vault(), this.vaultItems);
+ updateVaultItemList(this.vaultItems);
// Send 404 when fetching vault item
cy.intercept({url: this.vaultFetchRevisionUrl}, {
statusCode: 404,
body: {
'exception': 'NotFoundExc',
'reason': `Revision with ID '${this.revision}' not found.`
},
headers: {
'Content-Type': 'json'
}
}).as('fetchCookedArchive');
- cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-dl-link button`)
+ cy.visit(this.Urls.browse_vault())
+ .get(`#vault-task-${CSS.escape(this.revision)} .vault-dl-link button`)
.click();
cy.wait('@fetchCookedArchive').then(() => {
cy.intercept('POST', this.vaultRevisionUrl, {
body: this.genVaultRevCookingResponse('new')
}).as('createVaultCookingTask');
cy.intercept(this.vaultRevisionUrl, {
body: this.genVaultRevCookingResponse('new')
}).as('checkVaultCookingTask');
cy.get('#vault-recook-object-modal > .modal-dialog')
.should('be.visible')
.contains('button:visible', 'Ok')
.click();
cy.wait('@checkVaultCookingTask')
.then(() => {
testStatus(this.revision, progressbarColors['new'], 'new', 'new');
});
});
});
it('should remove selected vault items', function() {
- updateVaultItemList(this.Urls.browse_vault(), this.vaultItems);
+ updateVaultItemList(this.vaultItems);
- cy.get(`#vault-task-${CSS.escape(this.revision)}`)
+ cy.visit(this.Urls.browse_vault())
+ .get(`#vault-task-${CSS.escape(this.revision)}`)
.find('input[type="checkbox"]')
.click({force: true});
cy.contains('button', 'Remove selected tasks')
.click();
cy.get(`#vault-task-${CSS.escape(this.revision)}`)
.should('not.exist');
});
it('should offer to immediately download a directory tarball if already cooked', function() {
// Browse a directory
cy.visit(this.directoryUrl);
// Stub response to the vault API to simulate archive download
cy.intercept({url: this.vaultFetchDirectoryUrl}, {
fixture: `${this.directory}.tar.gz`,
headers: {
'Content-disposition': `attachment; filename=${this.directory}.tar.gz`,
'Content-Type': 'application/gzip'
}
}).as('fetchCookedArchive');
// Stub responses when requesting the vault API to simulate
// the directory tarball has already been cooked
cy.intercept(this.vaultDirectoryUrl, {
body: this.genVaultDirCookingResponse('done')
}).as('checkVaultCookingTask');
// Create a vault cooking task through the GUI
cy.contains('button', 'Download')
.click();
// Start archive download through the GUI
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.click();
cy.wait('@fetchCookedArchive');
});
it('should offer to immediately download a revision gitfast archive if already cooked', function() {
cy.adminLogin();
// Browse a directory
cy.visit(this.revisionUrl);
// Stub response to the vault API to simulate archive download
cy.intercept({url: this.vaultFetchRevisionUrl}, {
fixture: `${this.revision}.gitfast.gz`,
headers: {
'Content-disposition': `attachment; filename=${this.revision}.gitfast.gz`,
'Content-Type': 'application/gzip'
}
}).as('fetchCookedArchive');
// Stub responses when requesting the vault API to simulate
// the directory tarball has already been cooked
cy.intercept(this.vaultRevisionUrl, {
body: this.genVaultRevCookingResponse('done')
}).as('checkVaultCookingTask');
checkVaultCookingTask('as git');
// Start archive download through the GUI
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.click();
cy.wait('@fetchCookedArchive');
});
it('should offer to recook an object if previous vault task failed', function() {
cy.visit(this.directoryUrl);
// Stub responses when requesting the vault API to simulate
// the last cooking of the directory tarball has failed
cy.intercept(this.vaultDirectoryUrl, {
body: this.genVaultDirCookingResponse('failed')
}).as('checkVaultCookingTask');
cy.contains('button', 'Download')
.click();
// Check that recooking the directory is offered to user
cy.get('.modal-dialog')
.contains('button:visible', 'Ok')
.should('be.visible');
});
});