/* * Copyright (C) 2024 Xibo Signage Ltd * * Xibo - Digital Signage - https://xibosignage.com * * This file is part of Xibo. * * Xibo 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, either version 3 of the License, or * any later version. * * Xibo 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 Xibo. If not, see . */ // *********************************************** // This example commands.js shows you how to // create various custom commands and overwrite // existing commands. // // For more comprehensive examples of custom // commands please read more here: // https://on.cypress.io/custom-commands // *********************************************** // // // -- This is a parent command -- // Cypress.Commands.add("login", (email, password) => { ... }) // // // -- This is a child command -- // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) // // // -- This is a dual command -- // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) // // // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) /* eslint-disable max-len */ Cypress.Commands.add('login', function(callbackRoute = '/login') { cy.session('saveSession', () => { cy.visit(callbackRoute); cy.request({ method: 'POST', url: '/login', form: true, body: { username: 'xibo_admin', password: 'password', }, }).then((res) => { // Get access token and save it as a environment variable cy.getAccessToken().then(function() { cy.getCookie('PHPSESSID').should('exist'); }); }); }); }); Cypress.Commands.add('getAccessToken', function() { cy.request({ method: 'POST', url: '/api/authorize/access_token', form: true, body: { client_id: Cypress.env('client_id'), client_secret: Cypress.env('client_secret'), grant_type: 'client_credentials', }, }).then((res) => { Cypress.env('accessToken', res.body.access_token); }); }); Cypress.Commands.add('tutorialClose', function() { const csrf_token = Cypress.$('meta[name="token"]').attr('content'); // Make the ajax request to hide the user welcome tutorial Cypress.$.ajax({ url: '/user/welcome', type: 'PUT', headers: { 'X-XSRF-TOKEN': csrf_token, }, }); }); Cypress.Commands.add('formRequest', (method, url, formData) => { return new Promise(function(resolve, reject) { const xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.setRequestHeader('Authorization', 'Bearer ' + Cypress.env('accessToken')); xhr.onload = function() { if (this.status >= 200 && this.status < 300) { resolve(xhr.response); } else { reject({ status: this.status, statusText: xhr.statusText, }); } }; xhr.onerror = function() { reject({ status: this.status, statusText: xhr.statusText, }); }; xhr.send(formData); }); }); Cypress.Commands.add('addMediaToLibrary', (fileName) => { // Declarations const method = 'POST'; const url = '/api/library'; const fileType = '*/*'; // Get file from fixtures as binary return cy.fixture(fileName, 'binary').then((zipBin) => { // File in binary format gets converted to blob so it can be sent as Form data const fileBlob = Cypress.Blob.binaryStringToBlob(zipBin, fileType); // Build up the form const formData = new FormData(); formData.set('files[]', fileBlob, fileName); // adding a file to the form // Perform the request return cy.formRequest(method, url, formData).then((response) => { const { files } = JSON.parse(response); // Return id return files[0].name; }); }); }); // Campaign Cypress.Commands.add('createCampaign', function(name) { cy.request({ method: 'POST', url: '/api/campaign', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { name: name, }, }).then((res) => { return res.body.campaignId; }); }); // Dataset Cypress.Commands.add('createDataset', function(name) { cy.request({ method: 'POST', url: '/api/dataset', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { dataSet: name, }, }).then((res) => { return res.body.dataSetId; }); }); // Delete Dataset Cypress.Commands.add('deleteDataset', function(id) { cy.request({ method: 'DELETE', url: '/api/dataset/' + id, form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: {}, }).then((res) => { return res; }); }); // Sync Group Cypress.Commands.add('createSyncGroup', function(name) { cy.request({ method: 'POST', url: '/api/syncgroup/add', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { name: name, syncPublisherPort: 9590, }, }).then((res) => { return res.body.datasetId; }); }); // DayPart Cypress.Commands.add('createDayPart', function(name) { cy.request({ method: 'POST', url: '/api/daypart', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { name: name, startTime: '01:00:00', endTime: '02:00:00', }, }).then((res) => { return res.body.dayPartId; }); }); // Delete DayPart Cypress.Commands.add('deleteDayPart', function(id) { cy.request({ method: 'DELETE', url: '/api/daypart/' + id, form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: {}, }).then((res) => { return res; }); }); // Tag Cypress.Commands.add('createTag', function(name) { cy.request({ method: 'POST', url: '/api/tag', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { name: name, }, }).then((res) => { return res.body.id; }); }); // Application Cypress.Commands.add('createApplication', function(name) { cy.request({ method: 'POST', url: '/api/application', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { name: name, }, }).then((res) => { return res.body.key; }); }); /** * Open playlist editor modal and wait for toolbar user prefs to load * @param {String} playlistName */ Cypress.Commands.add('openPlaylistEditorAndLoadPrefs', function(playlistId) { cy.intercept('GET', '/user/pref?preference=toolbar').as('userPrefsLoad'); // Reload playlist table page cy.visit('/playlist/view'); // Clear toolbar preferences cy.clearToolbarPrefs(); cy.window().then((win) => { win.XiboCustomFormRender(win.$('
  • ')); // Wait for user prefs to load cy.wait('@userPrefsLoad'); }); }); /** * Add media items to library */ Cypress.Commands.add('populateLibraryWithMedia', function() { // Add audio media to library cy.addMediaToLibrary('../assets/audioSample.mp3'); // Add image media to library cy.addMediaToLibrary('../assets/imageSample.png'); }); /** * Drag one element to another one * @param {string} draggableSelector * @param {string} dropableSelector */ Cypress.Commands.add('dragToElement', function(draggableSelector, dropableSelector) { return cy.get(dropableSelector).then(($el) => { const position = { x: $el.offset().left + $el.width() / 2 + window.scrollX, y: $el.offset().top + $el.height() / 2 + window.scrollY, }; cy.get(draggableSelector).invoke('show'); cy.get(draggableSelector) .trigger('mousedown', { which: 1, }) .trigger('mousemove', { which: 1, pageX: position.x, pageY: position.y, }) .trigger('mouseup'); }); }); /** * Go to layout editor page and wait for toolbar user prefs to load * @param {number} layoutId */ Cypress.Commands.add('goToLayoutAndLoadPrefs', function(layoutId) { cy.intercept('GET', '/user/pref?preference=toolbar').as('userPrefsLoad'); cy.clearToolbarPrefs(); cy.visit('/layout/designer/' + layoutId); // Wait for user prefs to load cy.wait('@userPrefsLoad'); }); Cypress.Commands.add('removeAllSelectedOptions', (select2) => { cy.get(select2) .as('select2Container'); cy.get('@select2Container') .then(($select2Container) => { if ($select2Container.find('.select2-selection__choice').length > 0) { cy.wrap($select2Container) .find('.select2-selection__choice') .each(($selectedOption) => { cy.wrap($selectedOption) .find('.select2-selection__choice__remove') .click(); // Click on the remove button for each selected option }); } else { // No options are selected cy.log('No options are selected'); } }); }); // Select an item from the select2 dropdown Cypress.Commands.add('selectFromDropdown', (selector, searchText, expected, alias, index = 0) => { cy.get(selector).type(searchText); if (alias) { cy.wait(alias).its('response.statusCode').should('eq', 200); } cy.get('.select2-container--open .select2-dropdown .select2-results > ul') .should('contain', expected); cy.get('.select2-container--open .select2-dropdown .select2-results > ul > li') .eq(index) .click(); }); // Select an option from the select2 Cypress.Commands.add('selectOption', (content) => { cy.get('.select2-container--open').contains(content); cy.get('.select2-container--open .select2-results > ul > li').should('have.length', 1); cy.get('.select2-container--open .select2-results > ul > li:first').contains(content).click(); }); // Schedule a layout Cypress.Commands.add('scheduleCampaign', function(campaignId, displayName) { cy.request({ method: 'POST', url: '/api/scheduleCampaign', form: true, headers: { Authorization: 'Bearer ' + Cypress.env('accessToken'), }, body: { campaignId: campaignId, displayName: displayName, }, }).then((res) => { return res.body.eventId; }); }); // Open Options Menu within the Layout Editor Cypress.Commands.add('openOptionsMenu', () => { cy.get('.navbar-submenu') .should('be.visible') .within(() => { cy.get('#optionsContainerTop') .should('be.visible') .and('not.be.disabled') .click({force: true}) .should('have.attr', 'aria-expanded', 'true'); }); }); // Open Row Menu of the first item on the Layouts page Cypress.Commands.add('openRowMenu', () => { cy.get('#layouts tbody tr').first().within(() => { cy.get('.btn-group .btn.dropdown-toggle') .click() .should('have.attr', 'aria-expanded', 'true'); }); }); /** * Update data on CKEditor instance * @param {string} ckeditorId * @param {string} value */ Cypress.Commands.add('updateCKEditor', function(ckeditorId, value) { cy.get('textarea[name="' + ckeditorId + '"]').invoke('prop', 'id').then((id) => { cy.window().then((win) => { win.formHelpers.getCKEditorInstance( id, ).setData(value); }); }); });