// *********************************************** // 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 // *********************************************** // @author Roman Rezinkin roman.rezinkin@hotmail.com // // -- 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 will overwrite an existing command -- // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) import 'cypress-file-upload'; require('@4tw/cypress-drag-drop') // for waiting until page load Cypress.Commands.add('waitForSpinners', () => { cy.visit('http://localhost:3000', { retryOnNetworkFailure: true, timeout: 1200000, headers: { "Accept-Encoding": "gzip, deflate" } }) cy.get('#nuxt-loading', {timeout: 10_0000}).should('have.length', 0) }) Cypress.Commands.add('signinOrSignup', (_args) => { const args = Object.assign({username: 'user@nocodb.com', password: 'Password123.'}, _args) // signin/signup cy.get('body').then(($body) => { cy.wait(1000) cy.url().then(url => { if (!url.includes('/projects')) { // handle initial load if ($body.find('.welcome-page').length > 0) { cy.wait(8000); cy.get('body').trigger('mousemove'); cy.contains('Let\'s Begin').click(); cy.get('input[type="text"]', { timeout: 12000 }).type(args.username); cy.get('input[type="password"]').type(args.password); cy.get('button:contains("SIGN UP")').click() // handle signin } else { cy.get('input[type="text"]', { timeout: 12000 }).type(args.username); cy.get('input[type="password"]').type(args.password); cy.get('button:contains("SIGN IN")').click() } } }) }) }); // for opening/creating a rest project Cypress.Commands.add('openOrCreateRestProject', (_args) => { const args = Object.assign({new: false}, _args) // signin/signup cy.signinOrSignup() cy.wait(2000); cy.get('body').then($body => { const filter = args.meta ? '.nc-meta-project-row' : ':not(.nc-meta-project-row)'; // if project exist open if ($body.find('.nc-rest-project-row').filter(filter).length && !args.new) { cy.get('.nc-rest-project-row').filter(filter).first().click() } else { cy.contains('New Project').trigger('onmouseover').trigger('mouseenter'); if (args.meta) { cy.get('.nc-create-xc-db-project').click() cy.url({timeout: 6000}).should('contain', '#/project/xcdb') cy.get('.nc-metadb-project-name').type('test_proj' + Date.now()) cy.contains('button','Create', {timeout: 3000}).click() } else { cy.get('.nc-create-external-db-project').click() cy.url({timeout: 6000}).should('contain', '#/project') cy.get('.database-field input').click().clear().type('sakila') cy.contains('Test Database Connection').click() cy.contains('Ok & Save Project', {timeout: 3000}).click() } } }) cy.url({timeout: 20000}).should('contain', '#/nc/') } ) Cypress.Commands.add('openTableTab', (tn) => { cy.get('.nc-project-tree') .find('.v-list-item__title:contains(Tables)', { timeout: 10000 }) .first().click() cy.get('.nc-project-tree') .contains(tn, { timeout: 6000 }) .first() .click({ force: true }); cy.get(`.project-tab:contains(${tn}):visible`) .should('exist') cy.get('.nc-project-tree') .find('.v-list-item__title:contains(Tables)', { timeout: 10000 }) .first().click() // wait for page to load cy.wait(500) }) Cypress.Commands.add('closeTableTab', (tn) => { cy.get(`[href="#table||db||${tn}"]`).find('button.mdi-close').click() }) Cypress.Commands.add('openOrCreateGqlProject', (_args) => { const args = Object.assign({new: false, meta: false}, _args) cy.signinOrSignup() cy.wait(2000); cy.get('body').then($body => { const filter = args.meta ? '.nc-meta-project-row' : ':not(.nc-meta-project-row)'; // if project exist open if ($body.find('.nc-graphql-project-row').filter(filter).length && !args.new) { cy.get('.nc-graphql-project-row').filter(filter).first().click() } else { cy.contains('New Project').trigger('onmouseover').trigger('mouseenter'); if (args.meta) { cy.get('.nc-create-xc-db-project').click() cy.url({timeout: 6000}).should('contain', '#/project/xcdb') cy.contains('GRAPHQL APIs').closest('label').click(); cy.get('.nc-metadb-project-name').type('test_proj' + Date.now()) cy.contains('button','Create', {timeout: 3000}).click() } else { cy.get('.nc-create-external-db-project').click() cy.url({timeout: 6000}).should('contain', '#/project') cy.contains('GRAPHQL APIs').closest('label').click() cy.get('.database-field input').click().clear().type('sakila') cy.contains('Test Database Connection').click() cy.contains('Ok & Save Project', {timeout: 3000}).click() } } }) cy.url({timeout: 20000}).should('contain', '#/nc/') }) let LOCAL_STORAGE_MEMORY = {}; Cypress.Commands.add("saveLocalStorage", () => { Object.keys(localStorage).forEach(key => { LOCAL_STORAGE_MEMORY[key] = localStorage[key]; }); }); Cypress.Commands.add("restoreLocalStorage", () => { Object.keys(LOCAL_STORAGE_MEMORY).forEach(key => { localStorage.setItem(key, LOCAL_STORAGE_MEMORY[key]); }); }); Cypress.Commands.add("getActiveModal", () => { return cy.get('.v-dialog.v-dialog--active').last() }); Cypress.Commands.add("getActiveMenu", () => { return cy.get('.menuable__content__active').last() }); Cypress.Commands.add("getActiveContentModal", () => { return cy.get('.v-dialog__content--active').last() }); Cypress.Commands.add('createTable', (name) => { cy.get('.add-btn').click(); cy.get('.nc-create-table-card .nc-table-name input[type="text"]').first().click().clear().type(name) cy.get('.nc-create-table-card .nc-table-name-alias input[type="text"]').first().should('have.value', name.toLowerCase()) cy.get('.nc-create-table-card .nc-create-table-submit').first().click() cy.get(`.project-tab:contains(${name})`).should('exist') cy.url().should('contain', `name=${name}`) cy.wait(3000) }) Cypress.Commands.add('deleteTable', (name) => { cy.get('.nc-project-tree').find('.v-list-item__title:contains(Tables)', {timeout: 10000}) .first().click() cy.get('.nc-project-tree').contains(name, {timeout: 6000}).first().click({force: true}); cy.get(`.project-tab:contains(${name}):visible`).should('exist') cy.get('.nc-table-delete-btn:visible').click() cy.get('button:contains(Submit)').click() cy.get(`.project-tab:contains(${name}):visible`).first().should('not.exist') }) Cypress.Commands.add('createColumn', (table, columnName) => { cy.get('.nc-project-tree').find('.v-list-item__title:contains(Tables)', {timeout: 10000}) .first().click() cy.get('.nc-project-tree').contains(table, {timeout: 6000}).first().click({force: true}); cy.get(`.project-tab:contains(${table}):visible`).should('exist') cy.get('.v-window-item--active .nc-grid tr > th:last button').click({force: true}); cy.get('.nc-column-name-input input').clear().type(columnName) cy.get('.nc-col-create-or-edit-card').contains('Save').click() cy .get('th:contains(new_column)') .should('exist'); }) // Drag n Drop // refer: https://stackoverflow.com/a/55409853 /* const getCoords = ($el) => { const domRect = $el[0].getBoundingClientRect() const coords = { x: domRect.left + (domRect.width / 2 || 0), y: domRect.top + (domRect.height / 2 || 0) } return coords } const dragTo = (subject, to, opts) => { opts = Cypress._.defaults(opts, { // delay inbetween steps delay: 0, // interpolation between coords steps: 0, // >=10 steps smooth: false, }) if (opts.smooth) { opts.steps = Math.max(opts.steps, 10) } const win = subject[0].ownerDocument.defaultView const elFromCoords = (coords) => win.document.elementFromPoint(coords.x, coords.y) const winMouseEvent = win.MouseEvent const send = (type, coords, el) => { el = el || elFromCoords(coords) el.dispatchEvent( new winMouseEvent(type, Object.assign({}, { clientX: coords.x, clientY: coords.y }, { bubbles: true, cancelable: true })) ) } const toSel = to function drag (from, to, steps = 1) { const fromEl = elFromCoords(from) const _log = Cypress.log({ $el: fromEl, name: 'drag to', message: toSel, }) _log.snapshot('before', { next: 'after', at: 0 }) _log.set({ coords: to }) send('mouseover', from, fromEl) send('mousedown', from, fromEl) cy.then(() => { return Cypress.Promise.try(() => { if (steps > 0) { const dx = (to.x - from.x) / steps const dy = (to.y - from.y) / steps return Cypress.Promise.map(Array(steps).fill(), (v, i) => { i = steps - 1 - i let _to = { x: from.x + dx * (i), y: from.y + dy * (i), } send('mousemove', _to, fromEl) return Cypress.Promise.delay(opts.delay) }, { concurrency: 1 }) } }) .then(() => { send('mousemove', to, fromEl) send('mouseover', to) send('mousemove', to) send('mouseup', to) _log.snapshot('after', { at: 1 }).end() }) }) } const $el = subject const fromCoords = getCoords($el) const toCoords = getCoords(cy.$$(to)) drag(fromCoords, toCoords, opts.steps) } Cypress.Commands.addAll( { prevSubject: 'element' }, { dragTo, } ) */