Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4924df2ef3 | ||
| 2e141a5d52 | |||
|
|
cb1978bcaf | ||
|
|
387f5122f1 | ||
|
|
db5887de21 | ||
| fe24d9bcbd | |||
|
|
6c6b1cbf46 | ||
|
|
4d65c9c999 | ||
| 4417279275 | |||
|
|
365f12996d | ||
|
|
ef1015f33b | ||
| b43dfb5cf4 | |||
|
|
225e693d1f | ||
|
|
fda91770be | ||
| d512876e0b | |||
|
|
2ba4b5383e | ||
| ecc3184609 | |||
|
|
712b384848 | ||
|
|
26cdd73331 | ||
|
|
919aa6dcfe | ||
|
|
3bb3093b49 | ||
|
|
9c12250558 | ||
|
|
6c843f64fb | ||
|
|
3fda7dc5b0 | ||
|
|
22ec7f0340 | ||
|
|
378461dcbb | ||
|
|
905c7b9d3c | ||
|
|
670ec2c71c | ||
|
|
b419cd5078 | ||
|
|
b1db4ea590 | ||
| 822ddb1274 | |||
|
|
672dd6d4f1 | ||
|
|
b3ac73d903 | ||
|
|
f8554dd5e7 | ||
| 88679c0c9a | |||
|
|
a08a717ca8 | ||
| c8b6fdbfdb | |||
|
|
b495c41626 | ||
|
|
7f4be474c6 | ||
| 7f6f68fcbb | |||
|
|
03fd7db033 | ||
|
|
9dc5c66f7b | ||
|
|
aa1b08632e | ||
|
|
6bbe354c9e | ||
|
|
8ff429793b | ||
|
|
70d010127a | ||
|
|
696717c509 | ||
|
|
71c308d052 | ||
|
|
bed5b320ad | ||
| b0e827412e | |||
|
|
63e9af402e | ||
| fd55105f62 | |||
|
|
c2e3b362e7 | ||
|
|
5d2d60d040 | ||
| 0e59f5406f | |||
|
|
e7cb471c0b | ||
|
|
0465089207 | ||
|
|
4f2f59907c | ||
|
|
7d85328d41 | ||
| f2a9329196 | |||
|
|
7a8231615c | ||
|
|
0db6b25327 | ||
| e91f6f01a6 | |||
|
|
0b4042af60 | ||
|
|
519d8953b5 | ||
| 14a616fc1b | |||
| bfe5a8626f | |||
|
|
4ecd186e5c | ||
|
|
8c60473c15 | ||
| bb126eba5b | |||
|
|
d1998422d2 | ||
|
|
69f687a85f | ||
|
|
2aa19d1dca | ||
|
|
e44a25dcc3 | ||
|
|
efb5ffa906 | ||
|
|
b4c586a859 | ||
|
|
e874143a95 | ||
|
|
e4dbab8b16 | ||
|
|
f6d7d6f90c | ||
|
|
063c90caf4 | ||
|
|
2011c2eee7 | ||
|
|
24545f2acd | ||
| a7c81245ff | |||
|
|
4f2c993b2d | ||
|
|
e5f8e500c1 | ||
|
|
a61e2de140 | ||
| 881d2b060e | |||
|
|
4830c6d219 | ||
|
|
4c3c9ac88c | ||
| 7e1c610a4d | |||
|
|
8139f495ce | ||
|
|
89ab296151 | ||
|
|
a0dc92c403 | ||
|
|
86134f478a | ||
|
|
9a2addc18e | ||
| 9264ce2a60 | |||
|
|
cbd69df708 | ||
|
|
ca7caa25b6 | ||
| c10330627f | |||
| d80c59afce | |||
|
|
abdbb67471 | ||
|
|
037a97b6ff | ||
|
|
a0a529ad38 | ||
|
|
72239558af | ||
|
|
d2097ad6dd | ||
| 1bd542cddb | |||
| fb1c1ee874 | |||
|
|
624a7a8f37 | ||
|
|
381378f532 | ||
| af05486c0e | |||
|
|
4b558948d9 | ||
|
|
d9cff42f5c | ||
| 2a3d2b8d0d | |||
|
|
d0f453d291 | ||
|
|
8e65dd0eae | ||
|
|
da4d0b28c7 | ||
|
|
6c96ef7fb0 | ||
|
|
997f09adde | ||
|
|
0e8503ed2b | ||
| 97dfcd79b1 | |||
| 9a12a2e41f | |||
|
|
5c114e562b | ||
| ae696a0be0 | |||
|
|
22d46a5dcc | ||
|
|
f3125ff464 | ||
|
|
9682b548e6 | ||
|
|
ec11a74265 | ||
| 4be0614604 | |||
|
|
27cbff2bc5 | ||
|
|
c41c8963f2 | ||
|
|
7249d4fa29 | ||
|
|
2e0c60cc0d | ||
| 7c5e47f5e4 | |||
|
|
f9decbd366 | ||
|
|
1dc69341ca | ||
|
|
75ae19fa8e | ||
|
|
9de04e9a0c | ||
|
|
983f59cd51 | ||
|
|
7b5e7ae184 | ||
|
|
6e96b1daec | ||
|
|
9604661f3b | ||
|
|
4bd215491f | ||
|
|
6a7dd451b5 | ||
|
|
841201adab | ||
|
|
e013e62776 | ||
|
|
6c171a6394 | ||
|
|
a377f6e8d6 | ||
| 0337318e0b | |||
|
|
2844c70f95 | ||
|
|
7e11c8f375 | ||
| 23cbbce964 | |||
|
|
c63fcdd465 | ||
|
|
82412b2659 | ||
| eef3832e40 | |||
| 63b75a1c61 | |||
| d1f0879f0a | |||
|
|
36416aab2e | ||
|
|
7f3577c3ef | ||
|
|
69f883034f | ||
|
|
1c56af01d0 | ||
|
|
43c0f73c21 | ||
|
|
e8cd3d63da | ||
|
|
b7f564cb21 | ||
|
|
3f5cb1e2de | ||
|
|
7d8c0472f0 | ||
| b8b516ba77 | |||
|
|
83b3d775b6 | ||
|
|
aea252ccc6 | ||
| d8908f9c7f | |||
|
|
95289aa952 | ||
|
|
149e318a87 | ||
|
|
8657826e60 | ||
|
|
a45f5bb3b2 | ||
|
|
ae9a91a7a1 | ||
|
|
3638bde633 | ||
| 3a2361f42c | |||
|
|
1bd0eef913 | ||
| 85aa3b38b7 | |||
| 678859a68d | |||
|
|
e531acee3f | ||
|
|
4a45ebfe3b | ||
| 8fb9a344f2 | |||
|
|
8829b60220 | ||
|
|
4e64f28732 | ||
| a0749de700 | |||
| f9623e046e | |||
|
|
bce1fd57ef | ||
|
|
c6a1c53b46 | ||
| e36229e4c4 | |||
|
|
853c1bc23e | ||
|
|
3b6f6853bc | ||
|
|
b415437662 | ||
|
|
24df878abe | ||
|
|
f474673a14 | ||
|
|
c53ab85107 | ||
|
|
5c4dd7c9e3 | ||
|
|
217220ffaa | ||
|
|
c89a3049fa | ||
| bb12bff9db | |||
|
|
30d5e51d0b | ||
|
|
cd3bcc0ee3 | ||
| ef1ba824c3 | |||
| bc45e92138 | |||
|
|
c2f36f5419 | ||
| 31a31612fc | |||
|
|
f9c2491ab6 | ||
|
|
3de095fe77 | ||
|
|
e4e04a193f | ||
|
|
a1a90519c5 | ||
|
|
522979835c | ||
| fe049256b5 | |||
|
|
31d1870198 | ||
|
|
6edf0dfb31 | ||
| 3bf3dceaa2 | |||
|
|
ce503653cd | ||
|
|
caa9854ff0 | ||
|
|
20c3a338c5 | ||
|
|
6547461637 | ||
|
|
bbb725c64c | ||
| 403d08c86a | |||
|
|
f66d9f511a | ||
|
|
dd2138ac5e | ||
| 74e9979c67 | |||
|
|
ddc22e5200 | ||
|
|
4218da91cd | ||
|
|
857b94f44f | ||
|
|
a3ce367950 | ||
|
|
75dac54591 | ||
| a156c0111b | |||
| e5d93fd7d6 | |||
|
|
67436f4ff9 | ||
|
|
b712f851a2 | ||
| e2c0b8da86 | |||
|
|
1b4560061d | ||
|
|
d94df7f0eb | ||
|
|
fa04d7bf4e | ||
|
|
4d4cabb465 | ||
|
|
d4fee791a7 | ||
|
|
82c285e348 | ||
|
|
4d276657b3 | ||
|
|
cffeab813d | ||
|
|
18363bbbeb | ||
|
|
6df7d8d2ba | ||
|
|
5deba44d2b | ||
|
|
0a8b1e764c | ||
|
|
fc52e8f41a | ||
|
|
efcdc694dd | ||
|
|
eb7c44333c |
@@ -1,11 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Avoid commits to the master branch
|
||||
BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||
REGEX="^(master|development)$"
|
||||
# Using `--silent` helps for showing any errs in the first line of the response
|
||||
# The first line is picked up by the VS Code GIT UI popup when rc is not 0
|
||||
|
||||
if [[ "$BRANCH" =~ $REGEX ]]; then
|
||||
echo "You are on branch $BRANCH. Are you sure you want to commit to this branch?"
|
||||
echo "If so, commit with -n to bypass the pre-commit hook."
|
||||
exit 1
|
||||
if npm run --silent lint:check:silent ; then
|
||||
exit 0
|
||||
else
|
||||
npm run --silent lint:fix:silent
|
||||
echo "❌ Prettier check failed! We ran lint:fix for you. Please add & commit again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## Avoid large commits
|
||||
# https://www.backblaze.com/blog/how-many-bytes-are-in-a-megabyte-really/
|
||||
size_limit=$((2 * 2**20)) # 2mbs
|
||||
# https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---disk-usage
|
||||
commit_size=$(git rev-list --disk-usage HEAD^..HEAD)
|
||||
test "$commit_size" -lt "$size_limit" || (
|
||||
echo "Commit size is too large: $commit_size > $size_limit"
|
||||
echo "Force commit using --no-verify"
|
||||
exit 1
|
||||
)
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.14.0
|
||||
node-version: 20.15.1
|
||||
|
||||
- name: Install Google Chrome
|
||||
run: |
|
||||
@@ -48,4 +48,94 @@ jobs:
|
||||
- name: Production Build
|
||||
run: |
|
||||
cd client
|
||||
npm run build
|
||||
npm run build
|
||||
|
||||
Build-and-test-development:
|
||||
runs-on: ubuntu-latest
|
||||
needs: Build-production-and-ng-test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.15.1
|
||||
|
||||
- name: Write .npmrc file
|
||||
run: |
|
||||
touch client/.npmrc
|
||||
echo '${{ secrets.NPMRC}}' > client/.npmrc
|
||||
|
||||
- run: apt-get update
|
||||
- run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
- run: apt install -y ./google-chrome*.deb;
|
||||
- run: export CHROME_BIN=/usr/bin/google-chrome
|
||||
- run: apt-get update -y
|
||||
- run: apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2t64 libxtst6 xauth xvfb
|
||||
- run: apt -y install jq
|
||||
|
||||
- name: Write cypress credentials
|
||||
run: echo "$CYPRESS_CREDS" > ./client/cypress.env.json
|
||||
shell: bash
|
||||
env:
|
||||
CYPRESS_CREDS: ${{ secrets.CYPRESS_CREDS }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd client
|
||||
# Decrypt and Install sheet
|
||||
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
|
||||
npm ci
|
||||
|
||||
# Install pm2 and prepare SASJS server
|
||||
- run: npm i -g pm2
|
||||
- run: curl -L https://github.com/sasjs/server/releases/latest/download/linux.zip > linux.zip
|
||||
- run: unzip linux.zip
|
||||
- run: touch .env
|
||||
- run: echo RUN_TIMES=js >> .env
|
||||
- run: echo NODE_PATH=node >> .env
|
||||
- run: echo CORS=enable >> .env
|
||||
- run: echo WHITELIST=http://localhost:4200 >> .env
|
||||
- run: cat .env
|
||||
- run: pm2 start api-linux --wait-ready
|
||||
|
||||
- name: Deploy mocked services
|
||||
run: |
|
||||
cd ./sas/mocks/sasjs
|
||||
npm install -g @sasjs/cli
|
||||
npm install -g replace-in-files-cli
|
||||
sasjs cbd -t server-ci
|
||||
# sasjs request services/admin/makedata -t server-ci -d ./deploy/makeData4GL.json -c ./deploy/requestConfig.json -o ./output.json
|
||||
|
||||
- name: Install ZIP
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install zip
|
||||
|
||||
- name: Prepare and run frontend and cypress
|
||||
run: |
|
||||
cd ./client
|
||||
mv ./cypress.env.example.json ./cypress.env.json
|
||||
replace-in-files --regex='"username".*' --replacement='"username":"'${{ secrets.CYPRESS_USERNAME_SASJS }}'",' ./cypress.env.json
|
||||
replace-in-files --regex='"password".*' --replacement='"password":"'${{ secrets.CYPRESS_PWD_SASJS }}'" ' ./cypress.env.json
|
||||
cat ./cypress.env.json
|
||||
npm run postinstall
|
||||
# Prepare index.html to SASJS local
|
||||
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='serverType=".*?"' --replacement='serverType="SASJS"' ./src/index.html
|
||||
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
|
||||
cat ./cypress.config.ts
|
||||
# Start frontend and run cypress
|
||||
npx ng serve --host 0.0.0.0 --port 4200 & 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-multi-load.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/csv.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
|
||||
|
||||
- name: Zip Cypress videos
|
||||
if: always()
|
||||
run: |
|
||||
zip -r cypress-videos ./client/cypress/videos
|
||||
|
||||
- name: Add cypress videos artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cypress-videos.zip
|
||||
path: cypress-videos.zip
|
||||
|
||||
101
.gitea/workflows/lighthouse.yaml
Normal file
101
.gitea/workflows/lighthouse.yaml
Normal file
@@ -0,0 +1,101 @@
|
||||
name: Lighthouse Checks
|
||||
run-name: Running Lighthouse Performance and Accessibility Checks on Pull Request
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
lighthouse:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.15.1]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install Google Chrome
|
||||
run: |
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
|
||||
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list
|
||||
apt-get update
|
||||
apt-get install -y google-chrome-stable xvfb
|
||||
|
||||
- name: Install pm2 for process management
|
||||
run: npm i -g pm2
|
||||
|
||||
- name: Install @sasjs/cli
|
||||
run: npm i -g @sasjs/cli
|
||||
|
||||
- name: Install wait-on globally
|
||||
run: npm install -g wait-on
|
||||
|
||||
- name: Create .env file for sasjs/server
|
||||
run: |
|
||||
touch .env
|
||||
echo RUN_TIMES=js >> .env
|
||||
echo NODE_PATH=node >> .env
|
||||
echo CORS=enable >> .env
|
||||
echo WHITELIST=http://localhost:4200 >> .env
|
||||
cat .env
|
||||
|
||||
- name: Download sasjs/server package from github using curl
|
||||
run: curl -L https://github.com/sasjs/server/releases/latest/download/linux.zip > linux.zip
|
||||
|
||||
- name: Unzip downloaded package
|
||||
run: unzip linux.zip
|
||||
|
||||
- name: Run sasjs server
|
||||
run: pm2 start api-linux --wait-ready
|
||||
|
||||
- name: Write .npmrc file
|
||||
run: echo "$NPMRC" > client/.npmrc
|
||||
shell: bash
|
||||
env:
|
||||
NPMRC: ${{ secrets.NPMRC}}
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: |
|
||||
cd client
|
||||
# Decrypt and Install sheet
|
||||
echo ${{ secrets.SHEET_PWD }} | gpg --batch --yes --passphrase-fd 0 ./libraries/sheet-crypto.tgz.gpg
|
||||
npm ci
|
||||
npm install -g replace-in-files-cli
|
||||
|
||||
- name: Update appLoc in index.html
|
||||
run: |
|
||||
cd client
|
||||
replace-in-files --regex='appLoc=".*?"' --replacement='appLoc="/proj/sasjs/genesis-mocks"' ./src/index.html
|
||||
|
||||
- name: Build Frontend
|
||||
run: |
|
||||
cd client
|
||||
npm run build
|
||||
|
||||
- name: Deploy JS mocked services and frontend to the local SASjs Server instance
|
||||
run: |
|
||||
cd sas/mocks
|
||||
npm ci
|
||||
sasjs cbd -t server-ci
|
||||
|
||||
- name: Start frontend server
|
||||
run: |
|
||||
cd client
|
||||
npx ng serve --host 0.0.0.0 --port 4200 &
|
||||
wait-on http://localhost:4200
|
||||
|
||||
- name: Run Lighthouse CI
|
||||
run: |
|
||||
cd client
|
||||
npx lhci autorun
|
||||
|
||||
- name: Lighthouse Result Artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Lighthouse results
|
||||
path: client/lighthouse-reports
|
||||
include-hidden-files: true
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
- run: apt install -y ./google-chrome*.deb;
|
||||
- run: export CHROME_BIN=/usr/bin/google-chrome
|
||||
- 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 libnss3 libxss1 libasound2t64 libxtst6 xauth xvfb
|
||||
- run: apt -y install jq
|
||||
|
||||
- name: Write cypress credentials
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
replace-in-files --regex='"hosturl".*' --replacement='hosturl:"http://localhost:4200",' ./cypress.config.ts
|
||||
cat ./cypress.config.ts
|
||||
# Start frontend and run cypress
|
||||
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"
|
||||
npx ng serve --host 0.0.0.0 --port 4200 & 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-multi-load.cy.ts,cypress/e2e/excel.cy.ts,cypress/e2e/csv.cy.ts,cypress/e2e/filtering.cy.ts,cypress/e2e/licensing.cy.ts"
|
||||
|
||||
- name: Zip Cypress videos
|
||||
if: always()
|
||||
@@ -237,20 +237,20 @@ jobs:
|
||||
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
|
||||
sed -i -e 's/servertype="SASJS"/servertype="SASVIYA"/g' sasjsbuild/services/DC.html
|
||||
sasjs b -t viya
|
||||
cp sasjsbuild/viya.sas ./viya.sas
|
||||
cp sasjsbuild/viya.json ./viya.json
|
||||
# compile Viya Full deploy (without web)
|
||||
rm -rf sasjsbuild/services/web
|
||||
rm sasjsbuild/services/DC.html
|
||||
sasjs b -t viya
|
||||
cp sasjsbuild/viya.sas ./viya_noweb.sas
|
||||
cp sasjsbuild/viya.json ./viya_noweb.json
|
||||
|
||||
- name: Zip Frontend (including viya.json for full viya deploy)
|
||||
run: |
|
||||
cd sas
|
||||
cp sasjsbuild/viya.json ../client/dist
|
||||
cp sasjsbuild/viya.json ../client/dist/viya.json
|
||||
cd ..
|
||||
zip -r frontend.zip ./client/dist
|
||||
|
||||
@@ -277,8 +277,8 @@ jobs:
|
||||
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/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
|
||||
curl -k $URL -F attachment=@sas/viya.json
|
||||
curl -k $URL -F attachment=@sas/viya_noweb.sas
|
||||
curl -k $URL -F attachment=@sas/viya_noweb.json
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,3 +21,4 @@ sasjsresults
|
||||
.sasjsrc
|
||||
client/.npmrc
|
||||
*~
|
||||
.lighthouseci
|
||||
348
CHANGELOG.md
348
CHANGELOG.md
@@ -1,3 +1,351 @@
|
||||
## [7.2.4](https://git.datacontroller.io/dc/dc/compare/v7.2.3...v7.2.4) (2025-10-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ensure reload after applying licence key ([cb1978b](https://git.datacontroller.io/dc/dc/commit/cb1978bcaf23b0bf45b5d3b78b9707fd4e48a5f4))
|
||||
* snyk report security patches ([387f512](https://git.datacontroller.io/dc/dc/commit/387f5122f1ea6dff55d23c9223f17737283a94d3))
|
||||
|
||||
## [7.2.3](https://git.datacontroller.io/dc/dc/compare/v7.2.2...v7.2.3) (2025-10-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* opening second table in viewer throws an error ([6c6b1cb](https://git.datacontroller.io/dc/dc/commit/6c6b1cbf460e5291ec746af017e764b894fff8d5))
|
||||
|
||||
## [7.2.2](https://git.datacontroller.io/dc/dc/compare/v7.2.1...v7.2.2) (2025-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* jsrsasign, @sasjs/cli bump ([365f129](https://git.datacontroller.io/dc/dc/commit/365f12996db3ef50a4f4f099d5af15696c43bb42))
|
||||
|
||||
## [7.2.1](https://git.datacontroller.io/dc/dc/compare/v7.2.0...v7.2.1) (2025-08-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* removing localhost from index.html ([225e693](https://git.datacontroller.io/dc/dc/commit/225e693d1fd4381f2b8ce42fecb508f0a9e9dad8))
|
||||
|
||||
# [7.2.0](https://git.datacontroller.io/dc/dc/compare/v7.1.1...v7.2.0) (2025-08-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** cypress dependency package not available anymore ([26cdd73](https://git.datacontroller.io/dc/dc/commit/26cdd733315ef8babe9498ce93f6eb29c587dabd))
|
||||
* **hot v16 migration:** multi dataset fixed issues, and cypress tests adapted ([712b384](https://git.datacontroller.io/dc/dc/commit/712b3848480a8769d149e00b0d2de91396022b66))
|
||||
* obsolete cypress deps ([2ba4b53](https://git.datacontroller.io/dc/dc/commit/2ba4b5383e23bff8dfeb82b0ef473e5871c94709))
|
||||
* remaining hot migrations - handsontable/angular-wrapper ([b419cd5](https://git.datacontroller.io/dc/dc/commit/b419cd507837e846e9dfcc6b729254d56cc196e6))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* lighthouse accessibility check pipeline ([670ec2c](https://git.datacontroller.io/dc/dc/commit/670ec2c71cb2d24e9d79e297a8cbc6136aa315c8))
|
||||
|
||||
## [7.1.1](https://git.datacontroller.io/dc/dc/compare/v7.1.0...v7.1.1) (2025-07-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **viewboxes:** hot v16 fails to load because of relative height `100%` ([672dd6d](https://git.datacontroller.io/dc/dc/commit/672dd6d4f1fda27e3706dd7caa42b45922319497))
|
||||
|
||||
# [7.1.0](https://git.datacontroller.io/dc/dc/compare/v7.0.3...v7.1.0) (2025-07-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* adapter bump ([b495c41](https://git.datacontroller.io/dc/dc/commit/b495c41626c85b7c4141d9361e4d3a826efd6c05))
|
||||
* bumping CLI to 4.12.10 ([a08a717](https://git.datacontroller.io/dc/dc/commit/a08a717ca8d49e8a7d63f3fd91c6a7d42a1d6d8b))
|
||||
* bumping sasjs/core and sasjs/cli ([63e9af4](https://git.datacontroller.io/dc/dc/commit/63e9af402ed65f6be4426e76ee1376a40e6ed097))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improving accessibility score up to 100, hot update to v16.0.1 ([71c308d](https://git.datacontroller.io/dc/dc/commit/71c308d052400ecedc03f8020a5a69471ac6b116))
|
||||
|
||||
## [7.0.3](https://git.datacontroller.io/dc/dc/compare/v7.0.2...v7.0.3) (2025-06-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* makedata vars ([e7cb471](https://git.datacontroller.io/dc/dc/commit/e7cb471c0b60058b03fe8cbed5e3e2e70dd72e26))
|
||||
* viya deploy makedata missing params ([7a82316](https://git.datacontroller.io/dc/dc/commit/7a8231615cb56710351fae5868e8fdeed54d180c))
|
||||
|
||||
## [7.0.2](https://git.datacontroller.io/dc/dc/compare/v7.0.1...v7.0.2) (2025-06-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **viya deploy:** run makedata in new window to ensure logs are available for the user ([0b4042a](https://git.datacontroller.io/dc/dc/commit/0b4042af6011fdc65cfaaa5d4b1d8f48cd67f3b3))
|
||||
|
||||
## [7.0.1](https://git.datacontroller.io/dc/dc/compare/v7.0.0...v7.0.1) (2025-06-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* refresh process ([4ecd186](https://git.datacontroller.io/dc/dc/commit/4ecd186e5cb22dd436f2d7f1200956f4e3f27425))
|
||||
|
||||
# [7.0.0](https://git.datacontroller.io/dc/dc/compare/v6.16.2...v7.0.0) (2025-06-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* bumping adapter to re-enable JES API method ([e874143](https://git.datacontroller.io/dc/dc/commit/e874143a95d0ac2e56c0793e04b979c27f96d74b))
|
||||
* commit git hooks checking lint ([69f687a](https://git.datacontroller.io/dc/dc/commit/69f687a85f1cc562346b6167813d617cb9bd3404))
|
||||
* ensuring apploc is not case sensitive. Closes [#171](https://git.datacontroller.io/dc/dc/issues/171) ([24545f2](https://git.datacontroller.io/dc/dc/commit/24545f2acdd5bd73cbe062526f2bd043269cc6a3))
|
||||
* export unregistered formats ([f6d7d6f](https://git.datacontroller.io/dc/dc/commit/f6d7d6f90c978ac8c071471dfb67a60834424de5)), closes [#158](https://git.datacontroller.io/dc/dc/issues/158)
|
||||
* reload startupservice after user approves the MPE_TABLES page ([e5f8e50](https://git.datacontroller.io/dc/dc/commit/e5f8e500c125ee233c6f7af5ad0077c0ed6abfcb))
|
||||
* showing catalog_cnt in libinfo ([e44a25d](https://git.datacontroller.io/dc/dc/commit/e44a25dcc39ba4b9714257c60da84c2dfa613a85)), closes [#160](https://git.datacontroller.io/dc/dc/issues/160)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* adding 4 new tables for catalogs ([e4dbab8](https://git.datacontroller.io/dc/dc/commit/e4dbab8b1654b24e610e4b0603d1cf2b02a451e2))
|
||||
* capturing catalog specific information, closes [#159](https://git.datacontroller.io/dc/dc/issues/159) ([b4c586a](https://git.datacontroller.io/dc/dc/commit/b4c586a859929e0122cd46449e43d4ca597b8b2b))
|
||||
* viewer added catalog_cnt ([2aa19d1](https://git.datacontroller.io/dc/dc/commit/2aa19d1dca747f41274a032cde78d8ba73d66224))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* Introduction of 4 new tables for capturing information related to catalogs and their objects. Migration script prepared and available in the DB folder (usual place)
|
||||
|
||||
## [6.16.2](https://git.datacontroller.io/dc/dc/compare/v6.16.1...v6.16.2) (2025-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* streaming viya deploy `isStreaming` function stability fix ([4830c6d](https://git.datacontroller.io/dc/dc/commit/4830c6d2191cb47abcc7919bc1d49e55595e6121))
|
||||
|
||||
## [6.16.1](https://git.datacontroller.io/dc/dc/compare/v6.16.0...v6.16.1) (2025-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* viya deploy updating index html based on URL ([86134f4](https://git.datacontroller.io/dc/dc/commit/86134f478ae0b9426e01bfcc9ca4ee597ca733f7))
|
||||
* viya streamed app deploy page flow fix ([89ab296](https://git.datacontroller.io/dc/dc/commit/89ab2961513b245eeea48d1867c6496d3261761e))
|
||||
|
||||
# [6.16.0](https://git.datacontroller.io/dc/dc/compare/v6.15.2...v6.16.0) (2025-06-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* adapter bump ([ca7caa2](https://git.datacontroller.io/dc/dc/commit/ca7caa25b6eea1bd4579fb8b67ec9b211a893079))
|
||||
* automatic viya deploy timing issue ([037a97b](https://git.datacontroller.io/dc/dc/commit/037a97b6ffa27b40891531ae6812ebe5b5e71e34))
|
||||
* bump core to ensure ff works on viya streaming deploy ([cbd69df](https://git.datacontroller.io/dc/dc/commit/cbd69df708edf3a8446115ca7315fac3557dcf97)), closes [#156](https://git.datacontroller.io/dc/dc/issues/156)
|
||||
* viya deploy load data timing ([abdbb67](https://git.datacontroller.io/dc/dc/commit/abdbb674713796e5308eb4272197a5c253868a85))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* viya deploy, update the index.html contextname ([7223955](https://git.datacontroller.io/dc/dc/commit/72239558af2ee50cdfc71b7e185e6661ab568ba1))
|
||||
|
||||
## [6.15.2](https://git.datacontroller.io/dc/dc/compare/v6.15.1...v6.15.2) (2025-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* pipeline updates for DC.html ([624a7a8](https://git.datacontroller.io/dc/dc/commit/624a7a8f37f0265cf576da310ac330c75aa417cf))
|
||||
|
||||
## [6.15.1](https://git.datacontroller.io/dc/dc/compare/v6.15.0...v6.15.1) (2025-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* updating pipeline to default to streaming on viya ([4b55894](https://git.datacontroller.io/dc/dc/commit/4b558948d997f456ff25a12a58827fe0d2075493))
|
||||
|
||||
# [6.15.0](https://git.datacontroller.io/dc/dc/compare/v6.14.10...v6.15.0) (2025-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* makedata with context name ([da4d0b2](https://git.datacontroller.io/dc/dc/commit/da4d0b28c7109afd6f96455e1e0e80a40d25a942))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* viya deploy context ([6c96ef7](https://git.datacontroller.io/dc/dc/commit/6c96ef7fb0a55754a84ff0a8bbab838b78c1acaf))
|
||||
|
||||
## [6.14.10](https://git.datacontroller.io/dc/dc/compare/v6.14.9...v6.14.10) (2025-06-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* bump core ([0e8503e](https://git.datacontroller.io/dc/dc/commit/0e8503ed2bb22a0fc3924ac929e7f19626772e0a))
|
||||
* default to home directory for SAS Drive in Viya ([9682b54](https://git.datacontroller.io/dc/dc/commit/9682b548e6106d99d97dcc023a35d93addfd5170))
|
||||
|
||||
## [6.14.9](https://git.datacontroller.io/dc/dc/compare/v6.14.8...v6.14.9) (2025-06-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* default DC path for viya ([f3125ff](https://git.datacontroller.io/dc/dc/commit/f3125ff4641e47e33cb203228f5b1014ea3343bc))
|
||||
|
||||
## [6.14.8](https://git.datacontroller.io/dc/dc/compare/v6.14.7...v6.14.8) (2025-05-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* CSP issues, clarity local library build, fixed some style issues ([841201a](https://git.datacontroller.io/dc/dc/commit/841201adab582149b1cca3a42e75f7cac75167f9))
|
||||
* deploy page, makedata error handling, added local build of clarity, to address clr-stack-view CSP issues (inline styles) ([7b5e7ae](https://git.datacontroller.io/dc/dc/commit/7b5e7ae18414152f9b9d8f2d94fc94de43152003))
|
||||
* improved deploy flow for Viya ([9604661](https://git.datacontroller.io/dc/dc/commit/9604661f3b76111387bc9474cc26348d73ab112e))
|
||||
* requests modal causing VIYA CSP errors ([1dc6934](https://git.datacontroller.io/dc/dc/commit/1dc69341cadb837e1f11624d5cf35788bbb98d96))
|
||||
* sas viya service init timing issue ([9de04e9](https://git.datacontroller.io/dc/dc/commit/9de04e9a0ce016e1a9fb8b19c656077079ddcf2f))
|
||||
* scss of components transferred to the global styles.scss so we do not cause CSP (inline styles) issues when streaming to Viya ([6c171a6](https://git.datacontroller.io/dc/dc/commit/6c171a6394aba8104fe0f50aa8a4e6b9fa8023a2))
|
||||
* viya deploy page improved flow ([4bd2154](https://git.datacontroller.io/dc/dc/commit/4bd215491f8cdc68f78bade68e7cb98e07edc81e))
|
||||
|
||||
## [6.14.7](https://git.datacontroller.io/dc/dc/compare/v6.14.6...v6.14.7) (2025-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* updated hot, clarity and improved accessibility score. ([2844c70](https://git.datacontroller.io/dc/dc/commit/2844c70f9507036216b8b621900c2bb9010c1d34))
|
||||
|
||||
## [6.14.6](https://git.datacontroller.io/dc/dc/compare/v6.14.5...v6.14.6) (2025-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* history table modal links styling ([c63fcdd](https://git.datacontroller.io/dc/dc/commit/c63fcdd465950ada439d7d69622a3886e8f3a783))
|
||||
|
||||
## [6.14.5](https://git.datacontroller.io/dc/dc/compare/v6.14.4...v6.14.5) (2025-03-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improving accessibility lighthouse score ([7f3577c](https://git.datacontroller.io/dc/dc/commit/7f3577c3ef9f44e55a58bc64fbf89a3a64006dd4))
|
||||
* prevent errors when using sqlrc in a DI job in a HOOK ([d1f0879](https://git.datacontroller.io/dc/dc/commit/d1f0879f0acf7e816c80f7635fd02f4f284214ed))
|
||||
* user profile style fix, new select library and table icons ([69f8830](https://git.datacontroller.io/dc/dc/commit/69f883034fabbed31aa5d832e20561c4ae3042db))
|
||||
|
||||
## [6.14.4](https://git.datacontroller.io/dc/dc/compare/v6.14.3...v6.14.4) (2025-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* removing cli dependency warnings2 ([43c0f73](https://git.datacontroller.io/dc/dc/commit/43c0f73c2189ff762986a964caae6b0b108164fc))
|
||||
|
||||
## [6.14.3](https://git.datacontroller.io/dc/dc/compare/v6.14.2...v6.14.3) (2025-03-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* NLDAT & NLDATM formats are now being staged ([3f5cb1e](https://git.datacontroller.io/dc/dc/commit/3f5cb1e2defe390220e904e4bf04a165cb31fec4))
|
||||
|
||||
## [6.14.2](https://git.datacontroller.io/dc/dc/compare/v6.14.1...v6.14.2) (2025-03-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improving instructions for setup ([83b3d77](https://git.datacontroller.io/dc/dc/commit/83b3d775b6e33653b087ca9f4eb3ad5b0dbbd479))
|
||||
|
||||
## [6.14.1](https://git.datacontroller.io/dc/dc/compare/v6.14.0...v6.14.1) (2025-03-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* handle national language datetime formats ([149e318](https://git.datacontroller.io/dc/dc/commit/149e318a8787be0109f25aeec3a1270ea75a97b2))
|
||||
* updating logic to use NLDAT formats ([95289aa](https://git.datacontroller.io/dc/dc/commit/95289aa9524d3cb2b1c248cfb84f6b0d0a490c32))
|
||||
|
||||
# [6.14.0](https://git.datacontroller.io/dc/dc/compare/v6.13.2...v6.14.0) (2025-02-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* uses SORTSEQ=LINGUISTIC for the services/metanav/metadetails service ([a45f5bb](https://git.datacontroller.io/dc/dc/commit/a45f5bb3b27a86da5f55ff28c9c7669956484ddf))
|
||||
|
||||
## [6.13.2](https://git.datacontroller.io/dc/dc/compare/v6.13.1...v6.13.2) (2025-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* get metadata email if exists ([1bd0eef](https://git.datacontroller.io/dc/dc/commit/1bd0eef913593579771c647d80010ce628c00819))
|
||||
|
||||
## [6.13.1](https://git.datacontroller.io/dc/dc/compare/v6.13.0...v6.13.1) (2025-02-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Avoiding LATIN1 unprintables in various UI locations ([bce1fd5](https://git.datacontroller.io/dc/dc/commit/bce1fd57ef397cfdd030552c3f424a8407174729))
|
||||
* updated @sasjs/adapter, crypto-browserify ([4e64f28](https://git.datacontroller.io/dc/dc/commit/4e64f28732868b07ec2ab403912bd384c62c7e1d))
|
||||
|
||||
# [6.13.0](https://git.datacontroller.io/dc/dc/compare/v6.12.3...v6.13.0) (2025-01-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* editor page csv upload ([217220f](https://git.datacontroller.io/dc/dc/commit/217220ffaaf688133321cc68d770aaf1e50590a9))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* csv test ([c53ab85](https://git.datacontroller.io/dc/dc/commit/c53ab85107f10c023117a099cc06321afc3e1f03))
|
||||
|
||||
## [6.12.3](https://git.datacontroller.io/dc/dc/compare/v6.12.2...v6.12.3) (2025-01-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* adding missing=STRING to three services ([30d5e51](https://git.datacontroller.io/dc/dc/commit/30d5e51d0b9cf27774038476bd90559600952304))
|
||||
|
||||
## [6.12.2](https://git.datacontroller.io/dc/dc/compare/v6.12.1...v6.12.2) (2025-01-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* unnecessary zeros when adding new row (data schema default values) ([a1a9051](https://git.datacontroller.io/dc/dc/commit/a1a90519c535ca25e00822b4d3358c991ac9662e))
|
||||
|
||||
## [6.12.1](https://git.datacontroller.io/dc/dc/compare/v6.12.0...v6.12.1) (2024-12-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* no upcase of pk fields in MPE_TABLES in delete scenario ([3de095f](https://git.datacontroller.io/dc/dc/commit/3de095fe7797cde60f0e232c188305fe423c27eb)), closes [#134](https://git.datacontroller.io/dc/dc/issues/134)
|
||||
* reduce length of tmp table names. Closes [#130](https://git.datacontroller.io/dc/dc/issues/130) ([f9c2491](https://git.datacontroller.io/dc/dc/commit/f9c2491ab6e7b528b7ffc011fd9e45c963c5f6bf))
|
||||
|
||||
# [6.12.0](https://git.datacontroller.io/dc/dc/compare/v6.11.1...v6.12.0) (2024-09-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* added appLoc to the system page ([dd2138a](https://git.datacontroller.io/dc/dc/commit/dd2138ac5e6067de310e83d16fccc9b9764ba3ff))
|
||||
* bumping core for passthrough fix, [#124](https://git.datacontroller.io/dc/dc/issues/124) ([caa9854](https://git.datacontroller.io/dc/dc/commit/caa9854ff0431ccbb6ff1d6d3509dc877362cceb))
|
||||
* excel with password flow, introducing web worker for XLSX.read ([a3ce367](https://git.datacontroller.io/dc/dc/commit/a3ce36795007a4e3b6ac3499ffd119dc3758f387))
|
||||
* implemented the new request wrapper usage, added XLSX read with a Web Worker, multi load preview data, full height ([4218da9](https://git.datacontroller.io/dc/dc/commit/4218da91cd193aa45346ad7e34ccc00ca89df4fb))
|
||||
* **multi load:** xlsx read file ahead of time, while user choose datasets ([6547461](https://git.datacontroller.io/dc/dc/commit/65474616379e1dacc1329b3bdc5eb14f34428bb1))
|
||||
* refactored adapter request wrapper function to return job log as well ([67436f4](https://git.datacontroller.io/dc/dc/commit/67436f4ff9bb4d77d5f897f47a3e3d472981f275))
|
||||
* using temporary names for temporary tables ([ce50365](https://git.datacontroller.io/dc/dc/commit/ce503653cd9fc36f72fb172bd14816e07c792e14)), closes [#124](https://git.datacontroller.io/dc/dc/issues/124)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* searching data in excel files using new algorithm (massive performance improvement) ([bbb725c](https://git.datacontroller.io/dc/dc/commit/bbb725c64cc23ed701b189623992408c42fdde8f))
|
||||
|
||||
## [6.11.1](https://git.datacontroller.io/dc/dc/compare/v6.11.0...v6.11.1) (2024-07-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* adding SYSSITE, part of [#116](https://git.datacontroller.io/dc/dc/issues/116) ([a156c01](https://git.datacontroller.io/dc/dc/commit/a156c0111b3de5e3744e38d377d6e9aa09915803))
|
||||
* ensuring review_reason_txt in output. Closes [#117](https://git.datacontroller.io/dc/dc/issues/117) ([e5d93fd](https://git.datacontroller.io/dc/dc/commit/e5d93fd7d6d86bc47ff56664bd812b4d9d0749a5))
|
||||
|
||||
# [6.11.0](https://git.datacontroller.io/dc/dc/compare/v6.10.1...v6.11.0) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* addressing PR comments ([d94df7f](https://git.datacontroller.io/dc/dc/commit/d94df7f0ebae8feab5e1d5cf8011af8c8be2ca18))
|
||||
* **multi load:** fixed parsing algorithm reused for the multi load, the fix affects the normal upload as well. ([d4fee79](https://git.datacontroller.io/dc/dc/commit/d4fee791a72021e449cf9680c3e3a525dce41ac1))
|
||||
* **multi load:** label rename ([fa04d7b](https://git.datacontroller.io/dc/dc/commit/fa04d7bf4e5ba337146bdaa926c60488f8851449))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **multi load:** added HOT for user datasets input ([18363bb](https://git.datacontroller.io/dc/dc/commit/18363bbbeb9cf96183ba4841da8134b2f66f735c))
|
||||
* **multi load:** implemented matching libds and parsing of the multiple sheets ([efcdc69](https://git.datacontroller.io/dc/dc/commit/efcdc694dd275cdb9a4e19f26e5522b8dadc5fd9))
|
||||
* **multi load:** licence submit limits ([cffeab8](https://git.datacontroller.io/dc/dc/commit/cffeab813d8d4b324f82710dfd73953d4cbf8ffe))
|
||||
* **multi load:** multiple csv files ([4d27665](https://git.datacontroller.io/dc/dc/commit/4d276657b35a147a2233a03afcb1716348555f52))
|
||||
* **multi load:** refactored range find function, unlocking excel with password is reusable ([eb7c443](https://git.datacontroller.io/dc/dc/commit/eb7c44333c865e7f7bbfb54dd7f73bfc110f86a7))
|
||||
* **multi load:** submitting multiple found tables at once ([5deba44](https://git.datacontroller.io/dc/dc/commit/5deba44d2b7352866d821b70dbbfbbf54955dc47))
|
||||
|
||||
## [6.10.1](https://git.datacontroller.io/dc/dc/compare/v6.10.0...v6.10.1) (2024-06-07)
|
||||
|
||||
|
||||
|
||||
36
README.md
36
README.md
@@ -23,10 +23,42 @@ _Problems with the above include:_
|
||||
|
||||
Data Controller for SAS® solves all these issues in a simple-to-install, user-friendly, secure, documented, battle-tested web application. Available on Viya, SAS 9 EBI, and [SASjs Server](https://server.sasjs.io).
|
||||
|
||||
For more information:
|
||||
An individual Viya deploy can be done in just 2 lines of #SAS code!
|
||||
|
||||
```sas
|
||||
filename dc url "https://git.datacontroller.io/dc/dc/releases/download/latest/viya.sas";
|
||||
%inc dc;
|
||||
```
|
||||
|
||||
For a multi-user deploy, using a shared system account, please see [deploy docs](https://docs.datacontroller.io/deploy-viya/).
|
||||
|
||||
For further information:
|
||||
|
||||
* Main site: https://datacontroller.io
|
||||
* Docs: https://docs.datacontroller.io
|
||||
* Code: https://code.datacontroller.io
|
||||
|
||||
For support, contact support@4gl.io or reach out on [Matrix](https://matrix.to/#/#dc:4gl.io)!
|
||||
For support, contact support@4gl.io or reach out on [Matrix](https://matrix.to/#/#dc:4gl.io)!
|
||||
|
||||
## Development
|
||||
|
||||
### Lighthouse CI
|
||||
|
||||
This project includes automated Lighthouse performance and accessibility checks that run on pull requests. The checks ensure:
|
||||
|
||||
- **Accessibility Score**: Minimum 1.0 (100%) median score across all tested pages
|
||||
|
||||
The Lighthouse CI workflow:
|
||||
1. Sets up the development environment with SASjs server and mocked services
|
||||
2. Builds and serves the Angular frontend
|
||||
3. Runs Lighthouse CI against key application pages
|
||||
4. Uploads results as artifacts for review
|
||||
|
||||
To run Lighthouse checks locally:
|
||||
```bash
|
||||
cd client
|
||||
npm install
|
||||
npm run lighthouse
|
||||
```
|
||||
|
||||
Configuration is in `client/lighthouserc.js`.
|
||||
@@ -69,7 +69,8 @@
|
||||
],
|
||||
"scripts": [
|
||||
"node_modules/marked/marked.min.js"
|
||||
]
|
||||
],
|
||||
"webWorkerTsConfig": "tsconfig.worker.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
@@ -148,7 +149,8 @@
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"karmaConfig": "karma.conf.js"
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"webWorkerTsConfig": "tsconfig.worker.json"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
|
||||
114
client/cypress/e2e/csv.cy.ts
Normal file
114
client/cypress/e2e/csv.cy.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
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 = 'csvs/'
|
||||
|
||||
context('excel tests: ', function () {
|
||||
this.beforeAll(() => {
|
||||
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
cy.loginAndUpdateValidKey(true)
|
||||
})
|
||||
|
||||
this.beforeEach(() => {
|
||||
cy.visit(hostUrl + appLocation)
|
||||
|
||||
visitPage('home')
|
||||
|
||||
colorLog(
|
||||
`TEST START ---> ${
|
||||
Cypress.mocha.getRunner().suite.ctx.currentTest.title
|
||||
}`,
|
||||
'#3498DB'
|
||||
)
|
||||
})
|
||||
|
||||
it('1 | Uploads regular csv file', () => {
|
||||
openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')
|
||||
|
||||
attachExcelFile('regular.csv', () => {
|
||||
cy.get('#approval-btn', { 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 cell: any = data[0].children[0].children[1]
|
||||
// expect(cell.innerText).to.equal('0')
|
||||
// cell = data[0].children[0].children[2]
|
||||
// expect(cell.innerText).to.equal('44')
|
||||
// cell = data[0].children[0].children[3]
|
||||
// expect(cell.innerText).to.equal('abc')
|
||||
// cell = data[0].children[0].children[6]
|
||||
// expect(cell.innerText).to.equal('Option abc')
|
||||
// })
|
||||
// })
|
||||
})
|
||||
})
|
||||
|
||||
this.afterEach(() => {
|
||||
colorLog(`TEST END -------------`, '#3498DB')
|
||||
})
|
||||
})
|
||||
|
||||
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(() => {
|
||||
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;')
|
||||
}
|
||||
@@ -15,9 +15,6 @@ context('editor tests: ', function () {
|
||||
|
||||
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')
|
||||
})
|
||||
@@ -118,10 +115,6 @@ context('editor tests: ', function () {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
this.afterEach(() => {
|
||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
})
|
||||
})
|
||||
|
||||
const clickOnEdit = (callback?: any) => {
|
||||
@@ -224,11 +217,7 @@ const rejectExcel = (callback?: any) => {
|
||||
.should('contain', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (
|
||||
approvalButton.innerText
|
||||
.toLowerCase()
|
||||
.includes('approve')
|
||||
) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
approvalButton.click()
|
||||
break
|
||||
}
|
||||
|
||||
317
client/cypress/e2e/excel-multi-load.cy.ts
Normal file
317
client/cypress/e2e/excel-multi-load.cy.ts
Normal file
@@ -0,0 +1,317 @@
|
||||
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_multi_load/'
|
||||
|
||||
const library = 'DC996664'
|
||||
const mpeXTestTable = 'MPE_X_TEST'
|
||||
const mpeTablesTable = 'MPE_TABLES'
|
||||
|
||||
context('excel multi load tests: ', function () {
|
||||
this.beforeAll(() => {
|
||||
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
cy.loginAndUpdateValidKey(true)
|
||||
})
|
||||
|
||||
this.beforeEach(() => {
|
||||
cy.visit(hostUrl + appLocation)
|
||||
|
||||
visitPage('home/multi-load')
|
||||
|
||||
colorLog(
|
||||
`TEST START ---> ${
|
||||
Cypress.mocha.getRunner().suite.ctx.currentTest.title
|
||||
}`,
|
||||
'#3498DB'
|
||||
)
|
||||
})
|
||||
|
||||
it('1 | Uploads Excel file with multiple sheets, 3 sheets including data, 2 sheets matched with dataset', (done) => {
|
||||
attachExcelFile('multi_load_test_2.xlsx', () => {
|
||||
checkHotUserDatasetTable(
|
||||
'hotTableUserDataset',
|
||||
[
|
||||
[library, mpeXTestTable],
|
||||
[library, mpeTablesTable]
|
||||
],
|
||||
() => {
|
||||
cy.get('#continue-btn')
|
||||
.trigger('click')
|
||||
.then(() => {
|
||||
checkIfTreeHasTables(
|
||||
[`${library}.${mpeXTestTable}`, `${library}.${mpeTablesTable}`],
|
||||
undefined,
|
||||
(includes: boolean) => {
|
||||
if (includes) {
|
||||
// MPE_TABLES sheet does not have data so 1 error image must be shown
|
||||
hasErrorTables(1, (valid: boolean) => {
|
||||
if (valid) done()
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('2 | Uploads Excel file with multiple sheets, 2 sheets matched with dataset, 1 matched sheet does not have data', (done) => {
|
||||
attachExcelFile('multi_load_test_1.xlsx', () => {
|
||||
checkHotUserDatasetTable(
|
||||
'hotTableUserDataset',
|
||||
[
|
||||
[library, mpeXTestTable],
|
||||
[library, mpeTablesTable]
|
||||
],
|
||||
() => {
|
||||
cy.get('#continue-btn')
|
||||
.trigger('click')
|
||||
.then(() => {
|
||||
checkIfTreeHasTables(
|
||||
[`${library}.${mpeXTestTable}`, `${library}.${mpeTablesTable}`],
|
||||
`${library}.${mpeXTestTable}`,
|
||||
(includes: boolean) => {
|
||||
if (includes) {
|
||||
cy.get('#hotTable')
|
||||
.should('be.visible')
|
||||
.then(() => {
|
||||
checkHotUserDatasetTable(
|
||||
'hotTable',
|
||||
[
|
||||
['No', '1', 'more dummy data'],
|
||||
[
|
||||
'No',
|
||||
'1',
|
||||
'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:'
|
||||
],
|
||||
[
|
||||
'No',
|
||||
'1',
|
||||
'if you can fill the unforgiving minute'
|
||||
]
|
||||
],
|
||||
() => {
|
||||
submitTables()
|
||||
|
||||
hasSuccessSubmits(2, (valid: boolean) => {
|
||||
if (valid) done()
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('3 | Uploads Excel file with multiple sheets, 1 sheets has 2 tables', (done) => {
|
||||
attachExcelFile('multi_load_test_1.xlsx', () => {
|
||||
checkHotUserDatasetTable(
|
||||
'hotTableUserDataset',
|
||||
[
|
||||
[library, mpeXTestTable],
|
||||
[library, mpeTablesTable]
|
||||
],
|
||||
() => {
|
||||
cy.get('#continue-btn')
|
||||
.trigger('click')
|
||||
.then(() => {
|
||||
checkIfTreeHasTables(
|
||||
[`${library}.${mpeXTestTable}`, `${library}.${mpeTablesTable}`],
|
||||
`${library}.${mpeXTestTable}`,
|
||||
(includes: boolean) => {
|
||||
if (includes) {
|
||||
cy.get('#hotTable')
|
||||
.should('be.visible')
|
||||
.then(() => {
|
||||
checkHotUserDatasetTable(
|
||||
'hotTable',
|
||||
[
|
||||
['No', '1', 'more dummy data'],
|
||||
[
|
||||
'No',
|
||||
'1',
|
||||
'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:'
|
||||
],
|
||||
[
|
||||
'No',
|
||||
'1',
|
||||
'if you can fill the unforgiving minute'
|
||||
]
|
||||
],
|
||||
() => {
|
||||
clickOnTreeNode('DC996664.MPE_TABLES', () => {
|
||||
cy.wait(1000).then(() => {
|
||||
cy.get('#hotTable')
|
||||
.should('be.visible')
|
||||
.then(() => {
|
||||
checkHotUserDatasetTable(
|
||||
'hotTable',
|
||||
[
|
||||
[
|
||||
'No',
|
||||
'DC914286',
|
||||
'MPE_COLUMN_LEVEL_SECURITY'
|
||||
],
|
||||
['No', 'DC914286', 'MPE_XLMAP_INFO'],
|
||||
['No', 'DC914286', 'MPE_XLMAP_RULES']
|
||||
],
|
||||
() => {
|
||||
submitTables()
|
||||
|
||||
hasSuccessSubmits(
|
||||
2,
|
||||
(valid: boolean) => {
|
||||
if (valid) done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
this.afterEach(() => {
|
||||
colorLog(`TEST END -------------`, '#3498DB')
|
||||
})
|
||||
})
|
||||
|
||||
const attachExcelFile = (excelFilename: string, callback?: any) => {
|
||||
cy.get('#browse-file')
|
||||
.should('exist')
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get('input[type="file"]#file-upload')
|
||||
.attachFile(`/${fixturePath}/${excelFilename}`)
|
||||
.then(() => {
|
||||
if (callback) callback()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const checkHotUserDatasetTable = (
|
||||
hotId: string,
|
||||
dataToContain: any[][],
|
||||
callback?: () => void
|
||||
) => {
|
||||
cy.get(`#${hotId}`, { timeout: longerCommandTimeout })
|
||||
.find('div.ht_master.handsontable')
|
||||
.find('div.wtHolder')
|
||||
.find('div.wtHider')
|
||||
.find('div.wtSpreader')
|
||||
.find('table.htCore')
|
||||
.find('tbody')
|
||||
.then((data) => {
|
||||
cy.wait(2000).then(() => {
|
||||
for (let rowI = 0; rowI < dataToContain.length; rowI++) {
|
||||
for (let colI = 0; colI < dataToContain[rowI].length; colI++) {
|
||||
expect(data[0].children[rowI].children[colI]).to.contain(
|
||||
dataToContain[rowI][colI]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) callback()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const clickOnTreeNode = (clickOnNode: string, callback?: () => void) => {
|
||||
cy.get('.nav-tree clr-tree > clr-tree-node').then((treeNodes: any) => {
|
||||
for (let node of treeNodes) {
|
||||
if (node.innerText.toUpperCase().trim().includes(clickOnNode)) {
|
||||
cy.get(node).trigger('click')
|
||||
if (callback) callback()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const checkIfTreeHasTables = (
|
||||
tables: string[],
|
||||
clickOnNode?: string,
|
||||
callback?: (includes: boolean) => void
|
||||
) => {
|
||||
cy.get('.nav-tree clr-tree > clr-tree-node').then((treeNodes: any) => {
|
||||
let datasets = tables
|
||||
let nodesCorrect = true
|
||||
let nodeToClick
|
||||
|
||||
for (let node of treeNodes) {
|
||||
if (!datasets.includes(node.innerText.toUpperCase().trim())) {
|
||||
nodesCorrect = false
|
||||
}
|
||||
|
||||
if (clickOnNode) {
|
||||
if (node.innerText.toUpperCase().trim().includes(clickOnNode)) {
|
||||
nodeToClick = node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeToClick) {
|
||||
cy.wait(1000)
|
||||
cy.get(nodeToClick).trigger('click')
|
||||
}
|
||||
|
||||
if (callback) callback(nodesCorrect)
|
||||
})
|
||||
}
|
||||
|
||||
const submitTables = () => {
|
||||
cy.get('#submit-all').trigger('click')
|
||||
cy.get('#submit-tables').trigger('click')
|
||||
cy.wait(1000)
|
||||
}
|
||||
|
||||
const hasSuccessSubmits = (
|
||||
expectedNoOfSubmits: number,
|
||||
callback: (valid: boolean) => void
|
||||
) => {
|
||||
cy.get('.nav-tree clr-tree > clr-tree-node cds-icon[status="success"]')
|
||||
.should('be.visible')
|
||||
.then(($nodes) => {
|
||||
callback(expectedNoOfSubmits === $nodes.length)
|
||||
})
|
||||
}
|
||||
|
||||
const hasErrorTables = (
|
||||
expectedNoOfErrors: number,
|
||||
callback: (valid: boolean) => void
|
||||
) => {
|
||||
cy.get('.nav-tree clr-tree > clr-tree-node cds-icon[status="danger"]')
|
||||
.should('be.visible')
|
||||
.then(($nodes) => {
|
||||
callback(expectedNoOfErrors === $nodes.length)
|
||||
})
|
||||
}
|
||||
|
||||
const visitPage = (url: string) => {
|
||||
cy.visit(`${hostUrl}${appLocation}/#/${url}`)
|
||||
}
|
||||
|
||||
const colorLog = (msg: string, color: string) => {
|
||||
console.log('%c' + msg, 'color:' + color + ';font-weight:bold;')
|
||||
}
|
||||
@@ -17,9 +17,6 @@ context('excel tests: ', function () {
|
||||
|
||||
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')
|
||||
|
||||
@@ -112,13 +109,8 @@ context('excel tests: ', function () {
|
||||
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()
|
||||
}
|
||||
})
|
||||
submitExcel()
|
||||
rejectExcel(done)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -242,7 +234,7 @@ context('excel tests: ', function () {
|
||||
cy.get('.btn-upload-preview', { timeout: 60000 })
|
||||
.should('be.visible')
|
||||
.then(() => {
|
||||
cy.get('#hotInstance', { timeout: 30000 })
|
||||
cy.get('#hotTable', { timeout: 30000 })
|
||||
.find('div.ht_master.handsontable')
|
||||
.find('div.wtHolder')
|
||||
.find('div.wtHider')
|
||||
@@ -291,7 +283,7 @@ context('excel tests: ', function () {
|
||||
cy.get('.btn-upload-preview', { timeout: 60000 })
|
||||
.should('be.visible')
|
||||
.then(() => {
|
||||
cy.get('#hotInstance', { timeout: 30000 })
|
||||
cy.get('#hotTable', { timeout: 30000 })
|
||||
.find('div.ht_master.handsontable')
|
||||
.find('div.wtHolder')
|
||||
.find('div.wtHider')
|
||||
@@ -337,7 +329,6 @@ context('excel tests: ', function () {
|
||||
|
||||
this.afterEach(() => {
|
||||
colorLog(`TEST END -------------`, '#3498DB')
|
||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -408,11 +399,7 @@ const rejectExcel = (callback?: any) => {
|
||||
.should('contain', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (
|
||||
approvalButton.innerText
|
||||
.toLowerCase()
|
||||
.includes('approve')
|
||||
) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
approvalButton.click()
|
||||
break
|
||||
}
|
||||
@@ -441,11 +428,7 @@ const acceptExcel = (callback?: any) => {
|
||||
.should('contain', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (
|
||||
approvalButton.innerText
|
||||
.toLowerCase()
|
||||
.includes('approve')
|
||||
) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
approvalButton.click()
|
||||
break
|
||||
}
|
||||
@@ -464,7 +447,7 @@ const acceptExcel = (callback?: any) => {
|
||||
}
|
||||
|
||||
const checkResultOfFormulaUpload = (callback?: any) => {
|
||||
cy.get('#hotInstance', { timeout: longerCommandTimeout })
|
||||
cy.get('#hotTable', { timeout: longerCommandTimeout })
|
||||
.find('div.ht_master.handsontable')
|
||||
.find('div.wtHolder')
|
||||
.find('div.wtHider')
|
||||
@@ -480,7 +463,7 @@ const checkResultOfFormulaUpload = (callback?: any) => {
|
||||
|
||||
const checkResultOfXLSUpload = (callback?: any) => {
|
||||
cy.viewport(1280, 720)
|
||||
cy.get('#hotInstance', { timeout: 30000 })
|
||||
cy.get('#hotTable', { timeout: 30000 })
|
||||
.find('div.ht_master.handsontable')
|
||||
.find('div.wtHolder')
|
||||
.find('div.wtHider')
|
||||
@@ -509,7 +492,7 @@ const checkResultOfXLSUpload = (callback?: any) => {
|
||||
if (callback) callback()
|
||||
})
|
||||
|
||||
cy.get('#hotInstance', { timeout: 30000 })
|
||||
cy.get('#hotTable', { timeout: 30000 })
|
||||
.find('div.ht_master.handsontable')
|
||||
.find('div.wtHolder')
|
||||
.scrollTo('right')
|
||||
|
||||
@@ -15,9 +15,6 @@ context('filtering tests: ', function () {
|
||||
|
||||
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')
|
||||
})
|
||||
@@ -174,10 +171,6 @@ context('filtering tests: ', function () {
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
|
||||
this.afterEach(() => {
|
||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
})
|
||||
})
|
||||
|
||||
const checkInfoBarIncludes = (text: string, callback: any) => {
|
||||
@@ -305,14 +298,16 @@ const setFilterWithValue = (
|
||||
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('.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()
|
||||
cy.get('.modal-footer .btn-success-outline').click()
|
||||
|
||||
if (callback) callback()
|
||||
})
|
||||
if (callback) callback()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -23,15 +23,11 @@ interface EditConfigTableCells {
|
||||
|
||||
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')
|
||||
})
|
||||
@@ -374,10 +370,6 @@ context('licensing tests: ', function () {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.afterEach(() => {
|
||||
// cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
})
|
||||
})
|
||||
|
||||
const logout = (callback?: any) => {
|
||||
@@ -702,11 +694,7 @@ const approveTable = (callback?: any) => {
|
||||
.should('contain', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (
|
||||
approvalButton.innerText
|
||||
.toLowerCase()
|
||||
.includes('approve')
|
||||
) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
approvalButton.click()
|
||||
break
|
||||
}
|
||||
|
||||
@@ -18,10 +18,6 @@ context('liveness tests: ', function () {
|
||||
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')
|
||||
})
|
||||
|
||||
@@ -128,11 +124,7 @@ const rejectExcel = (callback?: any) => {
|
||||
.should('contain', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (
|
||||
approvalButton.innerText
|
||||
.toLowerCase()
|
||||
.includes('approve')
|
||||
) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
approvalButton.click()
|
||||
break
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ context('editor tests: ', function () {
|
||||
|
||||
this.beforeEach(() => {
|
||||
cy.visit(hostUrl + appLocation)
|
||||
|
||||
cy.wait(2000)
|
||||
|
||||
cy.get('body').then(($body) => {
|
||||
@@ -77,7 +76,8 @@ context('editor tests: ', function () {
|
||||
cy.get('.viewbox-open').click()
|
||||
openTableFromViewboxTree(
|
||||
libraryToOpenIncludes,
|
||||
viewboxes.map((viewbox) => viewbox.viewbox_table))
|
||||
viewboxes.map((viewbox) => viewbox.viewbox_table)
|
||||
)
|
||||
cy.get('.open-viewbox').then((viewboxNodes: any) => {
|
||||
let found = 0
|
||||
|
||||
@@ -92,32 +92,34 @@ context('editor tests: ', function () {
|
||||
|
||||
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()
|
||||
}
|
||||
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()
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -393,18 +395,16 @@ context('editor tests: ', function () {
|
||||
// }
|
||||
// )
|
||||
// })
|
||||
|
||||
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()
|
||||
cy.get('.configuration-wrapper clr-icon[shape="trash"]').then(
|
||||
(removeNodes) => {
|
||||
for (let removeNode of removeNodes) {
|
||||
removeNode.click()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const checkColumns = (columns: string[], callback: () => void) => {
|
||||
@@ -417,7 +417,7 @@ const checkColumns = (columns: string[], callback: () => void) => {
|
||||
console.log('viewboxColNode', viewboxColNodes)
|
||||
console.log('columns', columns)
|
||||
for (let i = 0; i < viewboxColNodes.length; i++) {
|
||||
const col = columns[i]|| ''
|
||||
const col = columns[i] || ''
|
||||
const colNode = viewboxColNodes[i]
|
||||
|
||||
if (
|
||||
|
||||
497
client/cypress/fixtures/csvs/regular.csv
Normal file
497
client/cypress/fixtures/csvs/regular.csv
Normal file
@@ -0,0 +1,497 @@
|
||||
PRIMARY_KEY_FIELD,SOME_CHAR,SOME_DROPDOWN,SOME_NUM,SOME_DATE,SOME_DATETIME,SOME_TIME,SOME_SHORTNUM,SOME_BESTNUM
|
||||
0,abc,Option abc,42,12FEB1960,01JAN1960:00:00:42,0:00:42,3,44
|
||||
1,more dummy data,Option 2,42,12FEB1960,01JAN1960:00:00:42,0:07:02,3,44
|
||||
2,even more dummy data,Option 3,42,12FEB1960,01JAN1960:00:00:42,0:02:22,3,44
|
||||
3,"It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:",Option 2,1613.001,27FEB1961,01JAN1960:00:07:03,0:00:44,3,44
|
||||
4,if you can fill the unforgiving minute,Option 1,1613.0011235,02AUG1971,29MAY1973:06:12:03,0:06:52,3,44
|
||||
1010,10 bottles of beer on the wall,Option 1,0.9153696885,04MAR1962,01JAN1960:12:47:55,0:01:40,92,76
|
||||
1011,11 bottles of beer on the wall,Option 1,0.3531217558,29MAR1960,01JAN1960:03:33:24,0:01:03,80,29
|
||||
1012,12 bottles of beer on the wall,Option 1,0.6743748717,02AUG1962,01JAN1960:07:25:59,0:00:10,16,98
|
||||
1013,13 bottles of beer on the wall,Option 1,0.1305445992,11SEP1960,01JAN1960:13:51:32,0:00:35,73,15
|
||||
1014,14 bottles of beer on the wall,Option 1,0.7409067949,26JUL1960,01JAN1960:05:18:10,0:00:41,30,89
|
||||
1015,15 bottles of beer on the wall,Option 1,0.0869016028,28FEB1961,01JAN1960:13:23:45,0:00:44,80,3
|
||||
1016,16 bottles of beer on the wall,Option 1,0.0462121419,09AUG1962,01JAN1960:07:42:38,0:01:17,62,2
|
||||
1017,17 bottles of beer on the wall,Option 1,0.7501918947,14MAY1962,01JAN1960:04:40:20,0:00:15,53,65
|
||||
1018,18 bottles of beer on the wall,Option 1,0.7300173294,03AUG1962,01JAN1960:03:20:41,0:00:41,21,60
|
||||
1019,19 bottles of beer on the wall,Option 1,0.6960950437,01JUN1960,01JAN1960:01:58:52,0:01:08,38,5
|
||||
1020,20 bottles of beer on the wall,Option 1,0.6190566065,30MAY1961,01JAN1960:09:04:20,0:01:07,92,23
|
||||
1021,21 bottles of beer on the wall,Option 1,0.5173368238,07JAN1961,01JAN1960:07:52:34,0:00:52,57,21
|
||||
1022,22 bottles of beer on the wall,Option 1,0.4720626452,07NOV1960,01JAN1960:12:12:00,0:00:26,53,32
|
||||
1023,23 bottles of beer on the wall,Option 1,0.2856596393,08AUG1960,01JAN1960:06:09:25,0:00:28,40,12
|
||||
1024,24 bottles of beer on the wall,Option 1,0.5160869418,02JUN1960,01JAN1960:06:36:06,0:01:10,41,81
|
||||
1025,25 bottles of beer on the wall,Option 1,0.1683158517,05JAN1961,01JAN1960:08:14:35,0:00:06,18,53
|
||||
1026,26 bottles of beer on the wall,Option 1,0.8951142248,28NOV1961,01JAN1960:03:31:17,0:00:58,79,54
|
||||
1027,27 bottles of beer on the wall,Option 1,0.7037817481,01SEP1961,01JAN1960:05:48:34,0:00:29,50,15
|
||||
1028,28 bottles of beer on the wall,Option 1,0.6193826714,31MAR1962,01JAN1960:02:49:39,0:00:24,78,87
|
||||
1029,29 bottles of beer on the wall,Option 1,0.9339028457,06DEC1961,01JAN1960:02:57:57,0:00:24,73,64
|
||||
1030,30 bottles of beer on the wall,Option 1,0.5647351339,10AUG1960,01JAN1960:11:02:59,0:00:55,39,28
|
||||
1031,31 bottles of beer on the wall,Option 1,0.1218988607,19JUN1961,01JAN1960:04:19:32,0:00:58,51,32
|
||||
1032,32 bottles of beer on the wall,Option 1,0.3459929113,14MAY1962,01JAN1960:05:42:48,0:00:54,96,46
|
||||
1033,33 bottles of beer on the wall,Option 1,0.092664999,31AUG1962,01JAN1960:00:08:34,0:00:51,69,90
|
||||
1034,34 bottles of beer on the wall,Option 1,0.9793458097,08FEB1960,01JAN1960:01:55:23,0:00:42,45,28
|
||||
1035,35 bottles of beer on the wall,Option 1,0.8964386624,18DEC1961,01JAN1960:04:42:45,0:00:07,49,97
|
||||
1036,36 bottles of beer on the wall,Option 1,0.0961652911,13NOV1960,01JAN1960:03:44:53,0:01:25,62,59
|
||||
1037,37 bottles of beer on the wall,Option 1,0.3475089201,16JAN1962,01JAN1960:01:35:19,0:00:15,23,50
|
||||
1038,38 bottles of beer on the wall,Option 1,0.3096271312,21MAY1960,01JAN1960:09:51:33,0:00:15,2,71
|
||||
1039,39 bottles of beer on the wall,Option 1,0.9445223114,28AUG1962,01JAN1960:07:09:31,0:00:12,30,31
|
||||
1040,40 bottles of beer on the wall,Option 1,0.5626084667,06NOV1960,01JAN1960:01:42:16,0:01:14,18,97
|
||||
1041,41 bottles of beer on the wall,Option 1,0.9432962513,01JUN1962,01JAN1960:03:30:04,0:00:11,20,34
|
||||
1042,42 bottles of beer on the wall,Option 1,0.5802429382,08JUL1961,01JAN1960:08:12:43,0:01:26,18,5
|
||||
1043,43 bottles of beer on the wall,Option 1,0.1970176255,27MAR1961,01JAN1960:00:19:45,0:01:29,13,76
|
||||
1044,44 bottles of beer on the wall,Option 1,0.4980671608,05JAN1961,01JAN1960:13:36:08,0:00:56,4,36
|
||||
1045,45 bottles of beer on the wall,Option 1,0.2486515531,05MAY1962,01JAN1960:08:47:09,0:00:42,2,23
|
||||
1046,46 bottles of beer on the wall,Option 1,0.4097825794,20JUN1960,01JAN1960:03:33:26,0:00:31,98,71
|
||||
1047,47 bottles of beer on the wall,Option 1,0.138754441,28JAN1960,01JAN1960:00:57:41,0:00:18,80,32
|
||||
1048,48 bottles of beer on the wall,Option 1,0.0249874415,03MAR1960,01JAN1960:11:33:53,0:00:04,96,76
|
||||
1049,49 bottles of beer on the wall,Option 1,0.8395310011,06NOV1961,01JAN1960:09:54:04,0:00:52,28,45
|
||||
1050,50 bottles of beer on the wall,Option 1,0.0942291618,14APR1962,01JAN1960:08:09:30,0:01:36,37,86
|
||||
1051,51 bottles of beer on the wall,Option 1,0.1670458001,13NOV1961,01JAN1960:01:05:55,0:00:25,42,83
|
||||
1052,52 bottles of beer on the wall,Option 1,0.3122402715,04JUN1960,01JAN1960:03:47:47,0:01:01,18,78
|
||||
1053,53 bottles of beer on the wall,Option 1,0.3854694261,14JUN1960,01JAN1960:02:43:08,0:00:06,22,67
|
||||
1054,54 bottles of beer on the wall,Option 1,0.1950434345,14NOV1961,01JAN1960:02:46:34,0:00:55,42,0
|
||||
1055,55 bottles of beer on the wall,Option 1,0.4948673586,29MAR1962,01JAN1960:00:48:06,0:01:04,28,4
|
||||
1056,56 bottles of beer on the wall,Option 1,0.6464513832,06SEP1962,01JAN1960:10:08:36,0:01:02,43,82
|
||||
1057,57 bottles of beer on the wall,Option 1,0.0724864798,20JUN1961,01JAN1960:12:22:51,0:01:27,82,53
|
||||
1058,58 bottles of beer on the wall,Option 1,0.8114467793,20MAR1962,01JAN1960:06:11:33,0:01:29,40,89
|
||||
1059,59 bottles of beer on the wall,Option 1,0.6348024321,28JUN1962,01JAN1960:05:21:21,0:01:37,55,41
|
||||
1060,60 bottles of beer on the wall,Option 1,0.8019492933,08APR1961,01JAN1960:12:37:00,0:01:29,49,88
|
||||
1061,61 bottles of beer on the wall,Option 1,0.4695742002,29JAN1962,01JAN1960:08:54:24,0:00:15,40,91
|
||||
1062,62 bottles of beer on the wall,Option 1,0.902706475,15JUN1961,01JAN1960:09:46:49,0:00:23,74,70
|
||||
1063,63 bottles of beer on the wall,Option 1,0.4557614594,16JUL1961,01JAN1960:02:06:05,0:01:09,7,3
|
||||
1064,64 bottles of beer on the wall,Option 1,0.6632444466,20MAY1961,01JAN1960:02:44:44,0:00:20,42,100
|
||||
1065,65 bottles of beer on the wall,Option 1,0.3901674,31AUG1961,01JAN1960:07:56:49,0:00:32,98,3
|
||||
1066,66 bottles of beer on the wall,Option 1,0.8453234848,30JUN1962,01JAN1960:04:51:54,0:01:02,51,22
|
||||
1067,67 bottles of beer on the wall,Option 1,0.9370150906,26APR1960,01JAN1960:04:05:08,0:01:39,28,86
|
||||
1068,68 bottles of beer on the wall,Option 1,0.8854161277,22MAR1962,01JAN1960:10:38:49,0:01:07,60,85
|
||||
1069,69 bottles of beer on the wall,Option 1,0.1327841906,24MAY1960,01JAN1960:01:18:46,0:01:15,88,85
|
||||
1070,70 bottles of beer on the wall,Option 1,0.5846563226,27JUL1962,01JAN1960:03:52:31,0:00:09,20,8
|
||||
1071,71 bottles of beer on the wall,Option 1,0.0257193684,18FEB1961,01JAN1960:03:25:01,0:00:29,1,62
|
||||
1072,72 bottles of beer on the wall,Option 1,0.9471486034,01JUN1962,01JAN1960:04:05:25,0:01:22,65,20
|
||||
1073,73 bottles of beer on the wall,Option 1,0.3037446282,16MAY1962,01JAN1960:05:10:19,0:00:01,14,34
|
||||
1074,74 bottles of beer on the wall,Option 1,0.2508690675,01NOV1961,01JAN1960:11:26:03,0:00:15,8,74
|
||||
1075,75 bottles of beer on the wall,Option 1,0.814380363,17SEP1960,01JAN1960:09:00:38,0:00:25,95,1
|
||||
1076,76 bottles of beer on the wall,Option 1,0.3761493621,16AUG1961,01JAN1960:01:48:17,0:00:52,5,38
|
||||
1077,77 bottles of beer on the wall,Option 1,0.3621215761,25JUL1961,01JAN1960:11:48:47,0:01:20,86,90
|
||||
1078,78 bottles of beer on the wall,Option 1,0.0268799584,20MAY1961,01JAN1960:12:43:34,0:01:00,70,96
|
||||
1079,79 bottles of beer on the wall,Option 1,0.4112483945,27JUL1962,01JAN1960:01:20:24,0:01:26,66,20
|
||||
1080,80 bottles of beer on the wall,Option 1,0.9501868011,15APR1961,01JAN1960:09:58:20,0:00:51,93,79
|
||||
1081,81 bottles of beer on the wall,Option 1,0.9866548018,13SEP1961,01JAN1960:05:20:04,0:00:14,28,97
|
||||
1082,82 bottles of beer on the wall,Option 1,0.9907830073,22FEB1962,01JAN1960:03:29:03,0:00:17,16,91
|
||||
1083,83 bottles of beer on the wall,Option 1,0.8927816567,11MAR1960,01JAN1960:05:52:48,0:01:26,54,14
|
||||
1084,84 bottles of beer on the wall,Option 1,0.12871663,02FEB1961,01JAN1960:10:34:37,0:00:44,52,90
|
||||
1085,85 bottles of beer on the wall,Option 1,0.5490252802,02JAN1960,01JAN1960:06:11:58,0:00:27,4,98
|
||||
1086,86 bottles of beer on the wall,Option 1,0.5432773864,11FEB1960,01JAN1960:08:40:00,0:01:15,79,19
|
||||
1087,87 bottles of beer on the wall,Option 1,0.8223943137,01OCT1960,01JAN1960:08:11:33,0:01:19,2,86
|
||||
1088,88 bottles of beer on the wall,Option 1,0.8496777699,09FEB1962,01JAN1960:03:10:35,0:00:15,95,6
|
||||
1089,89 bottles of beer on the wall,Option 1,0.9308730536,27MAY1962,01JAN1960:11:57:53,0:01:18,86,90
|
||||
1090,90 bottles of beer on the wall,Option 1,0.3072653344,23FEB1962,01JAN1960:04:52:38,0:00:25,85,17
|
||||
1091,91 bottles of beer on the wall,Option 1,0.7687679575,12FEB1960,01JAN1960:08:47:11,0:01:20,8,7
|
||||
1092,92 bottles of beer on the wall,Option 1,0.1873595105,29SEP1961,01JAN1960:04:29:58,0:00:29,17,78
|
||||
1093,93 bottles of beer on the wall,Option 1,0.0495966631,03OCT1961,01JAN1960:03:18:50,0:00:39,89,56
|
||||
1094,94 bottles of beer on the wall,Option 1,0.2607690526,19SEP1960,01JAN1960:03:22:28,0:00:29,81,16
|
||||
1095,95 bottles of beer on the wall,Option 1,0.549640266,07JUN1962,01JAN1960:06:15:32,0:00:04,57,70
|
||||
1096,96 bottles of beer on the wall,Option 1,0.9993291092,08MAR1961,01JAN1960:13:49:08,0:00:33,37,28
|
||||
1097,97 bottles of beer on the wall,Option 1,0.9517237963,02SEP1960,01JAN1960:05:16:03,0:00:40,77,61
|
||||
1098,98 bottles of beer on the wall,Option 1,0.5952155588,14FEB1962,01JAN1960:05:05:11,0:01:29,63,83
|
||||
1099,99 bottles of beer on the wall,Option 1,0.7526210732,05MAY1961,01JAN1960:06:58:36,0:00:02,95,1
|
||||
10100,100 bottles of beer on the wall,Option 1,0.307558153,17MAY1961,01JAN1960:06:13:01,0:01:37,68,7
|
||||
10101,101 bottles of beer on the wall,Option 1,0.6596710829,15APR1962,01JAN1960:08:34:02,0:00:43,66,43
|
||||
10102,102 bottles of beer on the wall,Option 1,0.0202811998,31AUG1961,01JAN1960:07:22:35,0:01:31,57,35
|
||||
10103,103 bottles of beer on the wall,Option 1,0.6699061034,02MAY1962,01JAN1960:05:13:17,0:00:36,30,23
|
||||
10104,104 bottles of beer on the wall,Option 1,0.330972748,04JUN1961,01JAN1960:06:47:20,0:01:05,69,82
|
||||
10105,105 bottles of beer on the wall,Option 1,0.2274839176,25JAN1961,01JAN1960:05:34:51,0:00:56,63,68
|
||||
10106,106 bottles of beer on the wall,Option 1,0.5612243989,27JUN1962,01JAN1960:04:32:03,0:01:15,19,73
|
||||
10107,107 bottles of beer on the wall,Option 1,0.7398902111,03SEP1962,01JAN1960:08:34:07,0:00:17,90,6
|
||||
10108,108 bottles of beer on the wall,Option 1,0.6124899791,08AUG1960,01JAN1960:04:59:34,0:00:25,56,12
|
||||
10109,109 bottles of beer on the wall,Option 1,0.882404773,26JAN1961,01JAN1960:01:29:15,0:01:26,36,4
|
||||
10110,110 bottles of beer on the wall,Option 1,0.4427004733,27FEB1961,01JAN1960:06:16:49,0:01:40,97,84
|
||||
10111,111 bottles of beer on the wall,Option 1,0.3609524622,10JAN1962,01JAN1960:09:48:37,0:01:11,87,62
|
||||
10112,112 bottles of beer on the wall,Option 1,0.9408929562,03AUG1960,01JAN1960:06:54:26,0:00:08,19,33
|
||||
10113,113 bottles of beer on the wall,Option 1,0.3149107319,10AUG1962,01JAN1960:13:01:00,0:00:04,75,60
|
||||
10114,114 bottles of beer on the wall,Option 1,0.0525069181,17APR1962,01JAN1960:13:00:52,0:00:35,9,23
|
||||
10115,115 bottles of beer on the wall,Option 1,0.145448105,14FEB1962,01JAN1960:04:06:08,0:00:26,45,91
|
||||
10116,116 bottles of beer on the wall,Option 1,0.2444279959,10OCT1961,01JAN1960:08:03:12,0:01:37,12,41
|
||||
10117,117 bottles of beer on the wall,Option 1,0.4619846043,30JUL1960,01JAN1960:09:40:16,0:00:50,2,88
|
||||
10118,118 bottles of beer on the wall,Option 1,0.0316203502,13JUL1961,01JAN1960:08:31:39,0:01:05,60,94
|
||||
10119,119 bottles of beer on the wall,Option 1,0.4738720574,13AUG1960,01JAN1960:01:31:05,0:01:17,43,79
|
||||
10120,120 bottles of beer on the wall,Option 1,0.8058761856,11JUN1960,01JAN1960:12:56:35,0:00:08,92,36
|
||||
10121,121 bottles of beer on the wall,Option 1,0.2955600979,08JUL1962,01JAN1960:06:09:22,0:00:03,94,80
|
||||
10122,122 bottles of beer on the wall,Option 1,0.0064115427,18SEP1962,01JAN1960:00:06:24,0:00:13,72,75
|
||||
10123,123 bottles of beer on the wall,Option 1,0.5678159327,21APR1960,01JAN1960:10:54:21,0:00:16,75,67
|
||||
10124,124 bottles of beer on the wall,Option 1,0.1431510994,10JAN1962,01JAN1960:01:57:00,0:00:12,48,31
|
||||
10125,125 bottles of beer on the wall,Option 1,0.3805634409,26JAN1962,01JAN1960:03:03:19,0:01:29,83,52
|
||||
10126,126 bottles of beer on the wall,Option 1,0.3833517993,26APR1960,01JAN1960:11:27:41,0:00:44,99,36
|
||||
10127,127 bottles of beer on the wall,Option 1,0.5669089111,04MAR1961,01JAN1960:05:36:22,0:01:18,43,27
|
||||
10128,128 bottles of beer on the wall,Option 1,0.1514211843,01NOV1960,01JAN1960:07:45:50,0:01:02,22,12
|
||||
10129,129 bottles of beer on the wall,Option 1,0.0446588583,05JAN1961,01JAN1960:02:13:55,0:00:42,27,46
|
||||
10130,130 bottles of beer on the wall,Option 1,0.7892141611,22APR1962,01JAN1960:04:17:54,0:01:05,75,84
|
||||
10131,131 bottles of beer on the wall,Option 1,0.5012088001,24DEC1960,01JAN1960:13:03:23,0:01:22,87,82
|
||||
10132,132 bottles of beer on the wall,Option 1,0.2327582944,07APR1961,01JAN1960:01:33:15,0:01:14,18,46
|
||||
10133,133 bottles of beer on the wall,Option 1,0.2234651173,20MAR1961,01JAN1960:13:52:02,0:01:06,42,58
|
||||
10134,134 bottles of beer on the wall,Option 1,0.4954405918,10FEB1961,01JAN1960:13:51:14,0:01:36,35,11
|
||||
10135,135 bottles of beer on the wall,Option 1,0.7874922891,15AUG1960,01JAN1960:00:21:57,0:00:52,45,36
|
||||
10136,136 bottles of beer on the wall,Option 1,0.3992494891,06SEP1961,01JAN1960:09:51:46,0:01:25,26,9
|
||||
10137,137 bottles of beer on the wall,Option 1,0.3964866136,25MAY1960,01JAN1960:03:19:48,0:00:28,44,3
|
||||
10138,138 bottles of beer on the wall,Option 1,0.9466173323,06APR1962,01JAN1960:13:19:18,0:01:27,78,51
|
||||
10139,139 bottles of beer on the wall,Option 1,0.6525219277,09APR1960,01JAN1960:05:43:49,0:00:21,63,6
|
||||
10140,140 bottles of beer on the wall,Option 1,0.4684071925,29MAY1961,01JAN1960:02:53:36,0:00:46,68,4
|
||||
10141,141 bottles of beer on the wall,Option 1,0.8581724013,16MAY1960,01JAN1960:01:45:44,0:01:32,31,85
|
||||
10142,142 bottles of beer on the wall,Option 1,0.825792401,23APR1961,01JAN1960:12:03:13,0:00:49,36,45
|
||||
10143,143 bottles of beer on the wall,Option 1,0.3172852538,20FEB1962,01JAN1960:12:38:31,0:01:34,51,78
|
||||
10144,144 bottles of beer on the wall,Option 1,0.670397946,27JAN1962,01JAN1960:04:59:37,0:00:39,38,99
|
||||
10145,145 bottles of beer on the wall,Option 1,0.3304372441,04JUN1960,01JAN1960:00:39:12,0:00:29,88,76
|
||||
10146,146 bottles of beer on the wall,Option 1,0.845151971,31JUL1962,01JAN1960:05:03:34,0:00:13,2,80
|
||||
10147,147 bottles of beer on the wall,Option 1,0.7957223709,02FEB1961,01JAN1960:00:03:07,0:01:11,29,99
|
||||
10148,148 bottles of beer on the wall,Option 1,0.323337108,29FEB1960,01JAN1960:01:58:05,0:01:17,23,65
|
||||
10149,149 bottles of beer on the wall,Option 1,0.1813316611,29JUN1960,01JAN1960:02:18:08,0:00:40,45,52
|
||||
10150,150 bottles of beer on the wall,Option 1,0.7860426655,05MAR1962,01JAN1960:01:57:15,0:00:26,31,91
|
||||
10151,151 bottles of beer on the wall,Option 1,0.3305453571,09APR1960,01JAN1960:07:08:32,0:01:30,72,15
|
||||
10152,152 bottles of beer on the wall,Option 1,0.9367212513,18AUG1962,01JAN1960:10:36:03,0:01:26,85,81
|
||||
10153,153 bottles of beer on the wall,Option 1,0.3385623458,19MAR1962,01JAN1960:04:21:46,0:01:29,11,54
|
||||
10154,154 bottles of beer on the wall,Option 1,0.9756794413,17JUN1961,01JAN1960:08:35:40,0:00:34,3,72
|
||||
10155,155 bottles of beer on the wall,Option 1,0.6385958868,21OCT1961,01JAN1960:08:51:00,0:00:50,1,6
|
||||
10156,156 bottles of beer on the wall,Option 1,0.3569769959,14AUG1960,01JAN1960:10:57:16,0:00:05,5,94
|
||||
10157,157 bottles of beer on the wall,Option 1,0.8559997239,23MAR1962,01JAN1960:12:03:38,0:00:08,96,68
|
||||
10158,158 bottles of beer on the wall,Option 1,0.2293701918,13AUG1960,01JAN1960:06:36:47,0:00:07,87,87
|
||||
10159,159 bottles of beer on the wall,Option 1,0.0007910165,20SEP1962,01JAN1960:11:49:02,0:00:55,18,69
|
||||
10160,160 bottles of beer on the wall,Option 1,0.5876370373,08JAN1960,01JAN1960:00:59:15,0:01:26,27,36
|
||||
10161,161 bottles of beer on the wall,Option 1,0.2354667514,11OCT1961,01JAN1960:01:27:14,0:01:04,90,28
|
||||
10162,162 bottles of beer on the wall,Option 1,0.0144103263,11AUG1961,01JAN1960:02:37:41,0:01:39,92,8
|
||||
10163,163 bottles of beer on the wall,Option 1,0.7087855668,03JUL1962,01JAN1960:02:07:23,0:01:35,51,33
|
||||
10164,164 bottles of beer on the wall,Option 1,0.7251478106,20MAY1960,01JAN1960:12:15:23,0:01:28,58,7
|
||||
10165,165 bottles of beer on the wall,Option 1,0.9629398403,06APR1962,01JAN1960:01:05:24,0:01:39,84,6
|
||||
10166,166 bottles of beer on the wall,Option 1,0.5155049164,14OCT1960,01JAN1960:04:02:06,0:00:30,63,96
|
||||
10167,167 bottles of beer on the wall,Option 1,0.1016342775,11MAY1960,01JAN1960:05:55:03,0:00:01,31,44
|
||||
10168,168 bottles of beer on the wall,Option 1,0.3690353596,12NOV1961,01JAN1960:12:49:02,0:00:03,2,79
|
||||
10169,169 bottles of beer on the wall,Option 1,0.5573803501,02SEP1962,01JAN1960:12:59:56,0:00:31,7,95
|
||||
10170,170 bottles of beer on the wall,Option 1,0.2008119497,10JUN1961,01JAN1960:05:59:06,0:01:29,88,4
|
||||
10171,171 bottles of beer on the wall,Option 1,0.6939068505,25MAY1962,01JAN1960:07:20:06,0:01:08,87,8
|
||||
10172,172 bottles of beer on the wall,Option 1,0.7013406594,14JUL1960,01JAN1960:04:04:24,0:00:11,44,96
|
||||
10173,173 bottles of beer on the wall,Option 1,0.83506724,30APR1961,01JAN1960:12:44:40,0:00:10,74,70
|
||||
10174,174 bottles of beer on the wall,Option 1,0.9339991943,26JAN1962,01JAN1960:04:59:32,0:01:09,13,66
|
||||
10175,175 bottles of beer on the wall,Option 1,0.8333402787,18FEB1961,01JAN1960:07:25:44,0:00:28,47,2
|
||||
10176,176 bottles of beer on the wall,Option 1,0.5998844433,03MAR1962,01JAN1960:03:45:33,0:00:52,2,61
|
||||
10177,177 bottles of beer on the wall,Option 1,0.6161394634,18DEC1960,01JAN1960:05:35:25,0:00:50,70,22
|
||||
10178,178 bottles of beer on the wall,Option 1,0.0821002392,21APR1960,01JAN1960:10:08:56,0:01:40,28,9
|
||||
10179,179 bottles of beer on the wall,Option 1,0.6845213462,23MAY1960,01JAN1960:13:15:46,0:00:03,89,13
|
||||
10180,180 bottles of beer on the wall,Option 1,0.3839034477,14MAY1960,01JAN1960:03:22:17,0:01:11,15,38
|
||||
10181,181 bottles of beer on the wall,Option 1,0.7949567609,21AUG1962,01JAN1960:02:41:01,0:00:57,90,93
|
||||
10182,182 bottles of beer on the wall,Option 1,0.5079025419,23SEP1962,01JAN1960:02:22:31,0:01:07,83,32
|
||||
10183,183 bottles of beer on the wall,Option 1,0.3215162574,26DEC1961,01JAN1960:09:03:00,0:01:38,46,94
|
||||
10184,184 bottles of beer on the wall,Option 1,0.3322958058,12MAY1961,01JAN1960:02:48:05,0:00:46,80,54
|
||||
10185,185 bottles of beer on the wall,Option 1,0.6510801453,07SEP1960,01JAN1960:11:49:02,0:00:59,51,47
|
||||
10186,186 bottles of beer on the wall,Option 1,0.060995535,15AUG1960,01JAN1960:02:21:08,0:01:40,5,61
|
||||
10187,187 bottles of beer on the wall,Option 1,0.8541180551,14SEP1960,01JAN1960:13:29:33,0:01:23,17,14
|
||||
10188,188 bottles of beer on the wall,Option 1,0.9427926219,23JUL1960,01JAN1960:05:19:05,0:01:13,22,97
|
||||
10189,189 bottles of beer on the wall,Option 1,0.2325015186,01FEB1960,01JAN1960:11:50:07,0:01:22,6,53
|
||||
10190,190 bottles of beer on the wall,Option 1,0.3687101493,21FEB1962,01JAN1960:06:44:23,0:00:13,16,30
|
||||
10191,191 bottles of beer on the wall,Option 1,0.7647511232,09JAN1960,01JAN1960:13:06:29,0:01:35,6,97
|
||||
10192,192 bottles of beer on the wall,Option 1,0.4105463565,17AUG1961,01JAN1960:11:04:32,0:01:14,38,33
|
||||
10193,193 bottles of beer on the wall,Option 1,0.8785403831,12JUL1962,01JAN1960:04:11:05,0:00:29,19,82
|
||||
10194,194 bottles of beer on the wall,Option 1,0.9304303433,11JUL1961,01JAN1960:12:36:57,0:01:02,20,35
|
||||
10195,195 bottles of beer on the wall,Option 1,0.7302505256,01MAR1961,01JAN1960:01:38:35,0:00:42,16,35
|
||||
10196,196 bottles of beer on the wall,Option 1,0.2536906177,04SEP1962,01JAN1960:05:18:23,0:01:18,91,50
|
||||
10197,197 bottles of beer on the wall,Option 1,0.1181504503,08AUG1961,01JAN1960:09:27:54,0:01:26,20,13
|
||||
10198,198 bottles of beer on the wall,Option 1,0.9275614228,17JUL1961,01JAN1960:01:52:18,0:00:06,52,73
|
||||
10199,199 bottles of beer on the wall,Option 1,0.7495222128,04APR1961,01JAN1960:09:28:04,0:00:42,30,41
|
||||
10200,200 bottles of beer on the wall,Option 1,0.925741082,02FEB1962,01JAN1960:12:23:10,0:00:07,79,17
|
||||
10201,201 bottles of beer on the wall,Option 1,0.2591843359,04DEC1960,01JAN1960:12:46:41,0:00:00,53,58
|
||||
10202,202 bottles of beer on the wall,Option 1,0.4289995704,17NOV1961,01JAN1960:02:20:52,0:00:35,41,25
|
||||
10203,203 bottles of beer on the wall,Option 1,0.4625803807,24JAN1960,01JAN1960:08:20:44,0:01:11,84,66
|
||||
10204,204 bottles of beer on the wall,Option 1,0.858440102,31AUG1962,01JAN1960:08:51:40,0:00:12,18,51
|
||||
10205,205 bottles of beer on the wall,Option 1,0.8964499016,01SEP1962,01JAN1960:05:33:47,0:00:23,34,77
|
||||
10206,206 bottles of beer on the wall,Option 1,0.5742789063,24OCT1961,01JAN1960:02:31:04,0:01:08,27,66
|
||||
10207,207 bottles of beer on the wall,Option 1,0.4864150954,29SEP1960,01JAN1960:09:27:46,0:01:28,31,26
|
||||
10208,208 bottles of beer on the wall,Option 1,0.4511992249,04DEC1960,01JAN1960:09:39:26,0:00:42,49,98
|
||||
10209,209 bottles of beer on the wall,Option 1,0.4218624157,13SEP1961,01JAN1960:01:40:55,0:01:39,35,50
|
||||
10210,210 bottles of beer on the wall,Option 1,0.1572868331,15FEB1960,01JAN1960:07:01:15,0:00:51,43,1
|
||||
10211,211 bottles of beer on the wall,Option 1,0.713915177,23MAR1960,01JAN1960:11:08:53,0:00:15,18,61
|
||||
10212,212 bottles of beer on the wall,Option 1,0.5677882165,19MAY1960,01JAN1960:01:27:23,0:01:02,34,89
|
||||
10213,213 bottles of beer on the wall,Option 1,0.7552938581,12SEP1961,01JAN1960:11:47:33,0:00:38,44,46
|
||||
10214,214 bottles of beer on the wall,Option 1,0.6071256071,28DEC1961,01JAN1960:05:28:18,0:01:23,84,66
|
||||
10215,215 bottles of beer on the wall,Option 1,0.7717189266,12MAR1960,01JAN1960:01:21:26,0:01:00,28,22
|
||||
10216,216 bottles of beer on the wall,Option 1,0.8985594329,24MAR1961,01JAN1960:10:48:58,0:01:31,93,2
|
||||
10217,217 bottles of beer on the wall,Option 1,0.3156879904,13AUG1960,01JAN1960:07:10:46,0:01:18,100,54
|
||||
10218,218 bottles of beer on the wall,Option 1,0.3408455315,08JUN1961,01JAN1960:02:26:49,0:00:05,65,82
|
||||
10219,219 bottles of beer on the wall,Option 1,0.6263580553,08JUN1962,01JAN1960:05:59:46,0:01:03,76,88
|
||||
10220,220 bottles of beer on the wall,Option 1,0.2878925355,19DEC1961,01JAN1960:08:23:41,0:00:00,92,1
|
||||
10221,221 bottles of beer on the wall,Option 1,0.0901017348,19JUL1962,01JAN1960:09:50:47,0:00:43,21,84
|
||||
10222,222 bottles of beer on the wall,Option 1,0.8967759362,14SEP1960,01JAN1960:12:25:58,0:01:22,34,50
|
||||
10223,223 bottles of beer on the wall,Option 1,0.9878171943,03DEC1961,01JAN1960:03:43:09,0:00:17,11,84
|
||||
10224,224 bottles of beer on the wall,Option 1,0.5275036886,13DEC1961,01JAN1960:03:12:56,0:01:36,85,49
|
||||
10225,225 bottles of beer on the wall,Option 1,0.442012436,12JUN1960,01JAN1960:11:40:23,0:01:40,76,87
|
||||
10226,226 bottles of beer on the wall,Option 1,0.582103689,10FEB1961,01JAN1960:01:50:49,0:00:59,53,29
|
||||
10227,227 bottles of beer on the wall,Option 1,0.5757669842,01NOV1960,01JAN1960:13:47:33,0:00:43,55,6
|
||||
10228,228 bottles of beer on the wall,Option 1,0.4786617507,07JAN1960,01JAN1960:13:36:24,0:01:22,91,53
|
||||
10229,229 bottles of beer on the wall,Option 1,0.1386274957,06APR1962,01JAN1960:03:48:29,0:01:27,36,48
|
||||
10230,230 bottles of beer on the wall,Option 1,0.4188394893,31MAY1962,01JAN1960:10:30:51,0:00:54,5,87
|
||||
10231,231 bottles of beer on the wall,Option 1,0.9250617777,18OCT1960,01JAN1960:04:29:52,0:00:38,34,94
|
||||
10232,232 bottles of beer on the wall,Option 1,0.3077528124,05FEB1960,01JAN1960:09:37:42,0:01:13,58,75
|
||||
10233,233 bottles of beer on the wall,Option 1,0.7316332277,29NOV1960,01JAN1960:08:56:57,0:01:13,34,53
|
||||
10234,234 bottles of beer on the wall,Option 1,0.5666298352,21NOV1960,01JAN1960:07:51:09,0:01:08,97,71
|
||||
10235,235 bottles of beer on the wall,Option 1,0.5736639409,03JUL1962,01JAN1960:11:57:25,0:00:51,15,49
|
||||
10236,236 bottles of beer on the wall,Option 1,0.6785667616,11FEB1962,01JAN1960:09:47:20,0:00:50,65,21
|
||||
10237,237 bottles of beer on the wall,Option 1,0.3721726869,05JUL1962,01JAN1960:11:58:22,0:01:32,82,21
|
||||
10238,238 bottles of beer on the wall,Option 1,0.0332283876,17AUG1961,01JAN1960:13:11:34,0:00:54,83,30
|
||||
10239,239 bottles of beer on the wall,Option 1,0.9734656848,02JAN1961,01JAN1960:00:36:43,0:00:19,31,54
|
||||
10240,240 bottles of beer on the wall,Option 1,0.3022106021,16FEB1961,01JAN1960:13:50:38,0:00:40,22,66
|
||||
10241,241 bottles of beer on the wall,Option 1,0.7546903294,06JUL1961,01JAN1960:12:36:17,0:01:29,16,85
|
||||
10242,242 bottles of beer on the wall,Option 1,0.2509871834,07MAR1962,01JAN1960:10:38:28,0:00:39,7,8
|
||||
10243,243 bottles of beer on the wall,Option 1,0.9526996668,15JAN1960,01JAN1960:04:24:42,0:01:01,69,80
|
||||
10244,244 bottles of beer on the wall,Option 1,0.1816610122,06FEB1962,01JAN1960:08:46:51,0:00:54,89,91
|
||||
10245,245 bottles of beer on the wall,Option 1,0.3928658876,21JUL1962,01JAN1960:12:59:42,0:00:38,24,27
|
||||
10246,246 bottles of beer on the wall,Option 1,0.3774878524,18FEB1961,01JAN1960:07:40:49,0:01:31,88,93
|
||||
10247,247 bottles of beer on the wall,Option 1,0.6063659362,01NOV1960,01JAN1960:01:19:07,0:00:05,82,73
|
||||
10248,248 bottles of beer on the wall,Option 1,0.119603098,14JUN1960,01JAN1960:04:29:22,0:00:58,87,47
|
||||
10249,249 bottles of beer on the wall,Option 1,0.4833748445,03JUL1960,01JAN1960:01:53:54,0:00:37,34,33
|
||||
10250,250 bottles of beer on the wall,Option 1,0.2244539946,10AUG1961,01JAN1960:06:19:01,0:01:15,87,97
|
||||
10251,251 bottles of beer on the wall,Option 1,0.9368193191,11JUN1962,01JAN1960:06:37:14,0:00:46,94,39
|
||||
10252,252 bottles of beer on the wall,Option 1,0.1791427751,10NOV1961,01JAN1960:00:49:22,0:00:47,96,21
|
||||
10253,253 bottles of beer on the wall,Option 1,0.5836302874,06JUN1961,01JAN1960:08:39:34,0:01:01,78,49
|
||||
10254,254 bottles of beer on the wall,Option 1,0.1289398275,28DEC1960,01JAN1960:12:25:05,0:00:43,67,99
|
||||
10255,255 bottles of beer on the wall,Option 1,0.7833669785,05SEP1962,01JAN1960:02:47:35,0:00:20,25,2
|
||||
10256,256 bottles of beer on the wall,Option 1,0.4945342483,29JAN1960,01JAN1960:00:54:13,0:01:13,72,56
|
||||
10257,257 bottles of beer on the wall,Option 1,0.0635836129,05JAN1961,01JAN1960:08:10:04,0:00:52,11,10
|
||||
10258,258 bottles of beer on the wall,Option 1,0.8188241654,09FEB1962,01JAN1960:06:33:00,0:01:21,41,96
|
||||
10259,259 bottles of beer on the wall,Option 1,0.3398916076,11FEB1960,01JAN1960:07:12:29,0:00:56,18,76
|
||||
10260,260 bottles of beer on the wall,Option 1,0.0814064155,21MAY1961,01JAN1960:11:03:51,0:01:18,78,29
|
||||
10261,261 bottles of beer on the wall,Option 1,0.6653245542,20JAN1962,01JAN1960:08:03:31,0:00:18,39,95
|
||||
10262,262 bottles of beer on the wall,Option 1,0.4036777021,04AUG1962,01JAN1960:12:32:27,0:00:08,57,63
|
||||
10263,263 bottles of beer on the wall,Option 1,0.8931138603,07JAN1962,01JAN1960:09:04:24,0:00:32,6,27
|
||||
10264,264 bottles of beer on the wall,Option 1,0.528584433,06APR1962,01JAN1960:09:43:19,0:01:00,24,41
|
||||
10265,265 bottles of beer on the wall,Option 1,0.8267822945,29JUL1960,01JAN1960:00:48:11,0:00:01,81,78
|
||||
10266,266 bottles of beer on the wall,Option 1,0.7218411401,17FEB1960,01JAN1960:07:30:38,0:00:08,35,81
|
||||
10267,267 bottles of beer on the wall,Option 1,0.1475262773,11NOV1960,01JAN1960:13:44:20,0:00:57,36,68
|
||||
10268,268 bottles of beer on the wall,Option 1,0.9412727286,30DEC1960,01JAN1960:02:46:30,0:01:19,5,92
|
||||
10269,269 bottles of beer on the wall,Option 1,0.3038877548,27NOV1960,01JAN1960:10:50:10,0:01:21,43,95
|
||||
10270,270 bottles of beer on the wall,Option 1,0.2756435532,15APR1962,01JAN1960:09:05:28,0:01:34,11,14
|
||||
10271,271 bottles of beer on the wall,Option 1,0.7056001121,31AUG1960,01JAN1960:08:48:52,0:00:02,9,51
|
||||
10272,272 bottles of beer on the wall,Option 1,0.5273708508,21SEP1962,01JAN1960:12:58:13,0:00:28,97,69
|
||||
10273,273 bottles of beer on the wall,Option 1,0.6002807215,03MAY1960,01JAN1960:10:14:48,0:00:40,52,32
|
||||
10274,274 bottles of beer on the wall,Option 1,0.6100557971,20JUN1960,01JAN1960:08:11:55,0:00:27,90,14
|
||||
10275,275 bottles of beer on the wall,Option 1,0.4197408638,07JUN1961,01JAN1960:12:07:18,0:00:26,64,100
|
||||
10276,276 bottles of beer on the wall,Option 1,0.4903712498,19JAN1960,01JAN1960:01:06:26,0:00:03,35,24
|
||||
10277,277 bottles of beer on the wall,Option 1,0.6658435406,04NOV1960,01JAN1960:00:04:17,0:00:37,7,84
|
||||
10278,278 bottles of beer on the wall,Option 1,0.5491365942,14JAN1961,01JAN1960:04:12:49,0:00:27,99,47
|
||||
10279,279 bottles of beer on the wall,Option 1,0.4473488622,13MAY1961,01JAN1960:12:06:34,0:01:16,19,20
|
||||
10280,280 bottles of beer on the wall,Option 1,0.4511988663,06JUL1962,01JAN1960:10:05:51,0:00:56,76,34
|
||||
10281,281 bottles of beer on the wall,Option 1,0.0783031066,11JUN1961,01JAN1960:09:58:43,0:01:05,9,63
|
||||
10282,282 bottles of beer on the wall,Option 1,0.776985302,20JUL1962,01JAN1960:10:44:29,0:01:00,59,10
|
||||
10283,283 bottles of beer on the wall,Option 1,0.468099362,31AUG1962,01JAN1960:05:26:33,0:00:20,35,52
|
||||
10284,284 bottles of beer on the wall,Option 1,0.4040679696,20FEB1962,01JAN1960:06:27:25,0:00:04,76,30
|
||||
10285,285 bottles of beer on the wall,Option 1,0.4549995947,20FEB1962,01JAN1960:10:36:57,0:00:34,2,43
|
||||
10286,286 bottles of beer on the wall,Option 1,0.7455339361,16SEP1961,01JAN1960:08:39:35,0:01:00,42,44
|
||||
10287,287 bottles of beer on the wall,Option 1,0.0209561712,04JAN1960,01JAN1960:05:52:58,0:00:24,32,7
|
||||
10288,288 bottles of beer on the wall,Option 1,0.4955981842,04JAN1962,01JAN1960:02:56:03,0:00:30,85,31
|
||||
10289,289 bottles of beer on the wall,Option 1,0.4131368219,10FEB1960,01JAN1960:11:57:31,0:00:16,37,88
|
||||
10290,290 bottles of beer on the wall,Option 1,0.3282186721,17OCT1960,01JAN1960:10:54:04,0:00:56,72,28
|
||||
10291,291 bottles of beer on the wall,Option 1,0.2116929005,18JAN1962,01JAN1960:06:56:27,0:00:11,87,82
|
||||
10292,292 bottles of beer on the wall,Option 1,0.8483731937,12FEB1962,01JAN1960:05:05:41,0:01:36,12,83
|
||||
10293,293 bottles of beer on the wall,Option 1,0.1560111345,13NOV1960,01JAN1960:10:04:22,0:00:03,94,4
|
||||
10294,294 bottles of beer on the wall,Option 1,0.7046207808,12APR1962,01JAN1960:13:50:47,0:00:32,31,97
|
||||
10295,295 bottles of beer on the wall,Option 1,0.2716620403,04AUG1961,01JAN1960:01:52:29,0:00:57,99,44
|
||||
10296,296 bottles of beer on the wall,Option 1,0.5543203496,12SEP1960,01JAN1960:13:43:54,0:00:44,49,1
|
||||
10297,297 bottles of beer on the wall,Option 1,0.983109036,31JUL1962,01JAN1960:01:07:33,0:00:36,4,10
|
||||
10298,298 bottles of beer on the wall,Option 1,0.8123072115,14SEP1962,01JAN1960:06:16:12,0:01:25,88,96
|
||||
10299,299 bottles of beer on the wall,Option 1,0.4276896559,05OCT1960,01JAN1960:02:55:07,0:00:58,83,76
|
||||
10300,300 bottles of beer on the wall,Option 1,0.8921809042,19JAN1962,01JAN1960:02:05:38,0:00:12,80,13
|
||||
10301,301 bottles of beer on the wall,Option 1,0.6041374279,10DEC1961,01JAN1960:01:06:29,0:01:27,62,9
|
||||
10302,302 bottles of beer on the wall,Option 1,0.0460550185,31MAY1962,01JAN1960:03:03:56,0:00:05,33,88
|
||||
10303,303 bottles of beer on the wall,Option 1,0.1868385622,12APR1962,01JAN1960:12:42:44,0:01:05,65,18
|
||||
10304,304 bottles of beer on the wall,Option 1,0.3386632657,28SEP1961,01JAN1960:11:24:06,0:00:42,2,93
|
||||
10305,305 bottles of beer on the wall,Option 1,0.6400271019,01JUN1960,01JAN1960:13:33:07,0:01:30,60,72
|
||||
10306,306 bottles of beer on the wall,Option 1,0.9534907304,18NOV1961,01JAN1960:02:02:51,0:00:54,7,57
|
||||
10307,307 bottles of beer on the wall,Option 1,0.6663103745,06SEP1961,01JAN1960:05:36:49,0:00:43,88,2
|
||||
10308,308 bottles of beer on the wall,Option 1,0.5392553073,13FEB1962,01JAN1960:11:28:18,0:01:08,16,8
|
||||
10309,309 bottles of beer on the wall,Option 1,0.0747909025,17OCT1961,01JAN1960:08:36:12,0:00:41,49,42
|
||||
10310,310 bottles of beer on the wall,Option 1,0.3249381847,30SEP1960,01JAN1960:08:12:54,0:00:09,96,89
|
||||
10311,311 bottles of beer on the wall,Option 1,0.9231011951,19MAY1962,01JAN1960:05:10:33,0:00:50,30,9
|
||||
10312,312 bottles of beer on the wall,Option 1,0.4658221637,21MAY1961,01JAN1960:12:55:25,0:01:39,16,20
|
||||
10313,313 bottles of beer on the wall,Option 1,0.7215524673,21FEB1960,01JAN1960:02:00:07,0:01:40,95,94
|
||||
10314,314 bottles of beer on the wall,Option 1,0.7328679942,28OCT1961,01JAN1960:09:07:00,0:00:25,42,71
|
||||
10315,315 bottles of beer on the wall,Option 1,0.1276036776,12JUN1960,01JAN1960:01:54:08,0:00:56,57,42
|
||||
10316,316 bottles of beer on the wall,Option 1,0.1270824723,15SEP1960,01JAN1960:03:19:25,0:00:21,85,9
|
||||
10317,317 bottles of beer on the wall,Option 1,0.3750520117,13JUN1961,01JAN1960:04:33:09,0:01:15,24,20
|
||||
10318,318 bottles of beer on the wall,Option 1,0.5777822102,10DEC1960,01JAN1960:13:32:14,0:00:09,98,28
|
||||
10319,319 bottles of beer on the wall,Option 1,0.140476402,27AUG1962,01JAN1960:08:52:46,0:01:08,64,83
|
||||
10320,320 bottles of beer on the wall,Option 1,0.2589205551,31MAY1961,01JAN1960:08:33:06,0:00:53,28,98
|
||||
10321,321 bottles of beer on the wall,Option 1,0.7350722825,16SEP1962,01JAN1960:05:47:44,0:01:17,79,95
|
||||
10322,322 bottles of beer on the wall,Option 1,0.1476364542,15JAN1960,01JAN1960:12:21:20,0:00:20,86,62
|
||||
10323,323 bottles of beer on the wall,Option 1,0.8700561099,15MAY1962,01JAN1960:00:47:05,0:00:20,90,15
|
||||
10324,324 bottles of beer on the wall,Option 1,0.6408788802,12SEP1962,01JAN1960:11:50:31,0:00:53,41,72
|
||||
10325,325 bottles of beer on the wall,Option 1,0.6961101623,27NOV1960,01JAN1960:00:10:49,0:01:17,28,72
|
||||
10326,326 bottles of beer on the wall,Option 1,0.1467710059,24FEB1961,01JAN1960:01:13:38,0:00:33,14,5
|
||||
10327,327 bottles of beer on the wall,Option 1,0.0215573572,09JUN1961,01JAN1960:11:47:17,0:00:21,57,10
|
||||
10328,328 bottles of beer on the wall,Option 1,0.4173900054,25JUL1962,01JAN1960:12:28:20,0:00:23,73,90
|
||||
10329,329 bottles of beer on the wall,Option 1,0.6395625713,02NOV1961,01JAN1960:08:49:34,0:00:37,77,79
|
||||
10330,330 bottles of beer on the wall,Option 1,0.0091438908,18MAY1962,01JAN1960:05:10:05,0:00:41,15,31
|
||||
10331,331 bottles of beer on the wall,Option 1,0.1024675197,11DEC1960,01JAN1960:13:12:57,0:00:23,50,13
|
||||
10332,332 bottles of beer on the wall,Option 1,0.057470562,11MAY1961,01JAN1960:03:43:04,0:00:17,48,14
|
||||
10333,333 bottles of beer on the wall,Option 1,0.8478633872,21JUL1961,01JAN1960:03:45:42,0:01:31,22,40
|
||||
10334,334 bottles of beer on the wall,Option 1,0.3442252541,24JUN1960,01JAN1960:01:19:31,0:00:48,82,25
|
||||
10335,335 bottles of beer on the wall,Option 1,0.7338460184,06JUN1962,01JAN1960:03:32:34,0:01:04,6,31
|
||||
10336,336 bottles of beer on the wall,Option 1,0.6217917342,09MAR1961,01JAN1960:06:37:39,0:00:50,70,84
|
||||
10337,337 bottles of beer on the wall,Option 1,0.6684890807,10OCT1961,01JAN1960:05:34:24,0:01:20,66,18
|
||||
10338,338 bottles of beer on the wall,Option 1,0.3695247562,05SEP1962,01JAN1960:00:25:21,0:01:18,48,37
|
||||
10339,339 bottles of beer on the wall,Option 1,0.9429265987,06DEC1960,01JAN1960:07:11:17,0:00:38,59,1
|
||||
10340,340 bottles of beer on the wall,Option 1,0.9266307265,17JUL1960,01JAN1960:06:33:59,0:00:21,12,13
|
||||
10341,341 bottles of beer on the wall,Option 1,0.7280535543,23FEB1961,01JAN1960:05:01:10,0:00:34,73,25
|
||||
10342,342 bottles of beer on the wall,Option 1,0.488654495,15AUG1962,01JAN1960:01:24:33,0:00:56,59,25
|
||||
10343,343 bottles of beer on the wall,Option 1,0.9526806548,28DEC1960,01JAN1960:07:26:17,0:00:58,97,61
|
||||
10344,344 bottles of beer on the wall,Option 1,0.526025336,14JAN1960,01JAN1960:10:02:08,0:00:55,11,77
|
||||
10345,345 bottles of beer on the wall,Option 1,0.807215352,03JUL1961,01JAN1960:12:49:47,0:00:01,40,7
|
||||
10346,346 bottles of beer on the wall,Option 1,0.9305162979,28FEB1960,01JAN1960:09:46:40,0:00:59,56,28
|
||||
10347,347 bottles of beer on the wall,Option 1,0.7591318552,18FEB1962,01JAN1960:13:25:32,0:01:10,41,9
|
||||
10348,348 bottles of beer on the wall,Option 1,0.4177664911,11SEP1961,01JAN1960:09:55:17,0:01:39,76,82
|
||||
10349,349 bottles of beer on the wall,Option 1,0.4690050443,05DEC1961,01JAN1960:11:05:15,0:01:09,63,40
|
||||
10350,350 bottles of beer on the wall,Option 1,0.7541399979,31AUG1961,01JAN1960:12:30:45,0:00:33,57,12
|
||||
10351,351 bottles of beer on the wall,Option 1,0.1392844325,17MAR1962,01JAN1960:08:20:38,0:00:41,85,45
|
||||
10352,352 bottles of beer on the wall,Option 1,0.1020530235,23DEC1961,01JAN1960:09:46:20,0:00:01,55,56
|
||||
10353,353 bottles of beer on the wall,Option 1,0.0257998794,04DEC1961,01JAN1960:09:47:10,0:00:31,100,2
|
||||
10354,354 bottles of beer on the wall,Option 1,0.1238113316,20MAR1962,01JAN1960:09:15:30,0:00:01,74,11
|
||||
10355,355 bottles of beer on the wall,Option 1,0.4214245292,24NOV1960,01JAN1960:04:24:09,0:01:01,79,83
|
||||
10356,356 bottles of beer on the wall,Option 1,0.3243381057,12FEB1961,01JAN1960:00:55:59,0:00:50,30,52
|
||||
10357,357 bottles of beer on the wall,Option 1,0.9735697345,24NOV1960,01JAN1960:07:10:56,0:01:33,64,2
|
||||
10358,358 bottles of beer on the wall,Option 1,0.4796259461,28JAN1961,01JAN1960:11:51:29,0:01:03,19,29
|
||||
10359,359 bottles of beer on the wall,Option 1,0.003359966,01SEP1960,01JAN1960:13:24:25,0:00:09,66,60
|
||||
10360,360 bottles of beer on the wall,Option 1,0.5773700334,21JAN1960,01JAN1960:10:15:32,0:00:40,9,21
|
||||
10361,361 bottles of beer on the wall,Option 1,0.0792848342,25JAN1962,01JAN1960:06:00:35,0:01:25,73,73
|
||||
10362,362 bottles of beer on the wall,Option 1,0.9339359365,30MAY1961,01JAN1960:09:08:13,0:00:56,12,56
|
||||
10363,363 bottles of beer on the wall,Option 1,0.3517632132,12FEB1961,01JAN1960:12:07:19,0:00:01,74,69
|
||||
10364,364 bottles of beer on the wall,Option 1,0.4088954895,17MAR1961,01JAN1960:08:04:51,0:01:01,70,66
|
||||
10365,365 bottles of beer on the wall,Option 1,0.1254259623,30DEC1961,01JAN1960:06:47:12,0:00:01,79,43
|
||||
10366,366 bottles of beer on the wall,Option 1,0.9190132958,28MAY1961,01JAN1960:06:35:42,0:00:07,19,31
|
||||
10367,367 bottles of beer on the wall,Option 1,0.3033860015,17MAY1962,01JAN1960:05:32:03,0:00:32,57,73
|
||||
10368,368 bottles of beer on the wall,Option 1,0.1463442846,02SEP1962,01JAN1960:01:24:29,0:00:53,19,64
|
||||
10369,369 bottles of beer on the wall,Option 1,0.5516236343,18JUN1962,01JAN1960:10:52:23,0:00:11,51,40
|
||||
10370,370 bottles of beer on the wall,Option 1,0.5205378246,19JAN1960,01JAN1960:06:54:14,0:00:58,2,72
|
||||
10371,371 bottles of beer on the wall,Option 1,0.9941610768,28MAR1962,01JAN1960:04:55:58,0:00:22,46,65
|
||||
10372,372 bottles of beer on the wall,Option 1,0.065678,07MAY1961,01JAN1960:10:17:35,0:00:10,54,100
|
||||
10373,373 bottles of beer on the wall,Option 1,0.7222646138,17JUL1961,01JAN1960:01:47:32,0:00:51,26,96
|
||||
10374,374 bottles of beer on the wall,Option 1,0.8772228294,23JUL1960,01JAN1960:00:30:51,0:00:40,18,45
|
||||
10375,375 bottles of beer on the wall,Option 1,0.3651081847,11DEC1961,01JAN1960:00:46:15,0:00:15,14,90
|
||||
10376,376 bottles of beer on the wall,Option 1,0.3800431529,15AUG1960,01JAN1960:05:30:55,0:00:19,13,74
|
||||
10377,377 bottles of beer on the wall,Option 1,0.1077003503,26FEB1960,01JAN1960:04:48:40,0:00:08,51,53
|
||||
10378,378 bottles of beer on the wall,Option 1,0.7945664035,06MAR1961,01JAN1960:05:36:47,0:00:45,65,39
|
||||
10379,379 bottles of beer on the wall,Option 1,0.8754883054,06JUN1960,01JAN1960:06:09:33,0:00:04,3,3
|
||||
10380,380 bottles of beer on the wall,Option 1,0.9975561108,10AUG1960,01JAN1960:10:34:33,0:00:28,92,29
|
||||
10381,381 bottles of beer on the wall,Option 1,0.9817031599,07JUL1960,01JAN1960:01:40:00,0:00:39,63,45
|
||||
10382,382 bottles of beer on the wall,Option 1,0.4427802341,07JAN1962,01JAN1960:01:21:32,0:01:31,7,54
|
||||
10383,383 bottles of beer on the wall,Option 1,0.03180474,17JUL1962,01JAN1960:07:15:54,0:01:08,72,60
|
||||
10384,384 bottles of beer on the wall,Option 1,0.1031627707,10MAY1962,01JAN1960:02:52:58,0:01:31,6,64
|
||||
10385,385 bottles of beer on the wall,Option 1,0.911744344,01MAY1960,01JAN1960:03:51:16,0:01:04,1,54
|
||||
10386,386 bottles of beer on the wall,Option 1,0.4912374353,13FEB1961,01JAN1960:07:22:49,0:01:21,70,71
|
||||
10387,387 bottles of beer on the wall,Option 1,0.8803869509,04JUL1960,01JAN1960:12:14:05,0:00:18,78,88
|
||||
10388,388 bottles of beer on the wall,Option 1,0.0596609544,17DEC1960,01JAN1960:08:29:20,0:00:53,13,84
|
||||
10389,389 bottles of beer on the wall,Option 1,0.6625022132,12JAN1961,01JAN1960:11:15:39,0:01:05,10,31
|
||||
10390,390 bottles of beer on the wall,Option 1,0.2669677358,05OCT1961,01JAN1960:00:48:03,0:01:33,29,31
|
||||
10391,391 bottles of beer on the wall,Option 1,0.8095563454,04DEC1961,01JAN1960:07:54:13,0:01:15,95,2
|
||||
10392,392 bottles of beer on the wall,Option 1,0.6406704796,27JAN1961,01JAN1960:03:35:55,0:00:36,92,47
|
||||
10393,393 bottles of beer on the wall,Option 1,0.2188341847,02MAR1960,01JAN1960:04:05:21,0:00:11,28,34
|
||||
10394,394 bottles of beer on the wall,Option 1,0.7052043424,09JUN1962,01JAN1960:07:00:21,0:01:14,84,19
|
||||
10395,395 bottles of beer on the wall,Option 1,0.9843204464,18APR1960,01JAN1960:04:54:31,0:01:29,46,46
|
||||
10396,396 bottles of beer on the wall,Option 1,0.329249541,10SEP1961,01JAN1960:13:21:04,0:00:21,70,11
|
||||
10397,397 bottles of beer on the wall,Option 1,0.2073628675,13JUL1962,01JAN1960:11:16:26,0:01:23,17,97
|
||||
10398,398 bottles of beer on the wall,Option 1,0.7881676665,29JUN1962,01JAN1960:11:36:47,0:00:50,39,72
|
||||
10399,399 bottles of beer on the wall,Option 1,0.4347905537,31AUG1962,01JAN1960:02:30:30,0:00:21,86,61
|
||||
10400,400 bottles of beer on the wall,Option 1,0.2937454084,05APR1962,01JAN1960:02:44:06,0:00:32,27,81
|
||||
10401,401 bottles of beer on the wall,Option 1,0.6659902565,10APR1961,01JAN1960:11:53:59,0:00:01,80,17
|
||||
10402,402 bottles of beer on the wall,Option 1,0.7637229686,07APR1962,01JAN1960:05:45:25,0:01:28,11,17
|
||||
10403,403 bottles of beer on the wall,Option 1,0.3325480941,19MAR1961,01JAN1960:09:57:05,0:00:27,9,99
|
||||
10404,404 bottles of beer on the wall,Option 1,0.580015553,10AUG1960,01JAN1960:06:15:44,0:00:25,27,99
|
||||
10405,405 bottles of beer on the wall,Option 1,0.2514696071,08APR1961,01JAN1960:10:37:45,0:00:17,29,59
|
||||
10406,406 bottles of beer on the wall,Option 1,0.3792107284,19MAR1962,01JAN1960:04:49:30,0:00:07,44,38
|
||||
10407,407 bottles of beer on the wall,Option 1,0.4702913125,13DEC1961,01JAN1960:09:03:31,0:00:38,95,90
|
||||
10408,408 bottles of beer on the wall,Option 1,0.4207190659,03FEB1961,01JAN1960:00:37:47,0:00:38,37,65
|
||||
10409,409 bottles of beer on the wall,Option 1,0.2485069117,08DEC1961,01JAN1960:07:18:28,0:01:39,91,64
|
||||
10410,410 bottles of beer on the wall,Option 1,0.3257893502,27NOV1961,01JAN1960:11:33:02,0:00:54,41,7
|
||||
10411,411 bottles of beer on the wall,Option 1,0.0967283533,11AUG1962,01JAN1960:07:23:15,0:00:21,90,1
|
||||
10412,412 bottles of beer on the wall,Option 1,0.532676542,01SEP1960,01JAN1960:02:46:29,0:00:45,31,48
|
||||
10413,413 bottles of beer on the wall,Option 1,0.2564602151,15JAN1961,01JAN1960:01:09:11,0:01:21,16,89
|
||||
10414,414 bottles of beer on the wall,Option 1,0.0865634024,20MAR1962,01JAN1960:12:56:45,0:00:05,75,51
|
||||
10415,415 bottles of beer on the wall,Option 1,0.2926342321,07FEB1960,01JAN1960:06:48:55,0:00:36,66,33
|
||||
10416,416 bottles of beer on the wall,Option 1,0.0678594029,06OCT1961,01JAN1960:07:14:58,0:01:26,50,16
|
||||
10417,417 bottles of beer on the wall,Option 1,0.6376664767,09JUN1960,01JAN1960:05:00:13,0:01:37,7,92
|
||||
10418,418 bottles of beer on the wall,Option 1,0.4795483525,14JUN1962,01JAN1960:00:00:50,0:00:50,33,74
|
||||
10419,419 bottles of beer on the wall,Option 1,0.3492934342,22MAR1960,01JAN1960:08:54:52,0:01:26,61,72
|
||||
10420,420 bottles of beer on the wall,Option 1,0.5085071356,14MAR1960,01JAN1960:09:47:51,0:00:56,36,63
|
||||
10421,421 bottles of beer on the wall,Option 1,0.414953564,25MAR1961,01JAN1960:03:35:19,0:00:30,47,30
|
||||
10422,422 bottles of beer on the wall,Option 1,0.2431976652,25SEP1960,01JAN1960:08:47:25,0:00:17,6,42
|
||||
10423,423 bottles of beer on the wall,Option 1,0.2370444998,04MAR1962,01JAN1960:00:16:44,0:01:36,54,100
|
||||
10424,424 bottles of beer on the wall,Option 1,0.8687893324,12OCT1961,01JAN1960:03:16:33,0:00:56,97,25
|
||||
10425,425 bottles of beer on the wall,Option 1,0.0470510335,10MAY1960,01JAN1960:02:44:07,0:01:05,83,59
|
||||
10426,426 bottles of beer on the wall,Option 1,0.7114342887,12APR1960,01JAN1960:02:17:40,0:00:39,57,97
|
||||
10427,427 bottles of beer on the wall,Option 1,0.6176668283,05JUL1962,01JAN1960:09:09:12,0:01:03,92,38
|
||||
10428,428 bottles of beer on the wall,Option 1,0.0657907743,01JUL1962,01JAN1960:11:03:37,0:01:35,97,63
|
||||
10429,429 bottles of beer on the wall,Option 1,0.280104912,13MAR1962,01JAN1960:10:35:08,0:01:07,42,35
|
||||
10430,430 bottles of beer on the wall,Option 1,0.3639827088,02APR1960,01JAN1960:12:00:50,0:00:40,91,84
|
||||
10431,431 bottles of beer on the wall,Option 1,0.2130561137,25AUG1961,01JAN1960:12:07:22,0:01:37,70,9
|
||||
10432,432 bottles of beer on the wall,Option 1,0.9656705889,23DEC1960,01JAN1960:02:36:48,0:01:28,23,92
|
||||
10433,433 bottles of beer on the wall,Option 1,0.5824601052,22JAN1961,01JAN1960:01:19:48,0:00:32,73,6
|
||||
10434,434 bottles of beer on the wall,Option 1,0.5207124942,23APR1961,01JAN1960:10:45:16,0:01:08,45,85
|
||||
10435,435 bottles of beer on the wall,Option 1,0.9280530661,01NOV1960,01JAN1960:12:46:59,0:01:36,57,4
|
||||
10436,436 bottles of beer on the wall,Option 1,0.8982810149,29NOV1961,01JAN1960:09:23:13,0:01:15,100,68
|
||||
10437,437 bottles of beer on the wall,Option 1,0.3268259467,04MAR1960,01JAN1960:01:22:42,0:00:04,99,61
|
||||
10438,438 bottles of beer on the wall,Option 1,0.2038002704,12FEB1962,01JAN1960:09:03:24,0:00:40,97,78
|
||||
10439,439 bottles of beer on the wall,Option 1,0.0798850833,11MAY1960,01JAN1960:00:32:50,0:00:37,7,49
|
||||
10440,440 bottles of beer on the wall,Option 1,0.6697000566,01SEP1960,01JAN1960:08:04:03,0:00:30,7,68
|
||||
10441,441 bottles of beer on the wall,Option 1,0.550699767,11JAN1960,01JAN1960:06:33:15,0:01:09,19,10
|
||||
10442,442 bottles of beer on the wall,Option 1,0.9514032798,07FEB1962,01JAN1960:06:03:16,0:01:13,65,87
|
||||
10443,443 bottles of beer on the wall,Option 1,0.1182718324,08FEB1960,01JAN1960:11:28:52,0:00:46,61,59
|
||||
10444,444 bottles of beer on the wall,Option 1,0.5772118874,11FEB1962,01JAN1960:01:14:29,0:01:07,16,22
|
||||
10445,445 bottles of beer on the wall,Option 1,0.9828714463,06DEC1960,01JAN1960:05:47:08,0:01:40,66,4
|
||||
10446,446 bottles of beer on the wall,Option 1,0.1229167269,02JUN1960,01JAN1960:09:43:51,0:01:34,29,24
|
||||
10447,447 bottles of beer on the wall,Option 1,0.2102257522,09MAR1961,01JAN1960:04:06:09,0:01:27,53,78
|
||||
10448,448 bottles of beer on the wall,Option 1,0.9958884935,20FEB1962,01JAN1960:06:43:53,0:00:07,42,65
|
||||
10449,449 bottles of beer on the wall,Option 1,0.3530408085,04MAY1961,01JAN1960:11:26:59,0:01:37,76,35
|
||||
10450,450 bottles of beer on the wall,Option 1,0.2848354258,03SEP1960,01JAN1960:13:26:36,0:00:25,69,38
|
||||
10451,451 bottles of beer on the wall,Option 1,0.1461860818,10JUN1960,01JAN1960:01:24:25,0:00:02,61,23
|
||||
10452,452 bottles of beer on the wall,Option 1,0.2033735766,29AUG1960,01JAN1960:12:30:17,0:00:19,32,75
|
||||
10453,453 bottles of beer on the wall,Option 1,0.7973149958,26JUN1961,01JAN1960:04:46:06,0:00:21,94,14
|
||||
10454,454 bottles of beer on the wall,Option 1,0.6812086425,07NOV1961,01JAN1960:01:59:51,0:00:12,89,59
|
||||
10455,455 bottles of beer on the wall,Option 1,0.6111464974,24FEB1962,01JAN1960:07:42:56,0:00:15,23,92
|
||||
10456,456 bottles of beer on the wall,Option 1,0.9542484209,09APR1961,01JAN1960:09:09:17,0:01:26,87,93
|
||||
10457,457 bottles of beer on the wall,Option 1,0.9818577077,18AUG1960,01JAN1960:12:24:47,0:01:08,18,20
|
||||
10458,458 bottles of beer on the wall,Option 1,0.9331120881,06JUL1961,01JAN1960:10:10:02,0:01:40,78,36
|
||||
10459,459 bottles of beer on the wall,Option 1,0.8953045587,22APR1960,01JAN1960:04:47:34,0:00:37,13,46
|
||||
10460,460 bottles of beer on the wall,Option 1,0.1584420461,08JAN1961,01JAN1960:07:47:49,0:00:05,85,61
|
||||
10461,461 bottles of beer on the wall,Option 1,0.9324573814,24DEC1960,01JAN1960:02:13:36,0:00:22,55,94
|
||||
10462,462 bottles of beer on the wall,Option 1,0.0813189871,21AUG1961,01JAN1960:09:18:28,0:00:36,42,49
|
||||
10463,463 bottles of beer on the wall,Option 1,0.8736312594,17MAY1962,01JAN1960:12:52:58,0:00:30,45,7
|
||||
10464,464 bottles of beer on the wall,Option 1,0.1894013794,06NOV1960,01JAN1960:12:56:13,0:01:30,11,50
|
||||
10465,465 bottles of beer on the wall,Option 1,0.9149773772,07JUN1960,01JAN1960:08:53:28,0:00:22,23,17
|
||||
10466,466 bottles of beer on the wall,Option 1,0.6329479598,27JUN1962,01JAN1960:07:38:23,0:00:06,68,14
|
||||
10467,467 bottles of beer on the wall,Option 1,0.1897066413,21AUG1961,01JAN1960:10:15:28,0:01:12,59,46
|
||||
10468,468 bottles of beer on the wall,Option 1,0.8352205767,16MAR1961,01JAN1960:06:48:50,0:00:44,60,37
|
||||
10469,469 bottles of beer on the wall,Option 1,0.3339443432,09OCT1960,01JAN1960:00:52:53,0:00:27,70,44
|
||||
10470,470 bottles of beer on the wall,Option 1,0.1096137567,09JUL1962,01JAN1960:08:28:10,0:01:15,88,81
|
||||
10471,471 bottles of beer on the wall,Option 1,0.1481936733,10JAN1962,01JAN1960:06:38:41,0:00:56,21,77
|
||||
10472,472 bottles of beer on the wall,Option 1,0.5630390432,01MAR1960,01JAN1960:06:35:09,0:01:08,70,32
|
||||
10473,473 bottles of beer on the wall,Option 1,0.0604085713,12APR1962,01JAN1960:02:41:26,0:00:46,36,17
|
||||
10474,474 bottles of beer on the wall,Option 1,0.6011423606,25DEC1961,01JAN1960:02:57:45,0:01:11,36,18
|
||||
10475,475 bottles of beer on the wall,Option 1,0.7698335782,31JUL1962,01JAN1960:07:46:29,0:01:34,72,17
|
||||
10476,476 bottles of beer on the wall,Option 1,0.3823641224,17MAR1962,01JAN1960:03:34:37,0:00:09,27,86
|
||||
10477,477 bottles of beer on the wall,Option 1,0.9225378446,12JAN1962,01JAN1960:08:41:25,0:01:06,45,20
|
||||
10478,478 bottles of beer on the wall,Option 1,0.2979750453,23JUN1962,01JAN1960:10:06:36,0:01:28,88,7
|
||||
10479,479 bottles of beer on the wall,Option 1,0.4988665942,15JUL1961,01JAN1960:02:33:06,0:01:33,85,1
|
||||
10480,480 bottles of beer on the wall,Option 1,0.5243853585,29JUL1960,01JAN1960:00:26:18,0:00:31,48,77
|
||||
10481,481 bottles of beer on the wall,Option 1,0.6049248826,12JUL1962,01JAN1960:10:01:41,0:00:16,66,45
|
||||
10482,482 bottles of beer on the wall,Option 1,0.6312438024,01OCT1961,01JAN1960:05:18:12,0:00:04,43,27
|
||||
10483,483 bottles of beer on the wall,Option 1,0.3366865974,17MAY1962,01JAN1960:01:44:17,0:00:01,31,25
|
||||
10484,484 bottles of beer on the wall,Option 1,0.0813266188,08AUG1962,01JAN1960:06:18:27,0:00:08,71,63
|
||||
10485,485 bottles of beer on the wall,Option 1,0.3601163455,23JAN1962,01JAN1960:11:26:01,0:00:37,41,88
|
||||
10486,486 bottles of beer on the wall,Option 1,0.9033777345,13AUG1961,01JAN1960:00:16:14,0:00:56,82,33
|
||||
10487,487 bottles of beer on the wall,Option 1,0.1716986667,23DEC1960,01JAN1960:12:06:34,0:01:13,2,32
|
||||
10488,488 bottles of beer on the wall,Option 1,0.9734818912,11SEP1961,01JAN1960:00:34:41,0:00:28,17,7
|
||||
10489,489 bottles of beer on the wall,Option 1,0.0618140223,17DEC1961,01JAN1960:06:26:30,0:00:38,94,40
|
||||
10490,490 bottles of beer on the wall,Option 1,0.0204490144,22AUG1960,01JAN1960:01:50:18,0:00:19,40,56
|
||||
10491,491 bottles of beer on the wall,Option 1,0.8719323929,23MAY1960,01JAN1960:12:36:06,0:00:08,49,44
|
||||
10492,492 bottles of beer on the wall,Option 1,0.2656292181,28JUN1962,01JAN1960:05:32:50,0:01:35,15,39
|
||||
10493,493 bottles of beer on the wall,Option 1,0.37794835,23JUL1962,01JAN1960:13:15:43,0:00:56,6,86
|
||||
10494,494 bottles of beer on the wall,Option 1,0.6395865733,17JAN1961,01JAN1960:12:20:12,0:01:31,22,87
|
||||
10495,495 bottles of beer on the wall,Option 1,0.4408595098,05JUL1960,01JAN1960:12:21:53,0:01:40,25,27
|
||||
10496,496 bottles of beer on the wall,Option 1,0.4846261169,02DEC1961,01JAN1960:12:41:08,0:00:06,7,63
|
||||
10497,497 bottles of beer on the wall,Option 1,0.7903671478,14MAY1962,01JAN1960:05:09:21,0:01:03,98,25
|
||||
10498,498 bottles of beer on the wall,Option 1,0.60474184,13OCT1961,01JAN1960:03:52:59,0:01:22,98,98
|
||||
10499,499 bottles of beer on the wall,Option 1,0.1213259218,23APR1962,01JAN1960:06:29:47,0:01:35,38,70
|
||||
10500,500 bottles of beer on the wall,Option 1,0.7882370487,17FEB1962,01JAN1960:02:00:25,0:00:12,1,74
|
||||
|
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx
Normal file
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_1.xlsx
Normal file
Binary file not shown.
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx
Normal file
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_2.xlsx
Normal file
Binary file not shown.
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx
Normal file
BIN
client/cypress/fixtures/excels_multi_load/multi_load_test_3.xlsx
Normal file
Binary file not shown.
@@ -1,255 +0,0 @@
|
||||
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/'
|
||||
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`)
|
||||
})
|
||||
|
||||
this.afterAll(() => {
|
||||
cy.visit(`https://sas.4gl.io/mihmed/cypress_finish`)
|
||||
})
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
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', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
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}`)
|
||||
}
|
||||
@@ -1,531 +0,0 @@
|
||||
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/'
|
||||
|
||||
// TODO: 4 and 9 failing
|
||||
|
||||
context('excel 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')
|
||||
|
||||
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('.abortMsg', { 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')
|
||||
.should((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')
|
||||
.should((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', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
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', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
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')
|
||||
.should((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')
|
||||
.should((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')
|
||||
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')
|
||||
cell = data[0].children[0].children[9]
|
||||
expect(cell.innerText).to.equal('3')
|
||||
|
||||
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')
|
||||
.should((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;')
|
||||
}
|
||||
@@ -1,383 +0,0 @@
|
||||
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.only('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('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}`)
|
||||
}
|
||||
@@ -1,727 +0,0 @@
|
||||
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', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
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}`)
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
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', 'Approve')
|
||||
.then((allButtons: any) => {
|
||||
for (let approvalButton of allButtons) {
|
||||
if (approvalButton.innerText.toLowerCase().includes('approve')) {
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
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}`)
|
||||
}
|
||||
@@ -1,629 +0,0 @@
|
||||
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}`)
|
||||
const fixturePath = 'excels_general/'
|
||||
|
||||
context('editor tests: ', function () {
|
||||
this.beforeAll(() => {
|
||||
cy.visit(`${hostUrl}/SASLogon/logout`)
|
||||
cy.loginAndUpdateValidKey()
|
||||
})
|
||||
|
||||
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').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)
|
||||
|
||||
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)
|
||||
|
||||
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()
|
||||
|
||||
addColumns(additionalColumns, () => {
|
||||
cy.wait(1000)
|
||||
//reorder
|
||||
cy.get('.col-box.column-MOVE_TYPE')
|
||||
.realMouseDown({ button: 'left', position: 'center' })
|
||||