Changeset View
Changeset View
Standalone View
Standalone View
cypress/integration/vault.spec.js
Show All 15 Lines | cy.contains('button', 'Download') | ||||
.click(); | .click(); | ||||
cy.contains('.dropdown-item', objectType) | cy.contains('.dropdown-item', objectType) | ||||
.click(); | .click(); | ||||
cy.wait('@checkVaultCookingTask'); | cy.wait('@checkVaultCookingTask'); | ||||
} | } | ||||
function getVaultItemList() { | |||||
return JSON.parse(window.localStorage.getItem('swh-vault-cooking-tasks')); | |||||
} | |||||
function updateVaultItemList(vaultUrl, vaultItems) { | function updateVaultItemList(vaultUrl, vaultItems) { | ||||
cy.visit(vaultUrl) | cy.visit(vaultUrl) | ||||
.then(() => { | .then(() => { | ||||
// Add uncooked task to localStorage | // Add uncooked task to localStorage | ||||
// which updates it in vault items list | // which updates it in vault items list | ||||
window.localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultItems)); | window.localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultItems)); | ||||
}); | }); | ||||
} | } | ||||
// Mocks API response : /api/1/vault/(:objectType)/(:hash) | // Mocks API response : /api/1/vault/(:bundleType)/(:swhid) | ||||
// objectType : {'directory', 'revision'} | // bundleType : {'flat', 'gitfast'} | ||||
function genVaultCookingResponse(objectType, objectId, status, message, fetchUrl) { | function genVaultCookingResponse(bundleType, swhid, status, message, fetchUrl) { | ||||
return { | return { | ||||
'obj_type': objectType, | 'bundle_type': bundleType, | ||||
'id': 1, | 'id': 1, | ||||
'progress_message': message, | 'progress_message': message, | ||||
'status': status, | 'status': status, | ||||
'obj_id': objectId, | 'swhid': swhid, | ||||
'fetch_url': fetchUrl | 'fetch_url': fetchUrl | ||||
}; | }; | ||||
}; | }; | ||||
// Tests progressbar color, status | // Tests progressbar color, status | ||||
// And status in localStorage | // And status in localStorage | ||||
function testStatus(taskId, color, statusMsg, status) { | function testStatus(taskId, color, statusMsg, status) { | ||||
cy.get(`.swh-vault-table #vault-task-${taskId}`) | cy.get(`.swh-vault-table #vault-task-${CSS.escape(taskId)}`) | ||||
.should('be.visible') | .should('be.visible') | ||||
.find('.progress-bar') | .find('.progress-bar') | ||||
.should('be.visible') | .should('be.visible') | ||||
.and('have.css', 'background-color', color) | .and('have.css', 'background-color', color) | ||||
.and('contain', statusMsg) | .and('contain', statusMsg) | ||||
.then(() => { | .then(() => { | ||||
// Vault item with object_id as taskId should exist in localStorage | // Vault item with object_id as taskId should exist in localStorage | ||||
const currentVaultItems = JSON.parse(window.localStorage.getItem('swh-vault-cooking-tasks')); | const currentVaultItems = getVaultItemList(); | ||||
const vaultItem = currentVaultItems.find(obj => obj.object_id === taskId); | const vaultItem = currentVaultItems.find(obj => obj.swhid === taskId); | ||||
assert.isNotNull(vaultItem); | assert.isNotNull(vaultItem); | ||||
assert.strictEqual(vaultItem.status, status); | assert.strictEqual(vaultItem.status, status); | ||||
}); | }); | ||||
} | } | ||||
describe('Vault Cooking User Interface Tests', function() { | describe('Vault Cooking User Interface Tests', function() { | ||||
before(function() { | before(function() { | ||||
const dirInfo = this.origin[0].directory[0]; | const dirInfo = this.origin[0].directory[0]; | ||||
this.directory = dirInfo.id; | this.directory = `swh:1:dir:${dirInfo.id}`; | ||||
this.directoryUrl = this.Urls.browse_origin_directory() + | this.directoryUrl = this.Urls.browse_origin_directory() + | ||||
`?origin_url=${this.origin[0].url}&path=${dirInfo.path}`; | `?origin_url=${this.origin[0].url}&path=${dirInfo.path}`; | ||||
this.vaultDirectoryUrl = this.Urls.api_1_vault_cook_directory(this.directory); | this.vaultDirectoryUrl = this.Urls.api_1_vault_cook_flat(this.directory); | ||||
this.vaultFetchDirectoryUrl = this.Urls.api_1_vault_fetch_directory(this.directory); | this.vaultFetchDirectoryUrl = this.Urls.api_1_vault_fetch_flat(this.directory); | ||||
this.revision = this.origin[1].revisions[0]; | this.revisionId = this.origin[1].revisions[0]; | ||||
this.revisionUrl = this.Urls.browse_revision(this.revision); | this.revision = `swh:1:rev:${this.revisionId}`; | ||||
this.vaultRevisionUrl = this.Urls.api_1_vault_cook_revision_gitfast(this.revision); | this.revisionUrl = this.Urls.browse_revision(this.revisionId); | ||||
this.vaultFetchRevisionUrl = this.Urls.api_1_vault_fetch_revision_gitfast(this.revision); | 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; | const release = this.origin[1].release; | ||||
this.releaseUrl = this.Urls.browse_release(release.id) + `?origin_url=${this.origin[1].url}`; | this.releaseUrl = this.Urls.browse_release(release.id) + `?origin_url=${this.origin[1].url}`; | ||||
this.vaultReleaseDirectoryUrl = this.Urls.api_1_vault_cook_directory(release.directory); | this.vaultReleaseDirectoryUrl = this.Urls.api_1_vault_cook_flat(`swh:1:dir:${release.directory}`); | ||||
}); | }); | ||||
beforeEach(function() { | beforeEach(function() { | ||||
// For some reason, this gets reset if we define it in the before() hook, | // For some reason, this gets reset if we define it in the before() hook, | ||||
// so we need to define it here | // so we need to define it here | ||||
this.vaultItems = [ | 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_type': 'revision', | ||||
'object_id': this.revision, | 'object_id': this.revisionId, | ||||
'email': '', | 'email': '', | ||||
'status': 'done', | 'status': 'done', | ||||
'fetch_url': `/api/1/vault/revision/${this.revision}/gitfast/raw/`, | 'fetch_url': `/api/1/vault/revision/${this.revisionId}/gitfast/raw/`, | ||||
'progress_message': null | 'progress_message': null | ||||
} | } | ||||
]; | ]; | ||||
this.genVaultDirCookingResponse = (status, message = null) => { | this.genVaultDirCookingResponse = (status, message = null) => { | ||||
return genVaultCookingResponse('directory', this.directory, status, | return genVaultCookingResponse('flat', this.directory, status, | ||||
message, this.vaultFetchDirectoryUrl); | message, this.vaultFetchDirectoryUrl); | ||||
}; | }; | ||||
this.genVaultRevCookingResponse = (status, message = null) => { | this.genVaultRevCookingResponse = (status, message = null) => { | ||||
return genVaultCookingResponse('revision', this.revision, status, | return genVaultCookingResponse('gitfast', this.revision, status, | ||||
message, this.vaultFetchRevisionUrl); | message, this.vaultFetchRevisionUrl); | ||||
}; | }; | ||||
}); | }); | ||||
it('should report an error when vault service is experiencing issues', function() { | it('should report an error when vault service is experiencing issues', function() { | ||||
// Browse a directory | // Browse a directory | ||||
cy.visit(this.directoryUrl); | cy.visit(this.directoryUrl); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | cy.intercept('GET', this.vaultDirectoryUrl, req => this.genVaultDirCookingResponse('done')) | ||||
.as('checkVaultCookingTask'); | .as('checkVaultCookingTask'); | ||||
// Stub responses when requesting the vault API to simulate | // Stub responses when requesting the vault API to simulate | ||||
// a task has been created | // a task has been created | ||||
cy.intercept('POST', this.vaultDirectoryUrl, { | cy.intercept('POST', this.vaultDirectoryUrl, { | ||||
body: this.genVaultDirCookingResponse('new') | body: this.genVaultDirCookingResponse('new') | ||||
}).as('createVaultCookingTask'); | }).as('createVaultCookingTask'); | ||||
cy.contains(`#vault-task-${this.revision} button`, 'Download') | cy.contains(`#vault-task-${CSS.escape(this.revision)} button`, 'Download') | ||||
.click(); | .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)); | |||||
cy.visit(this.Urls.browse_vault()); | |||||
// trick to override the response of an intercepted request | |||||
// https://github.com/cypress-io/cypress/issues/9302 | |||||
cy.intercept('GET', this.vaultDirectoryUrl, req => this.genVaultDirCookingResponse('done')) | |||||
.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'); | |||||
anlambert: From my point of view, those intercepts can be removed as no requests will be sent as the… | |||||
// 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); | |||||
}); | |||||
it('should create a directory cooking task and report the success', function() { | it('should create a directory cooking task and report the success', function() { | ||||
// Browse a directory | // Browse a directory | ||||
cy.visit(this.directoryUrl); | cy.visit(this.directoryUrl); | ||||
// Stub response to the vault API to simulate archive download | // Stub response to the vault API to simulate archive download | ||||
cy.intercept('GET', this.vaultFetchDirectoryUrl, { | cy.intercept('GET', this.vaultFetchDirectoryUrl, { | ||||
fixture: `${this.directory}.tar.gz`, | fixture: `${this.directory}.tar.gz`, | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | cy.window().then(win => { | ||||
cy.wait('@checkVaultCookingTask').then(() => { | cy.wait('@checkVaultCookingTask').then(() => { | ||||
testStatus(this.directory, progressbarColors['pending'], 'Processing...', 'pending'); | testStatus(this.directory, progressbarColors['pending'], 'Processing...', 'pending'); | ||||
}); | }); | ||||
cy.wait('@checkVaultCookingTask').then(() => { | cy.wait('@checkVaultCookingTask').then(() => { | ||||
testStatus(this.directory, progressbarColors['done'], 'done', 'done'); | testStatus(this.directory, progressbarColors['done'], 'done', 'done'); | ||||
}); | }); | ||||
cy.get(`#vault-task-${this.directory} .vault-origin a`) | cy.get(`#vault-task-${CSS.escape(this.directory)} .vault-origin a`) | ||||
.should('contain', this.origin[0].url) | .should('contain', this.origin[0].url) | ||||
.should('have.attr', 'href', `${this.Urls.browse_origin()}?origin_url=${this.origin[0].url}`); | .should('have.attr', 'href', `${this.Urls.browse_origin()}?origin_url=${this.origin[0].url}`); | ||||
cy.get(`#vault-task-${this.directory} .vault-object-info a`) | cy.get(`#vault-task-${CSS.escape(this.directory)} .vault-object-info a`) | ||||
.should('have.text', this.directory) | .should('have.text', this.directory) | ||||
.should('have.attr', 'href', browseDirectoryUrl); | .should('have.attr', 'href', browseDirectoryUrl); | ||||
cy.get(`#vault-task-${this.directory} .vault-dl-link button`) | cy.get(`#vault-task-${CSS.escape(this.directory)} .vault-dl-link button`) | ||||
.click(); | .click(); | ||||
cy.wait('@fetchCookedArchive').then((xhr) => { | cy.wait('@fetchCookedArchive').then((xhr) => { | ||||
assert.isNotNull(xhr.response.body); | assert.isNotNull(xhr.response.body); | ||||
}); | }); | ||||
}); | }); | ||||
}); | }); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | cy.window().then(win => { | ||||
cy.wait('@checkVaultCookingTask').then(() => { | cy.wait('@checkVaultCookingTask').then(() => { | ||||
testStatus(this.revision, progressbarColors['pending'], 'Processing...', 'pending'); | testStatus(this.revision, progressbarColors['pending'], 'Processing...', 'pending'); | ||||
}); | }); | ||||
cy.wait('@checkVaultCookingTask').then(() => { | cy.wait('@checkVaultCookingTask').then(() => { | ||||
testStatus(this.revision, progressbarColors['done'], 'done', 'done'); | testStatus(this.revision, progressbarColors['done'], 'done', 'done'); | ||||
}); | }); | ||||
cy.get(`#vault-task-${this.revision} .vault-origin`) | cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-origin`) | ||||
.should('have.text', 'unknown'); | .should('have.text', 'unknown'); | ||||
cy.get(`#vault-task-${this.revision} .vault-object-info a`) | cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-object-info a`) | ||||
.should('have.text', this.revision) | .should('have.text', this.revision) | ||||
.should('have.attr', 'href', browseRevisionUrl); | .should('have.attr', 'href', browseRevisionUrl); | ||||
cy.get(`#vault-task-${this.revision} .vault-dl-link button`) | cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-dl-link button`) | ||||
.click(); | .click(); | ||||
cy.wait('@fetchCookedArchive').then((xhr) => { | cy.wait('@fetchCookedArchive').then((xhr) => { | ||||
assert.isNotNull(xhr.response.body); | assert.isNotNull(xhr.response.body); | ||||
}); | }); | ||||
}); | }); | ||||
}); | }); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | cy.intercept({url: this.vaultFetchRevisionUrl}, { | ||||
'exception': 'NotFoundExc', | 'exception': 'NotFoundExc', | ||||
'reason': `Revision with ID '${this.revision}' not found.` | 'reason': `Revision with ID '${this.revision}' not found.` | ||||
}, | }, | ||||
headers: { | headers: { | ||||
'Content-Type': 'json' | 'Content-Type': 'json' | ||||
} | } | ||||
}).as('fetchCookedArchive'); | }).as('fetchCookedArchive'); | ||||
cy.get(`#vault-task-${this.revision} .vault-dl-link button`) | cy.get(`#vault-task-${CSS.escape(this.revision)} .vault-dl-link button`) | ||||
.click(); | .click(); | ||||
cy.wait('@fetchCookedArchive').then(() => { | cy.wait('@fetchCookedArchive').then(() => { | ||||
cy.intercept('POST', this.vaultRevisionUrl, { | cy.intercept('POST', this.vaultRevisionUrl, { | ||||
body: this.genVaultRevCookingResponse('new') | body: this.genVaultRevCookingResponse('new') | ||||
}).as('createVaultCookingTask'); | }).as('createVaultCookingTask'); | ||||
cy.intercept(this.vaultRevisionUrl, { | cy.intercept(this.vaultRevisionUrl, { | ||||
Show All 11 Lines | cy.wait('@fetchCookedArchive').then(() => { | ||||
}); | }); | ||||
}); | }); | ||||
}); | }); | ||||
it('should remove selected vault items', function() { | it('should remove selected vault items', function() { | ||||
updateVaultItemList(this.Urls.browse_vault(), this.vaultItems); | updateVaultItemList(this.Urls.browse_vault(), this.vaultItems); | ||||
cy.get(`#vault-task-${this.revision}`) | cy.get(`#vault-task-${CSS.escape(this.revision)}`) | ||||
.find('input[type="checkbox"]') | .find('input[type="checkbox"]') | ||||
.click({force: true}); | .click({force: true}); | ||||
cy.contains('button', 'Remove selected tasks') | cy.contains('button', 'Remove selected tasks') | ||||
.click(); | .click(); | ||||
cy.get(`#vault-task-${this.revision}`) | cy.get(`#vault-task-${CSS.escape(this.revision)}`) | ||||
.should('not.exist'); | .should('not.exist'); | ||||
}); | }); | ||||
it('should offer to immediately download a directory tarball if already cooked', function() { | it('should offer to immediately download a directory tarball if already cooked', function() { | ||||
// Browse a directory | // Browse a directory | ||||
cy.visit(this.directoryUrl); | cy.visit(this.directoryUrl); | ||||
▲ Show 20 Lines • Show All 79 Lines • Show Last 20 Lines |
From my point of view, those intercepts can be removed as no requests will be sent as the cooking task in local storage has the done status plus the call to click below is not really needed.