Merging Development #5
@ -16,10 +16,9 @@ jobs:
|
|||||||
node-version: 18
|
node-version: 18
|
||||||
|
|
||||||
- name: Write .npmrc file
|
- name: Write .npmrc file
|
||||||
run: echo "$NPMRC" > client/.npmrc
|
run: |
|
||||||
shell: bash
|
touch client/.npmrc
|
||||||
env:
|
echo '${{ secrets.NPMRC}}' > client/.npmrc
|
||||||
NPMRC: ${{ secrets.NPMRC}}
|
|
||||||
|
|
||||||
- run: apt-get update
|
- run: apt-get update
|
||||||
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||||
@ -28,17 +27,13 @@ jobs:
|
|||||||
- run: apt-get update -y
|
- run: apt-get update -y
|
||||||
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
|
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
|
||||||
- run: apt -y install jq
|
- run: apt -y install jq
|
||||||
# - run: 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
|
|
||||||
# - run: eval $(ssh-agent -s)
|
|
||||||
# - run: echo "$ssh_key" | tr -d '\r' | ssh-add -
|
|
||||||
- name: Write cypress credentials
|
- name: Write cypress credentials
|
||||||
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
|
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
|
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
|
||||||
|
|
||||||
# - run: mkdir -p ~/.ssh
|
|
||||||
# - run: chmod 700 ~/.ssh
|
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
# Install pm2 and prepare SASJS server
|
# Install pm2 and prepare SASJS server
|
||||||
- run: npm i -g pm2
|
- run: npm i -g pm2
|
||||||
@ -49,12 +44,7 @@ jobs:
|
|||||||
- run: echo NODE_PATH=node >> .env
|
- run: echo NODE_PATH=node >> .env
|
||||||
- run: echo CORS=enable >> .env
|
- run: echo CORS=enable >> .env
|
||||||
- run: echo WHITELIST=http://localhost:4200 >> .env
|
- run: echo WHITELIST=http://localhost:4200 >> .env
|
||||||
# - run: echo "SERVER_URL=$server_url" >> .env
|
- run: cat .env
|
||||||
# - run: echo "SERVER_TYPE=$server_type" >> .env
|
|
||||||
# - run: echo "CLIENT=$client_sasjs" >> .env
|
|
||||||
# - run: echo "ACCESS_TOKEN=$access_token_sasjs" >> .env
|
|
||||||
# - run: echo "REFRESH_TOKEN=$refresh_token_sasjs" >> .env
|
|
||||||
# - run: cat .env
|
|
||||||
- run: pm2 start api-linux --wait-ready
|
- run: pm2 start api-linux --wait-ready
|
||||||
|
|
||||||
- name: Deploy mocked services
|
- name: Deploy mocked services
|
||||||
@ -65,28 +55,27 @@ jobs:
|
|||||||
sasjs cbd -t server-ci
|
sasjs cbd -t server-ci
|
||||||
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
|
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
|
||||||
|
|
||||||
- name: Prepare frontend
|
- name: Install ZIP
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install zip
|
||||||
|
|
||||||
|
- name: Prepare and run frontend and cypress
|
||||||
run: |
|
run: |
|
||||||
cd ./client
|
cd ./client
|
||||||
# mv ./cypress.env.example.json ./cypress.env.json
|
mv ./cypress.env.example.json ./cypress.env.json
|
||||||
# replace-in-files --regex='"username".*' --replacement='"username":"'$cypress_username_sasjs'",' ./cypress.env.json
|
replace-in-files --regex='"username".*' --replacement='"username":"'${{ secrets.CYPRESS_USERNAME_SASJS }}'",' ./cypress.env.json
|
||||||
# replace-in-files --regex='"password".*' --replacement='"password":"'$cypress_pwd_sasjs'" ' ./cypress.env.json
|
replace-in-files --regex='"password".*' --replacement='"password":"'${{ secrets.CYPRESS_PWD_SASJS }}'" ' ./cypress.env.json
|
||||||
cat ./cypress.env.json
|
cat ./cypress.env.json
|
||||||
npm run postinstall
|
npm run postinstall
|
||||||
# Prepare index.html to SASJS local
|
# Prepare index.html to SASJS local
|
||||||
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
|
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
|
||||||
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
|
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
|
||||||
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
|
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
|
||||||
# Prepare and deploy SASJS version
|
|
||||||
# replace-in-files --regex='serverurl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./dist/index.html
|
|
||||||
# replace-in-files --regex='apploc=".*?"' --replacement='appLoc="/30.SASApps/app/devtest"' ./dist/index.html
|
|
||||||
# replace-in-files --regex='servertype=".*?"' --replacement='serverType="SASJS"' ./dist/index.html
|
|
||||||
# scp -o stricthostkeychecking=no -r ./dist/* dcgitlab@sas.4gl.io:/var/www/html/dcviya/development/newadapter
|
|
||||||
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
|
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
|
||||||
# replace-in-files --regex='"appLocation".*' --replacement='appLocation:"/dcviya/development/newadapter",' ./cypress.config.ts
|
|
||||||
cat ./cypress.config.ts
|
cat ./cypress.config.ts
|
||||||
# Start frontend and run cypress
|
# Start frontend and run cypress
|
||||||
npm start & npx wait-on http://localhost:4200 && ./run-cypress-tests.sh
|
npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
|
||||||
|
|
||||||
Build-and-test-development-latest-adapter:
|
Build-and-test-development-latest-adapter:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -110,17 +99,13 @@ jobs:
|
|||||||
- run: apt-get update -y
|
- run: apt-get update -y
|
||||||
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
|
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
|
||||||
- run: apt -y install jq
|
- run: apt -y install jq
|
||||||
# - run: 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
|
|
||||||
# - run: eval $(ssh-agent -s)
|
|
||||||
# - run: echo "$ssh_key" | tr -d '\r' | ssh-add -
|
|
||||||
- name: Write cypress credentials
|
- name: Write cypress credentials
|
||||||
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
|
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
|
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
|
||||||
|
|
||||||
# - run: mkdir -p ~/.ssh
|
|
||||||
# - run: chmod 700 ~/.ssh
|
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
# Install pm2 and prepare SASJS server
|
# Install pm2 and prepare SASJS server
|
||||||
- run: npm i -g pm2
|
- run: npm i -g pm2
|
||||||
@ -131,12 +116,7 @@ jobs:
|
|||||||
- run: echo NODE_PATH=node >> .env
|
- run: echo NODE_PATH=node >> .env
|
||||||
- run: echo CORS=enable >> .env
|
- run: echo CORS=enable >> .env
|
||||||
- run: echo WHITELIST=http://localhost:4200 >> .env
|
- run: echo WHITELIST=http://localhost:4200 >> .env
|
||||||
# - run: echo "SERVER_URL=$server_url" >> .env
|
- run: cat .env
|
||||||
# - run: echo "SERVER_TYPE=$server_type" >> .env
|
|
||||||
# - run: echo "CLIENT=$client_sasjs" >> .env
|
|
||||||
# - run: echo "ACCESS_TOKEN=$access_token_sasjs" >> .env
|
|
||||||
# - run: echo "REFRESH_TOKEN=$refresh_token_sasjs" >> .env
|
|
||||||
# - run: cat .env
|
|
||||||
- run: pm2 start api-linux --wait-ready
|
- run: pm2 start api-linux --wait-ready
|
||||||
|
|
||||||
- name: Deploy mocked services
|
- name: Deploy mocked services
|
||||||
@ -147,12 +127,17 @@ jobs:
|
|||||||
sasjs cbd -t server-ci
|
sasjs cbd -t server-ci
|
||||||
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
|
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
|
||||||
|
|
||||||
- name: Prepare frontend
|
- name: Install ZIP
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install zip
|
||||||
|
|
||||||
|
- name: Prepare and run frontend and cypress
|
||||||
run: |
|
run: |
|
||||||
cd ./client
|
cd ./client
|
||||||
# mv ./cypress.env.example.json ./cypress.env.json
|
mv ./cypress.env.example.json ./cypress.env.json
|
||||||
# replace-in-files --regex='"username".*' --replacement='"username":"'$cypress_username_sasjs'",' ./cypress.env.json
|
replace-in-files --regex='"username".*' --replacement='"username":"'${{ secrets.CYPRESS_USERNAME_SASJS }}'",' ./cypress.env.json
|
||||||
# replace-in-files --regex='"password".*' --replacement='"password":"'$cypress_pwd_sasjs'" ' ./cypress.env.json
|
replace-in-files --regex='"password".*' --replacement='"password":"'${{ secrets.CYPRESS_PWD_SASJS }}'" ' ./cypress.env.json
|
||||||
cat ./cypress.env.json
|
cat ./cypress.env.json
|
||||||
npm run postinstall
|
npm run postinstall
|
||||||
npm install @sasjs/adapter@latest
|
npm install @sasjs/adapter@latest
|
||||||
@ -160,13 +145,7 @@ jobs:
|
|||||||
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
|
replace-in-files --regex='serverUrl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./src/index.html
|
||||||
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
|
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/Public/app/devtest"' ./src/index.html
|
||||||
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
|
replace-in-files --regex='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
|
||||||
# Prepare and deploy SASJS version
|
|
||||||
# replace-in-files --regex='serverurl=".*?"' --replacement='serverUrl="http://localhost:5000"' ./dist/index.html
|
|
||||||
# replace-in-files --regex='apploc=".*?"' --replacement='appLoc="/30.SASApps/app/devtest"' ./dist/index.html
|
|
||||||
# replace-in-files --regex='servertype=".*?"' --replacement='serverType="SASJS"' ./dist/index.html
|
|
||||||
# scp -o stricthostkeychecking=no -r ./dist/* dcgitlab@sas.4gl.io:/var/www/html/dcviya/development/newadapter
|
|
||||||
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
|
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
|
||||||
# replace-in-files --regex='"appLocation".*' --replacement='appLocation:"/dcviya/development/newadapter",' ./cypress.config.ts
|
|
||||||
cat ./cypress.config.ts
|
cat ./cypress.config.ts
|
||||||
# Start frontend and run cypress
|
# Start frontend and run cypress
|
||||||
npm start & npx wait-on http://localhost:4200 && ./run-cypress-tests.sh
|
npm start & npx wait-on http://localhost:4200 && npx cypress run --browser chrome --spec "cypress/e2e/liveness.cy.ts,cypress/e2e/editor.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
|
@ -22,29 +22,92 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
NPMRC: ${{ secrets.NPMRC}}
|
NPMRC: ${{ secrets.NPMRC}}
|
||||||
|
|
||||||
- name: Install ZIP
|
- name: Install ZIP and SASjs CLI
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install zip
|
apt-get install zip -y
|
||||||
|
npm i -g @sasjs/cli
|
||||||
|
# test
|
||||||
|
|
||||||
- name: release-build
|
- name: Install JQ for parsing JSON
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install jq -y
|
||||||
|
|
||||||
|
- name: Install Semantic Release and plugins and create Release
|
||||||
|
run: |
|
||||||
|
npm i
|
||||||
|
npm i -g semantic-release
|
||||||
|
GITEA_TOKEN=${{ secrets.RELEASE_TOKEN }} GITEA_URL=https://git.datacontroller.io semantic-release
|
||||||
|
|
||||||
|
- name: Frontend Build
|
||||||
run: |
|
run: |
|
||||||
cd client
|
cd client
|
||||||
npm ci
|
npm ci
|
||||||
npm run build
|
npm run build
|
||||||
zip -r dist.zip ./dist
|
|
||||||
|
|
||||||
- name: Install Semantic Release and plugins
|
- name: Build SAS9 EBI Release
|
||||||
|
description: compile SAS 9 services, remove tests & create deployment program
|
||||||
run: |
|
run: |
|
||||||
npm i
|
cd sas
|
||||||
npm i -g semantic-release
|
npm ci
|
||||||
|
sasjs c -t sas9
|
||||||
|
rm -rf sasjsbuild/tests
|
||||||
|
sasjs b -t sas9
|
||||||
|
cp sasjsbuild/mysas9deploy.sas ./demostream_sas9.sas
|
||||||
|
#
|
||||||
|
# remove streamed component and rebuild SAS 9 services
|
||||||
|
#
|
||||||
|
rm -rf sasjsbuild/services/web9
|
||||||
|
rm sasjsbuild/services/clickme.sas
|
||||||
|
sasjs b -t sas9
|
||||||
|
cp sasjsbuild/mysas9deploy.sas ./sas9.sas
|
||||||
|
|
||||||
- name: Release
|
- name: Build SASjs Server Release
|
||||||
|
description: compile Base (SASjs) services, remove tests & create deployment JSON
|
||||||
run: |
|
run: |
|
||||||
GITEA_TOKEN=${{ secrets.RELEASE_TOKEN }} GITEA_URL=https://git.datacontroller.io semantic-release
|
cd sas
|
||||||
|
cp sasjs/utils/favicon.ico ../client/dist/favicon.ico
|
||||||
|
sasjs c -t server
|
||||||
|
rm -rf sasjsbuild/tests
|
||||||
|
sasjs b -t server
|
||||||
|
cp sasjsbuild/server.json.zip ./sasjs_server.json.zip
|
||||||
|
|
||||||
|
- name: Build Viya Release
|
||||||
|
description: compile Viya Streaming Deploy (without tests)
|
||||||
|
run: |
|
||||||
|
cd sas
|
||||||
|
sasjs c -t viya
|
||||||
|
rm -rf sasjsbuild/tests
|
||||||
|
sed -i -e 's/servertype="SASJS"/servertype="SASVIYA"/g' sasjsbuild/services/clickme.html
|
||||||
|
sasjs b -t viya
|
||||||
|
cp sasjsbuild/viya.sas ./demostream_viya.sas
|
||||||
|
# compile Viya Full deploy (without web)
|
||||||
|
rm -rf sasjsbuild/services/web
|
||||||
|
rm sasjsbuild/services/clickme.html
|
||||||
|
sasjs b -t viya
|
||||||
|
cp sasjsbuild/viya.sas ./viya.sas
|
||||||
|
|
||||||
|
- name: Zip Frontend (including viya.json for full viya deploy)
|
||||||
|
run: |
|
||||||
|
cd sas
|
||||||
|
cp sasjsbuild/viya.json ../client/dist
|
||||||
|
cd ..
|
||||||
|
zip -r frontend.zip ./client/dist
|
||||||
|
|
||||||
- name: Release Typedoc
|
- name: Release Typedoc
|
||||||
run: |
|
run: |
|
||||||
cd client
|
cd client
|
||||||
npm run typedoc
|
npm run typedoc
|
||||||
# deploy docs
|
# deploy docs
|
||||||
|
|
||||||
|
- name: Upload assets to release
|
||||||
|
run: |
|
||||||
|
RELEASE_ID=`curl -k 'https://git.datacontroller.io/api/v1/repos/dc/dc/releases/latest?access_token=${{ secrets.RELEASE_TOKEN }}' | jq -r '.id'`
|
||||||
|
URL="https://git.datacontroller.io/api/v1/repos/dc/dc/releases/$RELEASE_ID/assets?access_token=${{ secrets.RELEASE_TOKEN }}"
|
||||||
|
curl -k $URL -F attachment=@frontend.zip
|
||||||
|
curl -k $URL -F attachment=@sas/demostream_sas9.sas
|
||||||
|
curl -k $URL -F attachment=@sas/demostream_viya.sas
|
||||||
|
curl -k $URL -F attachment=@sas/sasjs_server.json.zip
|
||||||
|
curl -k $URL -F attachment=@sas/sas9.sas
|
||||||
|
curl -k $URL -F attachment=@sas/viya.sas
|
||||||
|
48
.releaserc
48
.releaserc
@ -1,22 +1,44 @@
|
|||||||
{
|
{
|
||||||
"branches": ["main"],
|
"branches": [
|
||||||
|
"main"
|
||||||
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@semantic-release/commit-analyzer",
|
"@semantic-release/commit-analyzer",
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/changelog",
|
"@semantic-release/changelog",
|
||||||
[
|
[
|
||||||
"@semantic-release/git",
|
"@semantic-release/git",
|
||||||
{
|
{
|
||||||
"assets": [
|
"assets": [
|
||||||
"CHANGELOG.md"
|
"CHANGELOG.md"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
["@saithodev/semantic-release-gitea", {
|
[
|
||||||
"giteaUrl": "https://git.datacontroller.io",
|
"@saithodev/semantic-release-gitea",
|
||||||
"assets": [
|
{
|
||||||
{"path": "client/dist.zip"}
|
"giteaUrl": "https://git.datacontroller.io",
|
||||||
]
|
"assets": [
|
||||||
}]
|
{
|
||||||
|
"path": "sas/demostream_sas9.sas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "sas/demostream_viya.sas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "sas/frontend.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "sas/sasjs_server.json.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "sas/sas9.sas"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "sas/viya.sas"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,9 +0,0 @@
|
|||||||
pipeline:
|
|
||||||
build:
|
|
||||||
image: debian
|
|
||||||
commands:
|
|
||||||
- echo "This is the build step"
|
|
||||||
a-test-step:
|
|
||||||
image: debian
|
|
||||||
commands:
|
|
||||||
- echo "Testing.."
|
|
@ -1,17 +1,20 @@
|
|||||||
import { defineConfig } from 'cypress'
|
import { defineConfig } from "cypress";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
reporter: 'mochawesome',
|
reporter: "mochawesome",
|
||||||
|
|
||||||
reporterOptions: {
|
reporterOptions: {
|
||||||
reportDir: 'cypress/results',
|
reportDir: "cypress/results",
|
||||||
overwrite: false,
|
overwrite: false,
|
||||||
html: true,
|
html: true,
|
||||||
json: false,
|
json: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
chromeWebSecurity: false,
|
chromeWebSecurity: false,
|
||||||
defaultCommandTimeout: 30000,
|
defaultCommandTimeout: 30000,
|
||||||
|
|
||||||
env: {
|
env: {
|
||||||
hosturl:"http://localhost:4200",
|
hosturl: "http://localhost:4200",
|
||||||
appLocation: "",
|
appLocation: "",
|
||||||
site_id_SAS9: "70221618",
|
site_id_SAS9: "70221618",
|
||||||
site_id_SASVIYA: "70253615",
|
site_id_SASVIYA: "70253615",
|
||||||
@ -23,6 +26,12 @@ export default defineConfig({
|
|||||||
debug: false,
|
debug: false,
|
||||||
screenshotOnRunFailure: false,
|
screenshotOnRunFailure: false,
|
||||||
longerCommandTimeout: 50000,
|
longerCommandTimeout: 50000,
|
||||||
testLicenceUserLimits: false
|
testLicenceUserLimits: false,
|
||||||
}
|
},
|
||||||
})
|
|
||||||
|
e2e: {
|
||||||
|
setupNodeEvents(on, config) {
|
||||||
|
// implement node event listeners here
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
250
client/cypress/e2e/download.cy.ts
Normal file
250
client/cypress/e2e/download.cy.ts
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const downloadsFolder = Cypress.config('downloadsFolder')
|
||||||
|
|
||||||
|
import { deleteDownloadsFolder } from '../util/deleteDownloadFolder'
|
||||||
|
|
||||||
|
context('download files test: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
cy.get('input.username').type(username)
|
||||||
|
cy.get('input.password').type(password)
|
||||||
|
cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
deleteDownloadsFolder()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | downloads audit file', (done) => {
|
||||||
|
visitPage('approve/toapprove')
|
||||||
|
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-success')
|
||||||
|
.should('be.visible')
|
||||||
|
.then((buttons) => {
|
||||||
|
buttons[0].click()
|
||||||
|
const id = buttons[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'zip', () => done())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | downloads viewer csv', (done) => {
|
||||||
|
visitPage('view/data')
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openDownloadModal(() => {
|
||||||
|
cy.get('select')
|
||||||
|
.select('CSV')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-success-outline').then((button) => {
|
||||||
|
button.trigger('click')
|
||||||
|
|
||||||
|
const id = button[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'csv', () => done())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | downloads viewer excel', (done) => {
|
||||||
|
visitPage('view/data')
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openDownloadModal(() => {
|
||||||
|
cy.get('select')
|
||||||
|
.select('Excel')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-success-outline').then((button) => {
|
||||||
|
button.trigger('click')
|
||||||
|
|
||||||
|
const id = button[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'xlsx', () => done())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4 | downloads viewer SAS Datalines', (done) => {
|
||||||
|
visitPage('view/data')
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openDownloadModal(() => {
|
||||||
|
cy.get('select')
|
||||||
|
.select('SAS Datalines')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-success-outline').then((button) => {
|
||||||
|
button.trigger('click')
|
||||||
|
|
||||||
|
const id = button[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'sas', () => done())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5 | downloads viewer SAS DDL', (done) => {
|
||||||
|
visitPage('view/data')
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openDownloadModal(() => {
|
||||||
|
cy.get('select')
|
||||||
|
.select('SAS DDL')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-success-outline').then((button) => {
|
||||||
|
button.trigger('click')
|
||||||
|
|
||||||
|
const id = button[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'ddl', () => done(), '_')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('6 | downloads viewer TSQL DDL', (done) => {
|
||||||
|
visitPage('view/data')
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openDownloadModal(() => {
|
||||||
|
cy.get('select')
|
||||||
|
.select('TSQL DDL')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-success-outline').then((button) => {
|
||||||
|
button.trigger('click')
|
||||||
|
|
||||||
|
const id = button[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'ddl', () => done(), '_')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('7 | downloads viewer PGSQL DDL', (done) => {
|
||||||
|
visitPage('view/data')
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openDownloadModal(() => {
|
||||||
|
cy.get('select')
|
||||||
|
.select('PGSQL DDL')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-success-outline').then((button) => {
|
||||||
|
button.trigger('click')
|
||||||
|
|
||||||
|
const id = button[0].id
|
||||||
|
|
||||||
|
checkForFileDownloaded(id, 'ddl', () => done(), '_')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkForFileDownloaded = (
|
||||||
|
id: string,
|
||||||
|
extension: string,
|
||||||
|
callback?: any,
|
||||||
|
libDivider: string = '.'
|
||||||
|
) => {
|
||||||
|
cy.on('url:changed', (newUrl) => {
|
||||||
|
console.log('newUrl', newUrl)
|
||||||
|
})
|
||||||
|
|
||||||
|
id = id.replace('.', libDivider)
|
||||||
|
|
||||||
|
const filename = downloadsFolder + '/' + id + '.' + extension
|
||||||
|
// browser might take a while to download the file,
|
||||||
|
// so use "cy.readFile" to retry until the file exists
|
||||||
|
// and has length - and we assume that it has finished downloading then
|
||||||
|
cy.readFile(filename, { timeout: longerCommandTimeout })
|
||||||
|
.should('have.length.gt', 10)
|
||||||
|
.then((file) => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDownloadModal = (callback?: any) => {
|
||||||
|
cy.get('.btn.btn-sm.btn-outline.filterSide.dropdown-toggle')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('clr-dropdown-menu button').then((buttons) => {
|
||||||
|
for (let button of buttons) {
|
||||||
|
if (button.innerText.toLowerCase().includes('download')) {
|
||||||
|
button.click()
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromTree = (libNameIncludes: string, tablename: string) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('viyaLib', viyaLib)
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get(
|
||||||
|
'.clr-tree-node-content-container .clr-treenode-content p'
|
||||||
|
).click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
257
client/cypress/e2e/editor.cy.ts
Normal file
257
client/cypress/e2e/editor.cy.ts
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'excels_general/'
|
||||||
|
|
||||||
|
context('editor tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
// cy.get('input.username').type(username)
|
||||||
|
// cy.get('input.password').type(password)
|
||||||
|
// cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Submits duplicate primary keys', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')
|
||||||
|
|
||||||
|
attachExcelFile('MPE_DATADICTIONARY_duplicate_keys.xlsx', () => {
|
||||||
|
clickOnUploadPreview(() => {
|
||||||
|
confirmEditPreviewFile(() => {
|
||||||
|
submitTable(() => {
|
||||||
|
cy.get('.modal-body').then((modalBody: any) => {
|
||||||
|
if (modalBody[0].innerText.includes(`Duplicates found:`)) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | Submits null cells which must not be null', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
clickOnEdit(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-icon.btn-outline-danger', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then(() => {
|
||||||
|
cy.get('.ht_master tbody tr').then((rows: any) => {
|
||||||
|
cy.get(rows[1].childNodes[2])
|
||||||
|
.dblclick({ force: true })
|
||||||
|
.then(() => {
|
||||||
|
cy.focused()
|
||||||
|
.clear()
|
||||||
|
.type('{enter}')
|
||||||
|
.then(() => {
|
||||||
|
submitTable(() => {
|
||||||
|
cy.get('.modal-body').then((modalBody: any) => {
|
||||||
|
if (
|
||||||
|
modalBody[0].innerHTML
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(`invalid values are present`)
|
||||||
|
) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | Gets basic dynamic cell validation', () => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
clickOnEdit(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-icon.btn-outline-danger', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then(() => {
|
||||||
|
cy.get('.ht_master tbody tr').then((rows: any) => {
|
||||||
|
cy.get(rows[1].childNodes[5])
|
||||||
|
.click({ force: true })
|
||||||
|
.then(($td) => {
|
||||||
|
cy.get('.htAutocompleteArrow', { withinSubject: $td }).should(
|
||||||
|
'exist'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4 | Gets advanced dynamic cell validation', () => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_tables')
|
||||||
|
|
||||||
|
clickOnEdit(() => {
|
||||||
|
cy.get('.btn.btn-sm.btn-icon.btn-outline-danger', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then(() => {
|
||||||
|
cy.get('.ht_master tbody tr').then((rows: any) => {
|
||||||
|
cy.get(rows[1].childNodes[3])
|
||||||
|
.click({ force: true })
|
||||||
|
.then(($td) => {
|
||||||
|
cy.get('.htAutocompleteArrow', { withinSubject: $td }).should(
|
||||||
|
'exist'
|
||||||
|
)
|
||||||
|
cy.get('.htAutocompleteArrow', {
|
||||||
|
withinSubject: rows[1].childNodes[7]
|
||||||
|
}).should('exist')
|
||||||
|
cy.get('.htAutocompleteArrow', {
|
||||||
|
withinSubject: rows[1].childNodes[8]
|
||||||
|
}).should('exist')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const clickOnEdit = (callback?: any) => {
|
||||||
|
cy.get('.btnCtrl button.btn-primary', { timeout: longerCommandTimeout })
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromTree = (libNameIncludes: string, tablename: string) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container > button').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const attachExcelFile = (excelFilename: string, callback?: any) => {
|
||||||
|
cy.get('.buttonBar button:last-child')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('input[type="file"]#file-upload')
|
||||||
|
.attachFile(`/${fixturePath}/${excelFilename}`)
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.modal-footer .btn.btn-primary').then((modalBtn) => {
|
||||||
|
modalBtn.click()
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickOnUploadPreview = (callback?: any) => {
|
||||||
|
cy.get('.buttonBar button.btn-primary.btn-upload-preview')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmEditPreviewFile = (callback?: any) => {
|
||||||
|
cy.get('.modal-footer button.btn-success-outline')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitTable = (callback?: any) => {
|
||||||
|
cy.get('.btnCtrl button.btn-primary')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitTableMessage = (callback?: any) => {
|
||||||
|
cy.get('.modal-footer .btn.btn-sm.btn-success-outline')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitExcel = (callback?: any) => {
|
||||||
|
cy.get('.buttonBar button.preview-submit')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rejectExcel = (callback?: any) => {
|
||||||
|
cy.get('button', { timeout: longerCommandTimeout })
|
||||||
|
.should('contain', 'Go to approvals screen')
|
||||||
|
.then((allButtons: any) => {
|
||||||
|
for (let approvalButton of allButtons) {
|
||||||
|
if (
|
||||||
|
approvalButton.innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('go to approvals screen')
|
||||||
|
) {
|
||||||
|
approvalButton.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get('button.btn-danger')
|
||||||
|
.should('exist')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.modal-footer button.btn-success-outline')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('app-history')
|
||||||
|
.should('exist')
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
537
client/cypress/e2e/excel.cy.ts
Normal file
537
client/cypress/e2e/excel.cy.ts
Normal file
@ -0,0 +1,537 @@
|
|||||||
|
import { Callbacks } from 'cypress/types/jquery/index'
|
||||||
|
|
||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'excels/'
|
||||||
|
|
||||||
|
context('excel tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
// cy.get('input.username').type(username)
|
||||||
|
// cy.get('input.password').type(password)
|
||||||
|
// cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
|
||||||
|
colorLog(
|
||||||
|
`TEST START ---> ${
|
||||||
|
Cypress.mocha.getRunner().suite.ctx.currentTest.title
|
||||||
|
}`,
|
||||||
|
'#3498DB'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Uploads regular Excel file', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('regular_excel.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | Uploads Excel with data on the 7th tab', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('7th_tab_excel.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | Uploads Excel with missing columns (should fail)', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('missing_columns_excel.xlsx', () => {
|
||||||
|
cy.get('.abortMsg', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then((elements: any) => {
|
||||||
|
if (elements[0]) {
|
||||||
|
if (elements[0].innerText.toLowerCase().includes('missing')) done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4 | Uploads Excel with formulas', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')
|
||||||
|
|
||||||
|
attachExcelFile('formulas_excel.xlsx', () => {
|
||||||
|
checkResultOfFormulaUpload(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5 | Uploads Excel with no data rows', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('nodata_rows_excel.xlsx', () => {
|
||||||
|
cy.get('.abortMsg', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then((elements: any) => {
|
||||||
|
if (elements[0]) {
|
||||||
|
if (
|
||||||
|
elements[0].innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('no relevant data found')
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('6 | Uploads Excel with a table that is surrounded by other data', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('surrounded_data_excel.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('7 | Uploads Excel with a extra columns in the middle', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('extra_column_excel.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('8 | Uploads Excel with a duplicate column', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('duplicate_column_excel.xlsx', () => {
|
||||||
|
cy.get('.abortMsg', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then((elements: any) => {
|
||||||
|
if (elements[0]) {
|
||||||
|
if (elements[0].innerText.toLowerCase().includes('missing')) done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('9 | Uploads Excel with a duplicate row', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('duplicate_row_excel.xlsx', () => {
|
||||||
|
submitExcel(() => {
|
||||||
|
cy.get('.duplicate-keys-modal', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then((elements: any) => {
|
||||||
|
if (elements[0]) {
|
||||||
|
if (elements[0].innerText.toLowerCase().includes('duplicates'))
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('10 | Uploads Excel with a mixed content', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('mixed_content_excel.xlsx', () => {
|
||||||
|
submitExcel(() => {
|
||||||
|
cy.get('.modal-body').then((modalBody: any) => {
|
||||||
|
if (
|
||||||
|
modalBody[0].innerHTML
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(`invalid values are present`)
|
||||||
|
) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('11 | Uploads Excel with a blank columns', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('blank_columns_excel.xlsx', () => {
|
||||||
|
cy.get('.abortMsg', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then((elements: any) => {
|
||||||
|
if (elements[0]) {
|
||||||
|
if (elements[0].innerText.toLowerCase().includes('missing')) done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('12 | Uploads Excel xls extension', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('regular_excel_xls.xls', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// For some strange reason this file breaks cypress. When uploaded manually in DC it is working.
|
||||||
|
// it('13 | Uploads Excel xlsm extension', (done) => {
|
||||||
|
// openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
// attachExcelFile('regular_excel_macro.xlsm', () => {
|
||||||
|
// submitExcel()
|
||||||
|
// rejectExcel(done)
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
|
it('14 | Uploads Excel with composite primary key', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')
|
||||||
|
|
||||||
|
attachExcelFile('MPE_DATADICTIONARY_composite_keys.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('15 | Uploads Excel with missing row (empty table)', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')
|
||||||
|
|
||||||
|
attachExcelFile('MPE_DATADICTIONARY_missing_row.xlsx', () => {
|
||||||
|
cy.get('.abortMsg', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then((elements: any) => {
|
||||||
|
if (elements[0]) {
|
||||||
|
if (
|
||||||
|
elements[0].innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('no relevant data found')
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('16 | Uploads Excel with merged cells', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')
|
||||||
|
|
||||||
|
attachExcelFile('MPE_DATADICTIONARY_merged_cells.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('17 | Check uploaded values from excel with xls extension', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('regular_excel_xls.xls', () => {
|
||||||
|
checkResultOfXLSUpload(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('18 | Uploads Excel with missing row (empty table)', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('blank_column_with_header.xlsx', () => {
|
||||||
|
cy.get('.btn-upload-preview', { timeout: 60000 })
|
||||||
|
.should('be.visible')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('#hotInstance', { timeout: 30000 })
|
||||||
|
.find('div.ht_master.handsontable')
|
||||||
|
.find('div.wtHolder')
|
||||||
|
.find('div.wtHider')
|
||||||
|
.find('div.wtSpreader')
|
||||||
|
.find('table.htCore')
|
||||||
|
.find('tbody')
|
||||||
|
.then((data) => {
|
||||||
|
let allEmpty = true
|
||||||
|
|
||||||
|
for (let col = 0; col < data[0].children.length; col++) {
|
||||||
|
const cell: any = data[0].children[col].children[5]
|
||||||
|
|
||||||
|
if (cell.innerText !== '') {
|
||||||
|
allEmpty = false
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allEmpty) done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('19 | Uploads Excel with data on random sheet surrounded with all empty cells', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('surrounded_data_all_cells_empty_excel.xlsx', () => {
|
||||||
|
checkResultOfXLSUpload(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('20 | Uploads Excel with data surrounded with empty cells ', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('surrounded_data_empty_cells_excel.xlsx', () => {
|
||||||
|
checkResultOfXLSUpload(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('21 | Uploads regular Excel file with first row marked for Delete (yes)', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('regular_excel_with_delete.xlsx', () => {
|
||||||
|
cy.get('.btn-upload-preview', { timeout: 60000 })
|
||||||
|
.should('be.visible')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('#hotInstance', { timeout: 30000 })
|
||||||
|
.find('div.ht_master.handsontable')
|
||||||
|
.find('div.wtHolder')
|
||||||
|
.find('div.wtHider')
|
||||||
|
.find('div.wtSpreader')
|
||||||
|
.find('table.htCore')
|
||||||
|
.find('tbody')
|
||||||
|
.then((data: JQuery<HTMLTableSectionElement>) => {
|
||||||
|
const firstRowFirstCol: Partial<HTMLElement> =
|
||||||
|
data[0].children[0].children[1]
|
||||||
|
|
||||||
|
if (
|
||||||
|
firstRowFirstCol.innerText &&
|
||||||
|
!firstRowFirstCol.innerText.toLowerCase().includes('yes')
|
||||||
|
) {
|
||||||
|
done('Delete? column from file not applied')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Large files break Cypress
|
||||||
|
|
||||||
|
// it ('? | Uploads Excel with size of 5MB', (done) => {
|
||||||
|
// attachExcelFile('5mb_excel.xlsx', () => {
|
||||||
|
// submitExcel();
|
||||||
|
// rejectExcel(done);
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
|
||||||
|
// it ('? | Uploads Excel with size of 15MB', (done) => {
|
||||||
|
// attachExcelFile('15mb_excel.xlsx', () => {
|
||||||
|
// submitExcel();
|
||||||
|
// rejectExcel(done);
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
|
||||||
|
//Large files tests end
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
colorLog(`TEST END -------------`, '#3498DB')
|
||||||
|
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const openTableFromTree = (libNameIncludes: string, tablename: string) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container > button').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const attachExcelFile = (excelFilename: string, callback?: any) => {
|
||||||
|
cy.get('.buttonBar button:last-child')
|
||||||
|
.should('exist')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('input[type="file"]#file-upload')
|
||||||
|
.attachFile(`/${fixturePath}/${excelFilename}`)
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.clr-abort-modal .modal-title').then((modalTitle) => {
|
||||||
|
if (!modalTitle[0].innerHTML.includes('Abort Message')) {
|
||||||
|
cy.get('.modal-footer .btn.btn-primary').then((modalBtn) => {
|
||||||
|
modalBtn.click()
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitExcel = (callback?: any) => {
|
||||||
|
cy.get('.buttonBar button.preview-submit', { timeout: longerCommandTimeout })
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rejectExcel = (callback?: any) => {
|
||||||
|
cy.get('button', { timeout: longerCommandTimeout })
|
||||||
|
.should('contain', 'Go to approvals screen')
|
||||||
|
.then((allButtons: any) => {
|
||||||
|
for (let approvalButton of allButtons) {
|
||||||
|
if (
|
||||||
|
approvalButton.innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('go to approvals screen')
|
||||||
|
) {
|
||||||
|
approvalButton.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get('button.btn-danger')
|
||||||
|
.should('exist')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.modal-footer button.btn-success-outline')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('app-history')
|
||||||
|
.should('exist')
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const acceptExcel = (callback?: any) => {
|
||||||
|
cy.get('button', { timeout: longerCommandTimeout })
|
||||||
|
.should('contain', 'Go to approvals screen')
|
||||||
|
.then((allButtons: any) => {
|
||||||
|
for (let approvalButton of allButtons) {
|
||||||
|
if (
|
||||||
|
approvalButton.innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('go to approvals screen')
|
||||||
|
) {
|
||||||
|
approvalButton.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get('#acceptBtn')
|
||||||
|
.should('exist')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkResultOfFormulaUpload = (callback?: any) => {
|
||||||
|
cy.get('#hotInstance', { timeout: longerCommandTimeout })
|
||||||
|
.find('div.ht_master.handsontable')
|
||||||
|
.find('div.wtHolder')
|
||||||
|
.find('div.wtHider')
|
||||||
|
.find('div.wtSpreader')
|
||||||
|
.find('table.htCore')
|
||||||
|
.find('tbody')
|
||||||
|
.then((data) => {
|
||||||
|
const cell: any = data[0].children[0].children[5]
|
||||||
|
expect(cell.innerText).to.equal('=1+1')
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkResultOfXLSUpload = (callback?: any) => {
|
||||||
|
cy.viewport(1280, 720)
|
||||||
|
cy.get('#hotInstance', { timeout: 30000 })
|
||||||
|
.find('div.ht_master.handsontable')
|
||||||
|
.find('div.wtHolder')
|
||||||
|
.find('div.wtHider')
|
||||||
|
.find('div.wtSpreader')
|
||||||
|
.find('table.htCore')
|
||||||
|
.find('tbody')
|
||||||
|
.then((data) => {
|
||||||
|
let cell: any = data[0].children[0].children[2]
|
||||||
|
|
||||||
|
expect(cell.innerText).to.equal('0')
|
||||||
|
cell = data[0].children[0].children[3]
|
||||||
|
expect(cell.innerText).to.equal('this is dummy data changed in excel')
|
||||||
|
cell = data[0].children[0].children[4]
|
||||||
|
expect(cell.innerText).to.equal('▼\nOption 1')
|
||||||
|
cell = data[0].children[0].children[5]
|
||||||
|
expect(cell.innerText).to.equal('42')
|
||||||
|
cell = data[0].children[0].children[6]
|
||||||
|
expect(cell.innerText).to.equal('▼\n1960-02-12')
|
||||||
|
// When CI detached browser screen is smaller, below cells are not visible so test fails
|
||||||
|
// Commenting it out now until we figure out workaround
|
||||||
|
// cell = data[0].children[0].children[7]
|
||||||
|
// expect(cell.innerText).to.equal('▼\n1960-01-01 00:00:42')
|
||||||
|
// cell = data[0].children[0].children[8]
|
||||||
|
// expect(cell.innerText).to.equal('00:00:42')
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('#hotInstance', { timeout: 30000 })
|
||||||
|
.find('div.ht_master.handsontable')
|
||||||
|
.find('div.wtHolder')
|
||||||
|
.scrollTo('right')
|
||||||
|
.find('div.wtHider')
|
||||||
|
.find('div.wtSpreader')
|
||||||
|
.find('table.htCore')
|
||||||
|
.find('tbody')
|
||||||
|
.then((data) => {
|
||||||
|
let cell: any = data[0].children[0].children[1]
|
||||||
|
|
||||||
|
cell = data[0].children[0].children[9]
|
||||||
|
|
||||||
|
expect(cell.innerText).to.equal('44')
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorLog = (msg: string, color: string) => {
|
||||||
|
console.log('%c' + msg, 'color:' + color + ';font-weight:bold;')
|
||||||
|
}
|
383
client/cypress/e2e/filtering.cy.ts
Normal file
383
client/cypress/e2e/filtering.cy.ts
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'excels_general/'
|
||||||
|
|
||||||
|
context('filtering tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`, { timeout: longerCommandTimeout })
|
||||||
|
cy.loginAndUpdateValidKey()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation, { timeout: longerCommandTimeout })
|
||||||
|
// cy.get('input.username').type(username)
|
||||||
|
// cy.get('input.password').type(password)
|
||||||
|
// cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | filter char field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_CHAR', 'this is dummy data', 'value', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_CHAR,=,"'this is dummy data'"`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | filter number field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_NUM', '42', 'value', () => {
|
||||||
|
checkInfoBarIncludes(`AND,AND,0,SOME_NUM,=,42`, (includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | filter time field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_TIME', '00:00:42', 'time', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_TIME,=,42`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3.1 | Non picker - filter time field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_TIME', '42', 'value', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_TIME,=,42`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4 | filter date field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_DATE', '12/02/1960', 'date', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_DATE,=,42`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4.1 | Non picker - filter date field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_DATE', '42', 'value', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_DATE,=,42`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5 | filter datetime field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue(
|
||||||
|
'SOME_DATETIME',
|
||||||
|
'01/01/1960 00:00:42',
|
||||||
|
'datetime',
|
||||||
|
() => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_DATETIME,=,42`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5.1 | Non picker - filter datetime field', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_DATETIME', '42', 'value', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_DATETIME,=,42`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('6 | filter date field IN', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_DATE', '', 'in', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_DATE,IN,(0)`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('7 | filter bestnum field BETWEEN', (done) => {
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
openFilterPopup(() => {
|
||||||
|
setFilterWithValue('SOME_BESTNUM', '0-10', 'between', () => {
|
||||||
|
checkInfoBarIncludes(
|
||||||
|
`AND,AND,0,SOME_BESTNUM,BETWEEN,0 AND 10`,
|
||||||
|
(includes: boolean) => {
|
||||||
|
if (includes) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const checkInfoBarIncludes = (text: string, callback: any) => {
|
||||||
|
cy.get('.infoBar b', { timeout: longerCommandTimeout }).then((el: any) => {
|
||||||
|
const includes = el[0].innerText.toLowerCase().includes(text.toLowerCase())
|
||||||
|
|
||||||
|
if (callback) callback(includes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const openFilterPopup = (
|
||||||
|
callback?: any,
|
||||||
|
usePickers: boolean = true,
|
||||||
|
isViewerFiltering: boolean = false
|
||||||
|
) => {
|
||||||
|
const filterButton = isViewerFiltering
|
||||||
|
? '.btn-outline.filterSide'
|
||||||
|
: '.btnCtrl .btnView'
|
||||||
|
|
||||||
|
cy.get(filterButton, { timeout: longerCommandTimeout }).then(
|
||||||
|
(optionsButton: any) => {
|
||||||
|
optionsButton.click()
|
||||||
|
|
||||||
|
if (isViewerFiltering) {
|
||||||
|
cy.wait(300)
|
||||||
|
|
||||||
|
cy.get('.dropdown-menu button').then(async (dropdownButtons: any) => {
|
||||||
|
let filterButton = null
|
||||||
|
|
||||||
|
for (let btn of dropdownButtons) {
|
||||||
|
if (btn.innerText.toLowerCase().includes('filter')) {
|
||||||
|
filterButton = btn
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterButton) {
|
||||||
|
filterButton.click()
|
||||||
|
|
||||||
|
if (usePickers) turnOnPickers()
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usePickers) turnOnPickers()
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const turnOnPickers = () => {
|
||||||
|
cy.get('#usePickers')
|
||||||
|
.should('exist')
|
||||||
|
.then((picker: any) => {
|
||||||
|
picker[0].click()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFilterWithValue = (
|
||||||
|
variableValue: string,
|
||||||
|
valueString: string,
|
||||||
|
valueField: 'value' | 'time' | 'date' | 'datetime' | 'in' | 'between',
|
||||||
|
callback?: any
|
||||||
|
) => {
|
||||||
|
cy.wait(600)
|
||||||
|
|
||||||
|
cy.focused().type(variableValue)
|
||||||
|
cy.wait(100)
|
||||||
|
// cy.focused().trigger('input')
|
||||||
|
cy.get('.variable-col .autocomplete-wrapper', { withinSubject: null })
|
||||||
|
.first()
|
||||||
|
.trigger('keydown', { key: 'ArrowDown' })
|
||||||
|
cy.get('.variable-col .autocomplete-wrapper', {
|
||||||
|
withinSubject: null
|
||||||
|
}).trigger('keydown', { key: 'Enter' })
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
|
||||||
|
if (valueField === 'in') {
|
||||||
|
cy.focused().select(valueField.toUpperCase()).trigger('change')
|
||||||
|
} else if (valueField === 'between') {
|
||||||
|
cy.focused().select(valueField.toUpperCase()).trigger('change')
|
||||||
|
} else {
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (valueField) {
|
||||||
|
case 'value': {
|
||||||
|
cy.focused().type(valueString)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'time': {
|
||||||
|
cy.focused().type(valueString)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'date': {
|
||||||
|
cy.focused().type(valueString)
|
||||||
|
cy.focused().tab()
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'datetime': {
|
||||||
|
const date = valueString.split(' ')[0]
|
||||||
|
const time = valueString.split(' ')[1]
|
||||||
|
|
||||||
|
cy.focused().type(date)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().type(time)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'in': {
|
||||||
|
cy.get('.checkbox-vals').then(() => {
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().click()
|
||||||
|
cy.get('.no-values')
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.in-values-modal clr-checkbox-wrapper input').then((inputs: any) => {
|
||||||
|
inputs[0].click()
|
||||||
|
cy.get('.in-values-modal .modal-footer button').click()
|
||||||
|
|
||||||
|
cy.get('.modal-footer .btn-success-outline').click()
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'between': {
|
||||||
|
cy.focused().tab()
|
||||||
|
|
||||||
|
const start = valueString.split('-')[0]
|
||||||
|
const end = valueString.split('-')[1]
|
||||||
|
|
||||||
|
cy.focused().type(start)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().type(end)
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().click()
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromTree = (libNameIncludes: string, tablename: string) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (new RegExp(libNameIncludes).test(node.innerText.toLowerCase())) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container p').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
731
client/cypress/e2e/licensing.cy.ts
Normal file
731
client/cypress/e2e/licensing.cy.ts
Normal file
@ -0,0 +1,731 @@
|
|||||||
|
import { arrayBufferToBase64 } from './../util/helper-functions'
|
||||||
|
import * as moment from 'moment'
|
||||||
|
|
||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const fixturePath = 'excels_general/'
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const site_id = Cypress.env(`site_id_${serverType}`)
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const testLicenceUserLimits = Cypress.env('testLicenceUserLimits')
|
||||||
|
|
||||||
|
/** IMPORTANT NOTICE
|
||||||
|
* Before running tests, make sure that table `MPE_USERS` is present
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface EditConfigTableCells {
|
||||||
|
varName: string
|
||||||
|
varValue: string
|
||||||
|
}
|
||||||
|
|
||||||
|
context('licensing tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
// cy.get('input.username').type(username)
|
||||||
|
// cy.get('input.password').type(password)
|
||||||
|
// cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | key valid, not expired', (done) => {
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().add(1, 'year').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 4,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys: { licenseKey: any; activationKey: any }
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
keys = keysGen
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
isLicensingPage((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
inputLicenseKeyPage(keys.licenseKey, keys.activationKey)
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(10000)
|
||||||
|
}
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | Key will expire in less then 14 days, not free tier', (done) => {
|
||||||
|
// make 2 separate for this one
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().add(10, 'day').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 4,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys: { licenseKey: any; activationKey: any }
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
keys = keysGen
|
||||||
|
console.log('keys', keys)
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
updateLicenseKeyQuick(keysGen, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
verifyLicensingWarning('This license key will expire in ', () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | key expired, free tier works', (done) => {
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().subtract(1, 'day').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 4,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys: { licenseKey: any; activationKey: any }
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
keys = keysGen
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
cy.wait(2000)
|
||||||
|
updateLicenseKeyQuick(keysGen, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
verifyLicensingPage(
|
||||||
|
'Licence key is expired - please contact',
|
||||||
|
(success: boolean) => {
|
||||||
|
if (success) {
|
||||||
|
verifyLicensingWarning(
|
||||||
|
'(FREE Tier) - Problem with licence',
|
||||||
|
() => {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4 | key invalid, free tier works', (done) => {
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().subtract(1, 'day').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 4,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys: { licenseKey: any; activationKey: any }
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
keys = keysGen
|
||||||
|
keys.activationKey = 'invalid' + keys.activationKey
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
cy.wait(2000)
|
||||||
|
updateLicenseKeyQuick(keysGen, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
verifyLicensingPage(
|
||||||
|
'Licence key is invalid - please contact',
|
||||||
|
(success: boolean) => {
|
||||||
|
if (success) {
|
||||||
|
verifyLicensingWarning(
|
||||||
|
'(FREE Tier) - Problem with licence',
|
||||||
|
() => {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5 | key for wrong organisation, free tier works', (done) => {
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().add(1, 'year').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 4,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: 100
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys: { licenseKey: any; activationKey: any }
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
keys = keysGen
|
||||||
|
keys.activationKey = keys.activationKey
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
cy.wait(2000)
|
||||||
|
updateLicenseKeyQuick(keysGen, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
verifyLicensingPage(
|
||||||
|
'SYSSITE (below) is not found',
|
||||||
|
(success: boolean) => {
|
||||||
|
if (success) {
|
||||||
|
verifyLicensingWarning(
|
||||||
|
'(FREE Tier) - Problem with licence',
|
||||||
|
() => {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (testLicenceUserLimits) {
|
||||||
|
it('4 | User try to register when limit is reached', (done) => {
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().add(1, 'month').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 10,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
let keyData2 = {
|
||||||
|
valid_until: moment().add(1, 'month').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 1,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
generateKeys(keyData2, (keysGen2: any) => {
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
updateLicenseKeyQuick(keysGen, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLicenseKeyQuick(keysGen2, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
const random = Cypress._.random(0, 1000)
|
||||||
|
const newUser = {
|
||||||
|
username: `randomusername${random}notregistered`,
|
||||||
|
last_seen_at: moment().add(1, 'month').format('YYYY-MM-DD'),
|
||||||
|
registered_at: moment().add(1, 'month').format('YYYY-MM-DD')
|
||||||
|
}
|
||||||
|
updateUsersTable(
|
||||||
|
{ deleteAll: true, newUsers: [newUser] },
|
||||||
|
() => {
|
||||||
|
logout(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
// cy.get('input.username').type(username)
|
||||||
|
// cy.get('input.password').type(password)
|
||||||
|
// cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
verifyLicensingPage(
|
||||||
|
'The registered number of users reached the limit specified for your licence.',
|
||||||
|
(success: boolean) => {
|
||||||
|
if (success) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5 | Show warning banner when limit is exceeded', (done) => {
|
||||||
|
let keyData = {
|
||||||
|
valid_until: moment().add(1, 'month').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 10,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
let keyData2 = {
|
||||||
|
valid_until: moment().add(1, 'month').format('YYYY-MM-DD'),
|
||||||
|
users_allowed: 1,
|
||||||
|
hot_license_key: '',
|
||||||
|
demo: false,
|
||||||
|
site_id: site_id
|
||||||
|
}
|
||||||
|
|
||||||
|
generateKeys(keyData, (keysGen: any) => {
|
||||||
|
generateKeys(keyData2, (keysGen2: any) => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
updateLicenseKeyQuick(keysGen, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
acceptTermsIfPresented((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.wait(20000)
|
||||||
|
}
|
||||||
|
const random = Cypress._.random(0, 1000)
|
||||||
|
const newUser = {
|
||||||
|
username: `randomusername${random}`,
|
||||||
|
last_seen_at: moment().add(1, 'month').format('YYYY-MM-DD'),
|
||||||
|
registered_at: moment().add(1, 'month').format('YYYY-MM-DD')
|
||||||
|
}
|
||||||
|
updateUsersTable(
|
||||||
|
{ deleteAll: true, keep: username, newUsers: [newUser] },
|
||||||
|
() => {
|
||||||
|
updateLicenseKeyQuick(keysGen2, () => {
|
||||||
|
cy.wait(2000)
|
||||||
|
verifyLicensingWarning(
|
||||||
|
'The registered number of users exceeds the limit specified for your license.',
|
||||||
|
() => {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const logout = (callback?: any) => {
|
||||||
|
cy.get('.header-actions .dropdown-toggle')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.header-actions .dropdown-menu > .separator')
|
||||||
|
.next()
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const acceptTermsIfPresented = (callback?: any) => {
|
||||||
|
cy.url().then((url: string) => {
|
||||||
|
if (url.includes('licensing/register')) {
|
||||||
|
cy.get('.card-block')
|
||||||
|
.scrollTo('bottom')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('#checkbox1')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if (callback) callback(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const isLicensingPage = (callback: any) => {
|
||||||
|
return cy.url().then((url: string) => {
|
||||||
|
callback(
|
||||||
|
url.includes('#/licensing/') && !url.includes('licensing/register')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifyLicensingPage = (text: string, callback: any) => {
|
||||||
|
// visitPage('home')
|
||||||
|
|
||||||
|
cy.wait(1000)
|
||||||
|
isLicensingPage((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
cy.get('p.key-error')
|
||||||
|
.should('contain', text)
|
||||||
|
.then((treeNodes: any) => {
|
||||||
|
callback(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifyLicensingWarning = (text: string, callback: any) => {
|
||||||
|
visitPage('home')
|
||||||
|
|
||||||
|
cy.wait(1000)
|
||||||
|
cy.get("div[role='alert'] .alert-text")
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', text)
|
||||||
|
.then(() => {
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputLicenseKeyPage = (licenseKey: string, activationKey: string) => {
|
||||||
|
cy.get('button').contains('Paste licence').click()
|
||||||
|
|
||||||
|
cy.get('.license-key-form textarea', { timeout: longerCommandTimeout })
|
||||||
|
.invoke('val', licenseKey)
|
||||||
|
.trigger('input')
|
||||||
|
.should('not.be.undefined')
|
||||||
|
cy.get('.activation-key-form textarea', { timeout: longerCommandTimeout })
|
||||||
|
.invoke('val', activationKey)
|
||||||
|
.trigger('input')
|
||||||
|
.should('not.be.undefined')
|
||||||
|
cy.get('button.apply-keys').click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateUsersTable = (options: any, callback?: any) => {
|
||||||
|
visitPage('home')
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_users')
|
||||||
|
|
||||||
|
clickOnEdit(() => {
|
||||||
|
cy.get('.ht_master tbody tr').then((rows: any) => {
|
||||||
|
if (options.deleteAll) {
|
||||||
|
for (let row of rows) {
|
||||||
|
const user_id = row.childNodes[2]
|
||||||
|
if (!options.keep || user_id.innerText !== options.keep) {
|
||||||
|
cy.get(row.childNodes[1])
|
||||||
|
.dblclick()
|
||||||
|
.then(() => {
|
||||||
|
cy.focused().type('{selectall}').type('Yes').type('{enter}')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (options.newUsers && options.newUsers.length) {
|
||||||
|
for (let newUser of options.newUsers) {
|
||||||
|
clickOnAddRow(() => {
|
||||||
|
cy.get('#hotInstance tbody tr:last-child').then((rows: any) => {
|
||||||
|
cy.get(rows[0].childNodes[2])
|
||||||
|
.dblclick()
|
||||||
|
.then(() => {
|
||||||
|
cy.focused()
|
||||||
|
.type('{selectall}')
|
||||||
|
.type(newUser.username)
|
||||||
|
.type('{enter}')
|
||||||
|
})
|
||||||
|
// cy.get(rows[0].childNodes[3])
|
||||||
|
// .dblclick()
|
||||||
|
// .then(() => {
|
||||||
|
// cy.focused()
|
||||||
|
// .type('{selectall}')
|
||||||
|
// .type(newUser.last_seen_at)
|
||||||
|
// .type('{enter}')
|
||||||
|
// })
|
||||||
|
// cy.get(rows[0].childNodes[4])
|
||||||
|
// .dblclick()
|
||||||
|
// .then(() => {
|
||||||
|
// cy.focused()
|
||||||
|
// .type('{selectall}')
|
||||||
|
// .type(newUser.registered_at)
|
||||||
|
// .type('{enter}')
|
||||||
|
// })
|
||||||
|
submitTable(() => {
|
||||||
|
cy.wait(2000)
|
||||||
|
approveTable(callback)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeLicenseKeyTable = (keys: any, callback?: any) => {
|
||||||
|
visitPage('home')
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_config')
|
||||||
|
|
||||||
|
clickOnEdit(() => {
|
||||||
|
editTableField(
|
||||||
|
[
|
||||||
|
{ varName: 'DC_ACTIVATION_KEY', varValue: keys.activationKey },
|
||||||
|
{ varName: 'DC_LICENCE_KEY', varValue: keys.licenseKey }
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
submitTable(() => {
|
||||||
|
cy.wait(2000)
|
||||||
|
approveTable(() => {
|
||||||
|
cy.reload()
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateLicenseKeyQuick = (keys: any, callback: any) => {
|
||||||
|
isLicensingPage((result: boolean) => {
|
||||||
|
if (!result) {
|
||||||
|
visitPage('licensing/update')
|
||||||
|
cy.wait(2000)
|
||||||
|
}
|
||||||
|
inputLicenseKeyPage(keys.licenseKey, keys.activationKey)
|
||||||
|
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateKeys = async (licenseData: any, resultCallback?: any) => {
|
||||||
|
let keyPair = await window.crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: 'RSA-OAEP',
|
||||||
|
modulusLength: 2024,
|
||||||
|
publicExponent: new Uint8Array([1, 0, 1]),
|
||||||
|
hash: 'SHA-256'
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['encrypt', 'decrypt']
|
||||||
|
)
|
||||||
|
|
||||||
|
const encoded = new TextEncoder().encode(JSON.stringify(licenseData))
|
||||||
|
|
||||||
|
const cipher = await window.crypto.subtle
|
||||||
|
.encrypt(
|
||||||
|
{
|
||||||
|
name: 'RSA-OAEP'
|
||||||
|
},
|
||||||
|
keyPair.publicKey,
|
||||||
|
encoded
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(value) => {
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log('Encrpyt error', err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!cipher) {
|
||||||
|
alert('Encryptin keys failed')
|
||||||
|
throw new Error('Encryptin keys failed')
|
||||||
|
}
|
||||||
|
|
||||||
|
const privateKeyBytes = await window.crypto.subtle.exportKey(
|
||||||
|
'pkcs8',
|
||||||
|
keyPair.privateKey
|
||||||
|
)
|
||||||
|
|
||||||
|
const activationKey = await arrayBufferToBase64(privateKeyBytes)
|
||||||
|
const licenseKey = await arrayBufferToBase64(cipher)
|
||||||
|
|
||||||
|
if (resultCallback)
|
||||||
|
resultCallback({
|
||||||
|
activationKey,
|
||||||
|
licenseKey
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const editTableField = (edits: EditConfigTableCells[], callback?: any) => {
|
||||||
|
cy.get('td').then((tdNodes: any) => {
|
||||||
|
for (let edit of edits) {
|
||||||
|
let correctRow = false
|
||||||
|
|
||||||
|
for (let node of tdNodes) {
|
||||||
|
if (correctRow) {
|
||||||
|
cy.get(node)
|
||||||
|
.dblclick()
|
||||||
|
.then(() => {
|
||||||
|
// textarea update on long keys
|
||||||
|
cy.focused().invoke('val', edit.varValue).type('{enter}')
|
||||||
|
})
|
||||||
|
|
||||||
|
correctRow = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.innerText.includes(edit.varName)) {
|
||||||
|
correctRow = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromTree = (
|
||||||
|
libNameIncludes: string,
|
||||||
|
tablename: string,
|
||||||
|
callback?: any
|
||||||
|
) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container > button').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
if (callback) callback()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickOnAddRow = (callback?: any) => {
|
||||||
|
cy.get('.btnCtrl button.btn-success')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickOnEdit = (callback?: any) => {
|
||||||
|
cy.get('.btnCtrl button.btn-primary', { timeout: longerCommandTimeout })
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitTable = (callback?: any) => {
|
||||||
|
cy.get('.btnCtrl button.btn-primary', { timout: longerCommandTimeout })
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get(".modal.ng-star-inserted button[type='submit']")
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const approveTable = (callback?: any) => {
|
||||||
|
cy.get('button', { timeout: longerCommandTimeout })
|
||||||
|
.should('contain', 'Go to approvals screen')
|
||||||
|
.then((allButtons: any) => {
|
||||||
|
for (let approvalButton of allButtons) {
|
||||||
|
if (
|
||||||
|
approvalButton.innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('go to approvals screen')
|
||||||
|
) {
|
||||||
|
approvalButton.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get('button#acceptBtn', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('app-history', { timeout: longerCommandTimeout })
|
||||||
|
.should('exist')
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
157
client/cypress/e2e/liveness.cy.ts
Normal file
157
client/cypress/e2e/liveness.cy.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'excels/'
|
||||||
|
|
||||||
|
context('liveness tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
if (serverType !== 'SASJS') {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
}
|
||||||
|
cy.loginAndUpdateValidKey(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
|
// cy.get('input.username').type(username)
|
||||||
|
// cy.get('input.password').type(password)
|
||||||
|
// cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Login and submit test', (done) => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
libraryExistsInTree('viya', treeNodes)
|
||||||
|
? openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
: openTableFromTree('dc', 'mpe_x_test')
|
||||||
|
|
||||||
|
attachExcelFile('regular_excel.xlsx', () => {
|
||||||
|
submitExcel()
|
||||||
|
rejectExcel(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thist part will be needed if we add more tests in future
|
||||||
|
*/
|
||||||
|
// this.afterEach(() => {
|
||||||
|
// cy.visit('https://sas.4gl.io/SASLogon/logout');
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const libraryExistsInTree = (libName: string, nodes: any) => {
|
||||||
|
for (let node of nodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libName.toLowerCase()))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromTree = (
|
||||||
|
libNameIncludes: string,
|
||||||
|
tablename: string,
|
||||||
|
finish: any
|
||||||
|
) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!viyaLib && finish) finish(false)
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container > button').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
if (finish) finish(true)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const attachExcelFile = (excelFilename: string, callback?: any) => {
|
||||||
|
cy.get('.buttonBar button:last-child')
|
||||||
|
.should('exist')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('input[type="file"]#file-upload').attachFile(
|
||||||
|
`/${fixturePath}/${excelFilename}`
|
||||||
|
)
|
||||||
|
cy.get('.modal-footer .btn.btn-primary').then((modalBtn) => {
|
||||||
|
modalBtn.click()
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitExcel = (callback?: any) => {
|
||||||
|
cy.get('.buttonBar button.preview-submit', { timeout: longerCommandTimeout })
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rejectExcel = (callback?: any) => {
|
||||||
|
cy.get('button', { timeout: longerCommandTimeout })
|
||||||
|
.should('contain', 'Go to approvals screen')
|
||||||
|
.then((allButtons: any) => {
|
||||||
|
for (let approvalButton of allButtons) {
|
||||||
|
if (
|
||||||
|
approvalButton.innerText
|
||||||
|
.toLowerCase()
|
||||||
|
.includes('go to approvals screen')
|
||||||
|
) {
|
||||||
|
approvalButton.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get('button.btn-danger')
|
||||||
|
.should('exist')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.modal-footer button.btn-success-outline')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('app-history')
|
||||||
|
.should('exist')
|
||||||
|
.then(() => {
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
61
client/cypress/e2e/metanav.cy.ts
Normal file
61
client/cypress/e2e/metanav.cy.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
const fixturePath = 'excels_general/'
|
||||||
|
|
||||||
|
context('metanav tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
cy.get('input.username').type(username)
|
||||||
|
cy.get('input.password').type(password)
|
||||||
|
cy.get('.login-group button').click()
|
||||||
|
|
||||||
|
visitPage('view/metadata')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Opens metadata object', (done) => {
|
||||||
|
openFirstMetadataFromTree(() => {
|
||||||
|
// BLOCKER
|
||||||
|
// For unkown reasons, .clr-accordion-header-button always null although it is present on the page.
|
||||||
|
cy.get('.clr-accordion-header-button').then((panelNodes: any) => {
|
||||||
|
panelNodes[0].querySelector('button').click()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const openFirstMetadataFromTree = (callback?: any) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let firstMetaNode
|
||||||
|
|
||||||
|
firstMetaNode = treeNodes[1]
|
||||||
|
|
||||||
|
cy.get(firstMetaNode).within(() => {
|
||||||
|
cy.get('.clr-treenode-content').click()
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
655
client/cypress/e2e/viewbox.cy.ts
Normal file
655
client/cypress/e2e/viewbox.cy.ts
Normal file
@ -0,0 +1,655 @@
|
|||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
|
const username = Cypress.env('username')
|
||||||
|
const password = Cypress.env('password')
|
||||||
|
const hostUrl = Cypress.env('hosturl')
|
||||||
|
const appLocation = Cypress.env('appLocation')
|
||||||
|
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
|
||||||
|
const serverType = Cypress.env('serverType')
|
||||||
|
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
|
||||||
|
|
||||||
|
context('editor tests: ', function () {
|
||||||
|
this.beforeAll(() => {
|
||||||
|
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
cy.loginAndUpdateValidKey(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.beforeEach(() => {
|
||||||
|
cy.visit(hostUrl + appLocation)
|
||||||
|
|
||||||
|
cy.wait(2000)
|
||||||
|
|
||||||
|
cy.get('body').then(($body) => {
|
||||||
|
const usernameInput = $body.find('input.username')[0]
|
||||||
|
|
||||||
|
if (usernameInput && !Cypress.dom.isHidden(usernameInput)) {
|
||||||
|
cy.get('input.username').type(username)
|
||||||
|
cy.get('input.password').type(password)
|
||||||
|
|
||||||
|
cy.get('.login-group button').click()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
visitPage('home')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('1 | Add one viewbox', (done) => {
|
||||||
|
const viewbox_table = 'mpe_audit'
|
||||||
|
const columns = ['LOAD_REF', 'LIBREF', 'DSN', 'KEY_HASH', 'TGTVAR_NM']
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
cy.get('.viewbox-open').click()
|
||||||
|
openTableFromViewboxTree(libraryToOpenIncludes, [viewbox_table])
|
||||||
|
|
||||||
|
cy.get('.open-viewbox').then((viewboxNodes: any) => {
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
if (!viewboxNode.innerText.toLowerCase().includes(viewbox_table)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
checkColumns(columns, () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('2 | Add two viewboxes', (done) => {
|
||||||
|
const viewboxes = [
|
||||||
|
{
|
||||||
|
viewbox_table: 'mpe_audit',
|
||||||
|
columns: ['LOAD_REF', 'LIBREF', 'DSN', 'KEY_HASH', 'TGTVAR_NM']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
viewbox_table: 'mpe_alerts',
|
||||||
|
columns: [
|
||||||
|
'TX_FROM',
|
||||||
|
'ALERT_EVENT',
|
||||||
|
'ALERT_LIB',
|
||||||
|
'ALERT_DS',
|
||||||
|
'ALERT_USER'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
cy.get('.viewbox-open').click()
|
||||||
|
openTableFromViewboxTree(
|
||||||
|
libraryToOpenIncludes,
|
||||||
|
viewboxes.map((viewbox) => viewbox.viewbox_table))
|
||||||
|
cy.get('.open-viewbox').then((viewboxNodes: any) => {
|
||||||
|
let found = 0
|
||||||
|
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
for (let viewbox of viewboxes) {
|
||||||
|
if (
|
||||||
|
viewboxNode.innerText.toLowerCase().includes(viewbox.viewbox_table)
|
||||||
|
)
|
||||||
|
found++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found < viewboxes.length) return
|
||||||
|
|
||||||
|
cy.get('.viewboxes-container .viewbox', { withinSubject: null }).then((viewboxNodes: any) => {
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
cy.get(viewboxNode).within(() => {
|
||||||
|
cy.get('.table-title').then((tableTitle) => {
|
||||||
|
const title = tableTitle[0].innerText
|
||||||
|
const viewbox = viewboxes.find((vb) =>
|
||||||
|
title.toLowerCase().includes(vb.viewbox_table)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (viewbox) {
|
||||||
|
cy.get('.ht_master.handsontable .htCore thead tr').then(
|
||||||
|
(viewboxColNodes: any) => {
|
||||||
|
let allColsHtml = viewboxColNodes[0].innerHTML
|
||||||
|
|
||||||
|
for (let col of viewbox?.columns) {
|
||||||
|
if (!allColsHtml.includes(col)) return
|
||||||
|
}
|
||||||
|
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('3 | Add viewbox, add columns', (done) => {
|
||||||
|
const viewbox_table = 'mpe_audit'
|
||||||
|
const columns = ['LOAD_REF', 'LIBREF', 'DSN', 'KEY_HASH', 'TGTVAR_NM']
|
||||||
|
const additionalColumns = ['IS_PK']
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
cy.get('.viewbox-open').click()
|
||||||
|
openTableFromViewboxTree(libraryToOpenIncludes, [viewbox_table])
|
||||||
|
|
||||||
|
cy.get('.open-viewbox').then((viewboxNodes: any) => {
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
if (!viewboxNode.innerText.toLowerCase().includes(viewbox_table)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
openViewboxConfig(viewbox_table)
|
||||||
|
|
||||||
|
removeAllColumns()
|
||||||
|
|
||||||
|
addColumns(additionalColumns)
|
||||||
|
|
||||||
|
checkColumns([...columns, ...additionalColumns], () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('4 | Add viewbox, add columns and reorder', (done) => {
|
||||||
|
const viewbox_table = 'mpe_audit'
|
||||||
|
const columns = ['LOAD_REF', 'LIBREF', 'DSN', 'KEY_HASH', 'TGTVAR_NM']
|
||||||
|
const additionalColumns = ['IS_PK', 'MOVE_TYPE']
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
cy.get('.viewbox-open').click()
|
||||||
|
openTableFromViewboxTree(libraryToOpenIncludes, [viewbox_table])
|
||||||
|
|
||||||
|
cy.get('.open-viewbox').then((viewboxNodes: any) => {
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
if (!viewboxNode.innerText.toLowerCase().includes(viewbox_table)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
openViewboxConfig(viewbox_table)
|
||||||
|
|
||||||
|
removeAllColumns()
|
||||||
|
|
||||||
|
addColumns(additionalColumns, () => {
|
||||||
|
cy.wait(1000)
|
||||||
|
//reorder
|
||||||
|
cy.get('.col-box.column-MOVE_TYPE')
|
||||||
|
.realMouseDown({ button: 'left', position: 'center' })
|
||||||
|
.realMouseMove(0, 10, { position: 'center' })
|
||||||
|
cy.wait(200) // In our case, we wait 200ms cause we have animations which we are sure that take this amount of time
|
||||||
|
cy.get('.col-box.column-IS_PK')
|
||||||
|
.realMouseMove(0, 0, { position: 'center' })
|
||||||
|
.realMouseUp()
|
||||||
|
//reorder end
|
||||||
|
|
||||||
|
cy.wait(500)
|
||||||
|
|
||||||
|
checkColumns([...columns, ...additionalColumns.reverse()], () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('5 | Add viewbox, add columns, reorder, remove column, add again', (done) => {
|
||||||
|
const viewbox_table = 'mpe_audit'
|
||||||
|
const columns = ['LOAD_REF', 'LIBREF', 'DSN', 'KEY_HASH', 'TGTVAR_NM']
|
||||||
|
const additionalColumns = ['IS_PK', 'MOVE_TYPE']
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
cy.get('.viewbox-open').click()
|
||||||
|
openTableFromViewboxTree(libraryToOpenIncludes, [viewbox_table])
|
||||||
|
|
||||||
|
cy.get('.open-viewbox').then((viewboxNodes: any) => {
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
if (!viewboxNode.innerText.toLowerCase().includes(viewbox_table)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viewboxNode.click()
|
||||||
|
|
||||||
|
removeAllColumns()
|
||||||
|
|
||||||
|
addColumns(additionalColumns, () => {
|
||||||
|
cy.wait(1000)
|
||||||
|
//reorder
|
||||||
|
cy.get('.col-box.column-MOVE_TYPE')
|
||||||
|
.realMouseDown({ button: 'left', position: 'center' })
|
||||||
|
.realMouseMove(0, 10, { position: 'center' })
|
||||||
|
cy.wait(200) // In our case, we wait 200ms cause we have animations which we are sure that take this amount of time
|
||||||
|
cy.get('.col-box.column-IS_PK')
|
||||||
|
.realMouseMove(0, 0, { position: 'center' })
|
||||||
|
.realMouseUp()
|
||||||
|
//reorder end
|
||||||
|
|
||||||
|
cy.wait(500)
|
||||||
|
|
||||||
|
checkColumns([...columns, ...additionalColumns.reverse()], () => {
|
||||||
|
const colToRemove = 'MOVE_TYPE'
|
||||||
|
|
||||||
|
removeColumn(colToRemove)
|
||||||
|
checkColumns(
|
||||||
|
[
|
||||||
|
...columns,
|
||||||
|
...additionalColumns.filter((col) => col !== colToRemove)
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
addColumns([colToRemove], () => {
|
||||||
|
checkColumns(
|
||||||
|
[...columns, ...additionalColumns.reverse()],
|
||||||
|
() => {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('6 | Add viewboxes, reload and check url restored configuration', (done) => {
|
||||||
|
const viewboxes = [
|
||||||
|
{
|
||||||
|
viewbox_table: 'mpe_audit',
|
||||||
|
columns: ['LOAD_REF', 'LIBREF', 'DSN', 'KEY_HASH', 'TGTVAR_NM'],
|
||||||
|
additionalColumns: ['IS_PK', 'MOVE_TYPE']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
viewbox_table: 'mpe_alerts',
|
||||||
|
columns: [
|
||||||
|
'TX_FROM',
|
||||||
|
'ALERT_EVENT',
|
||||||
|
'ALERT_LIB',
|
||||||
|
'ALERT_DS',
|
||||||
|
'ALERT_USER'
|
||||||
|
],
|
||||||
|
additionalColumns: ['TX_TO']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
cy.get('.viewbox-open').click()
|
||||||
|
openTableFromViewboxTree(libraryToOpenIncludes, [
|
||||||
|
viewboxes[0].viewbox_table,
|
||||||
|
viewboxes[1].viewbox_table
|
||||||
|
])
|
||||||
|
|
||||||
|
openViewboxConfig(viewboxes[0].viewbox_table)
|
||||||
|
|
||||||
|
cy.wait(500)
|
||||||
|
|
||||||
|
removeAllColumns()
|
||||||
|
|
||||||
|
addColumns(viewboxes[0].additionalColumns, () => {
|
||||||
|
cy.wait(1000)
|
||||||
|
|
||||||
|
if (viewboxes[0].viewbox_table === 'mpe_audit') {
|
||||||
|
cy.get('.col-box.column-MOVE_TYPE')
|
||||||
|
.realMouseDown({ button: 'left', position: 'center' })
|
||||||
|
.realMouseMove(0, 10, { position: 'center' })
|
||||||
|
cy.wait(200) // In our case, we wait 200ms cause we have animations which we are sure that take this amount of time
|
||||||
|
cy.get('.col-box.column-IS_PK')
|
||||||
|
.realMouseMove(0, 0, { position: 'center' })
|
||||||
|
.realMouseUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.wait(1000)
|
||||||
|
|
||||||
|
openViewboxConfig(viewboxes[1].viewbox_table)
|
||||||
|
|
||||||
|
addColumns(viewboxes[1].additionalColumns, () => {
|
||||||
|
cy.wait(1000).reload()
|
||||||
|
|
||||||
|
let result = 0
|
||||||
|
|
||||||
|
checkColumns(
|
||||||
|
[
|
||||||
|
...viewboxes[0].columns,
|
||||||
|
...cloneDeep(viewboxes[0].additionalColumns.reverse())
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
result++
|
||||||
|
|
||||||
|
if (result === 2) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
checkColumns(
|
||||||
|
[...viewboxes[1].columns, ...viewboxes[1].additionalColumns],
|
||||||
|
() => {
|
||||||
|
result++
|
||||||
|
|
||||||
|
if (result === 2) done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// We will enable this test when we figure out how to mock filtering
|
||||||
|
// it('7 | Add viewboxes and filter', () => {
|
||||||
|
// const viewboxes = ['mpe_x_test', 'mpe_validations']
|
||||||
|
|
||||||
|
// openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||||
|
|
||||||
|
// cy.get('.viewbox-open').click()
|
||||||
|
// openTableFromViewboxTree(libraryToOpenIncludes, viewboxes)
|
||||||
|
|
||||||
|
// cy.wait(1000)
|
||||||
|
|
||||||
|
// closeViewboxModal()
|
||||||
|
|
||||||
|
// cy.get('.viewboxes-container .viewbox', { withinSubject: null }).then(
|
||||||
|
// (viewboxNodes: any) => {
|
||||||
|
// for (let viewboxNode of viewboxNodes) {
|
||||||
|
// cy.get(viewboxNode).within(() => {
|
||||||
|
// cy.get('.table-title').then((title: any) => {
|
||||||
|
// cy.get('.hot-spinner')
|
||||||
|
// .should('not.exist')
|
||||||
|
// .then(() => {
|
||||||
|
// cy.get('clr-icon[shape="filter"]').then((filterButton) => {
|
||||||
|
// filterButton[0].click()
|
||||||
|
// })
|
||||||
|
|
||||||
|
// if (title[0].innerText.includes('MPE_X_TEST')) {
|
||||||
|
// setFilterWithValue(
|
||||||
|
// 'SOME_CHAR',
|
||||||
|
// 'this is dummy data',
|
||||||
|
// 'value',
|
||||||
|
// () => {
|
||||||
|
// cy.get('app-query', { withinSubject: null })
|
||||||
|
// .should('not.exist')
|
||||||
|
// .get('.ht_master.handsontable tbody tr')
|
||||||
|
// .then((rowNodes) => {
|
||||||
|
// const tr = rowNodes[0]
|
||||||
|
|
||||||
|
// expect(rowNodes).to.have.length(1)
|
||||||
|
// expect(tr.innerText).to.equal('0')
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// } else if (title[0].innerText.includes('MPE_VALIDATIONS')) {
|
||||||
|
// setFilterWithValue('BASE_COL', 'ALERT_LIB', 'value', () => {
|
||||||
|
// cy.get('app-query', { withinSubject: null })
|
||||||
|
// .should('not.exist')
|
||||||
|
// .get('.ht_master.handsontable tbody tr')
|
||||||
|
// .then((rowNodes) => {
|
||||||
|
// const tr = rowNodes[0]
|
||||||
|
|
||||||
|
// expect(rowNodes).to.have.length(1)
|
||||||
|
// expect(tr.innerText).to.contain('ALERT_LIB')
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const removeAllColumns = () => {
|
||||||
|
cy.get('.configuration-wrapper clr-icon[shape="trash"]').then(removeNodes => {
|
||||||
|
for (let removeNode of removeNodes) {
|
||||||
|
removeNode.click()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkColumns = (columns: string[], callback: () => void) => {
|
||||||
|
cy.get('.viewboxes-container .viewbox', { withinSubject: null }).then(
|
||||||
|
(viewboxNodes: any) => {
|
||||||
|
for (let viewboxNode of viewboxNodes) {
|
||||||
|
cy.get(viewboxNode).within(() => {
|
||||||
|
cy.get('.ht_master.handsontable thead tr th').then(
|
||||||
|
(viewboxColNodes: any) => {
|
||||||
|
console.log('viewboxColNode', viewboxColNodes)
|
||||||
|
console.log('columns', columns)
|
||||||
|
for (let i = 0; i < viewboxColNodes.length; i++) {
|
||||||
|
const col = columns[i]|| ''
|
||||||
|
const colNode = viewboxColNodes[i]
|
||||||
|
|
||||||
|
if (
|
||||||
|
!colNode.innerHTML.toLowerCase().includes(col.toLowerCase())
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeViewboxModal = () => {
|
||||||
|
cy.get('app-viewboxes .close', { withinSubject: null }).click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeColumn = (column: string) => {
|
||||||
|
cy.get(`.col-box.column-${column} clr-icon`, { withinSubject: null }).click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const addColumns = (columns: string[], callback?: () => void) => {
|
||||||
|
for (let i = 0; i < columns.length; i++) {
|
||||||
|
const column = columns[i]
|
||||||
|
|
||||||
|
cy.get('.cols-search input', { withinSubject: null }).type(column)
|
||||||
|
cy.get('.cols-search .autocomplete-wrapper', { withinSubject: null })
|
||||||
|
.first()
|
||||||
|
.trigger('keydown', { key: 'ArrowDown' })
|
||||||
|
cy.get('.cols-search .autocomplete-wrapper', { withinSubject: null })
|
||||||
|
.first()
|
||||||
|
.trigger('keydown', { key: 'Enter' })
|
||||||
|
.then(() => {
|
||||||
|
if (i === columns.length - 1 && callback) callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const openViewboxConfig = (viewbox_tablename: string) => {
|
||||||
|
cy.get('.open-viewbox').then((viewboxes: any) => {
|
||||||
|
for (let openViewbox of viewboxes) {
|
||||||
|
if (openViewbox.innerText.toLowerCase().includes(viewbox_tablename))
|
||||||
|
openViewbox.click()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromTree = (libNameIncludes: string, tablename: string) => {
|
||||||
|
cy.get('.app-loading', { timeout: longerCommandTimeout })
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.nav-tree clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (new RegExp(libNameIncludes).test(node.innerText.toLowerCase())) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('.clr-tree-node-content-container p').click()
|
||||||
|
|
||||||
|
cy.get('.clr-treenode-link').then((innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFilterWithValue = (
|
||||||
|
variableValue: string,
|
||||||
|
valueString: string,
|
||||||
|
valueField: 'value' | 'time' | 'date' | 'datetime' | 'in' | 'between',
|
||||||
|
callback?: any
|
||||||
|
) => {
|
||||||
|
cy.wait(600)
|
||||||
|
|
||||||
|
cy.focused().type(variableValue)
|
||||||
|
cy.wait(100)
|
||||||
|
// cy.focused().trigger('input')
|
||||||
|
cy.get('.variable-col .autocomplete-wrapper', { withinSubject: null })
|
||||||
|
.first()
|
||||||
|
.trigger('keydown', { key: 'ArrowDown' })
|
||||||
|
cy.get('.variable-col .autocomplete-wrapper', {
|
||||||
|
withinSubject: null
|
||||||
|
}).trigger('keydown', { key: 'Enter' })
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
|
||||||
|
if (valueField === 'in') {
|
||||||
|
cy.focused().select(valueField.toUpperCase()).trigger('change')
|
||||||
|
} else if (valueField === 'between') {
|
||||||
|
cy.focused().select(valueField.toUpperCase()).trigger('change')
|
||||||
|
} else {
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (valueField) {
|
||||||
|
case 'value': {
|
||||||
|
cy.focused().type(valueString)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'time': {
|
||||||
|
cy.focused().type(valueString)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'date': {
|
||||||
|
cy.focused().type(valueString)
|
||||||
|
cy.focused().tab()
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'datetime': {
|
||||||
|
const date = valueString.split(' ')[0]
|
||||||
|
const time = valueString.split(' ')[1]
|
||||||
|
|
||||||
|
cy.focused().type(date)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().type(time)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'in': {
|
||||||
|
cy.get('.checkbox-vals').then(() => {
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().click()
|
||||||
|
cy.get('.no-values')
|
||||||
|
.should('not.exist')
|
||||||
|
.then(() => {
|
||||||
|
cy.get('clr-checkbox-wrapper input').then((inputs: any) => {
|
||||||
|
inputs[0].click()
|
||||||
|
cy.get('.in-values-modal .modal-footer button').click()
|
||||||
|
|
||||||
|
cy.get('.modal-footer .btn-success-outline').click()
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'between': {
|
||||||
|
cy.focused().tab()
|
||||||
|
|
||||||
|
const start = valueString.split('-')[0]
|
||||||
|
const end = valueString.split('-')[1]
|
||||||
|
|
||||||
|
cy.focused().type(start)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.focused().type(end)
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().tab()
|
||||||
|
cy.wait(100)
|
||||||
|
cy.focused().click()
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTableFromViewboxTree = (
|
||||||
|
libNameIncludes: string,
|
||||||
|
tablenames: string[]
|
||||||
|
) => {
|
||||||
|
cy.get('.add-new clr-tree > clr-tree-node', {
|
||||||
|
timeout: longerCommandTimeout
|
||||||
|
}).then((treeNodes: any) => {
|
||||||
|
let viyaLib
|
||||||
|
|
||||||
|
for (let node of treeNodes) {
|
||||||
|
if (node.innerText.toLowerCase().includes(libNameIncludes)) {
|
||||||
|
viyaLib = node
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(viyaLib).within(() => {
|
||||||
|
cy.get('p')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.get('.clr-treenode-link').then(async (innerNodes: any) => {
|
||||||
|
for (let innerNode of innerNodes) {
|
||||||
|
for (let tablename of tablenames) {
|
||||||
|
await pause(300)
|
||||||
|
if (innerNode.innerText.toLowerCase().includes(tablename)) {
|
||||||
|
innerNode.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const pause = (ms: number) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(null)
|
||||||
|
}, ms)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const visitPage = (url: string) => {
|
||||||
|
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||||
|
}
|
23
client/cypress/support/e2e.ts
Normal file
23
client/cypress/support/e2e.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// ***********************************************************
|
||||||
|
// This example support/e2e.ts is processed and
|
||||||
|
// loaded automatically before your test files.
|
||||||
|
//
|
||||||
|
// This is a great place to put global configuration and
|
||||||
|
// behavior that modifies Cypress.
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off
|
||||||
|
// automatically serving support files with the
|
||||||
|
// 'supportFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/configuration
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// Import commands.js using ES2015 syntax:
|
||||||
|
import './commands'
|
||||||
|
|
||||||
|
// Alternatively you can use CommonJS syntax:
|
||||||
|
// require('./commands')
|
||||||
|
|
||||||
|
import 'cypress-plugin-tab'
|
||||||
|
import "cypress-real-events"
|
1468
client/package-lock.json
generated
1468
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -88,7 +88,7 @@
|
|||||||
"@angular-eslint/template-parser": "16.0.3",
|
"@angular-eslint/template-parser": "16.0.3",
|
||||||
"@angular/cli": "^16.1.0",
|
"@angular/cli": "^16.1.0",
|
||||||
"@angular/compiler-cli": "^16.1.2",
|
"@angular/compiler-cli": "^16.1.2",
|
||||||
"@cypress/webpack-preprocessor": "^5.11.1",
|
"@cypress/webpack-preprocessor": "^5.17.1",
|
||||||
"@types/core-js": "^2.5.5",
|
"@types/core-js": "^2.5.5",
|
||||||
"@types/crypto-js": "^4.0.1",
|
"@types/crypto-js": "^4.0.1",
|
||||||
"@types/es6-shim": "^0.31.39",
|
"@types/es6-shim": "^0.31.39",
|
||||||
@ -99,10 +99,10 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
||||||
"@typescript-eslint/parser": "^5.29.0",
|
"@typescript-eslint/parser": "^5.29.0",
|
||||||
"core-js": "^2.5.4",
|
"core-js": "^2.5.4",
|
||||||
"cypress": "^9.5.3",
|
"cypress": "12.17.1",
|
||||||
"cypress-file-upload": "^5.0.8",
|
"cypress-file-upload": "^5.0.8",
|
||||||
"cypress-plugin-tab": "^1.0.5",
|
"cypress-plugin-tab": "^1.0.5",
|
||||||
"cypress-real-events": "^1.7.6",
|
"cypress-real-events": "^1.8.1",
|
||||||
"es6-shim": "^0.35.5",
|
"es6-shim": "^0.35.5",
|
||||||
"eslint": "^8.33.0",
|
"eslint": "^8.33.0",
|
||||||
"git-describe": "^4.0.4",
|
"git-describe": "^4.0.4",
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
npm run cy:run -- --browser chrome --spec "cypress/integration/liveness.tests.ts"
|
|
||||||
npm run cy:run -- --browser chrome --spec "cypress/integration/editor.tests.ts"
|
|
||||||
npm run cy:run -- --browser chrome --spec "cypress/integration/excel.tests.ts"
|
|
||||||
npm run cy:run -- --browser chrome --spec "cypress/integration/filtering.tests.ts"
|
|
||||||
npm run cy:run -- --browser chrome --spec "cypress/integration/licensing.tests.ts"
|
|
@ -597,7 +597,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</clr-modal>
|
</clr-modal>
|
||||||
<clr-modal [(clrModalOpen)]="pkDups">
|
<clr-modal class="duplicate-keys-modal" [(clrModalOpen)]="pkDups">
|
||||||
<h3 class="modal-title">Error</h3>
|
<h3 class="modal-title">Error</h3>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>
|
<p>
|
||||||
|
@ -1019,6 +1019,16 @@ export class EditorComponent implements OnInit, AfterViewInit {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.validatePrimaryKeys()
|
||||||
|
|
||||||
|
if (this.duplicatePkIndexes.length !== 0) {
|
||||||
|
this.pkDups = true
|
||||||
|
this.submit = false
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
this.pkDups = false
|
||||||
|
}
|
||||||
|
|
||||||
this.uploadLoading = true
|
this.uploadLoading = true
|
||||||
let filesToUpload: UploadFile[] = []
|
let filesToUpload: UploadFile[] = []
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
[(ngModel)]="usePickers"
|
[(ngModel)]="usePickers"
|
||||||
(change)="usePickersChange()"
|
(change)="usePickersChange()"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
id="usePickers"
|
||||||
/>
|
/>
|
||||||
<label class="clr-control-label"> Use pickers </label>
|
<label class="clr-control-label"> Use pickers </label>
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"licenceKey": "CFG2LNF1SYGgRPTwegsgRolmXw0xQmDpbagjRTniIarWXFE+/eClT4m+64U2kL5BBj0p3UwS80+wEer+jaw5w4OX27mDfXAUvkv90k54ER6GP5C5Z/t4VYucQo3Kn8wfhfFOymjRVtKZaHyavl9hBaWGwohX7W+97gsj5pnI9a/63w55OKNJvgeZrCxR04qhRiuf9K1J5EQtKP+wfW/ERoX3R4dPWKANjyFZkURs2GL/UDCGS6nPWTS8grlcinFUhh4V3hIZmzlWc5FG97lrbxnmq4FsdEaey4z4l70H4Yf/52ZZqJzaOyRGeQXmUtpS",
|
"licenceKey": "invalid",
|
||||||
"activationKey": "MIIEbQIBADANBgkqhkiG9w0BAQEFAASCBFcwggRTAgEAAoHxAM0ayGUZgn7ZBBoEDwGYbTaKf85WIGInISinE2WisHZv6AaivG/tNo/K+Ms7b2EnwvIg4vUKKbKtoD9E3Fk1B0LV2qmKlv+TcZQ0YXXhRguaHcewGcwof7aJr+iTrD4CoL/H7gs3JvVshCRq7bfX59dXDlVdm8TkDglQMTyxX+L3JirAII4xbbJ7cTNoBnzgyi4n2Aa0+zFlq2WDzRjECxdcAm79lipQRW/AOjPFxEYIjOl+Uzv9yxOGdrFLAJkCznhnWC+D28qCaM+vCEDDW9tvmSdf7nsnlY46xud6sNnVgO/1LvC3VGkZ5zNZCx9XRwIDAQABAoHwT0qjXjJWeKN9KnGXO46p6gPxFNvG+SsXbpfor8oNXjw0/xu6raqPBVf6htcbX/v3KZP9Ka4cIK9u3AbLCNGvVO9H8XNanMNrjVgStXe5lJKoIKK71mlxtifUkZ1FYVOywXGRXVSdAxRIoauU6xXU0zMcn3Po3F0tPpi/C5xCcz0eOjLCx+eJc3U2IZKsQ7lHO7azCT9woguj09/xVW0481T6zuF6e0Oq4MWlt0qJPkkuLcMF6ps+ObHUB3044VDcm6X7kZjtcwnj886Y6n9llTNzHiui4R5eMSzm1w57jwR5m/Q1AOTGCyiW1KLI1eIBAnkA8Ma4zvkn44w0E1Dlrq/97vdJsUiE7Ifs5DknRU81imm0+LP2yyX7tBRpVcvrVkH2x/qW3bHLHFdV5o9A262Wcqdk2ZkMHp+gD59OsrcbRBokiwqU6nagLbYbC7RA2PZRMR48s8bWAnzFae0P8FFJlmKUHggarUDnAnkA2hKrOplw1C0X2QVeVQOlU36PjayVJEwkxq30k0wg+q9F464TrraRr5uFqMrAmwGN5ziZQ1Jzx3R2uBHft67FwXJfGy21Hor47sb+f5VkAuXPurbp6K+sMWRfIehK9/G9Iju90Iv6Oto4uv/yfdWadxCLc8tYy4qhAngUA/EJA51VRSpvEKKHSwoI+3WczzJ9ly8SKc4h7Nu+jdsFcbBqYtXxumCnSTRfD0y8gxBXjZgc2wXBDNePa3a+QTwY+qgPQ6XCprOcF6yklKfFBzQp6YKXSjQlXO6nGpLVSnYxW64ettCSZaqVh6xeXAOEG5hcHrECeFTYEpqX/Ffwu2iKOCtnYblcckmyrcwTe/N41sFAS0x9SPnOToYZLhFett/3Eny8XBNr5+VTfQxK+a2f9qSmcPZUo0AVxnP9qeBst7O30dN2yh1g8RzAzIPjA0hT8mcJPIbHK5CqBU9Ee/H1hskChDhyzW7d3MxEQQJ4QB6FIMNVQQh05iIB64SzxVvpI/ggOKDGO2/b2zILsKWiw4NhppEphmhXvuJy5TGFYERoGydaW6dKfau6rDSWGNbjPuFwmkUTUjzh2gR5rCp0Ifapd6D5sWDFaI+F4gEUaxmC9yJL8i6/JpMx3LRut1g5dsH6chhT"
|
"activationKey": "invalid"
|
||||||
}
|
}
|
@ -1,16 +1,6 @@
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
let iwantFileText = ''
|
let iwantFileText = ''
|
||||||
// let filterQuery1 = `AND,AND,0,SOME_CHAR,=,"'this is dummy data'"`
|
|
||||||
// let filterQuery2 = `AND,AND,0,SOME_NUM,=,42`
|
|
||||||
// let filterQuery3 = `AND,AND,0,SOME_TIME,=,00:00:42`
|
|
||||||
// let filterQuery4 = `AND,AND,0,SOME_TIME,=,42`
|
|
||||||
// let filterQuery5 = `AND,AND,0,SOME_DATE,=,42`
|
|
||||||
// let filterQuery6 = `AND,AND,0,SOME_DATE,=,42`
|
|
||||||
// let filterQuery7 = `AND,AND,0,SOME_DATETIME,=,42`
|
|
||||||
// let filterQuery8 = `AND,AND,0,SOME_DATETIME,=,42`
|
|
||||||
// let filterQuery9 = `AND,AND,0,SOME_DATE,IN,(0)`
|
|
||||||
// let filterQuery10 = `AND,AND,0,SOME_BESTNUM,BETWEEN,0 AND 10`
|
|
||||||
|
|
||||||
let appLoc = path.join(..._program.split('services')[0].split('/'))
|
let appLoc = path.join(..._program.split('services')[0].split('/'))
|
||||||
const sessionStoragePath = path.resolve(__dirname, '..', '..', 'drive', 'files', appLoc, 'mock-storage')
|
const sessionStoragePath = path.resolve(__dirname, '..', '..', 'drive', 'files', appLoc, 'mock-storage')
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,15 @@ _webout = `{"SYSDATE" : "26SEP22"
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"MEMNAME": "MPE_X_TEST"
|
"MEMNAME": "MPE_X_TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MEMNAME": "MPE_AUDIT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MEMNAME": "MPE_ALERTS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MEMNAME": "MPE_VALIDATIONS"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
, "libinfo":
|
, "libinfo":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user