From e2aa4a025e233889e8100b15c2206c95011c3d90 Mon Sep 17 00:00:00 2001 From: anasark Date: Sat, 12 Nov 2022 20:45:20 +0700 Subject: [PATCH 1/2] TDD HRIS --- cypress.config.js | 34 ++ cypress.json | 3 - package.json | 2 + .../DEV - KPI Template Export - abc.xlsx | Bin 0 -> 10335 bytes tests/e2e/fixtures/example.pdf | Bin 0 -> 11049 bytes .../employee/additionalComponent.cy.js | 163 ++++++ .../human-resource/employee/departement.cy.js | 123 +++++ .../human-resource/employee/employee.cy.js | 144 ++++++ .../employee/employmentContract.cy.js | 129 +++++ .../human-resource/employee/jobLocation.cy.js | 125 +++++ tests/e2e/specs/human-resource/functions.js | 465 ++++++++++++++++++ .../specs/human-resource/kpi/assessment.cy.js | 162 ++++++ .../specs/human-resource/kpi/template.cy.js | 288 +++++++++++ tests/e2e/specs/index.cy.js | 30 ++ tests/e2e/specs/test.js | 8 - tests/e2e/support/commands.js | 54 ++ tests/e2e/support/index.js | 2 +- yarn.lock | 356 ++++++++++++-- 18 files changed, 2043 insertions(+), 45 deletions(-) create mode 100644 cypress.config.js delete mode 100644 cypress.json create mode 100644 tests/e2e/fixtures/DEV - KPI Template Export - abc.xlsx create mode 100644 tests/e2e/fixtures/example.pdf create mode 100644 tests/e2e/specs/human-resource/employee/additionalComponent.cy.js create mode 100644 tests/e2e/specs/human-resource/employee/departement.cy.js create mode 100644 tests/e2e/specs/human-resource/employee/employee.cy.js create mode 100644 tests/e2e/specs/human-resource/employee/employmentContract.cy.js create mode 100644 tests/e2e/specs/human-resource/employee/jobLocation.cy.js create mode 100644 tests/e2e/specs/human-resource/functions.js create mode 100644 tests/e2e/specs/human-resource/kpi/assessment.cy.js create mode 100644 tests/e2e/specs/human-resource/kpi/template.cy.js create mode 100644 tests/e2e/specs/index.cy.js delete mode 100644 tests/e2e/specs/test.js diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 00000000..2b8d1f57 --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,34 @@ +const { defineConfig } = require("cypress"); + +require('dotenv').config() + +module.exports = defineConfig({ + fixturesFolder: "tests/e2e/fixtures", + screenshotsFolder: "tests/e2e/screenshots", + videosFolder: "tests/e2e/videos", + + e2e: { + // We've imported your old cypress plugins here. + // You may want to clean this up later by importing these. + setupNodeEvents(on, config) { + config.env = { + ...process.env, + } + return config + }, + specPattern(on, config) { + return require("./tests/e2e/plugins/index.js")(on, config); + }, + specPattern: "tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}", + supportFile: "tests/e2e/support/index.js", + hosts: { "*.localhost": "127.0.0.1" }, + baseUrl: 'http://dev.localhost:8080', + }, + + component: { + devServer: { + framework: "vue-cli", + bundler: "webpack", + }, + }, +}); diff --git a/cypress.json b/cypress.json deleted file mode 100644 index 470c7201..00000000 --- a/cypress.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "pluginsFile": "tests/e2e/plugins/index.js" -} diff --git a/package.json b/package.json index 489028f7..2fac2c9a 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,8 @@ "@vue/test-utils": "^1.0.3", "babel-eslint": "^10.1.0", "chai": "^4.2.0", + "cypress": "^10.11.0", + "cypress-file-upload": "^5.0.8", "eslint": "^7.3.1", "eslint-plugin-import": "^2.21.2", "eslint-plugin-node": "^11.1.0", diff --git a/tests/e2e/fixtures/DEV - KPI Template Export - abc.xlsx b/tests/e2e/fixtures/DEV - KPI Template Export - abc.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5e196bf6203086a4c98d249b3d170142f434140d GIT binary patch literal 10335 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/fixtures/example.pdf b/tests/e2e/fixtures/example.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6fa1633b4d0e80af525af726ce094b147e19f79f GIT binary patch literal 11049 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/specs/human-resource/employee/additionalComponent.cy.js b/tests/e2e/specs/human-resource/employee/additionalComponent.cy.js new file mode 100644 index 00000000..386c7de3 --- /dev/null +++ b/tests/e2e/specs/human-resource/employee/additionalComponent.cy.js @@ -0,0 +1,163 @@ +import { generateText } from '../functions' + +const { should } = require("chai") +const randomString = generateText(7) +const url = '/human-resource/additional-component' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/additional-components' +const getList = apiUrl + '**' +const getDetail = apiUrl + '/*' +const timeOut = { timeout : 300000 } + +describe('HR - Additional Component', () => { + beforeEach(() => { + cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('index additional components', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + + cy.waitVisible('li.nav-item'); + cy.get('li.nav-item a').contains('ADDITIONAL COMPONENT').click() + + cy.intercept('GET', getList).as('getAdditionalComponent') + + cy.wait(5000) + cy.waitVisible('table'); + + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + cy.get('table th').should('contain', 'name') + cy.get('table th').should('contain', 'source') + cy.get('table th').should('contain', 'weight') + }) + + it('Create additional components', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getAdditionalComponent') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('.input-group-prepend'); + cy.get('.input-group-prepend').click() + + cy.get('.sweet-title', timeOut).should('contain', 'ADD ADDITIONAL COMPONENT') + cy.wait(1000) + cy.get('.sweet-content-content input').eq(0).type(randomString) + cy.wait(1000) + cy.get('.sweet-content-content input').eq(1).type(123) + cy.wait(1000) + cy.get('.sweet-content-content span.link').click() + cy.wait(1000) + cy.get('.sweet-content-content #selectautomated-code a').first().click() + + cy.intercept('POST', getList).as('createAdditionalComponent') + + cy.get('.sweet-content-content > .pull-right > button').click() + + cy.wait('@createAdditionalComponent', timeOut).its('response.statusCode').should('equal', 201) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') + + cy.wait(1500) + cy.url().should('contain', url) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(randomString) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table td'); + cy.get('table td').should('contain', randomString) + }) + + it('Edit additional components', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getAdditionalComponent') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.wait(2000) + cy.get('table a', timeOut).contains(randomString).click() + + cy.get('input#name', timeOut).should('have.value', randomString) + cy.get('.block-content').contains('EDIT').click() + + + cy.waitVisible('.sweet-title'); + cy.get('.sweet-title').should('contain', 'EDIT ADDITIONAL COMPONENT') + + cy.wait(2000) + cy.get('.sweet-content-content input#name').last(timeOut).should('have.value', randomString) + cy.get('.sweet-content-content input#name') + .last() + .clear() + .type(randomString + ' - edit') + + cy.wait(1500) + cy.intercept('PATCH', getDetail).as('updateAdditionalComponent') + cy.intercept('GET', getDetail).as('getDetailAdditionalComponent') + + cy.get('.sweet-content-content > .pull-right > button').last().click() + + cy.wait('@updateAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + cy.wait('@getDetailAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.wait(1500) + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + }) + + it('Delete additional components', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getAdditionalComponent') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) + + cy.wait(2000) + cy.waitVisible('table'); + cy.get('table a').contains(randomString + ' - edit').click() + + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + cy.get('.block-content').contains('DELETE').click() + + cy.intercept('DELETE', getDetail).as('deleteAdditionalComponent') + + cy.waitVisible('.swal2-container') + cy.get('.swal2-container button').contains('Confirm').click() + cy.wait('@deleteAdditionalComponent', timeOut).its('response.statusCode').should('equal', 204) + + cy.wait(1500) + cy.url().should('contain', url) + }) +}) + \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/employee/departement.cy.js b/tests/e2e/specs/human-resource/employee/departement.cy.js new file mode 100644 index 00000000..f3799922 --- /dev/null +++ b/tests/e2e/specs/human-resource/employee/departement.cy.js @@ -0,0 +1,123 @@ +import { generateText, createDepartement } from '../functions' + +const { should } = require("chai") +const randomString = generateText(7) +const url = '/human-resource/employee-group' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/groups' +const getList = apiUrl + '**' +const getDetail = apiUrl + '/*' +const timeOut = { timeout : 300000 } + +describe('HR - Departement', () => { + beforeEach(() => { + cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('index departemen', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + + cy.waitVisible('li.nav-item'); + cy.get('li.nav-item a').contains('DEPARTMENT').click() + + cy.intercept('GET', getList).as('getDepartement') + + cy.wait(5000) + cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Name') + }) + + it('Create departemen', () => { + createDepartement(randomString) + }) + + it('Edit departemen', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getDepartement') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailDepartement') + cy.wait(2000) + cy.waitVisible('table'); + cy.get('table a').contains(randomString).click() + + cy.wait('@getDetailDepartement', timeOut).its('response.statusCode').should('equal', 200) + cy.get('input#name', timeOut).should('have.value', randomString) + cy.get('.block-content').contains('EDIT').click() + + cy.waitVisible('.sweet-title'); + cy.get('.sweet-title').should('contain', 'EDIT DEPARTMENT') + + cy.wait('@getDetailDepartement', timeOut).its('response.statusCode').should('equal', 200) + cy.wait(2000) + cy.get('.sweet-content-content input#name') + .last() + .clear() + .type(randomString + ' - edit') + + cy.wait(1500) + cy.intercept('PATCH', getDetail).as('updateDepartement') + cy.get('.sweet-content-content > .pull-right > button').last().click() + + cy.wait('@updateDepartement', timeOut).its('response.statusCode').should('equal', 200) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + + cy.wait(1500) + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + }) + + it('Delete departemen', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getDepartement') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getDepartement').its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getDepartement').its('response.statusCode').should('equal', 200) + + cy.wait(2000) + cy.waitVisible('table'); + cy.get('table a').contains(randomString + ' - edit').click() + + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + cy.get('.block-content').contains('DELETE').click() + + cy.intercept('DELETE', getDetail).as('deleteDepartemen') + + cy.waitVisible('.swal2-container') + cy.get('.swal2-container button').contains('Confirm').click() + + cy.wait('@deleteDepartemen', timeOut).its('response.statusCode').should('equal', 204) + + cy.wait(1500) + cy.url().should('contain', url) + }) +}) + \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/employee/employee.cy.js b/tests/e2e/specs/human-resource/employee/employee.cy.js new file mode 100644 index 00000000..25c83f4b --- /dev/null +++ b/tests/e2e/specs/human-resource/employee/employee.cy.js @@ -0,0 +1,144 @@ +import { generateText, generateNumber, createEmployee } from '../functions' + +const { should } = require("chai") +const name = generateText(7) +const personalId = generateText(7) +const email = generateText(7) + '@mail.com' +const address = generateText(7) +const phone = generateNumber(11) +const code = generateNumber(4) +const jobTitle = generateText(6) +const note = generateText(15) +const url = '/human-resource/employee' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/employees' +const getList = apiUrl + '**' +const getDetail = apiUrl + '/*' +const timeOut = { timeout : 300000 } + +describe('HR - Employee', () => { + beforeEach(() => { + cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('index employee', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.intercept('GET', getList).as('getEmployee') + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + + cy.wait(5000) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'name') + cy.get('table th').should('contain', 'job title') + cy.get('table th').should('contain', 'department') + }) + + it('Create employee', () => { + createEmployee({ + name: name, + personalId: personalId, + email: email, + address: address, + phone: phone, + code: code, + jobTitle: jobTitle, + note: note + }) + }) + + it('Edit employee', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getEmployee') + + cy.visit(url) + + cy.waitToken() + cy.wait('@getEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(name) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + cy.get('table a', timeOut).contains(name).click() + + cy.intercept('GET', getDetail).as('getDetailEmployee') + + cy.get('.block-content table:nth-child(1) tbody > tr > td:nth-child(2)', timeOut) + .should('contain', name) + cy.wait(2000) + cy.get('.block-content').contains('EDIT').click() + + cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.get('.sweet-title', timeOut).should('contain', 'EMPLOYEE INFORMATION') + + cy.get('.sweet-content-content input#name').last(timeOut).should('have.value', name) + cy.wait(2000) + cy.get('.sweet-content-content input#name').last().clear().type(name + ' - edit') + + cy.intercept('PATCH', getDetail).as('updateEmployee') + + cy.get('.sweet-modal-overlay').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('.sweet-content-content > .pull-right > button').click() + } + }) + + cy.wait('@updateEmployee', timeOut).its('response.statusCode').should('equal', 200) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.get('.block-content table:nth-child(1) tbody > tr > td:nth-child(2)', timeOut) + .should('contain', name + ' - edit') + }) + + it('Delete employee', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getEmployee') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(name) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailEmployee') + + cy.waitVisible('table'); + cy.get('table a').contains(name + ' - edit').click() + + cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.get('.block-content table:nth-child(1) tbody > tr > td:nth-child(2)', timeOut) + .should('contain', name) + cy.wait(2000) + cy.get('.block-content').contains('DELETE').click() + + cy.intercept('DELETE', getDetail).as('deleteEmployee') + + cy.waitVisible('.swal2-container') + cy.get('.swal2-container button').contains('Confirm').click() + cy.wait('@deleteEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.wait(1500) + cy.url().should('contain', url) + }) +}) + \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/employee/employmentContract.cy.js b/tests/e2e/specs/human-resource/employee/employmentContract.cy.js new file mode 100644 index 00000000..4730cbf5 --- /dev/null +++ b/tests/e2e/specs/human-resource/employee/employmentContract.cy.js @@ -0,0 +1,129 @@ +import { generateText, createEmploymentContract } from '../functions' + +const { should } = require("chai") +const randomString = generateText(7) +const url = '/human-resource/employee-status' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/statuses' +const getList = apiUrl + '**' +const getDetail = apiUrl + '/*' +const timeOut = { timeout : 300000 } + +describe('HR - Employment Contract', () => { + beforeEach(() => { + cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('index employment contract', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + + cy.waitVisible('li.nav-item'); + cy.get('li.nav-item a').contains('EMPLOYMENT CONTRACT').click() + + cy.intercept('GET', getList).as('getEmploymentContract') + + cy.wait(5000) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Name') + }) + + it('Create employment contract', () => { + createEmploymentContract(randomString) + }) + + it('Edit employment contract', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getEmploymentContract') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailEmploymentContract') + + cy.waitVisible('table'); + cy.get('table a').contains(randomString).click() + + cy.wait('@getDetailEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.get('input#name', timeOut).should('have.value', randomString) + cy.wait(2000) + cy.get('.block-content').contains('EDIT').click() + + cy.waitVisible('.sweet-title'); + cy.get('.sweet-title').should('contain', 'EDIT EMPLOYMENT CONTRACT') + + cy.wait('@getDetailEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.wait(2000) + cy.get('.sweet-content-content input#name') + .last() + .clear() + .type(randomString + ' - edit') + + cy.intercept('PATCH', getDetail).as('updateEmploymentContract') + + cy.wait(1500) + cy.get('.sweet-content-content > .pull-right > button').last().click() + + cy.wait('@updateEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + + cy.wait(1500) + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + }) + + it('Delete employment contract', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getEmploymentContract') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailEmploymentContract') + + cy.wait(2000) + cy.waitVisible('table'); + cy.get('table a').contains(randomString + ' - edit').click() + + cy.wait('@getDetailEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + cy.wait(2000) + cy.get('.block-content').contains('DELETE').click() + + cy.intercept('DELETE', getDetail).as('deleteEmploymentContract') + + cy.waitVisible('.swal2-container') + cy.get('.swal2-container button').contains('Confirm').click() + + cy.wait('@deleteEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.wait(1500) + cy.url().should('contain', url) + }) +}) + \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/employee/jobLocation.cy.js b/tests/e2e/specs/human-resource/employee/jobLocation.cy.js new file mode 100644 index 00000000..45e2c625 --- /dev/null +++ b/tests/e2e/specs/human-resource/employee/jobLocation.cy.js @@ -0,0 +1,125 @@ +import { generateText, createJobLocation } from '../functions' + +const { should } = require("chai") +const randomString = generateText(7) +const url = '/human-resource/job-location' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/job-locations' +const getList = apiUrl + '**' +const getDetail = apiUrl + '/*' +const timeOut = { timeout : 300000 } + +describe('HR - Job Location', () => { + beforeEach(() => { + cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('index job location', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + + cy.waitVisible('li.nav-item'); + cy.get('li.nav-item a').contains('JOB LOCATION').click() + + cy.intercept('GET', getList).as('getJobLocation') + + cy.wait(5000) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'name') + cy.get('table th').should('contain', 'area value') + cy.get('table th').should('contain', 'kpi multiplier') + }) + + it('Create job location', () => { + createJobLocation(randomString) + }) + + it('Edit job location', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getJobLocation') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailJobLocation') + cy.wait(2000) + cy.waitVisible('table'); + cy.get('table a').contains(randomString).click() + + cy.wait('@getDetailJobLocation', timeOut).its('response.statusCode').should('equal', 200) + cy.get('input#name', timeOut).should('have.value', randomString) + cy.wait(2000) + cy.get('.block-content').contains('EDIT').click() + + cy.waitVisible('.sweet-title'); + cy.get('.sweet-title').should('contain', 'EDIT JOB LOCATION') + + cy.wait(2000) + cy.get('.sweet-content-content input#name') + .last() + .clear() + .type(randomString + ' - edit') + + cy.intercept('PATCH', getDetail).as('updateJobLocation') + cy.get('.sweet-content-content > .pull-right > button').last().click() + + cy.wait('@updateJobLocation', timeOut).its('response.statusCode').should('equal', 200) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + + cy.wait(1500) + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + }) + + it('Delete job location', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getJobLocation') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(randomString) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailJobLocation') + cy.wait(2000) + cy.waitVisible('table'); + cy.get('table a').contains(randomString + ' - edit').click() + + cy.wait('@getDetailJobLocation', timeOut).its('response.statusCode').should('equal', 200) + cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') + cy.get('.block-content').contains('DELETE').click() + + cy.intercept('DELETE', getDetail).as('deleteJobLocation') + cy.waitVisible('.swal2-container') + cy.get('.swal2-container button').contains('Confirm').click() + + cy.wait('@deleteJobLocation', timeOut).its('response.statusCode').should('equal', 204) + + cy.wait(1500) + cy.url().should('contain', url) + }) +}) + \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/functions.js b/tests/e2e/specs/human-resource/functions.js new file mode 100644 index 00000000..d3ae3f5f --- /dev/null +++ b/tests/e2e/specs/human-resource/functions.js @@ -0,0 +1,465 @@ +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') +const timeOut = { timeout : 500000 } + +export function generateText(length) { + var result = '' + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + var charactersLength = characters.length + for ( var i = 0; i < length; i++ ) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)) + } + return result +} + +export function generateNumber(length) { + var result = '' + var characters = '0123456789' + var charactersLength = characters.length + for ( var i = 0; i < length; i++ ) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)) + } + return parseInt(result) +} + +export function createDepartement(name) { + const apiDept = apiUrl + '/human-resource/employee/groups**' + const urlDept = '/human-resource/employee-group' + + cy.interceptToken() + cy.intercept('GET', apiDept).as('getDepartement') + + cy.visit(urlDept) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(name) + cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + + let exists = false + cy.waitVisible('table'); + cy.get('table tr').each(($tr) => { + if ($tr.find('td').length) { + exists = true + } + }).then(() => { + if (!exists) { + cy.waitVisible('.input-group-prepend'); + cy.get('.input-group-prepend').click() + + cy.get('.sweet-title', timeOut).should('contain', 'ADD DEPARTMENT') + cy.get('.sweet-content-content input').eq(0).type(name) + + cy.intercept('POST', apiDept).as('createDepartement') + + cy.wait(1500) + cy.get('.sweet-content-content > .pull-right > button').click() + + cy.wait('@createDepartement', timeOut).its('response.statusCode').should('equal', 201) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') + + cy.wait(1500) + cy.url().should('contain', urlDept) + + cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + + } + }) + + cy.waitVisible('table'); + cy.get('table td').should('contain', name) +} + +export function createJobLocation(name) { + const apiJobLoc = apiUrl + '/human-resource/employee/job-locations**' + const urlJobLoc = '/human-resource/job-location' + + cy.interceptToken() + cy.intercept('GET', apiJobLoc).as('getJobLocation') + + cy.visit(urlJobLoc) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(name) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + + let exists = false + cy.waitVisible('table'); + cy.get('table tr').each(($tr) => { + if ($tr.find('td').length) { + exists = true + } + }).then(() => { + if (! exists) { + cy.get('.input-group-prepend').click() + + cy.get('.sweet-title', timeOut).should('contain', 'ADD JOB LOCATION') + cy.wait(2000) + cy.get('.sweet-content-content input').eq(0).type(name) + cy.get('.sweet-content-content input').eq(1).type('123') + cy.get('.sweet-content-content input').eq(2).type('123') + + cy.intercept('POST', apiJobLoc).as('createJobLocation') + + cy.get('.sweet-content-content > .pull-right > button').click() + + cy.wait('@createJobLocation', timeOut).its('response.statusCode').should('equal', 201) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') + + cy.wait(1500) + cy.url().should('contain', urlJobLoc) + cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + } + }) + + cy.waitVisible('table'); + cy.get('table td').should('contain', name) +} + +export function createEmploymentContract(name) { + const apiContract = apiUrl + '/human-resource/employee/statuses**' + const urlContract = '/human-resource/employee-status' + + cy.interceptToken() + cy.intercept('GET', apiContract).as('getEmploymentContract') + + cy.visit(urlContract) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(name) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + + let exists = false + cy.waitVisible('table'); + cy.get('table tr').each(($tr) => { + if ($tr.find('td').length) { + exists = true + } + }).then(() => { + if (! exists) { + cy.get('.input-group-prepend').click() + + cy.intercept('POST', apiContract).as('createEmploymentContract') + + cy.get('.sweet-title', timeOut).should('contain', 'ADD EMPLOYMENT CONTRACT') + cy.wait(2000) + cy.get('.sweet-content-content input').eq(0).type(name) + cy.wait(1000) + cy.get('.sweet-content-content > .pull-right > button').click() + + cy.wait('@createEmploymentContract', timeOut).its('response.statusCode').should('equal', 201) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') + + cy.wait(1500) + cy.url().should('contain', urlContract) + cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + } + }) + + cy.waitVisible('table'); + cy.get('table td').should('contain', name) +} + +export function createEmployee(data) { + const apiEmployee = apiUrl + '/human-resource/employee/employees**' + const urlEmployee = '/human-resource/employee' + + cy.interceptToken() + cy.intercept('GET', apiEmployee).as('getEmployee') + + cy.visit(urlEmployee) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(data.name) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + let exists = false + cy.waitVisible('table'); + cy.get('table tr').each(($tr) => { + if ($tr.find('td').length) { + exists = true + } + }).then(() => { + if (! exists) { + cy.get('.input-group-prepend').click() + + cy.get('.sweet-title', timeOut).should('contain', 'EMPLOYEE INFORMATION') + cy.wait(1000) + cy.get('.sweet-content-content input#name').type(data.name) + cy.wait(1000) + cy.get('.sweet-content-content input#personal-identity').type(data.personalId) + cy.wait(1000) + cy.get('.sweet-content-content input#email').type(data.email) + cy.wait(1000) + cy.get('.sweet-content-content input#address').first().type(data.address) + cy.wait(1000) + cy.get('.sweet-content-content input#phone').type(data.phone) + + cy.wait(1000) + cy.get('.sweet-content-content #birth-date input').click() + cy.wait(1000) + cy.get('.mx-datepicker-sidebar button').contains('Last Year').click() + + cy.wait(1000) + cy.get('.sweet-content-content input#birth-place').type(data.address) + + cy.wait(1000) + cy.get('.sweet-content-content #gender button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content #marital-status button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content #religion button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content #employee-group button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content input#code').type(data.code) + cy.wait(1000) + cy.get('.sweet-content-content input#job-title').type(data.jobTitle) + + cy.wait(1000) + cy.get('.sweet-content-content #job-location button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content #join-date input').click() + cy.wait(1000) + cy.get('.mx-datepicker-sidebar button').contains('Today').click() + + cy.wait(1000) + cy.get('.sweet-content-content #status button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content input#company_email').type(data.email) + + cy.wait(1000) + cy.get('.sweet-content-content button').contains('Contract Period').click() + cy.wait(1000) + cy.get('.sweet-modal').each(($el) => { + if ($el.find('.sweet-title > h2').text() == 'ADD CONTRACT') { + cy.wait(1000) + cy.wrap($el).find('.sweet-content .form-group').eq(0).find('input').click() + cy.wait(1000) + cy.get('.mx-datepicker-sidebar button').contains('Last Year').click() + + cy.wait(1000) + cy.wrap($el).find('.sweet-content .form-group').eq(1).find('input').click() + cy.wait(1000) + cy.get('.mx-datepicker-sidebar button').contains('Today').click() + + cy.wait(1000) + cy.wrap($el).find('.sweet-content .form-group').eq(2).find('input').type(data.note) + + cy.wait(1000) + cy.wrap($el).find('.sweet-content-content > .pull-right > button').last().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content button').contains('Employee Assessor').click() + cy.wait(1000) + cy.get('.sweet-modal').each(($el) => { + if ($el.find('.sweet-title > h2').text() == 'ADD SCORER') { + cy.wait(1000) + cy.wrap($el).find('.sweet-content .list-group a').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-content-content #user-account button').click() + cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('li').first().click() + } + }) + + cy.wait(1000) + cy.get('.sweet-modal-overlay').each(($el) => { + if ($el.css('display') != 'none') { + cy.wrap($el).find('.sweet-content-content > .pull-right > button').click() + } + }) + + cy.wait(3000) + + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') + + cy.wait(1500) + cy.url().should('contain', urlEmployee) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + } + }) + + cy.waitVisible('table'); + cy.get('table td').should('contain', data.name) +} + +export function createKpiTemplate(name, group = false, indicator = false) { + const apiTemplate = apiUrl + '/human-resource/kpi/template**' + const urlTemplate = '/human-resource/kpi-template' + + cy.interceptToken() + cy.intercept('GET', apiTemplate).as('getTemplate') + + cy.visit(urlTemplate) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(name) + cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) + + let exists = false + cy.waitVisible('table'); + cy.get('table tr').each(($tr) => { + if ($tr.find('td').length) { + exists = true + } + }).then(() => { + if (!exists) { + cy.get('.nav-item > a').should('contain', 'ADD') + cy.get('.nav-item > a').contains('ADD').click() + + cy.intercept('POST', apiTemplate).as('createKpiTemplate') + + cy.waitVisible('#create') + cy.get('#create input#name').type(name) + cy.get('#create [type=submit]').click() + + cy.wait('@createKpiTemplate', timeOut).its('response.statusCode').should('equal', 201) + cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'Create success') + cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table td').should('contain', name) + if (group && indicator) { + editKpiTemplate(name, group, indicator) + } + } else { + cy.waitVisible('table'); + cy.get('table td').should('contain', name) + } + }) +} + +export function editKpiTemplate(name, group, indicator) { + const urlTemplate = '/human-resource/kpi-template' + const apiTemplate = apiUrl + '/human-resource/kpi/template' + const getList = apiTemplate + 's**' + const getDetail = apiTemplate + 's/*' + + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(urlTemplate) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(name) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getDetail).as('getDetailKpiTemplate') + + cy.waitVisible('table'); + cy.get('table td').contains(name).click() + + cy.log('Create group') + + cy.wait('@getDetailKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + cy.waitVisible('table'); + cy.get('table td').should('contain', 'NO') + cy.get('table td').should('contain', 'KEY PERFORMANCE INDICATOR') + cy.get('table td').should('contain', 'WEIGHT') + cy.get('table td button').should('contain', 'GROUP') + cy.wait(1500) + cy.get('table td button').contains('GROUP').click() + + cy.intercept('POST', apiTemplate + '-groups').as('createKpiTemplateGroups') + + cy.waitVisible('#group') + cy.get('#group .block-header').should('contain', 'KPI TEMPLATE GROUP') + cy.get('#group input').type(group) + cy.wait(2000) + cy.get('#group [type=submit]').click() + + cy.wait('@createKpiTemplateGroups', timeOut).its('response.statusCode').should('equal', 201) + + cy.get('#group .block-content tr td', timeOut).should('contain', group) + cy.wait(2000) + cy.get('#group .modal-footer [type=button]').click() + + cy.wait(2000) + cy.log('create indicator') + + cy.wait(1500) + cy.get('table td button').contains('INDICATOR').click() + + cy.intercept('POST', apiTemplate + '-indicators').as('createKpiTemplateIndicators') + + cy.waitVisible('#indicator') + cy.get('#indicator .block-header').should('contain', 'KPI TEMPLATE INDICATOR') + cy.get('#indicator input#name').type(indicator) + cy.wait(500) + cy.get('#indicator input#weight').type(100) + cy.wait(500) + cy.get('#indicator input#target').type(80) + cy.wait(500) + cy.get('#indicator [type=submit]').click() + + cy.wait('@createKpiTemplateIndicators', timeOut).its('response.statusCode').should('equal', 201) + + cy.get('#indicator .block-content tr td', timeOut).should('contain', indicator) + cy.wait(2000) + cy.get('#indicator .modal-footer [type=button]').click() +} \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/kpi/assessment.cy.js b/tests/e2e/specs/human-resource/kpi/assessment.cy.js new file mode 100644 index 00000000..4b875d53 --- /dev/null +++ b/tests/e2e/specs/human-resource/kpi/assessment.cy.js @@ -0,0 +1,162 @@ +import { generateText, createDepartement } from '../functions' +import * as hrFunctions from '../functions' + +const { should } = require("chai") +const randomString = generateText(7) +const url = '/human-resource/kpi/kpi-assessment' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') +const apiEmployee = apiUrl + '/human-resource/employee/employees' +const listEmployee = apiEmployee + '**' +const getEmployee = apiEmployee + '/*' +const apiAssignAssessment = getEmployee + '*/**' +const apiTemplate = apiUrl + '/human-resource/kpi/templates**' +const timeOut = { timeout : 300000 } + +const fileName = 'example.pdf' + +const departmentName = 'Departemen Name' +const jobLocation = 'Surabaya' +const employmentContract = 'Kontrak 1' +const employeeName = 'John Doe' +const kpiTemplateName = 'Template 1' +const kpiTemplateGroup = 'Template Group 1' +const kpiTemplateIndicator = 'Template Indicator 1' + +describe('KPI Assessement - Index', () => { + beforeEach(() => { + cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('Create Departemen', () => { + hrFunctions.createDepartement(departmentName) + }) + + it('Create Job location', () => { + hrFunctions.createJobLocation(jobLocation) + }) + + it('Create Employment Contract', () => { + hrFunctions.createEmploymentContract(employmentContract) + }) + + it('Create Employment', () => { + hrFunctions.createEmployee({ + name: employeeName, + personalId: 'A001', + email: 'john.doe@mail.com', + address: 'Lorem Ipsum', + phone: '08123456789', + code: '121314', + jobTitle: 'HR', + note: 'call my name JD' + }) + }) + + it('Create and Edit KPI Template', () => { + hrFunctions.createKpiTemplate(kpiTemplateName, kpiTemplateGroup, kpiTemplateIndicator) + }) + + it('Index KPI Assessement', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI').click() + + cy.intercept('GET', listEmployee).as('getEmployee') + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI ASSESSMENT').click() + + cy.wait('@getEmployee', timeOut).its('response.statusCode').should('equal', 200) + cy.url().should('contain', url) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'name') + cy.get('table th').should('contain', 'job title') + cy.get('table th').should('contain', 'department') + cy.get('table th').should('contain', 'action') + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(employeeName) + cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + + cy.get('table td').should('contain', employeeName) + }) + + it('Create KPI Assessement', () => { + cy.interceptToken() + cy.intercept('GET', listEmployee).as('getEmployee') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').type(employeeName) + cy.wait('@getEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', getEmployee).as('getDetailEmployee') + cy.waitVisible('table'); + cy.get('table td').contains(employeeName).parents('tr').find('a').first().click() + + cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('GET', apiTemplate).as('getTemplate') + + cy.waitVisible('#assign-assessment-modal') + cy.get('#assign-assessment-modal .block-title').should('contain', 'ASSIGN KPI TEMPLATE') + cy.get('#assign-assessment-modal #search-text').type(kpiTemplateName) + + cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) + cy.waitVisible('#assign-assessment-modal .list-group') + cy.get('#assign-assessment-modal .list-group a:first-child').click() + + cy.intercept('POST', apiAssignAssessment).as('assignAssessment') + + cy.wait(1000) + cy.get('#assign-assessment-modal [type=submit]').click() + + cy.wait('@assignAssessment', timeOut).its('response.statusCode').should('equal', 200) + + cy.get('form.row > .col-sm-12').find('h3', timeOut).shoul('contain', 'ASSESSMENT') + cy.get('form.row > .col-sm-12 div.col-form-label', timeOut).first().shoul('contain', employeeName) + cy.get('form.row > .col-sm-12 div.col-form-label', timeOut).eq(1).shoul('contain', kpiTemplateName) + + cy.get('form.row > .col-sm-12 .table-responsive tbody tr:first-child td:first-child').should('contain', kpiTemplateGroup) + cy.get('form.row > .col-sm-12 .table-responsive tbody tr:nth-child(2) td:nth-child(2)').should('contain', kpiTemplateIndicator) + + cy.get('form.row > .col-sm-12 .table-responsive tbody tr:nth-child(2) td:nth-child(5) a:first-child').click() + cy.waitVisible('#assign-notes') + cy.get('#assign-comment h3').should('contain','NOTES ASSESSMENT') + cy.get('#assign-notes textarea').type('note assessment') + cy.get('#assign-notes button[type=submit]').click() + cy.get('form.row > .col-sm-12 .table-responsive tbody tr:nth-child(2) td:nth-child(5) a:nth-child(2)', timeOut).should('be.visible') + + cy.get('form.row > .col-sm-12 input[type=file]').attachFile(fileName) + cy.get('form.row > .col-sm-12 input[type=file]').parent().find('label').contains(fileName) + + cy.get('form.row > .col-sm-12 .table-responsive tbody tr:nth-child(2) td:last-child a:first-child').click() + cy.waitVisible('#assign-comment') + cy.get('#assign-comment h3').should('contain','COMMENT ASSESSMENT') + cy.get('#assign-comment textarea').type('comment assessment') + cy.get('#assign-comment button[type=submit]').click() + + cy.get('.block-content-inner > div:last-child button').contains('SAVE').click() + + cy.get('#main-container .content .block nav .active', timeOut).should('contain', 'HISTORY ASSESSMENT') + + cy.get('.table-responsive table thead tr td:nth-child(2)').should('contain', 'kpi template') + cy.get('.table-responsive table tbody tr:first-child td:nth-child(2)').should('contain', kpiTemplateName) + }) +}) \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/kpi/template.cy.js b/tests/e2e/specs/human-resource/kpi/template.cy.js new file mode 100644 index 00000000..09931fb1 --- /dev/null +++ b/tests/e2e/specs/human-resource/kpi/template.cy.js @@ -0,0 +1,288 @@ +import { generateText, createKpiTemplate, editKpiTemplate } from '../functions' + +const { should } = require("chai") +const templateName = generateText(7) +const templateGroup = generateText(7) +const templateIndicator = generateText(7) +const url = '/human-resource/kpi-template' +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/kpi/template' +const getList = apiUrl + 's**' +const getDetail = apiUrl + 's/*' +const timeOut = { timeout : 300000 } + +describe('HR - KPI Template', () => { + beforeEach(() => { + // cy.hideXHR() + cy.login('admin', 'admin') + }) + + it('Index KPI Template', () => { + cy.interceptToken() + cy.visit('/') + cy.waitToken() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI').click() + + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.waitVisible('#main-container > .content'); + cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI TEMPLATE').click() + + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.get('.nav-item > a').should('contain', 'ADD') + cy.get('.nav-item > a').should('contain', 'IMPORT') + }) + + it('Create KPI Template', () => { + createKpiTemplate(templateName) + }) + + it('Edit KPI Template', () => { + editKpiTemplate(templateName, templateGroup, templateIndicator) + }) + + it('Duplicate KPI Template', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.get('.nav-item > a').should('contain', 'ADD') + cy.get('.nav-item > a').should('contain', 'IMPORT') + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(templateName) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('POST', getDetail).as('duplicate') + + cy.waitVisible('table'); + cy.get('table td').contains(templateName).parents('tr').find('button').contains('DUPLICATE').click() + cy.wait('@duplicate', timeOut).its('response.statusCode').should('equal', 201) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(templateName + ' (duplicate)') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table td').should('contain', templateName + ' (duplicate)') + }) + + it('Rename KPI Template', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.get('.nav-item > a').should('contain', 'ADD') + cy.get('.nav-item > a').should('contain', 'IMPORT') + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(templateName + ' (duplicate)') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('PATCH', getDetail).as('updateName') + + cy.waitVisible('table'); + cy.get('table td').contains(templateName + ' (duplicate)').parents('tr').find('a').contains('RENAME').click() + + cy.get('#edit input#name', timeOut).should('have.value', templateName + ' (duplicate)').clear().type(templateName + ' (renamed)') + cy.wait(1500) + cy.get('#edit [type=submit]').click() + + cy.wait('@updateName', timeOut).its('response.statusCode').should('equal', 200) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(templateName + ' (renamed)') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + + cy.get('table td').should('contain', templateName + ' (renamed)') + }) + + it('Export KPI Template', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.get('.nav-item > a').should('contain', 'ADD') + cy.get('.nav-item > a').should('contain', 'IMPORT') + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(templateName + ' (renamed)') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('POST', getDetail).as('export') + + const stub = cy.stub().as('open') + cy.on('window:before:load', (win) => { + cy.stub(win, 'open').callsFake(stub) + }) + + cy.waitVisible('table'); + cy.get('table td').contains(templateName + ' (renamed)').parents('tr').find('button').contains('EXPORT').click() + + cy.get('@open', timeOut).should('have.been.calledOnce') + + cy.wait('@export', timeOut).its('response.body.data.url') + .should('match', /download/).end() + }) + + it('Archive and filter', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type(templateName + ' (renamed)') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table td') + .contains(templateName + ' (renamed)') + .parents('tr') + .find('td:nth-child(2) input#subscibe') + .click({force: true}) + + cy.intercept('PATCH', getDetail).as('archive') + + cy.get('div.fadeIn button', timeOut).contains('ARCHIVE').click() + + cy.wait('@archive', timeOut).its('response.statusCode').should('equal', 200) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.log('filter archive') + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.wait(1500) + cy.get('.block-content a').contains('ADVANCE FILTER').click() + + cy.wait(1500) + cy.get('.fadeIn span').contains('SELECT').click() + + cy.wait(1500) + cy.get('.sweet-modal h2').should('contain', 'SELECT') + cy.get('.sweet-modal .sweet-content a').contains('ARCHIVED').click() + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table td').should('contain', templateName + ' (renamed)') + }) + + it('Impor\'t KPI Template', () => { + const fileName = 'DEV - KPI Template Export - abc.xlsx' + + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.intercept('POST', apiUrl + 's/import/check').as('importTemplate') + + cy.get('.nav-item > a').should('contain', 'IMPORT') + cy.get('.nav-item > a').contains('IMPORT').parent().find('[id="file"]').attachFile(fileName) + + cy.fixture(fileName, 'binary') + .then(Cypress.Blob.binaryStringToBlob) + .then(fileContent => { + cy.get('.nav-item > a').contains('IMPORT').parent().find('[id="file"]') + .attachFile({ fileContent, fileName, mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', encoding:'utf8' }) + }) + + cy.wait('@importTemplate', timeOut).its('response.statusCode').should('equal', 200) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type('abc') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table td').should('contain', 'abc') + }) + + it('Remove KPI Template', () => { + cy.interceptToken() + cy.intercept('GET', getList).as('getKpiTemplate') + + cy.visit(url) + + cy.waitToken() + cy.wait(2000) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.waitVisible('table'); + cy.get('table th').should('contain', 'Kpi Category') + cy.get('table th').should('contain', 'Total Weight') + + cy.waitVisible('#search-text'); + cy.get('#search-text').clear().type('abc') + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + + cy.intercept('DELETE', getDetail).as('delete') + + cy.waitVisible('table'); + cy.get('table td').contains('abc').parents('tr').find('button').contains('REMOVE').click() + cy.wait('@delete', timeOut).its('response.statusCode').should('equal', 200) + cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) + }) +}) \ No newline at end of file diff --git a/tests/e2e/specs/index.cy.js b/tests/e2e/specs/index.cy.js new file mode 100644 index 00000000..13ed35e7 --- /dev/null +++ b/tests/e2e/specs/index.cy.js @@ -0,0 +1,30 @@ +describe('Login Test', () => { + const url = '/' + + beforeEach(() => { + cy.hideXHR() + }) + + it('Visits the login page', () => { + cy.visit(url) + cy.url().should('contain', '/auth/signin') + cy.get('h1').should('contain', 'Welcome to Point.RED') + }) + + it('Try to login', () => { + cy.intercept('POST', '**/api/v1/auth/login**').as('getLogin') + cy.intercept('GET', '**/api/v1/reward/tokens**').as('getToken') + cy.intercept('POST', '**/api/v1/auth/fetch**').as('authFetch') + + cy.get('#username').type('admin') + cy.get('#password').type('admin') + cy.get('button').click() + + cy.wait('@getLogin').its('response.statusCode').should('equal', 200) + cy.wait('@getToken').its('response.statusCode').should('equal', 200) + cy.wait('@authFetch').its('response.statusCode').should('equal', 200) + + cy.url().should('contain', url) + cy.get('p').should('contain', 'MAIN MENU') + }) +}) diff --git a/tests/e2e/specs/test.js b/tests/e2e/specs/test.js deleted file mode 100644 index 41ad94a0..00000000 --- a/tests/e2e/specs/test.js +++ /dev/null @@ -1,8 +0,0 @@ -// https://docs.cypress.io/api/introduction/api.html - -describe('My First Test', () => { - it('Visits the app root url', () => { - cy.visit('/') - cy.contains('h1', 'Welcome to Your Vue.js App') - }) -}) diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js index c1f5a772..b265d6a6 100644 --- a/tests/e2e/support/commands.js +++ b/tests/e2e/support/commands.js @@ -23,3 +23,57 @@ // // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) + +const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + +// -- This is will hide request some xhr -- +Cypress.Commands.add('hideXHR', () => { + Cypress.on("log:added", ev => { + if (["xhr", "other", "new url"].includes(ev.displayName)) { + const el = Array.from( + window.top.document.querySelectorAll(".command-wrapper") + ).slice(-1)[0] + if (el) { + el.parentElement.style.display = "none" + } + } + }) +}) + +Cypress.Commands.add('login', (username, password) => { + cy.request({ + method: 'POST', + url: apiUrl + '/auth/login', + body: { + username: username, + password: password + } + }).then(({ body }) => { + cy.setCookie('TED', 'Undefined') + cy.setCookie('TTT', 'Bearer') + cy.setCookie('TAT', body.data.access_token) + cy.setCookie('TID', body.data.token_id) + }) +}) + +Cypress.Commands.add('interceptToken', () => { + cy.intercept('GET', apiUrl + '/reward/tokens**').as('getToken') + cy.intercept('POST', apiUrl + '/auth/fetch**').as('authFetch') +}) + +Cypress.Commands.add('waitToken', () => { + const timeOut = { timeout: 300000 } + + cy.wait('@getToken', timeOut).its('response.statusCode').should('equal', 200) + cy.wait('@authFetch', timeOut).its('response.statusCode').should('equal', 200) +}) + +Cypress.Commands.add('waitVisible', (target, idx) => { + const timeOut = { timeout: 300000 } + if (idx) { + cy.get(target).eq(idx, timeOut).should('be.visible'); + } else { + cy.get(target, timeOut).should('be.visible'); + } + cy.wait(2000) +}) diff --git a/tests/e2e/support/index.js b/tests/e2e/support/index.js index d68db96d..220e2cb2 100644 --- a/tests/e2e/support/index.js +++ b/tests/e2e/support/index.js @@ -15,6 +15,6 @@ // Import commands.js using ES2015 syntax: import './commands' - +import 'cypress-file-upload' // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/yarn.lock b/yarn.lock index b2661d8d..06c0f1b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -968,6 +968,11 @@ resolved "https://registry.yarnpkg.com/@bugsnag/safe-json-stringify/-/safe-json-stringify-2.1.0.tgz#c7dd30a33bd888c39cd36d45216f7252f307ed36" integrity sha512-tE2cPhAq+WFnA9XrfMfP+u/6L63eH7+PmONMNSXtP6kPt/iUXnwkDsxc1Q6lUP1oM3LsmWBrxn+/93M8JE6fpA== +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cypress/listr-verbose-renderer@0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" @@ -978,7 +983,31 @@ date-fns "^1.27.2" figures "^1.7.0" -"@cypress/xvfb@1.2.4": +"@cypress/request@^2.88.10": + version "2.88.10" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce" + integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + http-signature "~1.3.6" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^8.3.2" + +"@cypress/xvfb@1.2.4", "@cypress/xvfb@^1.2.4": version "1.2.4" resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== @@ -1501,6 +1530,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.36.tgz#c0d5f2fe76b47b63e0e0efc3d2049a9970d68794" integrity sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA== +"@types/node@^14.14.31": + version "14.18.33" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.33.tgz#8c29a0036771569662e4635790ffa9e057db379b" + integrity sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg== + "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -1516,11 +1550,28 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== +"@types/sinonjs__fake-timers@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" + integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== + "@types/sizzle@2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== +"@types/sizzle@^2.3.2": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" + integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + "@vue/babel-helper-vue-jsx-merge-props@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz#31624a7a505fb14da1d58023725a4c5f270e6a81" @@ -2243,7 +2294,7 @@ arch@2.1.1: resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== -arch@^2.1.1: +arch@^2.1.1, arch@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== @@ -2506,11 +2557,21 @@ async@^2.6.2: dependencies: lodash "^4.17.14" +async@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -2657,7 +2718,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2742,6 +2803,11 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +blob-util@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -2754,7 +2820,7 @@ bluebird@3.5.0: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" integrity sha512-3LE8m8bqjGdoxfvf71yhFNrUcwy3NLy00SAo+b6MfJ8l+Bc2DzQ7mUHwX6pjK2AxfgV+YfsjCeVW3T5HLQTBsQ== -bluebird@^3.1.1, bluebird@^3.5.5: +bluebird@^3.1.1, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -2984,6 +3050,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" @@ -3112,6 +3186,11 @@ cachedir@1.3.0: dependencies: os-homedir "^1.0.1" +cachedir@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -3304,7 +3383,7 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -check-more-types@2.24.0: +check-more-types@2.24.0, check-more-types@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== @@ -3363,6 +3442,11 @@ ci-info@^1.5.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +ci-info@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.5.0.tgz#bfac2a29263de4c829d806b1ab478e35091e171f" + integrity sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -3449,6 +3533,15 @@ cli-spinners@^2.0.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== +cli-table3@~0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -3677,6 +3770,11 @@ commander@^2.18.0, commander@^2.19.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + commander@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" @@ -4197,6 +4295,59 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A== +cypress-file-upload@^5.0.8: + version "5.0.8" + resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz#d8824cbeaab798e44be8009769f9a6c9daa1b4a1" + integrity sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g== + +cypress@^10.11.0: + version "10.11.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.11.0.tgz#e9fbdd7638bae3d8fb7619fd75a6330d11ebb4e8" + integrity sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA== + dependencies: + "@cypress/request" "^2.88.10" + "@cypress/xvfb" "^1.2.4" + "@types/node" "^14.14.31" + "@types/sinonjs__fake-timers" "8.1.1" + "@types/sizzle" "^2.3.2" + arch "^2.2.0" + blob-util "^2.0.2" + bluebird "^3.7.2" + buffer "^5.6.0" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-cursor "^3.1.0" + cli-table3 "~0.6.1" + commander "^5.1.0" + common-tags "^1.8.0" + dayjs "^1.10.4" + debug "^4.3.2" + enquirer "^2.3.6" + eventemitter2 "6.4.7" + execa "4.1.0" + executable "^4.1.1" + extract-zip "2.0.1" + figures "^3.2.0" + fs-extra "^9.1.0" + getos "^3.2.1" + is-ci "^3.0.0" + is-installed-globally "~0.4.0" + lazy-ass "^1.6.0" + listr2 "^3.8.3" + lodash "^4.17.21" + log-symbols "^4.0.0" + minimist "^1.2.6" + ospath "^1.2.2" + pretty-bytes "^5.6.0" + proxy-from-env "1.0.0" + request-progress "^3.0.0" + semver "^7.3.2" + supports-color "^8.1.1" + tmp "~0.2.1" + untildify "^4.0.0" + yauzl "^2.10.0" + cypress@^3.8.3: version "3.8.3" resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.3.tgz#e921f5482f1cbe5814891c878f26e704bbffd8f4" @@ -4275,6 +4426,11 @@ dateformat@^2.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" integrity sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw== +dayjs@^1.10.4: + version "1.11.6" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.6.tgz#2e79a226314ec3ec904e3ee1dd5a4f5e5b1c7afb" + integrity sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ== + de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" @@ -4308,7 +4464,7 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.4: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5232,6 +5388,11 @@ eventemitter2@4.1.2: resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-4.1.2.tgz#0e1a8477af821a6ef3995b311bf74c23a5247f15" integrity sha512-erx0niBaTi8B7ywjGAcg8ilGNRl/xs/o4MO2ZMpRlpZ62mYzjGTBlOpxxRIrPQqBs9mbXkEux6aR+Sc5vQ/wUw== +eventemitter2@6.4.7: + version "6.4.7" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" + integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== + eventemitter3@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba" @@ -5273,6 +5434,21 @@ execa@0.10.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@4.1.0, execa@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" @@ -5315,22 +5491,7 @@ execa@^3.3.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" - integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" - -executable@4.1.1: +executable@4.1.1, executable@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== @@ -5459,6 +5620,17 @@ extract-zip@1.6.7: mkdirp "0.5.1" yauzl "2.4.1" +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -5575,7 +5747,7 @@ figures@^1.7.0: escape-string-regexp "^1.0.5" object-assign "^4.1.0" -figures@^3.0.0: +figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -5878,6 +6050,16 @@ fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -6028,7 +6210,7 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-stream@^5.0.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -6055,6 +6237,13 @@ getos@3.1.1: dependencies: async "2.6.1" +getos@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" + integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== + dependencies: + async "^3.2.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -6161,6 +6350,13 @@ global-dirs@^0.1.0: dependencies: ini "^1.3.4" +global-dirs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" + integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + dependencies: + ini "2.0.0" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -6274,7 +6470,7 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.2: +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -6760,6 +6956,15 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" + integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== + dependencies: + assert-plus "^1.0.0" + jsprim "^2.0.2" + sshpk "^1.14.1" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -6789,7 +6994,7 @@ idb@3.0.2: resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384" integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw== -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -6917,6 +7122,11 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== +ini@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + ini@^1.3.4: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" @@ -7084,6 +7294,13 @@ is-ci@1.2.1, is-ci@^1.0.10: dependencies: ci-info "^1.5.0" +is-ci@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + is-color-stop@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" @@ -7213,6 +7430,14 @@ is-installed-globally@0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" +is-installed-globally@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" + integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" @@ -7283,6 +7508,11 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -7626,6 +7856,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -7641,6 +7880,16 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" +jsprim@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" + integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + jszip@^3.9.1: version "3.10.0" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.0.tgz#faf3db2b4b8515425e34effcdbb086750a346061" @@ -7713,7 +7962,7 @@ launch-editor@^2.2.1, launch-editor@^2.4.0: picocolors "^1.0.0" shell-quote "^1.6.1" -lazy-ass@1.6.0: +lazy-ass@1.6.0, lazy-ass@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== @@ -7836,7 +8085,7 @@ listr-verbose-renderer@^0.4.0: date-fns "^1.27.2" figures "^1.7.0" -listr2@^3.2.2: +listr2@^3.2.2, listr2@^3.8.3: version "3.14.0" resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== @@ -9274,6 +9523,11 @@ osenv@0: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +ospath@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA== + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -10074,7 +10328,7 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== -pretty-bytes@^5.1.0: +pretty-bytes@^5.1.0, pretty-bytes@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== @@ -10158,6 +10412,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -10589,7 +10848,7 @@ replace-homedir@^1.0.0: is-absolute "^1.0.0" remove-trailing-separator "^1.1.0" -request-progress@3.0.0: +request-progress@3.0.0, request-progress@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= @@ -10796,7 +11055,7 @@ rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1: dependencies: glob "^7.1.3" -rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -10993,6 +11252,13 @@ semver@^7.2.1, semver@^7.3.5, semver@^7.3.6: dependencies: lru-cache "^6.0.0" +semver@^7.3.2: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -11354,7 +11620,7 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -sshpk@^1.7.0: +sshpk@^1.14.1, sshpk@^1.7.0: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== @@ -11691,6 +11957,13 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -11933,6 +12206,13 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + to-absolute-glob@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" @@ -12277,6 +12557,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -12300,6 +12585,11 @@ untildify@3.0.3: resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" integrity sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + unzipper@^0.10.11: version "0.10.11" resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.11.tgz#0b4991446472cbdb92ee7403909f26c2419c782e" @@ -13377,7 +13667,7 @@ yargs@^7.1.0: y18n "^3.2.1" yargs-parser "^5.0.1" -yauzl@2.10.0: +yauzl@2.10.0, yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= From 023799dec0d4ffeb39adb88382e550112ca0b924 Mon Sep 17 00:00:00 2001 From: anasark Date: Wed, 7 Dec 2022 00:03:45 +0700 Subject: [PATCH 2/2] revision --- tests/e2e/fixtures/invoice.pdf | Bin 0 -> 105227 bytes .../employee/additionalComponent.cy.js | 163 --- .../human-resource/employee/departement.cy.js | 789 ++++++++++-- .../human-resource/employee/employee.cy.js | 1082 ++++++++++++++--- .../employee/employmentContract.cy.js | 795 ++++++++++-- .../human-resource/employee/jobLocation.cy.js | 819 +++++++++++-- tests/e2e/specs/human-resource/functions.js | 912 +++++++------- .../specs/human-resource/kpi/assessment.cy.js | 24 +- .../specs/human-resource/kpi/template.cy.js | 18 +- 9 files changed, 3574 insertions(+), 1028 deletions(-) create mode 100644 tests/e2e/fixtures/invoice.pdf delete mode 100644 tests/e2e/specs/human-resource/employee/additionalComponent.cy.js diff --git a/tests/e2e/fixtures/invoice.pdf b/tests/e2e/fixtures/invoice.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a30fbaa1ae0b92606f9f26ee2faf551c32b7820c GIT binary patch literal 105227 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 F{{tk3-aY^T literal 0 HcmV?d00001 diff --git a/tests/e2e/specs/human-resource/employee/additionalComponent.cy.js b/tests/e2e/specs/human-resource/employee/additionalComponent.cy.js deleted file mode 100644 index 386c7de3..00000000 --- a/tests/e2e/specs/human-resource/employee/additionalComponent.cy.js +++ /dev/null @@ -1,163 +0,0 @@ -import { generateText } from '../functions' - -const { should } = require("chai") -const randomString = generateText(7) -const url = '/human-resource/additional-component' -const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/additional-components' -const getList = apiUrl + '**' -const getDetail = apiUrl + '/*' -const timeOut = { timeout : 300000 } - -describe('HR - Additional Component', () => { - beforeEach(() => { - cy.hideXHR() - cy.login('admin', 'admin') - }) - - it('index additional components', () => { - cy.interceptToken() - cy.visit('/') - cy.waitToken() - - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() - - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() - - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() - - cy.waitVisible('li.nav-item'); - cy.get('li.nav-item a').contains('ADDITIONAL COMPONENT').click() - - cy.intercept('GET', getList).as('getAdditionalComponent') - - cy.wait(5000) - cy.waitVisible('table'); - - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - cy.get('table th').should('contain', 'name') - cy.get('table th').should('contain', 'source') - cy.get('table th').should('contain', 'weight') - }) - - it('Create additional components', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getAdditionalComponent') - - cy.visit(url) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('.input-group-prepend'); - cy.get('.input-group-prepend').click() - - cy.get('.sweet-title', timeOut).should('contain', 'ADD ADDITIONAL COMPONENT') - cy.wait(1000) - cy.get('.sweet-content-content input').eq(0).type(randomString) - cy.wait(1000) - cy.get('.sweet-content-content input').eq(1).type(123) - cy.wait(1000) - cy.get('.sweet-content-content span.link').click() - cy.wait(1000) - cy.get('.sweet-content-content #selectautomated-code a').first().click() - - cy.intercept('POST', getList).as('createAdditionalComponent') - - cy.get('.sweet-content-content > .pull-right > button').click() - - cy.wait('@createAdditionalComponent', timeOut).its('response.statusCode').should('equal', 201) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') - - cy.wait(1500) - cy.url().should('contain', url) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').clear().type(randomString) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('table td'); - cy.get('table td').should('contain', randomString) - }) - - it('Edit additional components', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getAdditionalComponent') - - cy.visit(url) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.wait(2000) - cy.get('table a', timeOut).contains(randomString).click() - - cy.get('input#name', timeOut).should('have.value', randomString) - cy.get('.block-content').contains('EDIT').click() - - - cy.waitVisible('.sweet-title'); - cy.get('.sweet-title').should('contain', 'EDIT ADDITIONAL COMPONENT') - - cy.wait(2000) - cy.get('.sweet-content-content input#name').last(timeOut).should('have.value', randomString) - cy.get('.sweet-content-content input#name') - .last() - .clear() - .type(randomString + ' - edit') - - cy.wait(1500) - cy.intercept('PATCH', getDetail).as('updateAdditionalComponent') - cy.intercept('GET', getDetail).as('getDetailAdditionalComponent') - - cy.get('.sweet-content-content > .pull-right > button').last().click() - - cy.wait('@updateAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') - cy.wait('@getDetailAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.wait(1500) - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - }) - - it('Delete additional components', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getAdditionalComponent') - - cy.visit(url) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getAdditionalComponent', timeOut).its('response.statusCode').should('equal', 200) - - cy.wait(2000) - cy.waitVisible('table'); - cy.get('table a').contains(randomString + ' - edit').click() - - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - cy.get('.block-content').contains('DELETE').click() - - cy.intercept('DELETE', getDetail).as('deleteAdditionalComponent') - - cy.waitVisible('.swal2-container') - cy.get('.swal2-container button').contains('Confirm').click() - cy.wait('@deleteAdditionalComponent', timeOut).its('response.statusCode').should('equal', 204) - - cy.wait(1500) - cy.url().should('contain', url) - }) -}) - \ No newline at end of file diff --git a/tests/e2e/specs/human-resource/employee/departement.cy.js b/tests/e2e/specs/human-resource/employee/departement.cy.js index f3799922..a2c943e4 100644 --- a/tests/e2e/specs/human-resource/employee/departement.cy.js +++ b/tests/e2e/specs/human-resource/employee/departement.cy.js @@ -1,123 +1,732 @@ -import { generateText, createDepartement } from '../functions' +import { + generateText, + changeRole, + createUserNoRole, + createDepartementApi, +} from "../functions"; -const { should } = require("chai") -const randomString = generateText(7) -const url = '/human-resource/employee-group' -const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/groups' -const getList = apiUrl + '**' -const getDetail = apiUrl + '/*' -const timeOut = { timeout : 300000 } +const randomString = generateText(7); +const name = randomString; +const url = "/human-resource/employee-group"; +const api = Cypress.env("VUE_APP_API_ENDPOINT"); +const apiUrl = api + "/human-resource/employee/groups"; +const getList = apiUrl + "**"; +const getDetail = apiUrl + "/*"; +const timeOut = { timeout: 300000 }; -describe('HR - Departement', () => { +describe("HRIS Departemen - Create", () => { beforeEach(() => { - cy.hideXHR() - cy.login('admin', 'admin') - }) + cy.hideXHR(); + }); - it('index departemen', () => { - cy.interceptToken() - cy.visit('/') - cy.waitToken() + it("test have access create", () => { + cy.login("admin", "admin"); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.waitVisible('li.nav-item'); - cy.get('li.nav-item a').contains('DEPARTMENT').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); - cy.intercept('GET', getList).as('getDepartement') + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("DEPARTMENT").click(); - cy.wait(5000) - cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + cy.intercept("GET", getList).as("getDepartement"); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.waitVisible('table'); - cy.get('table th').should('contain', 'Name') - }) + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); - it('Create departemen', () => { - createDepartement(randomString) - }) + // button add and form input departemen + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + cy.get(".sweet-modal h2", timeOut).should("contain", "ADD DEPARTMENT"); + cy.get('.sweet-modal [for="name"]').should("contain", "NAME"); + cy.get('.sweet-modal input[id="name"]').should("be.visible"); - it('Edit departemen', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getDepartement') + // input and save departement + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.intercept("POST", getList).as("createDepartement"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + cy.wait("@createDepartement", timeOut) + .its("response.statusCode") + .should("equal", 201); - cy.visit(url) + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "create success"); - cy.waitToken() - cy.wait(2000) - cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + // find name + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.intercept('GET', getDetail).as('getDetailDepartement') - cy.wait(2000) - cy.waitVisible('table'); - cy.get('table a').contains(randomString).click() + cy.waitVisible("table"); + cy.get("table td").should("contain", name); - cy.wait('@getDetailDepartement', timeOut).its('response.statusCode').should('equal', 200) - cy.get('input#name', timeOut).should('have.value', randomString) - cy.get('.block-content').contains('EDIT').click() + // detail name + cy.intercept("GET", getDetail).as("getDetailDepartement"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); - cy.waitVisible('.sweet-title'); - cy.get('.sweet-title').should('contain', 'EDIT DEPARTMENT') - - cy.wait('@getDetailDepartement', timeOut).its('response.statusCode').should('equal', 200) - cy.wait(2000) - cy.get('.sweet-content-content input#name') + it("create data if data table < 10", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('.pagination [class="page-item"]').then(($pagination) => { + if ($pagination.length <= 3) { + createDepartementApi(); + } + }); + }); + + it("test user no role - list 10 of data", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th").should("have.length", 10); + }); + + it("test user no role - pagination", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); + + it("test user no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); + + it("test user no role - not show button add", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get(".input-group-prepend").should("not.exist"); + }); + + it("test user has role - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS Departemen - Read", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access read", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("DEPARTMENT").click(); + + cy.intercept("GET", getList).as("getDepartement"); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test have access read - pagination, (detail) button:create,edit,delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("DEPARTMENT").click(); + + cy.intercept("GET", getList).as("getDepartement"); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // list pagination + cy.waitVisible(".pagination"); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailDepartement"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('[type="button"]').should("contain", "CREATE"); + cy.get('[type="button"]').should("contain", "EDIT"); + cy.get('[type="button"]').should("contain", "DELETE"); + }); + + it("test have access read - list 10 of data", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th").should("have.length", 10); + }); + + it("test have access read - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("DEPARTMENT").click(); + + cy.intercept("GET", getList).as("getDepartement"); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailDepartement"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // name column + cy.get('.block-content input[name="name"]').should("be.visible"); + }); + + it("test have access read - pagination", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); // button create + cy.waitVisible("#search-text"); // search + cy.waitVisible(".pagination"); // pagination + }); +}); + +describe("HRIS Departemen - Edit", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access edit", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("DEPARTMENT").click(); + + cy.intercept("GET", getList).as("getDepartement"); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test have access edit - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("DEPARTMENT").click(); + + cy.intercept("GET", getList).as("getDepartement"); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailDepartement"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get("input#name", timeOut).should("have.value", randomString); + cy.get('[type="button"]').contains("EDIT").click(); + + cy.waitVisible(".sweet-title"); + cy.get(".sweet-title").should("contain", "EDIT DEPARTMENT"); + + cy.wait("@getDetailDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible(".sweet-content-content button").last().should("be.visible"); // button update + cy.waitVisible(".sweet-modal .sweet-action-close"); // button close + + cy.wait(2000); + cy.get('.sweet-content-content input[name="name"]') .last() .clear() - .type(randomString + ' - edit') + .type(randomString + " - edit"); + + cy.wait(1500); + cy.intercept("PATCH", getDetail).as("updateDepartement"); + cy.get(".sweet-content-content button").last().click(); + + cy.wait("@updateDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "update success"); + }); + + it("test have access edit - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // clear input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).clear(); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + + // fill same input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "Please edit with a different name"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS Departemen - Delete", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement").its("response.statusCode").should("equal", 200); + + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + cy.waitVisible("#search-text"); + cy.get("#search-text").type(randomString); + cy.wait("@getDepartement").its("response.statusCode").should("equal", 200); + + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a") + .contains(randomString + " - edit") + .click(); - cy.wait(1500) - cy.intercept('PATCH', getDetail).as('updateDepartement') - cy.get('.sweet-content-content > .pull-right > button').last().click() + cy.get("input#name", timeOut).should( + "have.value", + randomString + " - edit" + ); + cy.get(".block-content").contains("DELETE").click(); - cy.wait('@updateDepartement', timeOut).its('response.statusCode').should('equal', 200) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + cy.intercept("DELETE", getDetail).as("deleteDepartemen"); - cy.wait(1500) - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - }) + cy.waitVisible(".swal2-container"); + cy.get(".swal2-container button").contains("Confirm").click(); - it('Delete departemen', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getDepartement') + cy.wait("@deleteDepartemen", timeOut) + .its("response.statusCode") + .should("equal", 204); - cy.visit(url) + cy.wait(1500); + cy.url().should("contain", url); - cy.waitToken() - cy.wait(2000) - cy.wait('@getDepartement').its('response.statusCode').should('equal', 200) + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement").its("response.statusCode").should("equal", 200); - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getDepartement').its('response.statusCode').should('equal', 200) + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); - cy.wait(2000) - cy.waitVisible('table'); - cy.get('table a').contains(randomString + ' - edit').click() + it("test delete no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + changeRole(this.userId, this.superAdminRoleId) + }); - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - cy.get('.block-content').contains('DELETE').click() + cy.interceptToken(); + cy.intercept("GET", getList).as("getDepartement"); - cy.intercept('DELETE', getDetail).as('deleteDepartemen') + cy.visit(url); - cy.waitVisible('.swal2-container') - cy.get('.swal2-container button').contains('Confirm').click() + cy.waitToken(); + cy.wait(2000); + cy.wait("@getDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.wait('@deleteDepartemen', timeOut).its('response.statusCode').should('equal', 204) - - cy.wait(1500) - cy.url().should('contain', url) - }) -}) - \ No newline at end of file + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); +}); diff --git a/tests/e2e/specs/human-resource/employee/employee.cy.js b/tests/e2e/specs/human-resource/employee/employee.cy.js index 25c83f4b..f07e275b 100644 --- a/tests/e2e/specs/human-resource/employee/employee.cy.js +++ b/tests/e2e/specs/human-resource/employee/employee.cy.js @@ -1,144 +1,948 @@ -import { generateText, generateNumber, createEmployee } from '../functions' - -const { should } = require("chai") -const name = generateText(7) -const personalId = generateText(7) -const email = generateText(7) + '@mail.com' -const address = generateText(7) -const phone = generateNumber(11) -const code = generateNumber(4) -const jobTitle = generateText(6) -const note = generateText(15) -const url = '/human-resource/employee' -const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/employees' -const getList = apiUrl + '**' -const getDetail = apiUrl + '/*' -const timeOut = { timeout : 300000 } - -describe('HR - Employee', () => { +import { + generateText, + changeRole, + createUserNoRole, +} from "../functions"; + +const name = generateText(7); +const personalId = generateText(7); +const email = generateText(7) + "@mail.com"; +const address = generateText(7); +const phone = generateNumber(11); +const code = generateNumber(4); +const jobTitle = generateText(6); +const note = generateText(15); +const url = "/human-resource/employee"; +const apiUrl = + Cypress.env("VUE_APP_API_ENDPOINT") + "/human-resource/employee/employees"; +const getList = apiUrl + "**"; +const getDetail = apiUrl + "/*"; +const timeOut = { timeout: 300000 }; + +describe("HRIS Employee - Create", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access create", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.intercept("GET", getList).as("getEmployee"); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list employee + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + // button add and form input employee + cy.waitVisible(".input-group-prepend"); + + cy.get(".input-group-prepend").click(); + cy.get(".sweet-modal h2", timeOut).should("contain", "EMPLOYEE INFORMATION"); + + cy.get(".sweet-title", timeOut).should("contain", "EMPLOYEE INFORMATION"); + cy.get(".sweet-content-content input#name", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#personal-identity", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#email", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#address", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#phone", timeOut).should("be.visible"); + cy.get(".sweet-content-content #birth-date input", timeOut).should("be.visible"); + cy.get(".sweet-content-content mx-datepicker-sidebar button", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#birth-place", timeOut).should("be.visible"); + cy.get(".sweet-content-content #gender button", timeOut).should("be.visible"); + cy.get(".sweet-content-content #marital-status button", timeOut).should("be.visible"); + cy.get(".sweet-content-content #religion button", timeOut).should("be.visible"); + cy.get(".sweet-content-content #employee-group button", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#code", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#job-title", timeOut).should("be.visible"); + cy.get(".sweet-content-content #job-location button", timeOut).should("be.visible"); + cy.get(".sweet-content-content #join-date input", timeOut).should("be.visible"); + cy.get(".sweet-content-content #status button", timeOut).should("be.visible"); + cy.get(".sweet-content-content input#company_email", timeOut).should("be.visible"); + cy.get(".sweet-content-content button", timeOut).should("contain", "Contract Period"); + cy.get(".sweet-content-content button", timeOut).should("contain", "Employee Assessor"); + + // address input + cy.wait(3000) + cy.get(".sweet-content-content input#address", timeOut) + .parents('.form-group.row') + .find('i') + .click() + + cy.get(".sweet-content-content input#address", timeOut).should("have.length", 2); + + cy.get(".sweet-content-content input#address", timeOut) + .first() + .parents('.form-group.row') + .find('i') + .click() + + // social media + cy.wait(3000); + cy.get(".sweet-content-content button") + .contains("Social Media") + .click(); + cy.wait(1000); + cy.get(".sweet-modal").each(($el) => { + if ($el.find(".sweet-title > h2").text() == "ADD SOCIAL MEDIA") { + cy.wait(1000); + cy.get('#social-media-type').click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($elm) => { + if ($elm.css("display") != "none") { + cy.wrap($elm).find("li").should("contain", "Facebook"); + cy.wrap($elm).find("li").should("contain", "Twitter"); + cy.wrap($elm).find("li").should("contain", "Instagram"); + } + }); + $el.find('.sweet-action-close').click() + } + }); + + // input and save employee + cy.wait(1000); + cy.get(".sweet-content-content input#name").type(data.name); + cy.wait(1000); + cy.get(".sweet-content-content input#personal-identity").type( + data.personalId + ); + cy.wait(1000); + cy.get(".sweet-content-content input#email").type(data.email); + cy.wait(1000); + cy.get(".sweet-content-content input#address") + .first() + .type(data.address); + cy.wait(1000); + cy.get(".sweet-content-content input#phone").type(data.phone); + + cy.wait(1000); + cy.get(".sweet-content-content #birth-date input").click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button").contains("Last Year").click(); + + cy.wait(1000); + cy.get(".sweet-content-content input#birth-place").type(data.address); + + cy.wait(1000); + cy.get(".sweet-content-content #gender button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #marital-status button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #religion button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #employee-group button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content input#code").type(data.code); + cy.wait(1000); + cy.get(".sweet-content-content input#job-title").type(data.jobTitle); + + cy.wait(1000); + cy.get(".sweet-content-content #job-location button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #join-date input").click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button").contains("Today").click(); + + cy.wait(1000); + cy.get(".sweet-content-content #status button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content input#company_email").type(data.email); + + cy.wait(1000); + cy.get(".sweet-content-content button") + .contains("Contract Period") + .click(); + cy.wait(1000); + cy.get(".sweet-modal").each(($el) => { + if ($el.find(".sweet-title > h2").text() == "ADD CONTRACT") { + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content .form-group") + .eq(0) + .find("input") + .click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button") + .contains("Last Year") + .click(); + + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content .form-group") + .eq(1) + .find("input") + .click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button").contains("Today").click(); + + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content .form-group") + .eq(2) + .find("input") + .type(data.note); + + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content-content > .pull-right > button") + .last() + .click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content button") + .contains("Employee Assessor") + .click(); + cy.wait(1000); + cy.get(".sweet-modal").each(($el) => { + if ($el.find(".sweet-title > h2").text() == "ADD SCORER") { + cy.wait(1000); + cy.wrap($el).find(".sweet-content .list-group a").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #user-account button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-modal-overlay").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el) + .find(".sweet-content-content > .pull-right > button") + .click(); + } + }); + + cy.wait(3000); + + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "create success"); + + cy.wait(1500); + cy.url().should("contain", urlEmployee); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); + + // find name + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // detail name + cy.intercept("GET", getDetail).as("getDetailEmployee"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); + + it("test user no role - pagination", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); + + it("test user no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); + + it("test user no role - not show button add", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get(".input-group-prepend").should("not.exist"); + }); + + it("test user has role - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + }); + + it("test user has role - duplicate name", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input#name', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "Integrity constraint violation: 1062 Duplicate entry"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input#name', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS Employee - Read", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access read", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.intercept("GET", getList).as("getEmployee"); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list employee + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test have access read - pagination, (detail) button:create,edit,delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.intercept("GET", getList).as("getEmployee"); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // list pagination + cy.waitVisible(".pagination"); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailEmployee"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('[type="button"]').should("contain", "CREATE"); + cy.get('[type="button"]').should("contain", "EDIT"); + cy.get('[type="button"]').should("contain", "DELETE"); + }); + + it("test have access read - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.intercept("GET", getList).as("getEmployee"); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailEmployee"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // name column + cy.get('.block-content input[name="name"]').should("be.visible"); + }); + + it("test have access read - archive", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get(".css-checkbox").last().click() + cy.get('button').contains('ARCHIVE').click() + + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.get("table").contains("th", "Name").should("not.exist"); + }); + + it("test have access read - active ", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('a').contains('ADVANCE FILTER').click() + cy.get('.select-link').click() + cy.get(".sweet-modal-overlay").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el) + .find("a") + .contains('ARCHIVED') + .click(); + } + }); + + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get(".css-checkbox").last().click() + cy.get('button').contains('ACTIVATE').click() + + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('a').contains('ADVANCE FILTER').click() + cy.get('.select-link').click() + cy.get(".sweet-modal-overlay").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el) + .find("a") + .contains('ARCHIVED') + .click(); + } + }); + + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.get("table").contains("th", "Name").should("not.exist"); + }); +}); + +describe("HRIS Employee - Edit", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access edit", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.intercept("GET", getList).as("getEmployee"); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list employee + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test have access edit - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.intercept("GET", getList).as("getEmployee"); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailEmployee"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get("input#name", timeOut).should("have.value", name); + cy.get('[type="button"]').contains("EDIT").click(); + + cy.waitVisible(".sweet-title"); + cy.get(".sweet-title").should("contain", "EDIT DEPARTMENT"); + + cy.wait("@getDetailEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible(".sweet-content-content button").last().should("be.visible"); // button update + cy.waitVisible(".sweet-modal .sweet-action-close"); // button close + + cy.wait(2000); + cy.get('.sweet-content-content input[name="name"]') + .last() + .clear() + .type(name + " - edit"); + + cy.wait(1500); + cy.intercept("PATCH", getDetail).as("updateEmployee"); + cy.get(".sweet-content-content button").last().click(); + + cy.wait("@updateEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "update success"); + }); + + it("test have access edit - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // clear input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input#name', timeOut).clear(); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + + // fill same input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input#name', timeOut).type(name + " - edit"); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "Please edit with a different name"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input#name', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS Employee - Delete", () => { beforeEach(() => { - cy.hideXHR() - cy.login('admin', 'admin') - }) + cy.hideXHR(); + }); + + it("test have access delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmployee"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); + + // table list employee + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); + + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a") + .contains(name + " - edit") + .click(); + + cy.get("input#name", timeOut).should("have.value", name + " - edit"); + cy.get(".block-content").contains("DELETE").click(); + + cy.intercept("DELETE", getDetail).as("deleteDepartemen"); + + cy.waitVisible(".swal2-container"); + cy.get(".swal2-container button").contains("Confirm").click(); - it('index employee', () => { - cy.interceptToken() - cy.visit('/') - cy.waitToken() + cy.wait("@deleteDepartemen", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + cy.wait(1500); + cy.url().should("contain", url); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); - cy.intercept('GET', getList).as('getEmployee') - - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() - - cy.wait(5000) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) - - cy.waitVisible('table'); - cy.get('table th').should('contain', 'name') - cy.get('table th').should('contain', 'job title') - cy.get('table th').should('contain', 'department') - }) - - it('Create employee', () => { - createEmployee({ - name: name, - personalId: personalId, - email: email, - address: address, - phone: phone, - code: code, - jobTitle: jobTitle, - note: note - }) - }) - - it('Edit employee', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getEmployee') - - cy.visit(url) - - cy.waitToken() - cy.wait('@getEmployee', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(name) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) - - cy.get('table a', timeOut).contains(name).click() - - cy.intercept('GET', getDetail).as('getDetailEmployee') - - cy.get('.block-content table:nth-child(1) tbody > tr > td:nth-child(2)', timeOut) - .should('contain', name) - cy.wait(2000) - cy.get('.block-content').contains('EDIT').click() - - cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) - - cy.get('.sweet-title', timeOut).should('contain', 'EMPLOYEE INFORMATION') - - cy.get('.sweet-content-content input#name').last(timeOut).should('have.value', name) - cy.wait(2000) - cy.get('.sweet-content-content input#name').last().clear().type(name + ' - edit') - - cy.intercept('PATCH', getDetail).as('updateEmployee') - - cy.get('.sweet-modal-overlay').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('.sweet-content-content > .pull-right > button').click() - } - }) - - cy.wait('@updateEmployee', timeOut).its('response.statusCode').should('equal', 200) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') - cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) - - cy.get('.block-content table:nth-child(1) tbody > tr > td:nth-child(2)', timeOut) - .should('contain', name + ' - edit') - }) - - it('Delete employee', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getEmployee') - - cy.visit(url) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(name) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) - - cy.intercept('GET', getDetail).as('getDetailEmployee') - - cy.waitVisible('table'); - cy.get('table a').contains(name + ' - edit').click() - - cy.wait('@getDetailEmployee', timeOut).its('response.statusCode').should('equal', 200) - - cy.get('.block-content table:nth-child(1) tbody > tr > td:nth-child(2)', timeOut) - .should('contain', name) - cy.wait(2000) - cy.get('.block-content').contains('DELETE').click() - - cy.intercept('DELETE', getDetail).as('deleteEmployee') - - cy.waitVisible('.swal2-container') - cy.get('.swal2-container button').contains('Confirm').click() - cy.wait('@deleteEmployee', timeOut).its('response.statusCode').should('equal', 200) - - cy.wait(1500) - cy.url().should('contain', url) - }) -}) - \ No newline at end of file + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); +}); diff --git a/tests/e2e/specs/human-resource/employee/employmentContract.cy.js b/tests/e2e/specs/human-resource/employee/employmentContract.cy.js index 4730cbf5..e65e8043 100644 --- a/tests/e2e/specs/human-resource/employee/employmentContract.cy.js +++ b/tests/e2e/specs/human-resource/employee/employmentContract.cy.js @@ -1,129 +1,732 @@ -import { generateText, createEmploymentContract } from '../functions' +import { + generateText, + changeRole, + createUserNoRole, + createEmploymentContractApi, +} from "../functions"; + +const randomString = generateText(7); +const name = randomString; +const url = "/human-resource/employee-status"; +const api = Cypress.env("VUE_APP_API_ENDPOINT"); +const apiUrl = api + "/human-resource/employee/statuses"; +const getList = apiUrl + "**"; +const getDetail = apiUrl + "/*"; +const timeOut = { timeout: 300000 }; + +describe("HRIS Employeement Contract - Create", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access create", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYMENT CONTRACT").click(); + + cy.intercept("GET", getList).as("getEmploymentContract"); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + // button add and form input departemen + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + cy.get(".sweet-modal h2", timeOut).should("contain", "ADD DEPARTMENT"); + cy.get('.sweet-modal [for="name"]').should("contain", "NAME"); + cy.get('.sweet-modal input[id="name"]').should("be.visible"); + + // input and save departement + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.intercept("POST", getList).as("createEmploymentContract"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + cy.wait("@createEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 201); + + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "create success"); + + // find name + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // detail name + cy.intercept("GET", getDetail).as("getDetailEmploymentContract"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); + + it("create data if data table < 10", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('.pagination [class="page-item"]').then(($pagination) => { + if ($pagination.length <= 3) { + createEmploymentContractApi(); + } + }); + }); + + it("test user no role - list 10 of data", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th").should("have.length", 10); + }); + + it("test user no role - pagination", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); + + it("test user no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); + + it("test user no role - not show button add", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get(".input-group-prepend").should("not.exist"); + }); + + it("test user has role - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS Employeement Contract - Read", () => { + beforeEach(() => { + cy.hideXHR(); + }); -const { should } = require("chai") -const randomString = generateText(7) -const url = '/human-resource/employee-status' -const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/statuses' -const getList = apiUrl + '**' -const getDetail = apiUrl + '/*' -const timeOut = { timeout : 300000 } + it("test have access read", () => { + cy.login("admin", "admin"); -describe('HR - Employment Contract', () => { - beforeEach(() => { - cy.hideXHR() - cy.login('admin', 'admin') - }) + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); - it('index employment contract', () => { - cy.interceptToken() - cy.visit('/') - cy.waitToken() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYMENT CONTRACT").click(); - cy.waitVisible('li.nav-item'); - cy.get('li.nav-item a').contains('EMPLOYMENT CONTRACT').click() + cy.intercept("GET", getList).as("getEmploymentContract"); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.intercept('GET', getList).as('getEmploymentContract') + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); - cy.wait(5000) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + it("test have access read - pagination, (detail) button:create,edit,delete", () => { + cy.login("admin", "admin"); - cy.waitVisible('table'); - cy.get('table th').should('contain', 'Name') - }) + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); - it('Create employment contract', () => { - createEmploymentContract(randomString) - }) + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - it('Edit employment contract', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getEmploymentContract') + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.visit(url) + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYMENT CONTRACT").click(); - cy.waitToken() - cy.wait(2000) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.intercept("GET", getList).as("getEmploymentContract"); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + // list pagination + cy.waitVisible(".pagination"); - cy.intercept('GET', getDetail).as('getDetailEmploymentContract') + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.waitVisible('table'); - cy.get('table a').contains(randomString).click() + cy.waitVisible("table"); + cy.get("table td").should("contain", name); - cy.wait('@getDetailEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) - cy.get('input#name', timeOut).should('have.value', randomString) - cy.wait(2000) - cy.get('.block-content').contains('EDIT').click() + // see detail name + cy.intercept("GET", getDetail).as("getDetailEmploymentContract"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('[type="button"]').should("contain", "CREATE"); + cy.get('[type="button"]').should("contain", "EDIT"); + cy.get('[type="button"]').should("contain", "DELETE"); + }); + + it("test have access read - list 10 of data", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th").should("have.length", 10); + }); + + it("test have access read - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYMENT CONTRACT").click(); + + cy.intercept("GET", getList).as("getEmploymentContract"); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailEmploymentContract"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // name column + cy.get('.block-content input[name="name"]').should("be.visible"); + }); + + it("test have access read - pagination", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); // button create + cy.waitVisible("#search-text"); // search + cy.waitVisible(".pagination"); // pagination + }); +}); + +describe("HRIS Employeement Contract - Edit", () => { + beforeEach(() => { + cy.hideXHR(); + }); - cy.waitVisible('.sweet-title'); - cy.get('.sweet-title').should('contain', 'EDIT EMPLOYMENT CONTRACT') - - cy.wait('@getDetailEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) - cy.wait(2000) - cy.get('.sweet-content-content input#name') - .last() - .clear() - .type(randomString + ' - edit') + it("test have access edit", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.intercept('PATCH', getDetail).as('updateEmploymentContract') + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); - cy.wait(1500) - cy.get('.sweet-content-content > .pull-right > button').last().click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYMENT CONTRACT").click(); - cy.wait('@updateEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') + cy.intercept("GET", getList).as("getEmploymentContract"); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.wait(1500) - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - }) + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); - it('Delete employment contract', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getEmploymentContract') + it("test have access edit - detail, name column", () => { + cy.login("admin", "admin"); - cy.visit(url) + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); - cy.waitToken() - cy.wait(2000) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.intercept('GET', getDetail).as('getDetailEmploymentContract') + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); - cy.wait(2000) - cy.waitVisible('table'); - cy.get('table a').contains(randomString + ' - edit').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYMENT CONTRACT").click(); - cy.wait('@getDetailEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - cy.wait(2000) - cy.get('.block-content').contains('DELETE').click() + cy.intercept("GET", getList).as("getEmploymentContract"); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.intercept('DELETE', getDetail).as('deleteEmploymentContract') + cy.waitVisible("table"); + cy.get("table td").should("contain", name); - cy.waitVisible('.swal2-container') - cy.get('.swal2-container button').contains('Confirm').click() + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.wait('@deleteEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) - - cy.wait(1500) - cy.url().should('contain', url) - }) -}) - \ No newline at end of file + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailEmploymentContract"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get("input#name", timeOut).should("have.value", randomString); + cy.get('[type="button"]').contains("EDIT").click(); + + cy.waitVisible(".sweet-title"); + cy.get(".sweet-title").should("contain", "EDIT DEPARTMENT"); + + cy.wait("@getDetailEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible(".sweet-content-content button").last().should("be.visible"); // button update + cy.waitVisible(".sweet-modal .sweet-action-close"); // button close + + cy.wait(2000); + cy.get('.sweet-content-content input[name="name"]') + .last() + .clear() + .type(randomString + " - edit"); + + cy.wait(1500); + cy.intercept("PATCH", getDetail).as("updateDepartement"); + cy.get(".sweet-content-content button").last().click(); + + cy.wait("@updateDepartement", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "update success"); + }); + + it("test have access edit - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // clear input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).clear(); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + + // fill same input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "Please edit with a different name"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS Employeement Contract - Delete", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract").its("response.statusCode").should("equal", 200); + + // table list departement + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + cy.waitVisible("#search-text"); + cy.get("#search-text").type(randomString); + cy.wait("@getEmploymentContract").its("response.statusCode").should("equal", 200); + + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a") + .contains(randomString + " - edit") + .click(); + + cy.get("input#name", timeOut).should( + "have.value", + randomString + " - edit" + ); + cy.get(".block-content").contains("DELETE").click(); + + cy.intercept("DELETE", getDetail).as("deleteDepartemen"); + + cy.waitVisible(".swal2-container"); + cy.get(".swal2-container button").contains("Confirm").click(); + + cy.wait("@deleteDepartemen", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.wait(1500); + cy.url().should("contain", url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract").its("response.statusCode").should("equal", 200); + + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test delete no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + changeRole(this.userId, this.superAdminRoleId); + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getEmploymentContract"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmploymentContract", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); +}); diff --git a/tests/e2e/specs/human-resource/employee/jobLocation.cy.js b/tests/e2e/specs/human-resource/employee/jobLocation.cy.js index 45e2c625..e187293b 100644 --- a/tests/e2e/specs/human-resource/employee/jobLocation.cy.js +++ b/tests/e2e/specs/human-resource/employee/jobLocation.cy.js @@ -1,125 +1,736 @@ -import { generateText, createJobLocation } from '../functions' +import { + generateText, + changeRole, + createUserNoRole, + createJobLocationApi, +} from "../functions"; -const { should } = require("chai") -const randomString = generateText(7) -const url = '/human-resource/job-location' -const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') + '/human-resource/employee/job-locations' -const getList = apiUrl + '**' -const getDetail = apiUrl + '/*' -const timeOut = { timeout : 300000 } +const randomString = generateText(7); +const name = randomString; +const url = "/human-resource/job-location"; +const apiUrl = + Cypress.env("VUE_APP_API_ENDPOINT") + + "/human-resource/employee/job-locations"; +const getList = apiUrl + "**"; +const getDetail = apiUrl + "/*"; +const timeOut = { timeout: 300000 }; -describe('HR - Job Location', () => { +describe("HRIS - Job Location - Create", () => { beforeEach(() => { - cy.hideXHR() - cy.login('admin', 'admin') - }) + cy.hideXHR(); + }); - it('index job location', () => { - cy.interceptToken() - cy.visit('/') - cy.waitToken() + it("test have access create", () => { + cy.login("admin", "admin"); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div:nth-child(1) > div > a').contains('EMPLOYEE').click() - - cy.waitVisible('li.nav-item'); - cy.get('li.nav-item a').contains('JOB LOCATION').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.intercept('GET', getList).as('getJobLocation') + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); - cy.wait(5000) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("JOB LOCATION").click(); - cy.waitVisible('table'); - cy.get('table th').should('contain', 'name') - cy.get('table th').should('contain', 'area value') - cy.get('table th').should('contain', 'kpi multiplier') - }) + cy.intercept("GET", getList).as("getJobLocation"); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); - it('Create job location', () => { - createJobLocation(randomString) - }) + // table list job location + cy.waitVisible("table"); + cy.get("table").contains("th", "name").should("be.visible"); + cy.get("table").contains("th", "area value").should("be.visible"); + cy.get("table").contains("th", "kpi multiplier").should("be.visible"); - it('Edit job location', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getJobLocation') + // button add and form input job location + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + cy.get(".sweet-modal h2", timeOut).should("contain", "ADD JOB LOCATION"); + cy.get(".sweet-content-content input").eq(0).type(name); + cy.get(".sweet-content-content input").eq(1).type("123"); + cy.get(".sweet-content-content input").eq(2).type("123"); - cy.visit(url) + // input and save job location + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.intercept("POST", getList).as("createJobLocation"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + cy.wait("@createJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 201); - cy.waitToken() - cy.wait(2000) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "create success"); - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + // find name + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); - cy.intercept('GET', getDetail).as('getDetailJobLocation') - cy.wait(2000) - cy.waitVisible('table'); - cy.get('table a').contains(randomString).click() + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); - cy.wait('@getDetailJobLocation', timeOut).its('response.statusCode').should('equal', 200) - cy.get('input#name', timeOut).should('have.value', randomString) - cy.wait(2000) - cy.get('.block-content').contains('EDIT').click() + cy.waitVisible("table"); + cy.get("table td").should("contain", name); - cy.waitVisible('.sweet-title'); - cy.get('.sweet-title').should('contain', 'EDIT JOB LOCATION') + // detail name + cy.intercept("GET", getDetail).as("getDetailJobLocation"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); - cy.wait(2000) - cy.get('.sweet-content-content input#name') + it("create data if data table < 10", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('.pagination [class="page-item"]').then(($pagination) => { + if ($pagination.length <= 3) { + createJobLocationApi(); + } + }); + }); + + it("test user no role - list 10 of data", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th").should("have.length", 10); + }); + + it("test user no role - pagination", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + }); + + it("test user no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); + + it("test user no role - not show button add", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get(".input-group-prepend").should("not.exist"); + }); + + it("test user has role - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS - Job Location - Read", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access read", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("JOB LOCATION").click(); + + cy.intercept("GET", getList).as("getJobLocation"); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list job location + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test have access read - pagination, (detail) button:create,edit,delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("JOB LOCATION").click(); + + cy.intercept("GET", getList).as("getJobLocation"); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // list pagination + cy.waitVisible(".pagination"); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailJobLocation"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get('[type="button"]').should("contain", "CREATE"); + cy.get('[type="button"]').should("contain", "EDIT"); + cy.get('[type="button"]').should("contain", "DELETE"); + }); + + it("test have access read - list 10 of data", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th").should("have.length", 10); + }); + + it("test have access read - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("JOB LOCATION").click(); + + cy.intercept("GET", getList).as("getJobLocation"); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailJobLocation"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // name column + cy.get('.block-content input[name="name"]').should("be.visible"); + }); + + it("test have access read - pagination", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get('.pagination [class="page-item"]').last().click(); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); // button create + cy.waitVisible("#search-text"); // search + cy.waitVisible(".pagination"); // pagination + }); +}); + +describe("HRIS - Job Location - Edit", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access edit", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("JOB LOCATION").click(); + + cy.intercept("GET", getList).as("getJobLocation"); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + // table list job location + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test have access edit - detail, name column", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.visit("/"); + cy.waitToken(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("EMPLOYEE").click(); + + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("JOB LOCATION").click(); + + cy.intercept("GET", getList).as("getJobLocation"); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // find name + cy.wait(3000); + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + + // see detail name + cy.intercept("GET", getDetail).as("getDetailJobLocation"); + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a").contains(name).click(); + cy.wait("@getDetailJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.get("input#name", timeOut).should("have.value", randomString); + cy.get('[type="button"]').contains("EDIT").click(); + + cy.waitVisible(".sweet-title"); + cy.get(".sweet-title").should("contain", "EDIT JOB LOCATION"); + + cy.wait("@getDetailJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible(".sweet-content-content button").last().should("be.visible"); // button update + cy.waitVisible(".sweet-modal .sweet-action-close"); // button close + + cy.wait(2000); + cy.get('.sweet-content-content input[name="name"]') .last() .clear() - .type(randomString + ' - edit') - - cy.intercept('PATCH', getDetail).as('updateJobLocation') - cy.get('.sweet-content-content > .pull-right > button').last().click() - - cy.wait('@updateJobLocation', timeOut).its('response.statusCode').should('equal', 200) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'update success') - - cy.wait(1500) - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - }) - - it('Delete job location', () => { - cy.interceptToken() - cy.intercept('GET', getList).as('getJobLocation') - - cy.visit(url) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(randomString) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) - - cy.intercept('GET', getDetail).as('getDetailJobLocation') - cy.wait(2000) - cy.waitVisible('table'); - cy.get('table a').contains(randomString + ' - edit').click() - - cy.wait('@getDetailJobLocation', timeOut).its('response.statusCode').should('equal', 200) - cy.get('input#name', timeOut).should('have.value', randomString + ' - edit') - cy.get('.block-content').contains('DELETE').click() - - cy.intercept('DELETE', getDetail).as('deleteJobLocation') - cy.waitVisible('.swal2-container') - cy.get('.swal2-container button').contains('Confirm').click() - - cy.wait('@deleteJobLocation', timeOut).its('response.statusCode').should('equal', 204) - - cy.wait(1500) - cy.url().should('contain', url) - }) -}) - \ No newline at end of file + .type(randomString + " - edit"); + + cy.wait(1500); + cy.intercept("PATCH", getDetail).as("updateJobLocation"); + cy.get(".sweet-content-content button").last().click(); + + cy.wait("@updateJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "update success"); + }); + + it("test have access edit - empty input and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // clear input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).clear(); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name field is required"); + + // fill same input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(name); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "Please edit with a different name"); + }); + + it("test user has role - input more than 255 and save", () => { + // login + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.waitVisible(".input-group-prepend"); + cy.get(".input-group-prepend").click(); + + // fill input and save + cy.get(".sweet-modal").contains("button", "SAVE").should("be.visible"); + cy.get('.sweet-modal input[id="name"]', timeOut).type(generateText(256)); + cy.get(".sweet-modal button").contains("SAVE").click(); + + // Error save + cy.get("div.vue-notification", timeOut) + .should("have.class", "danger") + .and("contain", "The name may not be greater than 255 characters"); + }); +}); + +describe("HRIS - Job Location - Delete", () => { + beforeEach(() => { + cy.hideXHR(); + }); + + it("test have access delete", () => { + cy.login("admin", "admin"); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation").its("response.statusCode").should("equal", 200); + + // table list job location + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + + cy.waitVisible("#search-text"); + cy.get("#search-text").type(randomString); + cy.wait("@getJobLocation").its("response.statusCode").should("equal", 200); + + cy.wait(2000); + cy.waitVisible("table"); + cy.get("table a") + .contains(randomString + " - edit") + .click(); + + cy.get("input#name", timeOut).should( + "have.value", + randomString + " - edit" + ); + cy.get(".block-content").contains("DELETE").click(); + + cy.intercept("DELETE", getDetail).as("deleteDepartemen"); + + cy.waitVisible(".swal2-container"); + cy.get(".swal2-container button").contains("Confirm").click(); + + cy.wait("@deleteDepartemen", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.wait(1500); + cy.url().should("contain", url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation").its("response.statusCode").should("equal", 200); + + cy.waitVisible("table"); + cy.get("table").contains("th", "Name").should("be.visible"); + }); + + it("test delete no role - see number", () => { + // login + cy.then(function () { + if (this.userName) { + cy.login(this.userName, this.userName + this.userName); + } else { + createUserNoRole(); + } + changeRole(this.userId, this.superAdminRoleId); + }); + + cy.interceptToken(); + cy.intercept("GET", getList).as("getJobLocation"); + + cy.visit(url); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getJobLocation", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("tbody th") + .first() + .invoke("text") + .should("match", /^[0-9]*$/); + }); +}); diff --git a/tests/e2e/specs/human-resource/functions.js b/tests/e2e/specs/human-resource/functions.js index d3ae3f5f..80f93d78 100644 --- a/tests/e2e/specs/human-resource/functions.js +++ b/tests/e2e/specs/human-resource/functions.js @@ -1,465 +1,549 @@ -const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') -const timeOut = { timeout : 500000 } +import { get } from "lodash"; + +const apiUrl = Cypress.env("VUE_APP_API_ENDPOINT"); +const timeOut = { timeout: 500000 }; export function generateText(length) { - var result = '' - var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' - var charactersLength = characters.length - for ( var i = 0; i < length; i++ ) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)) + var result = ""; + var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); } - return result + return result; } export function generateNumber(length) { - var result = '' - var characters = '0123456789' - var charactersLength = characters.length - for ( var i = 0; i < length; i++ ) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)) + var result = ""; + var characters = "0123456789"; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); } - return parseInt(result) + return parseInt(result); } -export function createDepartement(name) { - const apiDept = apiUrl + '/human-resource/employee/groups**' - const urlDept = '/human-resource/employee-group' - - cy.interceptToken() - cy.intercept('GET', apiDept).as('getDepartement') - - cy.visit(urlDept) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(name) - cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) - - let exists = false - cy.waitVisible('table'); - cy.get('table tr').each(($tr) => { - if ($tr.find('td').length) { - exists = true - } - }).then(() => { - if (!exists) { - cy.waitVisible('.input-group-prepend'); - cy.get('.input-group-prepend').click() - - cy.get('.sweet-title', timeOut).should('contain', 'ADD DEPARTMENT') - cy.get('.sweet-content-content input').eq(0).type(name) - - cy.intercept('POST', apiDept).as('createDepartement') - - cy.wait(1500) - cy.get('.sweet-content-content > .pull-right > button').click() - - cy.wait('@createDepartement', timeOut).its('response.statusCode').should('equal', 201) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') - - cy.wait(1500) - cy.url().should('contain', urlDept) - - cy.wait('@getDepartement', timeOut).its('response.statusCode').should('equal', 200) - - } - }) - - cy.waitVisible('table'); - cy.get('table td').should('contain', name) +export function getCookieValue(name) { + let document = cy.state("document"); + return document.cookie + .split("; ") + .find((row) => row.startsWith(name + "=")) + ?.split("=")[1]; } -export function createJobLocation(name) { - const apiJobLoc = apiUrl + '/human-resource/employee/job-locations**' - const urlJobLoc = '/human-resource/job-location' - - cy.interceptToken() - cy.intercept('GET', apiJobLoc).as('getJobLocation') - - cy.visit(urlJobLoc) +export function apiRequest( + method = "GET", + path = "", + params = {}, + alias = "request" +) { + cy.request({ + method: method, + url: apiUrl + "/" + path, + body: params, + headers: { + Accept: "application/json", + Authorization: "Bearer " + getCookieValue("TAT"), + Tenant: "dev", + }, + }).then((response) => { + cy.wrap(response).as(alias); + }); +} - cy.waitToken() - cy.wait(2000) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) +export function createUserNoRole() { + let name = generateText(7); + + let params = { + first_name: name, + last_name: name, + username: name, + email: name + "@mail.com", + password: name + name, + }; + + apiRequest("POST", "register", params, "createUser"); + cy.get("@createUser").then((req) => { + expect(req.status).to.eq(201); + }); + + apiRequest("GET", "project/projects", {}, "get_code"); + cy.get("@get_code").then((req) => { + expect(req.status).to.eq(200); + }); + + cy.login(params.username, params.password); + + cy.get("@get_code").then((getCode) => { + let code = getCode.body.data[0].invitation_code; + apiRequest( + "POST", + "project/request-join", + { invitation_code: code }, + "requestJoin" + ); + }); + + cy.get("@requestJoin", timeOut).then((res) => { + apiRequest( + "PATCH", + "project/request-join/" + res.body.data.id, + {}, + "approveJoin" + ); + }); + + cy.get("@approveJoin", timeOut).then((res) => { + cy.wrap(res.body.data.user_id).as("userId"); + cy.wrap(res.body.data.user_name).as("userName"); + + apiRequest("GET", "master/roles/", {}, "getAllRoles"); + }); + + cy.get("@getAllRoles", timeOut).then((res) => { + res.body.data.forEach((roles) => { + if (roles.name == "super admin") { + cy.wrap(roles.id).as("superAdminRoleId"); + } else if (roles.name == "no role") { + cy.wrap(roles.id).as("noRoleId"); + } + }); + }); - cy.waitVisible('#search-text'); - cy.get('#search-text').type(name) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) + cy.get("@noRoleId").then((id) => { + if (!id) { + apiRequest("POST", "master/roles", { name: "no role" }, "createNoRole"); - let exists = false - cy.waitVisible('table'); - cy.get('table tr').each(($tr) => { - if ($tr.find('td').length) { - exists = true + cy.get("@createNoRole", timeOut).then((res) => { + cy.wrap(res.body.data.id).as("noRoleId"); + }); } - }).then(() => { - if (! exists) { - cy.get('.input-group-prepend').click() - - cy.get('.sweet-title', timeOut).should('contain', 'ADD JOB LOCATION') - cy.wait(2000) - cy.get('.sweet-content-content input').eq(0).type(name) - cy.get('.sweet-content-content input').eq(1).type('123') - cy.get('.sweet-content-content input').eq(2).type('123') - - cy.intercept('POST', apiJobLoc).as('createJobLocation') - - cy.get('.sweet-content-content > .pull-right > button').click() - - cy.wait('@createJobLocation', timeOut).its('response.statusCode').should('equal', 201) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') - - cy.wait(1500) - cy.url().should('contain', urlJobLoc) - cy.wait('@getJobLocation', timeOut).its('response.statusCode').should('equal', 200) - } - }) + }); - cy.waitVisible('table'); - cy.get('table td').should('contain', name) + cy.then(function () { + changeRole(this.userId, this.noRoleId) + }); } -export function createEmploymentContract(name) { - const apiContract = apiUrl + '/human-resource/employee/statuses**' - const urlContract = '/human-resource/employee-status' - - cy.interceptToken() - cy.intercept('GET', apiContract).as('getEmploymentContract') - - cy.visit(urlContract) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) +export function changeRole(userId, roleId) { + cy.then(function () { + apiRequest( + "PATCH", + "master/user-roles/" + userId, + { role_id: roleId }, + "setNoRole" + ); + }); +} - cy.waitVisible('#search-text'); - cy.get('#search-text').type(name) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) +export function createDepartementApi(name = null, z = 10) { + const apiDept = "human-resource/employee/groups"; - let exists = false - cy.waitVisible('table'); - cy.get('table tr').each(($tr) => { - if ($tr.find('td').length) { - exists = true + for (let i = 0; i < z; i++) { + if (name == null) { + name = generateText(4) } - }).then(() => { - if (! exists) { - cy.get('.input-group-prepend').click() - cy.intercept('POST', apiContract).as('createEmploymentContract') + apiRequest("POST", apiDept, { name: name }, "createDepartemen"); - cy.get('.sweet-title', timeOut).should('contain', 'ADD EMPLOYMENT CONTRACT') - cy.wait(2000) - cy.get('.sweet-content-content input').eq(0).type(name) - cy.wait(1000) - cy.get('.sweet-content-content > .pull-right > button').click() + cy.get("@createDepartemen", timeOut).then((res) => { + cy.wrap(res.body.data.id).as("departemen" + i); + }); + } +} - cy.wait('@createEmploymentContract', timeOut).its('response.statusCode').should('equal', 201) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') +export function createJobLocationApi(name = null, z = 10) { + const apiDept = "human-resource/employee/statuses"; - cy.wait(1500) - cy.url().should('contain', urlContract) - cy.wait('@getEmploymentContract', timeOut).its('response.statusCode').should('equal', 200) + for (let i = 0; i < z; i++) { + if (name == null) { + name = generateText(4) } - }) - - cy.waitVisible('table'); - cy.get('table td').should('contain', name) -} -export function createEmployee(data) { - const apiEmployee = apiUrl + '/human-resource/employee/employees**' - const urlEmployee = '/human-resource/employee' - - cy.interceptToken() - cy.intercept('GET', apiEmployee).as('getEmployee') + let payload = { + name: name, + multiplier_kpi: 123, + base_salary: 123 + } - cy.visit(urlEmployee) + apiRequest("POST", apiDept, payload, "createEmploymentContract"); - cy.waitToken() - cy.wait(2000) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) + cy.get("@createEmploymentContract", timeOut).then((res) => { + cy.wrap(res.body.data.id).as("employee_contract_" + i); + }); + } +} - cy.waitVisible('#search-text'); - cy.get('#search-text').type(data.name) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) +export function createEmploymentContractApi(name = null, z = 10) { + const apiDept = "human-resource/employee/groups"; - let exists = false - cy.waitVisible('table'); - cy.get('table tr').each(($tr) => { - if ($tr.find('td').length) { - exists = true + for (let i = 0; i < z; i++) { + if (name == null) { + name = generateText(4) } - }).then(() => { - if (! exists) { - cy.get('.input-group-prepend').click() - - cy.get('.sweet-title', timeOut).should('contain', 'EMPLOYEE INFORMATION') - cy.wait(1000) - cy.get('.sweet-content-content input#name').type(data.name) - cy.wait(1000) - cy.get('.sweet-content-content input#personal-identity').type(data.personalId) - cy.wait(1000) - cy.get('.sweet-content-content input#email').type(data.email) - cy.wait(1000) - cy.get('.sweet-content-content input#address').first().type(data.address) - cy.wait(1000) - cy.get('.sweet-content-content input#phone').type(data.phone) - - cy.wait(1000) - cy.get('.sweet-content-content #birth-date input').click() - cy.wait(1000) - cy.get('.mx-datepicker-sidebar button').contains('Last Year').click() - - cy.wait(1000) - cy.get('.sweet-content-content input#birth-place').type(data.address) - - cy.wait(1000) - cy.get('.sweet-content-content #gender button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() - } - }) - - cy.wait(1000) - cy.get('.sweet-content-content #marital-status button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() - } - }) - cy.wait(1000) - cy.get('.sweet-content-content #religion button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() - } - }) + apiRequest("POST", apiDept, { name: name }, "createDepartemen"); - cy.wait(1000) - cy.get('.sweet-content-content #employee-group button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() - } - }) + cy.get("@createDepartemen", timeOut).then((res) => { + cy.wrap(res.body.data.id).as("departemen" + i); + }); + } +} - cy.wait(1000) - cy.get('.sweet-content-content input#code').type(data.code) - cy.wait(1000) - cy.get('.sweet-content-content input#job-title').type(data.jobTitle) +export function createEmployee(data) { + const apiEmployee = apiUrl + "/human-resource/employee/employees**"; + const urlEmployee = "/human-resource/employee"; - cy.wait(1000) - cy.get('.sweet-content-content #job-location button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() - } - }) + cy.interceptToken(); + cy.intercept("GET", apiEmployee).as("getEmployee"); - cy.wait(1000) - cy.get('.sweet-content-content #join-date input').click() - cy.wait(1000) - cy.get('.mx-datepicker-sidebar button').contains('Today').click() + cy.visit(urlEmployee); - cy.wait(1000) - cy.get('.sweet-content-content #status button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() - } - }) + cy.waitToken(); + cy.wait(2000); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); - cy.wait(1000) - cy.get('.sweet-content-content input#company_email').type(data.email) - - cy.wait(1000) - cy.get('.sweet-content-content button').contains('Contract Period').click() - cy.wait(1000) - cy.get('.sweet-modal').each(($el) => { - if ($el.find('.sweet-title > h2').text() == 'ADD CONTRACT') { - cy.wait(1000) - cy.wrap($el).find('.sweet-content .form-group').eq(0).find('input').click() - cy.wait(1000) - cy.get('.mx-datepicker-sidebar button').contains('Last Year').click() - - cy.wait(1000) - cy.wrap($el).find('.sweet-content .form-group').eq(1).find('input').click() - cy.wait(1000) - cy.get('.mx-datepicker-sidebar button').contains('Today').click() - - cy.wait(1000) - cy.wrap($el).find('.sweet-content .form-group').eq(2).find('input').type(data.note) - - cy.wait(1000) - cy.wrap($el).find('.sweet-content-content > .pull-right > button').last().click() - } - }) - - cy.wait(1000) - cy.get('.sweet-content-content button').contains('Employee Assessor').click() - cy.wait(1000) - cy.get('.sweet-modal').each(($el) => { - if ($el.find('.sweet-title > h2').text() == 'ADD SCORER') { - cy.wait(1000) - cy.wrap($el).find('.sweet-content .list-group a').first().click() - } - }) + cy.waitVisible("#search-text"); + cy.get("#search-text").type(data.name); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); - cy.wait(1000) - cy.get('.sweet-content-content #user-account button').click() - cy.get('.v-dropdown-container.v-dropdown-no-border').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('li').first().click() + let exists = false; + cy.waitVisible("table"); + cy.get("table tr") + .each(($tr) => { + if ($tr.find("td").length) { + exists = true; } }) - - cy.wait(1000) - cy.get('.sweet-modal-overlay').each(($el) => { - if ($el.css('display') != 'none') { - cy.wrap($el).find('.sweet-content-content > .pull-right > button').click() + .then(() => { + if (!exists) { + cy.get(".input-group-prepend").click(); + + cy.get(".sweet-title", timeOut).should( + "contain", + "EMPLOYEE INFORMATION" + ); + cy.wait(1000); + cy.get(".sweet-content-content input#name").type(data.name); + cy.wait(1000); + cy.get(".sweet-content-content input#personal-identity").type( + data.personalId + ); + cy.wait(1000); + cy.get(".sweet-content-content input#email").type(data.email); + cy.wait(1000); + cy.get(".sweet-content-content input#address") + .first() + .type(data.address); + cy.wait(1000); + cy.get(".sweet-content-content input#phone").type(data.phone); + + cy.wait(1000); + cy.get(".sweet-content-content #birth-date input").click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button").contains("Last Year").click(); + + cy.wait(1000); + cy.get(".sweet-content-content input#birth-place").type(data.address); + + cy.wait(1000); + cy.get(".sweet-content-content #gender button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #marital-status button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #religion button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #employee-group button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content input#code").type(data.code); + cy.wait(1000); + cy.get(".sweet-content-content input#job-title").type(data.jobTitle); + + cy.wait(1000); + cy.get(".sweet-content-content #job-location button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #join-date input").click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button").contains("Today").click(); + + cy.wait(1000); + cy.get(".sweet-content-content #status button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content input#company_email").type(data.email); + + cy.wait(1000); + cy.get(".sweet-content-content button") + .contains("Contract Period") + .click(); + cy.wait(1000); + cy.get(".sweet-modal").each(($el) => { + if ($el.find(".sweet-title > h2").text() == "ADD CONTRACT") { + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content .form-group") + .eq(0) + .find("input") + .click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button") + .contains("Last Year") + .click(); + + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content .form-group") + .eq(1) + .find("input") + .click(); + cy.wait(1000); + cy.get(".mx-datepicker-sidebar button").contains("Today").click(); + + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content .form-group") + .eq(2) + .find("input") + .type(data.note); + + cy.wait(1000); + cy.wrap($el) + .find(".sweet-content-content > .pull-right > button") + .last() + .click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content button") + .contains("Employee Assessor") + .click(); + cy.wait(1000); + cy.get(".sweet-modal").each(($el) => { + if ($el.find(".sweet-title > h2").text() == "ADD SCORER") { + cy.wait(1000); + cy.wrap($el).find(".sweet-content .list-group a").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-content-content #user-account button").click(); + cy.get(".v-dropdown-container.v-dropdown-no-border").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el).find("li").first().click(); + } + }); + + cy.wait(1000); + cy.get(".sweet-modal-overlay").each(($el) => { + if ($el.css("display") != "none") { + cy.wrap($el) + .find(".sweet-content-content > .pull-right > button") + .click(); + } + }); + + cy.wait(3000); + + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "create success"); + + cy.wait(1500); + cy.url().should("contain", urlEmployee); + cy.wait("@getEmployee").its("response.statusCode").should("equal", 200); } - }) - - cy.wait(3000) + }); - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'create success') - - cy.wait(1500) - cy.url().should('contain', urlEmployee) - cy.wait('@getEmployee').its('response.statusCode').should('equal', 200) - } - }) - - cy.waitVisible('table'); - cy.get('table td').should('contain', data.name) + cy.waitVisible("table"); + cy.get("table td").should("contain", data.name); } export function createKpiTemplate(name, group = false, indicator = false) { - const apiTemplate = apiUrl + '/human-resource/kpi/template**' - const urlTemplate = '/human-resource/kpi-template' - - cy.interceptToken() - cy.intercept('GET', apiTemplate).as('getTemplate') - - cy.visit(urlTemplate) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').type(name) - cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) - - let exists = false - cy.waitVisible('table'); - cy.get('table tr').each(($tr) => { - if ($tr.find('td').length) { - exists = true - } - }).then(() => { - if (!exists) { - cy.get('.nav-item > a').should('contain', 'ADD') - cy.get('.nav-item > a').contains('ADD').click() - - cy.intercept('POST', apiTemplate).as('createKpiTemplate') - - cy.waitVisible('#create') - cy.get('#create input#name').type(name) - cy.get('#create [type=submit]').click() - - cy.wait('@createKpiTemplate', timeOut).its('response.statusCode').should('equal', 201) - cy.get('div.vue-notification', timeOut).should('have.class', 'success').and('contain', 'Create success') - cy.wait('@getTemplate', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('table'); - cy.get('table td').should('contain', name) - if (group && indicator) { - editKpiTemplate(name, group, indicator) + const apiTemplate = apiUrl + "/human-resource/kpi/template**"; + const urlTemplate = "/human-resource/kpi-template"; + + cy.interceptToken(); + cy.intercept("GET", apiTemplate).as("getTemplate"); + + cy.visit(urlTemplate); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getTemplate", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("#search-text"); + cy.get("#search-text").type(name); + cy.wait("@getTemplate", timeOut) + .its("response.statusCode") + .should("equal", 200); + + let exists = false; + cy.waitVisible("table"); + cy.get("table tr") + .each(($tr) => { + if ($tr.find("td").length) { + exists = true; } - } else { - cy.waitVisible('table'); - cy.get('table td').should('contain', name) - } - }) + }) + .then(() => { + if (!exists) { + cy.get(".nav-item > a").should("contain", "ADD"); + cy.get(".nav-item > a").contains("ADD").click(); + + cy.intercept("POST", apiTemplate).as("createKpiTemplate"); + + cy.waitVisible("#create"); + cy.get("#create input#name").type(name); + cy.get("#create [type=submit]").click(); + + cy.wait("@createKpiTemplate", timeOut) + .its("response.statusCode") + .should("equal", 201); + cy.get("div.vue-notification", timeOut) + .should("have.class", "success") + .and("contain", "Create success"); + cy.wait("@getTemplate", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + if (group && indicator) { + editKpiTemplate(name, group, indicator); + } + } else { + cy.waitVisible("table"); + cy.get("table td").should("contain", name); + } + }); } export function editKpiTemplate(name, group, indicator) { - const urlTemplate = '/human-resource/kpi-template' - const apiTemplate = apiUrl + '/human-resource/kpi/template' - const getList = apiTemplate + 's**' - const getDetail = apiTemplate + 's/*' - - cy.interceptToken() - cy.intercept('GET', getList).as('getKpiTemplate') - - cy.visit(urlTemplate) - - cy.waitToken() - cy.wait(2000) - cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) - - cy.waitVisible('#search-text'); - cy.get('#search-text').clear().type(name) - cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) - - cy.intercept('GET', getDetail).as('getDetailKpiTemplate') - - cy.waitVisible('table'); - cy.get('table td').contains(name).click() - - cy.log('Create group') - - cy.wait('@getDetailKpiTemplate', timeOut).its('response.statusCode').should('equal', 200) - cy.waitVisible('table'); - cy.get('table td').should('contain', 'NO') - cy.get('table td').should('contain', 'KEY PERFORMANCE INDICATOR') - cy.get('table td').should('contain', 'WEIGHT') - cy.get('table td button').should('contain', 'GROUP') - cy.wait(1500) - cy.get('table td button').contains('GROUP').click() - - cy.intercept('POST', apiTemplate + '-groups').as('createKpiTemplateGroups') - - cy.waitVisible('#group') - cy.get('#group .block-header').should('contain', 'KPI TEMPLATE GROUP') - cy.get('#group input').type(group) - cy.wait(2000) - cy.get('#group [type=submit]').click() - - cy.wait('@createKpiTemplateGroups', timeOut).its('response.statusCode').should('equal', 201) - - cy.get('#group .block-content tr td', timeOut).should('contain', group) - cy.wait(2000) - cy.get('#group .modal-footer [type=button]').click() - - cy.wait(2000) - cy.log('create indicator') - - cy.wait(1500) - cy.get('table td button').contains('INDICATOR').click() - - cy.intercept('POST', apiTemplate + '-indicators').as('createKpiTemplateIndicators') - - cy.waitVisible('#indicator') - cy.get('#indicator .block-header').should('contain', 'KPI TEMPLATE INDICATOR') - cy.get('#indicator input#name').type(indicator) - cy.wait(500) - cy.get('#indicator input#weight').type(100) - cy.wait(500) - cy.get('#indicator input#target').type(80) - cy.wait(500) - cy.get('#indicator [type=submit]').click() - - cy.wait('@createKpiTemplateIndicators', timeOut).its('response.statusCode').should('equal', 201) - - cy.get('#indicator .block-content tr td', timeOut).should('contain', indicator) - cy.wait(2000) - cy.get('#indicator .modal-footer [type=button]').click() -} \ No newline at end of file + const urlTemplate = "/human-resource/kpi-template"; + const apiTemplate = apiUrl + "/human-resource/kpi/template"; + const getList = apiTemplate + "s**"; + const getDetail = apiTemplate + "s/*"; + + cy.interceptToken(); + cy.intercept("GET", getList).as("getKpiTemplate"); + + cy.visit(urlTemplate); + + cy.waitToken(); + cy.wait(2000); + cy.wait("@getKpiTemplate", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.waitVisible("#search-text"); + cy.get("#search-text").clear().type(name); + cy.wait("@getKpiTemplate", timeOut) + .its("response.statusCode") + .should("equal", 200); + + cy.intercept("GET", getDetail).as("getDetailKpiTemplate"); + + cy.waitVisible("table"); + cy.get("table td").contains(name).click(); + + cy.log("Create group"); + + cy.wait("@getDetailKpiTemplate", timeOut) + .its("response.statusCode") + .should("equal", 200); + cy.waitVisible("table"); + cy.get("table td").should("contain", "NO"); + cy.get("table td").should("contain", "KEY PERFORMANCE INDICATOR"); + cy.get("table td").should("contain", "WEIGHT"); + cy.get("table td button").should("contain", "GROUP"); + cy.wait(1500); + cy.get("table td button").contains("GROUP").click(); + + cy.intercept("POST", apiTemplate + "-groups").as("createKpiTemplateGroups"); + + cy.waitVisible("#group"); + cy.get("#group .block-header").should("contain", "KPI TEMPLATE GROUP"); + cy.get("#group input").type(group); + cy.wait(2000); + cy.get("#group [type=submit]").click(); + + cy.wait("@createKpiTemplateGroups", timeOut) + .its("response.statusCode") + .should("equal", 201); + + cy.get("#group .block-content tr td", timeOut).should("contain", group); + cy.wait(2000); + cy.get("#group .modal-footer [type=button]").click(); + + cy.wait(2000); + cy.log("create indicator"); + + cy.wait(1500); + cy.get("table td button").contains("INDICATOR").click(); + + cy.intercept("POST", apiTemplate + "-indicators").as( + "createKpiTemplateIndicators" + ); + + cy.waitVisible("#indicator"); + cy.get("#indicator .block-header").should( + "contain", + "KPI TEMPLATE INDICATOR" + ); + cy.get("#indicator input#name").type(indicator); + cy.wait(500); + cy.get("#indicator input#weight").type(100); + cy.wait(500); + cy.get("#indicator input#target").type(80); + cy.wait(500); + cy.get("#indicator [type=submit]").click(); + + cy.wait("@createKpiTemplateIndicators", timeOut) + .its("response.statusCode") + .should("equal", 201); + + cy.get("#indicator .block-content tr td", timeOut).should( + "contain", + indicator + ); + cy.wait(2000); + cy.get("#indicator .modal-footer [type=button]").click(); +} diff --git a/tests/e2e/specs/human-resource/kpi/assessment.cy.js b/tests/e2e/specs/human-resource/kpi/assessment.cy.js index 4b875d53..37e2136b 100644 --- a/tests/e2e/specs/human-resource/kpi/assessment.cy.js +++ b/tests/e2e/specs/human-resource/kpi/assessment.cy.js @@ -1,8 +1,6 @@ -import { generateText, createDepartement } from '../functions' import * as hrFunctions from '../functions' const { should } = require("chai") -const randomString = generateText(7) const url = '/human-resource/kpi/kpi-assessment' const apiUrl = Cypress.env('VUE_APP_API_ENDPOINT') const apiEmployee = apiUrl + '/human-resource/employee/employees' @@ -29,15 +27,15 @@ describe('KPI Assessement - Index', () => { }) it('Create Departemen', () => { - hrFunctions.createDepartement(departmentName) + hrFunctions.createDepartementApi(departmentName, 1) }) it('Create Job location', () => { - hrFunctions.createJobLocation(jobLocation) + hrFunctions.createJobLocationApi(jobLocation, 1) }) it('Create Employment Contract', () => { - hrFunctions.createEmploymentContract(employmentContract) + hrFunctions.createEmploymentContract(employmentContract, 1) }) it('Create Employment', () => { @@ -62,19 +60,19 @@ describe('KPI Assessement - Index', () => { cy.visit('/') cy.waitToken() - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("KPI").click(); cy.intercept('GET', listEmployee).as('getEmployee') - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI ASSESSMENT').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("KPI ASSESSMENT").click(); cy.wait('@getEmployee', timeOut).its('response.statusCode').should('equal', 200) cy.url().should('contain', url) diff --git a/tests/e2e/specs/human-resource/kpi/template.cy.js b/tests/e2e/specs/human-resource/kpi/template.cy.js index 09931fb1..5ef2e948 100644 --- a/tests/e2e/specs/human-resource/kpi/template.cy.js +++ b/tests/e2e/specs/human-resource/kpi/template.cy.js @@ -12,7 +12,7 @@ const timeOut = { timeout : 300000 } describe('HR - KPI Template', () => { beforeEach(() => { - // cy.hideXHR() + cy.hideXHR() cy.login('admin', 'admin') }) @@ -21,19 +21,19 @@ describe('HR - KPI Template', () => { cy.visit('/') cy.waitToken() - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('MAIN MENU').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("MAIN MENU").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > .row > div > div > a').contains('HUMAN RESOURCE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("HUMAN RESOURCE").click(); - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("KPI").click(); cy.intercept('GET', getList).as('getKpiTemplate') - cy.waitVisible('#main-container > .content'); - cy.get('#main-container > .content > div > .row > div > div > a').contains('KPI TEMPLATE').click() + cy.waitVisible("#main-container > .content"); + cy.get('#main-container a[href*="/"]').contains("KPI TEMPLATE").click(); cy.wait('@getKpiTemplate', timeOut).its('response.statusCode').should('equal', 200)