From bcf3270ddf5667539311133beb8353699cc59999 Mon Sep 17 00:00:00 2001 From: Alicia Zangger Date: Fri, 27 Nov 2020 10:31:59 +0100 Subject: [PATCH] tests: create cypress tests to check 0 day checkout * Adds a test to control that the 'zero day checkout' works correctly. * Adds a test to check the creation of a cipo. Co-Authored-by: Alicia Zangger --- tests/e2e/cypress/cypress/fixtures/cipo.json | 51 ++++++ .../cypress/cypress/fixtures/documents.json | 5 +- .../cypress/cypress/fixtures/item_types.json | 16 ++ tests/e2e/cypress/cypress/fixtures/items.json | 8 + .../cypress/fixtures/patron_types.json | 13 ++ tests/e2e/cypress/cypress/fixtures/users.json | 28 +++- .../circulation/scenario-a.spec.js | 5 +- .../circulation/scenario-b.spec.js | 3 +- .../circulation/test-on-site-cipo.spec.js | 144 +++++++++++++++++ .../editor/ci-po/create-ci-po.spec.js | 84 ++++++++++ .../document/create-simple-document.spec.js | 2 + .../examples/example-test-request.spec.js | 10 +- tests/e2e/cypress/cypress/support/api.js | 151 +++++++++++++++++- tests/e2e/cypress/cypress/support/cipo.js | 112 +++++++++++++ .../cypress/cypress/support/circulation.js | 2 +- tests/e2e/cypress/cypress/support/index.js | 2 +- tests/e2e/cypress/cypress/support/record.js | 2 +- tests/e2e/cypress/cypress/support/utils.js | 54 ++++++- 18 files changed, 670 insertions(+), 22 deletions(-) create mode 100644 tests/e2e/cypress/cypress/fixtures/cipo.json create mode 100644 tests/e2e/cypress/cypress/fixtures/item_types.json create mode 100644 tests/e2e/cypress/cypress/fixtures/patron_types.json create mode 100644 tests/e2e/cypress/cypress/integration/circulation/test-on-site-cipo.spec.js create mode 100644 tests/e2e/cypress/cypress/integration/editor/ci-po/create-ci-po.spec.js create mode 100644 tests/e2e/cypress/cypress/support/cipo.js diff --git a/tests/e2e/cypress/cypress/fixtures/cipo.json b/tests/e2e/cypress/cypress/fixtures/cipo.json new file mode 100644 index 0000000000..e19de25d9d --- /dev/null +++ b/tests/e2e/cypress/cypress/fixtures/cipo.json @@ -0,0 +1,51 @@ +{ + "on_site": { + "organisation_pid": 4, + "name": "On site", + "allow_requests": false, + "allow_checkout": true, + "checkout_duration": 0, + "policy_library_level": false, + "is_default": false + }, + "extended": { + "organisation_pid": 4, + "name":"Extended", + "description":"Extended loan (3 months).", + "allow_requests":true, + "allow_checkout":true, + "checkout_duration":84, + "number_of_days_after_due_date":5, + "number_of_days_before_due_date":5, + "number_renewals":3, + "renewal_duration":84, + "reminder_fee_amount":2, + "policy_library_level":false, + "is_default":false + }, + "default": { + "pid": 7, + "organisation_pid": 4, + "name":"Default", + "description":"Default circulation policy.", + "allow_requests":true, + "allow_checkout":true, + "checkout_duration":30, + "number_of_days_after_due_date":5, + "number_of_days_before_due_date":5, + "number_renewals":3, + "renewal_duration":30, + "reminder_fee_amount":2, + "policy_library_level":false, + "is_default":true + }, + "no_checkout": { + "organisation_pid": 4, + "name":"No checkout", + "description":"Ebooks circulation policy.", + "allow_requests":false, + "allow_checkout":false, + "policy_library_level":false, + "is_default":false + } +} diff --git a/tests/e2e/cypress/cypress/fixtures/documents.json b/tests/e2e/cypress/cypress/fixtures/documents.json index d470f6761b..74205a73c6 100644 --- a/tests/e2e/cypress/cypress/fixtures/documents.json +++ b/tests/e2e/cypress/cypress/fixtures/documents.json @@ -25,9 +25,10 @@ "place": "Afghanistan (af)" }, "issuance": { - "mainType": "Serial", + "mainType": "single unit", "mainTypeCode": "rdami:1001", - "subtype": "Material unit" + "subtype": "Material unit", + "subtypeCode": "materialUnit" }, "authors": { "person":{ diff --git a/tests/e2e/cypress/cypress/fixtures/item_types.json b/tests/e2e/cypress/cypress/fixtures/item_types.json new file mode 100644 index 0000000000..fba4f1b4c6 --- /dev/null +++ b/tests/e2e/cypress/cypress/fixtures/item_types.json @@ -0,0 +1,16 @@ +{ + "on_site": { + "pid": 11, + "type": "standard", + "name": "On site", + "description": "On site consultation", + "organisation_pid": 4 + }, + "default": { + "pid": 11, + "type": "standard", + "name": "Default", + "description": "Default item type", + "organisation_pid": 4 + } +} diff --git a/tests/e2e/cypress/cypress/fixtures/items.json b/tests/e2e/cypress/cypress/fixtures/items.json index b63655b478..35bc62fde5 100644 --- a/tests/e2e/cypress/cypress/fixtures/items.json +++ b/tests/e2e/cypress/cypress/fixtures/items.json @@ -22,5 +22,13 @@ "pickupName": "Vulcan library", "itemTypeUri": "Default", "itemTypePid": 11 + }, + "starfleet_on_site": { + "code": "STARFLEET-BIB", + "location": "Default location for Starfleet library", + "locationPid": 35, + "pickupName": "Starfleet library", + "itemTypeUri": "On site", + "itemTypePid": "" } } diff --git a/tests/e2e/cypress/cypress/fixtures/patron_types.json b/tests/e2e/cypress/cypress/fixtures/patron_types.json new file mode 100644 index 0000000000..bb851b1a21 --- /dev/null +++ b/tests/e2e/cypress/cypress/fixtures/patron_types.json @@ -0,0 +1,13 @@ +{ + "visitors": { + "name": "Visitor", + "description": "Visitor for on site consultation.", + "organisation_pid": 4 + }, + "standard": { + "name": "Standard", + "description": "Standard patron.", + "organisation_pid": 4, + "pid": 7 + } +} diff --git a/tests/e2e/cypress/cypress/fixtures/users.json b/tests/e2e/cypress/cypress/fixtures/users.json index 52938347b3..b238563a21 100644 --- a/tests/e2e/cypress/cypress/fixtures/users.json +++ b/tests/e2e/cypress/cypress/fixtures/users.json @@ -1,18 +1,34 @@ { "patrons": { "james": { + "patron":{ + "barcode": "cypress-1" + }, "email": "reroilstest+james@gmail.com", "first_name": "James", "last_name": "Kirk", - "barcode": "cypress-1", "initials": "JK" }, "nyota": { - "email": "reroilstest+nyota@gmail.com", - "first_name": "Nyota", - "last_name": "Uhura", - "barcode": "cypress-2", - "initials": "NU" + "patron": { + "barcode":"cypress-2", + "communication_channel":"email", + "communication_language":"eng", + "expiration_date":"2023-10-07", + "type": 7 + }, + "birth_date":"1932-12-28", + "city":"Betelgeuse", + "email":"reroilstest+nyota@gmail.com", + "first_name":"Nyota", + "last_name":"Uhura", + "phone":"+41324883123", + "pid":"53", + "postal_code":"4242", + "roles":["patron"], + "street":"Milky Way street", + "user_id":56, + "username":"Nyota" } }, "librarians": { diff --git a/tests/e2e/cypress/cypress/integration/circulation/scenario-a.spec.js b/tests/e2e/cypress/cypress/integration/circulation/scenario-a.spec.js index 60ebda4ea8..0fb6bca346 100644 --- a/tests/e2e/cypress/cypress/integration/circulation/scenario-a.spec.js +++ b/tests/e2e/cypress/cypress/integration/circulation/scenario-a.spec.js @@ -102,7 +102,8 @@ describe('Circulation scenario A: standard loan', function() { */ cy.adminLogin(this.users.librarians.leonard.email, this.common.uniquePwd); // Go to requests list - cy.visit('/professional/circulation/requests'); + cy.get('#user-services-menu').click(); + cy.get('#requests-menu').click(); // Check that the document is present cy.get('#request-' + this.itemBarcode + ' [name="barcode"]').should('contain', this.itemBarcode); // Enter the barcode and validate @@ -113,7 +114,7 @@ describe('Circulation scenario A: standard loan', function() { cy.get('#user-services-menu').click(); cy.get('#users-menu').click(); // Go to James patron profile - cy.get('#' + this.users.patrons.james.barcode + '-loans').click(); + cy.get('#' + this.users.patrons.james.patron.barcode + '-loans').click(); // Click on tab called "To pick up" cy.get('#pick-up-tab').click(); // The item should be present diff --git a/tests/e2e/cypress/cypress/integration/circulation/scenario-b.spec.js b/tests/e2e/cypress/cypress/integration/circulation/scenario-b.spec.js index b615d1e741..10c13b9e2c 100644 --- a/tests/e2e/cypress/cypress/integration/circulation/scenario-b.spec.js +++ b/tests/e2e/cypress/cypress/integration/circulation/scenario-b.spec.js @@ -106,7 +106,8 @@ describe('Circulation scenario B: standard loan with transit', function() { // Login as librarian (Leonard) cy.adminLogin(this.users.librarians.leonard.email, this.common.uniquePwd); // Go to requests list - cy.visit('/professional/circulation/requests'); + cy.get('#user-services-menu').click(); + cy.get('#requests-menu').click(); // Check that the document is present cy.get('#request-' + this.itemBarcode + ' [name="barcode"]').should('contain', this.itemBarcode); // Enter the barcode and validate diff --git a/tests/e2e/cypress/cypress/integration/circulation/test-on-site-cipo.spec.js b/tests/e2e/cypress/cypress/integration/circulation/test-on-site-cipo.spec.js new file mode 100644 index 0000000000..99cf1db6dc --- /dev/null +++ b/tests/e2e/cypress/cypress/integration/circulation/test-on-site-cipo.spec.js @@ -0,0 +1,144 @@ +/// +/* + +RERO ILS +Copyright (C) 2020 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +before(function () { + // Run once before all + // Use to load fixtures and set variable needed in all tests + cy.fixture('users').then(function (users) { + this.users = users; + }); + cy.fixture('common').then(function (common) { + this.common = common; + }); + cy.fixture('patron_types').then(function (patronTypes) { + this.patronTypes = patronTypes; + }); + cy.fixture('cipo').then(function (cipo) { + this.cipo = cipo; + }); + cy.fixture('item_types').then(function (itemTypes) { + this.itemTypes = itemTypes; + }); + cy.fixture('items').then(function (items) { + this.items = items; + }); + cy.fixture('documents').then(function (documents) { + this.documents = documents; + }); + this.currentDate = cy.getCurrentDateAndHour(); + this.itemBarcode = 'on-site-' + this.currentDate; + this.nameSuffix = ' ' + this.currentDate; +}); + +describe(`Test 'less than one day' checkout`, function() { + let cipoPid; + let itemTypePid; + let documentPid; + let itemPid; + let patronTypePid; + + before('Login and prepare app for tests', function() { + // Login as librarian (Leonard) + cy.adminLogin(this.users.librarians.leonard.email, this.common.uniquePwd); + // Create patron type + cy.apiCreatePatronType(this.patronTypes.visitors, this.nameSuffix); + cy.get('@getPatronTypePid').then((pid) => { + // Store pid + patronTypePid = pid; + // Apply patron type to a patron + cy.apiUpdatePatron(this.users.patrons.nyota, patronTypePid); + // Create an item type + cy.apiCreateItemType(this.itemTypes.on_site, this.nameSuffix); + cy.get('@getItemTypePid').then((pid) => { + // Store pid + itemTypePid = pid; + // Create 'on site' circulation policy + cy.apiCreateCipo(this.cipo.on_site, patronTypePid, itemTypePid, this.nameSuffix); + cy.get('@getCipoPid').then((pid) => { + // Store pid + cipoPid = pid; + }); + // Create a document + cy.apiCreateDocument(this.documents.book, this.nameSuffix); + cy.get('@getDocumentPid').then((pid) => { + // Store pid + documentPid = pid; + // Create item + cy.apiCreateItem(this.items.starfleet_on_site, this.itemBarcode, pid, itemTypePid); + }); + cy.get('@getItemPid').then((pid) => { + // Store item pid + itemPid = pid; + }); + }); + }); + }); + + beforeEach('Preserve cookies', function() { + // Preserve authentication information between the tests + Cypress.Cookies.preserveOnce('session'); + }); + + after('Clean data', function() { + // Remove cipo + cy.apiDeleteResources('circ_policies', cipoPid); + // Link patron with 'standard' patron type to allow 'visitor' patron type deletion + cy.apiUpdatePatron(this.users.patrons.nyota, this.users.patrons.nyota.patron.type); + // Remove patron type + cy.apiDeleteResources('patron_types', patronTypePid); + // Remove item + cy.apiDeleteResources('items', 'pid:"'+ itemPid + '"'); + // Remove item type + cy.apiDeleteResources('item_types', itemTypePid); + // Remove document + cy.apiDeleteResources('documents', 'pid:"'+ documentPid + '"'); + cy.logout(); + }); + + it('The item cannot be requested', function() { + // Go to document detailed view + cy.goToProfessionalDocumentDetailView(documentPid); + // Create a request + cy.get('#item-' + this.itemBarcode + ' > [name=buttons] > [name=request]').click(); + cy.get('#patronBarcode').type(this.users.patrons.nyota.patron.barcode); + cy.get('#pickupPid').select(this.items.starfleet_on_site.pickupName); + // Assert that the circ policy doesn't allow the request + cy.get('formly-validation-message').should('contain', 'Circulation policy disallows the operation.'); + cy.get('#new-request-button').should('be.disabled'); + cy.get('.close').click(); + }); + + it('Checkout the item', function() { + // Go to circulation view and do a checkout + cy.get('#user-services-menu').click(); + cy.get('#circulation-menu').click(); + cy.scanPatronBarcodeThenItemBarcode(this.users.patrons.nyota, this.itemBarcode); + cy.get('#item-' + this.itemBarcode + ' [name=circ-info').should('contain', cy.getDateDisplayed(this.currentDate, 'en', '/')); + }); + + it('Checkin the item', function() { + // Checkin + cy.scanItemBarcode(this.itemBarcode); + // Assert that the item was checked in and that it is on shelf + cy.get('#item-' + this.itemBarcode).should('contain', this.itemBarcode); + cy.get('#item-' + this.itemBarcode).should('contain', 'on shelf'); + cy.get('#item-' + this.itemBarcode).should('contain', 'checked in'); + }); +}); diff --git a/tests/e2e/cypress/cypress/integration/editor/ci-po/create-ci-po.spec.js b/tests/e2e/cypress/cypress/integration/editor/ci-po/create-ci-po.spec.js new file mode 100644 index 0000000000..c0359a9c01 --- /dev/null +++ b/tests/e2e/cypress/cypress/integration/editor/ci-po/create-ci-po.spec.js @@ -0,0 +1,84 @@ +/// +/* + +RERO ILS +Copyright (C) 2020 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +before(function () { + // Run once before all + // Use to load fixtures and set variable needed in all tests + cy.fixture('users').then(function (users) { + this.users = users; + }); + cy.fixture('common').then(function (common) { + this.common = common; + }); + cy.fixture('cipo').then(function (cipo) { + this.cipo = cipo; + }); + cy.fixture('item_types').then(function (itemTypes) { + this.itemTypes = itemTypes; + }); + cy.fixture('patron_types').then(function (patronTypes) { + this.patronTypes = patronTypes; + }); +}); + +describe('Create and edit a circulation policy', function() { + let cipoPid; + + before('Login and prepare app for tests', function() { + // Login as librarian (Leonard) + cy.adminLogin(this.users.librarians.leonard.email, this.common.uniquePwd); + }); + + beforeEach('Add description if needed', function() { + // Preserve authentication information between the tests + Cypress.Cookies.preserveOnce('session'); + }); + + after('Clean data: ...', function() { + // Remove circulation policy + cy.get('#detail-delete-button').click(); + cy.get('#modal-confirm-button') + cy.logout(); + }); + + it('Creates an extended circulation policy', function() { + cy.server(); + cy.route('/api/item_types/*').as('getItemTypes'); + cy.route('/api/patron_types/*').as('getpatronTypes'); + cy.route('POST', 'api/circ_policies').as('createCiPo'); + // Go to ci-po editor + cy.get('#admin-and-monitoring-menu').click(); + cy.get('#circulation-policies-menu').click(); + cy.get('#search-add-button').click(); + // Fill the form with an existing name + cy.get('#name').type(this.cipo.default.name); + // Assert that the name uniqueness is highlighted + cy.get('#cipo-name-unique').should('contain', 'This name is already taken.'); + cy.get('#name').clear(); + // Create a cipo + cy.uiCreateOrUpdateCipo(this.cipo.extended, this.patronTypes.standard.pid, this.itemTypes.on_site.pid); + // Assert that the ci-po has been correctly saved + cy.wait('@createCiPo').its('response').then((res) => { + cipoPid = res.body.indexOf; + }); + cy.wait(['@getItemTypes', '@getpatronTypes']); + cy.checkCipoCreated(this.cipo.extended, this.patronTypes.standard.pid, this.itemTypes.on_site.pid); + }); +}); diff --git a/tests/e2e/cypress/cypress/integration/editor/document/create-simple-document.spec.js b/tests/e2e/cypress/cypress/integration/editor/document/create-simple-document.spec.js index 6a0449efe3..b38dfd8b72 100644 --- a/tests/e2e/cypress/cypress/integration/editor/document/create-simple-document.spec.js +++ b/tests/e2e/cypress/cypress/integration/editor/document/create-simple-document.spec.js @@ -47,6 +47,8 @@ describe('Create a document', function() { it('Creates a document with only essential fields', function() { cy.server(); + // The json schema form is loaded 2 times, which can make this test fail. This should be corrected. + // See https://github.com/rero/rero-ils/issues/1531 cy.route('/schemaform/documents').as('documentSchemaform'); // Go to document editor cy.visit('/professional/records/documents/new'); diff --git a/tests/e2e/cypress/cypress/integration/examples/example-test-request.spec.js b/tests/e2e/cypress/cypress/integration/examples/example-test-request.spec.js index ce6de21f22..1d0d1014a0 100644 --- a/tests/e2e/cypress/cypress/integration/examples/example-test-request.spec.js +++ b/tests/e2e/cypress/cypress/integration/examples/example-test-request.spec.js @@ -86,7 +86,7 @@ describe('Template: librarian request', function() { cy.goToProfessionalDocumentDetailView(documentPid); cy.get('#item-' + this.itemBarcode + ' div a[name=barcode]').click(); // Remove request - cy.get('#' + this.users.patrons.james.barcode + ' div [name=cancel]').click(); + cy.get('#' + this.users.patrons.james.patron.barcode + ' div [name=cancel]').click(); cy.get('#modal-confirm-button').click(); // Go back to document detail view cy.goToProfessionalDocumentDetailView(documentPid); @@ -103,13 +103,13 @@ describe('Template: librarian request', function() { cy.route('/api/item/*/can_request?library_pid=' + this.users.librarians.spock.libraryPid + '&patron_barcode=' - + this.users.patrons.james.barcode) + + this.users.patrons.james.patron.barcode) .as('getCanRequest'); // Go to document detailed view cy.goToProfessionalDocumentDetailView(documentPid); // Create a request cy.get('#item-' + this.itemBarcode + ' > [name=buttons] > [name=request]').click(); - cy.get('#patronBarcode').type(this.users.patrons.james.barcode); + cy.get('#patronBarcode').type(this.users.patrons.james.patron.barcode); cy.get('#pickupPid').select(this.items.vulcanDefault.pickupName); // Wait for the button unabled cy.wait('@getCanRequest'); @@ -117,7 +117,7 @@ describe('Template: librarian request', function() { // Go to item detail view cy.goToItemDetailView(itemPid); // Check that the request has been done - cy.get('.card').should('contain', this.users.patrons.james.barcode); + cy.get('.card').should('contain', this.users.patrons.james.patron.barcode); }); // Second test @@ -125,7 +125,7 @@ describe('Template: librarian request', function() { console.log('second test'); // Go to patron profile view cy.visit('/professional/records/patrons'); - cy.get('#' + this.users.patrons.james.barcode + '-loans').click(); + cy.get('#' + this.users.patrons.james.patron.barcode + '-loans').click(); // Go to request tab cy.get('#pending-tab').click(); // Assert that the item is requested diff --git a/tests/e2e/cypress/cypress/support/api.js b/tests/e2e/cypress/cypress/support/api.js index cf0eaac9ab..60342a69d3 100644 --- a/tests/e2e/cypress/cypress/support/api.js +++ b/tests/e2e/cypress/cypress/support/api.js @@ -20,6 +20,7 @@ along with this program. If not, see . /** API call to create a document ================================================== * Create a document * :param document - the document to create + * :param titleSuffix - suffix to append to the title */ Cypress.Commands.add('apiCreateDocument', (document, titleSuffix) => { cy.request({ @@ -82,7 +83,13 @@ along with this program. If not, see . * :param resourceName - string: the resource type * :param query - string: criteria to find items to delete */ - Cypress.Commands.add('apiCreateItem', (item, barcode, documentPid) => { + Cypress.Commands.add('apiCreateItem', (item, barcode, documentPid, itemTypePid) => { + let itemTypeRef; + if (itemTypePid !== undefined) { + itemTypeRef = 'https://ils.rero.ch/api/item_types/' + itemTypePid; + } else { + itemTypeRef = 'https://ils.rero.ch/api/item_types/' + item.itemTypePid + } cy.request({ method: 'POST', url: '/api/items/', @@ -90,7 +97,7 @@ along with this program. If not, see . body: { "acquisition_date":cy.getCurrentDate(), "item_type":{ - "$ref":('https://ils.rero.ch/api/item_types/' + item.itemTypePid) + "$ref":itemTypeRef }, "location":{ "$ref":('https://ils.rero.ch/api/locations/' + item.locationPid) @@ -132,3 +139,143 @@ Cypress.Commands.add('apiDeleteResources', (resourceName, query) => { }) }) }); + +/** API call to create an item type ================================================== + * Create an item type + * :param itemType - the item type to create + * :param nameSuffix - suffix to append to the name + */ + Cypress.Commands.add('apiCreateItemType', (itemType, nameSuffix) => { + cy.request({ + method: 'POST', + url: '/api/item_types/', + followRedirect: false, + body: { + "type": itemType.type, + "name": (itemType.name + nameSuffix), + "description": itemType.description, + "organisation": { + "$ref":('https://ils.rero.ch/api/organisations/' + itemType.organisation_pid) + } + } + }) + .its('body').then((body) => { + cy.wrap(body.id).as('getItemTypePid'); + }) + .then(() => { + cy.get('@getItemTypePid').then((pid) => { + cy.log('Item type created, pid = ' + pid); + }); + }); +}); + +/** API call to create a patron type ================================================== + * Create patron type + * :param patronType - the patron type to create + * :param nameSuffix - suffix to append to the name + */ + Cypress.Commands.add('apiCreatePatronType', (patronType, nameSuffix) => { + cy.request({ + method: 'POST', + url: '/api/patron_types/', + followRedirect: false, + body: { + "name": (patronType.name + nameSuffix), + "description": patronType.description, + "organisation":{ + "$ref": ('https://ils.rero.ch/api/organisations/' + patronType.organisation_pid) + } + } + }) + .its('body').then((body) => { + cy.wrap(body.id).as('getPatronTypePid'); + }) + .then(() => { + cy.get('@getPatronTypePid').then((pid) => { + cy.log('Patron type created, pid = ' + pid); + }); + }); +}); + + /** API call to create a patron ================================================== + * Create patron + * :param patron - the patron to create + * :param patronTypePid - patron type pid + */ + Cypress.Commands.add('apiCreatePatron', (patron, patronTypePid) => { + cy.request({ + method: 'POST', + url: '/api/patrons/', + followRedirect: false, + body: { + "patron": { + "expiration_date": patron.patron.expiration_date, + "type": { + "$ref":('https://ils.rero.ch/api/patron_types/' + patronTypePid) + }, + "barcode": patron.patron.barcode, + "communication_channel": patron.patron.communication_channel, + "communication_language": patron.patron.communication_language + }, + "roles": patron.roles, + "first_name": patron.first_name, + "last_name": patron.last_name, + "birth_date": patron.birth_date, + "username": patron.username, + "email": patron.email + } + }) + .its('body').then((body) => { + cy.wrap(body.id).as('getPatronPid'); + }) + .then(() => { + cy.get('@getPatronPid').then((pid) => { + cy.log('Patron created, pid = ' + pid); + }); + }); +}); + +/** API call to update a patron ================================================== + * Update patron + * :param patron - the patron to update + * :param patronTypePid - patron type pid + */ + Cypress.Commands.add('apiUpdatePatron', (patron, patronTypePid) => { + cy.request({ + method: 'PUT', + url: '/api/patrons/' + patron.pid, + followRedirect: false, + body: { + "patron": { + "barcode": patron.patron.barcode, + "communication_channel": patron.patron.communication_channel, + "communication_language": patron.patron.communication_language, + "expiration_date": patron.patron.expiration_date, + "type": { + "$ref": ('https://ils.rero.ch/api/patron_types/' + patronTypePid) + } + }, + "$schema":"https://ils.rero.ch/schemas/patrons/patron-v0.0.1.json", + "birth_date": patron.birth_date, + "city": patron.city, + "email": patron.email, + "first_name": patron.first_name, + "last_name": patron.last_name, + "phone": patron.phone, + "pid": patron.pid, + "postal_code": patron.postal_code, + "roles": patron.roles, + "street": patron.street, + "user_id": patron.user_id, + "username": patron.username + } + }) + .its('body').then((body) => { + cy.wrap(body.id).as('getPatronPid'); + }) + .then(() => { + cy.get('@getPatronPid').then((pid) => { + cy.log('Patron updated, pid = ' + pid); + }); + }); +}); diff --git a/tests/e2e/cypress/cypress/support/cipo.js b/tests/e2e/cypress/cypress/support/cipo.js new file mode 100644 index 0000000000..f4b814d686 --- /dev/null +++ b/tests/e2e/cypress/cypress/support/cipo.js @@ -0,0 +1,112 @@ +/* + +RERO ILS +Copyright (C) 2020 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +/** API call to create a cipo ================================================== + * Create a circulation policy + * :param cipo - the cipo fixture + * :param patronTypePid - patron type pid linked to the cipo + * :param itemTypePid - item type pid linked to the cipo + * :param nameSuffix - suffix to append to the name + */ + Cypress.Commands.add('apiCreateCipo', (cipo, patronTypePid, itemTypePid, nameSuffix) => { + cy.request({ + method: 'POST', + url: '/api/circ_policies/', + followRedirect: false, + body: { + "organisation": { + "$ref": ('https://ils.rero.ch/api/organisations/' + cipo.organisation_pid) + }, + "name": (cipo.name + nameSuffix), + "allow_requests": cipo.allow_requests, + "allow_checkout": cipo.allow_checkout, + "checkout_duration": cipo.checkout_duration, + "policy_library_level": cipo.policy_library_level, + "is_default": cipo.is_default, + "settings":[{ + "patron_type": { + "$ref":('https://ils.rero.ch/api/patron_types/' + patronTypePid) + }, + "item_type":{ + "$ref":('https://ils.rero.ch/api/item_types/' + itemTypePid) + } + }] + } + }) + .its('body').then((body) => { + cy.wrap(body.id).as('getCipoPid'); + }) + .then(() => { + cy.get('@getCipoPid').then((pid) => { + cy.log('Ci-po created, pid = ' + pid); + }); + }); +}); + +/** UI actions to create a cipo ================================================== + * Create a circulation policy + * :param cipo - the cipo fixture + * :param patronTypePid - patron type pid linked to the cipo + * :param itemTypePid - item type pid linked to the cipo + */ +Cypress.Commands.add('uiCreateOrUpdateCipo', (cipo, patronTypePid, itemTypePid) => { + cy.get('#name').type(cipo.name); + cy.get('#description').type(cipo.description); + if (!cipo.allow_checkout) { + cy.get('#allow_checkout input[type="checkbox"]') + } else { + cy.get('#checkoutDuration').clear(); + cy.get('#checkoutDuration').type(cipo.checkout_duration); + } + if (!cipo.number_renewals) { + cy.get('#renewals').uncheck(); + } else { + cy.get('#numberRenewals').clear(); + cy.get('#numberRenewals').type(cipo.number_renewals); + cy.get('#renewalDuration').clear(); + cy.get('#renewalDuration').type(cipo.renewal_duration); + } + if (!cipo.allow_requests) { + cy.get('#requests').uncheck(); + } + cy.get('#ptty-p' + patronTypePid).check(); + cy.get('#ptty-p' + patronTypePid + '-itty-i' + itemTypePid).check(); + // Save form + // cy.get('#cipo-save-button').click(); +}); + +/** Check created circulation policy ================================================== + * :param cipo - the cipo fixture + * :param patronTypePid - patron type pid linked to the cipo + * :param itemTypePid - item type pid linked to the cipo + */ + Cypress.Commands.add('checkCipoCreated', (cipo, patronTypePid, itemTypePid) => { + cy.get('#cipo-allow-checkout').should('have.class', 'fa-check'); + cy.get('#cipo-checkout-duration').should('contain', cipo.checkout_duration); + cy.get('#cipo-cnumber-renewals').should('contain', cipo.number_renewals); + cy.get('#cipo-renewal-duration').should('contain', cipo.renewal_duration); + cy.get('#cipo-allow-request').should('have.class', 'fa-check'); + cy.get('#cipo-is-default').should('have.class', 'fa-times'); + cy.get('#cipo-after-due-date').should('contain', cipo.number_of_days_after_due_date); + cy.get('#cipo-before-due-date').should('contain', cipo.number_of_days_before_due_date); + cy.get('#cipo-first-reminder-fee-amount').should('contain', cipo.reminder_fee_amount); + cy.get('#ptty-' + patronTypePid).should('contain', 'Standard'); + cy.get('#itty-' + itemTypePid).should('contain', 'Default'); + cy.get('#ptty-' + patronTypePid + '-itty-' + itemTypePid).should('have.class', 'fa-check'); +}); diff --git a/tests/e2e/cypress/cypress/support/circulation.js b/tests/e2e/cypress/cypress/support/circulation.js index f340f79106..c0f999a567 100644 --- a/tests/e2e/cypress/cypress/support/circulation.js +++ b/tests/e2e/cypress/cypress/support/circulation.js @@ -20,7 +20,7 @@ along with this program. If not, see . // Scan the patron barcode, then the item barcode (this does a checkout) Cypress.Commands.add('scanPatronBarcodeThenItemBarcode', (patron, itemBarcode) => { // Enter patron barcode - cy.get('#search').type(patron.barcode).type('{enter}'); + cy.get('#search').type(patron.patron.barcode).type('{enter}'); // Assert that patron info is displayed cy.get('#patron-last-name').should('contain', patron.last_name); cy.get('#patron-first-name').should('contain', ', ' + patron.first_name); diff --git a/tests/e2e/cypress/cypress/support/index.js b/tests/e2e/cypress/cypress/support/index.js index 83d6c22edc..37f124a521 100644 --- a/tests/e2e/cypress/cypress/support/index.js +++ b/tests/e2e/cypress/cypress/support/index.js @@ -17,7 +17,7 @@ import './api' import './circulation' import './collection' -import './commands' +import './cipo' import './commands' import './navigation' import './record' diff --git a/tests/e2e/cypress/cypress/support/record.js b/tests/e2e/cypress/cypress/support/record.js index 1880f3a96e..8a24ed04fe 100644 --- a/tests/e2e/cypress/cypress/support/record.js +++ b/tests/e2e/cypress/cypress/support/record.js @@ -80,7 +80,7 @@ Cypress.Commands.add("saveRecord", () => { Cypress.Commands.add("checkDocumentEssentialFields", (document) => { cy.get('#doc-language-0').should('contain', document.language1); - cy.get('#doc-issuance').should('contain', document.issuance.mainTypeCode + ' / materialUnit'); + cy.get('#doc-issuance').should('contain', document.issuance.mainType + ' / ' + document.issuance.subtypeCode); cy.get('#doc-title').should('contain', document.title.mainTitle); cy.get('#doc-provision-activity-0').should('contain', document.provisionActivity.statement.place + ' : ' + document.provisionActivity.statement.agent + ', ' + document.provisionActivity.statement.date); }); diff --git a/tests/e2e/cypress/cypress/support/utils.js b/tests/e2e/cypress/cypress/support/utils.js index 0ec9ec57d1..75b6e924cf 100644 --- a/tests/e2e/cypress/cypress/support/utils.js +++ b/tests/e2e/cypress/cypress/support/utils.js @@ -1,8 +1,60 @@ -/* Get current date */ +/// +/* + +RERO ILS +Copyright (C) 2020 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +/** + * Get current date and hour + * Output example: 2020-11-30T15H26 +*/ cy.getCurrentDateAndHour = () => { return new Date().toISOString().substring(0,16).replace(':', 'H'); }; +/** + * Get current date + * Output example: 2020-11-30 +*/ cy.getCurrentDate = () => { return cy.getCurrentDateAndHour().substring(0,10); }; + +/** + * Get date displayed (translated) + * Output example for US-en: 12/30/20 or 1/1/20 +*/ +cy.getDateDisplayed = (date, locale, separator) => { + let dateInfo = []; + const year = date.substring(2, 4); + let month = date.substring(5, 7); + let day = date.substring(8, 10); + if (parseInt(month) < 10) { + month = month.substring(1,2); + } + if (parseInt(day) < 10) { + day = day.substring(1,2); + } + switch(locale) { + case 'fr': + dateInfo = [day, month, year]; + break; + default: + dateInfo = [month, day, year]; + } + return dateInfo.join(separator); +};