From 5456f2603edca1f4bb369aa4502f79ffca73a377 Mon Sep 17 00:00:00 2001 From: Sergio Eduardo Castro Ceballos <72516762+SergioCasCeb@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:03:12 +0200 Subject: [PATCH 01/56] Add playwright testing for the new web package --- packages/web-new/package-lock.json | 60 ++ packages/web-new/package.json | 1 + packages/web-new/playwright.config.js | 72 ++ .../trace.zip | Bin 0 -> 962 bytes .../trace.zip | Bin 0 -> 961 bytes .../trace.zip | Bin 0 -> 961 bytes .../trace.zip | Bin 0 -> 965 bytes .../trace.zip | Bin 0 -> 959 bytes .../trace.zip | Bin 0 -> 960 bytes packages/web-new/tests/test.spec.js | 946 ++++++++++++++++++ 10 files changed, 1079 insertions(+) create mode 100644 packages/web-new/playwright.config.js create mode 100644 packages/web-new/test-results/test-Load-initial-state-Has-TD-template-chromium/trace.zip create mode 100644 packages/web-new/test-results/test-Load-initial-state-Has-editor-tab-chromium/trace.zip create mode 100644 packages/web-new/test-results/test-Load-initial-state-Has-title-chromium/trace.zip create mode 100644 packages/web-new/test-results/test-Load-initial-state-JSON-button-is-checked-chromium/trace.zip create mode 100644 packages/web-new/test-results/test-Load-initial-state-Validation-tab-is-checked-chromium/trace.zip create mode 100644 packages/web-new/test-results/test-Load-initial-state-Validation-view-is-opened-chromium/trace.zip create mode 100644 packages/web-new/tests/test.spec.js diff --git a/packages/web-new/package-lock.json b/packages/web-new/package-lock.json index d17b93b82..c47e76fbf 100644 --- a/packages/web-new/package-lock.json +++ b/packages/web-new/package-lock.json @@ -23,6 +23,7 @@ "devDependencies": { "@babel/core": "^7.22.9", "@babel/preset-env": "^7.22.9", + "@playwright/test": "^1.39.0", "babel-loader": "^9.1.3", "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.8.1", @@ -1913,6 +1914,21 @@ "node": ">= 8" } }, + "node_modules/@playwright/test": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", + "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "dev": true, + "dependencies": { + "playwright": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", @@ -5952,6 +5968,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/playwright": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", + "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "dev": true, + "dependencies": { + "playwright-core": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", + "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/packages/web-new/package.json b/packages/web-new/package.json index 3a0af097b..e6d4ebcd1 100644 --- a/packages/web-new/package.json +++ b/packages/web-new/package.json @@ -23,6 +23,7 @@ "devDependencies": { "@babel/core": "^7.22.9", "@babel/preset-env": "^7.22.9", + "@playwright/test": "^1.39.0", "babel-loader": "^9.1.3", "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.8.1", diff --git a/packages/web-new/playwright.config.js b/packages/web-new/playwright.config.js new file mode 100644 index 000000000..a334a4854 --- /dev/null +++ b/packages/web-new/playwright.config.js @@ -0,0 +1,72 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + testDir: './tests', + // Folder for test artifacts such as screenshots, videos, traces, etc. + outputDir: 'test-results', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://127.0.0.1:5100', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + // use: { ...devices['Desktop Chrome'], headless: false, slowMo: 500}, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against branded browsers. */ + { + name: 'Microsoft Edge', + use: { ...devices['Desktop Edge'], channel: 'msedge' }, + }, + { + name: 'Google Chrome', + use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run serve', + url: 'http://127.0.0.1:5100', + reuseExistingServer: !process.env.CI, + }, +}); + diff --git a/packages/web-new/test-results/test-Load-initial-state-Has-TD-template-chromium/trace.zip b/packages/web-new/test-results/test-Load-initial-state-Has-TD-template-chromium/trace.zip new file mode 100644 index 0000000000000000000000000000000000000000..6d60317fcc127be4ad378b3c535014f126fa5639 GIT binary patch literal 962 zcmWIWW@Zs#VBp|jxLoENZYFS?--nrjp;3c@fs28Gp(M4qM6aYMF*)^ZRJ{Lf1A+Sc z%Qt-5Braw8clwrF%sC1UP8^wcFYjSD-)Y8pye}tR)2XK2S8A3?r~YyEn>$-C8J(KX z$Q0V=ms|Ah?%$f{f2vm1Jev8KY0o_KhJ_&y)>axmt}%D?)p~lds$mwF>0h1Wk&ery z&0aaG_uNV>K6|-M(^&SUiBz4oQ|y_U*D~(1=Uy;lpX~M8S6bu4OwpTmo7wIi_jK6Q z9B9HP;Uv?_Y1f+&#JagXywm3TK!N%A2KUIPaHZ>px(_y7B0vDK|X4 z6XsVO?z#PPe$|w^iwjJa{;>4YygQ|ErgFrUob^X}kvVl0n-Hyxa`YU9G0 zA>X$xYV^?azQFZ2P2l0Xsmj^?FU?+P&s9lS#jteArk|phwS2smm_B=OZPJ$$*CZZY z+Q7&@$>YMKy^03swkV#NP=9%Epvdeq243G)l$M%Y-};&*NNTy)v&fm(o2stts%eRu z+PS(~{+Pqjqc_)gZ1VXuzf)t!j?mY6O&qL?4%zgDF6|s#%F`HT*r0q}Qy{pW9 z{mjGSSZ+R7L$&L(A7%Oa7yMYmVQ(VdeejdI<)6>Ds^7Xky)%2`)a|J=Q@=Ssv3SyY zw6NpxgsBsXwf0=zZ8i6&TgkesoqzH!l&n1`E$$xNw=B#lX7%T+M;1p4Pk5c!yY}3h z`-gVgEq`6UxbJoGy&V>PMKW839{rjVE___E&pFIV?%Hz}?pnXy@7fbz{F-B~*SA>4 zeQnDQyXRMrKrEVFdv20)$y-(R6;9P5>Hk zmv8vANnFbG@BJ+P4UG((ic3oUKg->Da*IXAdehvc93N%PGBYlz?30r%fxqLM4F+mu zOGP)F-;;Rg?H7Mrul*STvx5G}9G#MP+Q45>C#y_&^K^cVvliB}nlrmO-d|*tX6zF) zSizy8VcOy8zrSX#;|uxQ86RC9F!8qNRnFsDf8A=ob;RM6oFdlQUsXS@TH6)AJ+do& z^~JBzj=u#z?uy&$&gLa1(e(dRaoCp&kJA?S)D$|OKCr!M0nff()?0jXliz4QvwQT( z^0cdj{-N(lYD#?bzn6dK|1HM<_|~Dm#)VazngVxTl{o5j;dW=$v91*w7c95C?VB6B zB1L32SDu;VrVB5;8ZN7ye)Q|4M}o`t#1j{iynA&_zVJG)S(stB?`UP^sT^m8ebafu zp7ipbRoQ>~5}VR4Kd0sIuCFRx6K}ccn?zpozDJ%6%eVr(w4~z=&mK~7jY{U3wrq)e z*)f4z<$so+g_tO@k5bNI8 z?khw(XWad5z^1iMuP!$BPelCB-0eRm%S7a<*;q0bneYp3)aRR+6&PyZ+gBW-&XnC; z-0`Nxrh7)?3H2A*uRe4zUv>!5>*#FcQGG7dY^}7=C%9&Q$HW;&oC;1VH668k%zIaP zY4*DhJJ(Hep4fZRH}K52FD&inyFNJYox?ND?&QPy*Vk@k>a?H!6CY0y z7dx)l=X}jcZ{>$`?_ZUOMPCeBeL2@OX7%S|M=wrUymG6+^;dglS@0FgY!WNVUv2z< zf5F1@nZM>nJ@_@pT(57jjQiTw9d^&J9x3d2JYnmE_OF(XJI`nS-rAR4d~b(ESCPn8 zu}8P&gbPD#$=hzJeeQy3xa`7B>5s+w14?(*U7g2S{XuY*?(Oiq#Yf)j2Y53w*)!wL gbijNE23s0I6e0@-c(byBL>Ph40!SAFGb#fE0D?fgQvd(} literal 0 HcmV?d00001 diff --git a/packages/web-new/test-results/test-Load-initial-state-Has-title-chromium/trace.zip b/packages/web-new/test-results/test-Load-initial-state-Has-title-chromium/trace.zip new file mode 100644 index 0000000000000000000000000000000000000000..64695147e8a234e6a4a13110a746ab0f4b82db00 GIT binary patch literal 961 zcmWIWW@Zs#VBp|jxLoENUb6PLzBe-iLz4yr0~Z4WLrH3JiC#%jVsh%+sCfU|1_Jf> zmv8vANnFbG@APfAm~#{yoH#P?Uf#oQzSE5HcwbJsrc+J3uhcA)PW|KRH+QyPGB`D# zktwv#FSqF1-M=-@|5UB2c{KB}%$|MbEfYf?tgRG$Tx0I$tMv3@Rl_VH(`J*yk&es7 z&0aaGzuC6?tf{~BvNJhLg5Upeyx>@TZj0M%#*F4|k~3VQ@^3lxo!9aIKGXDrogecg z*`7s(3h7;`85KoVU!`R$|E|C9cYp4k=Jkfgtch|BJFl-x;)|-&uV8s1*`_O|dW0>i z>DLkIrFZ=PUs?X8n{BD)(es5)FPHUn@oZd_W^HPHbi$=Mn;&nS)Y|b;PIiOggAC5Y zvl=D^HP86+=Ja(-mwyX=#r#>>G89WrcKbXC@_T>os>a+IP6w+#Pb)E;B}mQPzB(sXB(N|3jbcd9(QV*D%qakDBsW@4pQ>(C&DdKYHzPk?OX}h8;EM zxCB+ZKkRMkoN@U1-M4rDHXc2^W7`JdgcbAL3|4KBS{%VrWgL2bhjJEI$-%V~^V6qm z$*M1F>-KfmG1?V&JoEAf342-YGcVM7B%*RwY;0}Ym)KIRF|R+rAZ~8aRt16k+HBsh zj=7~p-M@W`O=+KwlktaYMX|Qi8@C=Wk^VB(N7x{^At>nPpRP#JWvZ8?iVLzmf2CwI z1t#8@z}%^t@$sI(j3u`O(oXDudGEw$-!zG()j|`4X1%;s%B0yVq`G;_i7dyxw|CXF zM9u74T`jNXaP;WS_1&B0S8MNoD^x$p*86PBa(4&5XP!#mjw%M}uJT%TGO_Vh$b)+i zWRk2Go=8qp_{RBbmZi;u1118Y97#e7$|rXodD7>pvYF?;dXkFRMv<6JGajVvf5dxN zeQNf*4?EX&IZyOI@pajbsLR4KcG`#d&t@4$d{b$!kE>q4cg39Q;%%R{>1;kz-zC$& zXM+V_q0Ad)G-(Rrs z{L7zT7d-zp$6T*(v5foLmK}D_uO2Dvcsyb1g!ZqNj!VyHw$=%>tUF)%_>sk_!Yf`K zuZ!b+W!f$HA~|>7e6C~Zd_AtHO)KY~h4aXAHzSihGww_W f%y(e0r4d9SvS5HWD;r3J5eO}SbTKfaGB5xDe3iY3 literal 0 HcmV?d00001 diff --git a/packages/web-new/test-results/test-Load-initial-state-JSON-button-is-checked-chromium/trace.zip b/packages/web-new/test-results/test-Load-initial-state-JSON-button-is-checked-chromium/trace.zip new file mode 100644 index 0000000000000000000000000000000000000000..374c1e6f9c34b1313d723b22eee026fea9288878 GIT binary patch literal 965 zcmWIWW@Zs#VBp|jxKidD{##3RvOhBeL$d}00~Z4WLrH3JiC#%jVsh%+sKD&o1_E{W z*9+9$^iGyBFMPD2y(~MEd$GthTi@z{H{NeTr}e0umt6Wkv3csj1@(FRQCY*JhgqJTle(oSeqHXZq!a zCjyHz_5>Ooq)5M9>b7lcRq!e1}Q=Uj>fc zXKPB6>|cDjcH(;J6-G&|$Yid6E6=6cI`mu5Rr_?5QaK)*to+Qo}dt+=LbY*B>5Z&&!Pd0XS z&77HHerEC;kGu#IZ}&Z%^ruG0U~#oUQpU#B$Hb(5wF$0USW;I%{qwU4vpE}o+%Sj; zG&eK4{7X+;y5q|(4#9N`1m;`l9ls`bIrl=inePD~Mla9Q&)R9BGp2cDpE-DG63>Z$ zER#-cP-LIvb>Y!YMT3)D70*n#e|c~8wCXbkUh&>8UYQG{w{tErIXOk=)2fWE&2`Uz z2}PCa<(;dY!60g{xBuUcKYMn5I_vk5yE1p@%nyHfPMoyyJYr|zvdT5|tjW)Sg;wG_ z%q-fk@U1vCMbe|TXOK8&!o)aELdWJibC!JVy;CZJ+r|TNl={l-AZsb=u z^Lsp=VO_Ig@xy>A!bQ6^@}8COxAS*>I9j$@V$F`}hu`<_z4mW)Ol9%5Pv3MmpQ-PX zY5$X6DD%i7Mfph=*ZW8QbI&DdSKWT~g~@(XeMijd&r6P8oU(XjufX+JHnS}F3S~A4 z7NxH?u8-ew;rW)oE97_EJ@4#(tZ_V0T5;X^N)xC_?|;oH+kBq$uiuk<&uvNzWu97O zDIfW2*{{~;EYqIT^5@p`H8)(Y$8K$3_4~Bi{&xO9KQH000OG0Mm9&SAI&emq`Nv0D&j~015yA0CZ(@bS`vqVPj?OT3=7w zFc5#=r?B#}7aBGFm$upiY#=~FXwulzyazYAHUY++YC%1tv78T$7hzO`^*}6?`HwY4o1;9 zkTbM@Bqveh%FW+#70^I`@|ck z+)n>6r1Y}}r76YFNkZwSjEW4wqGmfaJH?37oU`MJl7)!z9v!d=;Ajb>hJcb%gP3&n z~tPd>%qWod84iEP_#m)fmMh(3`1x!X432pbKt|d^@{T=_D}?Tx>dKkNU zJ*L~BuVj{hN&!kqW%DblD$GixHRj;fk_^e#6r#eg5eE`W(BiEjFio`~%#gp+y^-ge z%rHv#BqF6W(~au{QW_;nW@(W%f@Z&S`3Q|N6<7B@Oo57vv!54d-&a?D*(LrUdzPCC zPmh3noF|Fc7l%l-s4AHzhXtxrfqR2lwCKvW@!Nq~$c=Ms}U zA(6~7e4mJsSj19r$zp<={famAkkqcZ!>77x4n;mC*PG&MO^&0N%qa6Nz z>Am)>a_-I9%Gr^4cl1V zbHeWrP)h*+5-Ra z2&^b7$(p?R{h!ZwpI#4sx-s3a_(N5kJX=uX_Ghj=pZ7|bc1}^3X3X-sBC}NT9M_?| z-GTgv%C=u#v%d0{L28=vTDQ~uQjD{TmzhS%H=1S4ZuDI8bs6uIA7?&&X^3Qg|G30) zQ}^l&nG-XUB&GV)gZE$Ty#D)F?x(yO{(Z;Jh_qC4JS!6|-rPCkcK-nz=8b0;wcMCG z?SNc$^OV~!=T}XsySTt)=?_aEjk}WqCn`oLnDaIs3Cjec}BLTvqp;NEbF zA78^B3x3=cv(^2V*EETy|EG%MzFl~HtV;CfqqaQO`+Tb(+>Th__}uX1yhJ;v7`yb= zj!CXR;tsi-dHDI>xqAmE9zDEc+Xmr;74z05ge01}ZRGe8wrbu+r7W(JgKH<|r%%_C zRa@3J+m~I(XxFyB%gatb`t>p(!DV~GfeT5&yt*b|c$wEMtgzd6vaY9mbh;_*7`)kK_q@0JvBvR0 zZN+uxD@~#Hq|M*_L?AZ%q~xl+zsG>YaenE3ONMQk(yOb_{rJlo;LXTn&x||I0ka(# bY-t2hh#VN;&B_K6VFW@8AYBB^rwj}LgCMjf literal 0 HcmV?d00001 diff --git a/packages/web-new/tests/test.spec.js b/packages/web-new/tests/test.spec.js new file mode 100644 index 000000000..d59559c94 --- /dev/null +++ b/packages/web-new/tests/test.spec.js @@ -0,0 +1,946 @@ +const { test, expect } = require('@playwright/test') + +//Open the playground app before any test is runned +test.beforeEach(async ({ page }) => { + await page.goto('/') +}); + +test.describe("Load initial state", () => { + test('Has title', async ({ page }) => { + await expect(page).toHaveTitle("TD Playground") + }) + + test('Has editor tab', async ({ page }) => { + const editorTab = page.locator('#tab') + await expect(editorTab).toHaveText("TDThing TemplateCloseCancel") + }) + + test('Has TD template', async ({ page }) => { + const editor = page.locator('#editor1').getByRole('code').locator('div').filter({ hasText: '"title": "Thing Template",' }).nth(4) + await expect(editor).toHaveText('"title": "Thing Template",') + }) + + test('Validation tab is checked', async ({ page }) => { + const validationTab = page.locator('#validation-tab') + await expect(validationTab).toBeChecked() + }) + + test('Validation view is opened', async ({ page }) => { + const validationView = page.locator('#validation-view') + await expect(validationView).toHaveClass("console-view validation-view") + }) + + test('JSON button is checked', async ({ page }) => { + const jsonBtn = page.locator('#file-type-json') + await expect(jsonBtn).toBeChecked() + }) +}) + +test.describe("Check all links", () => { + test("Check Thingweb logo link", async ({ page }) => { + const thingwebPromise = page.waitForEvent('popup') + await page.locator(".logo").click() + const thingwebPage = await thingwebPromise + await expect(thingwebPage).toHaveTitle("Eclipse Thingweb") + await expect(thingwebPage).toHaveURL("https://www.thingweb.io") + }) + + test("Check CLI link", async ({ page }) => { + const cliPromise = page.waitForEvent('popup') + await page.locator(".cli-link").click() + const cliPage = await cliPromise + await expect(cliPage).toHaveURL("https://github.com/eclipse-thingweb/playground/tree/master/packages/cli") + }) + + test("Check Github link", async ({ page }) => { + const githubPromise = page.waitForEvent('popup') + await page.locator(".git-link").click() + const githubPage = await githubPromise + await expect(githubPage).toHaveTitle(/GitHub - eclipse-thingweb/) + await expect(githubPage).toHaveURL("https://github.com/eclipse-thingweb/playground") + }) + + test("Check Thingweb footer link", async ({ page }) => { + await page.locator('#settings-btn').click() + const thingwebPromise = page.waitForEvent('popup') + await page.locator("#thingweb-link").click() + const thingwebPage = await thingwebPromise + await expect(thingwebPage).toHaveTitle("Eclipse Thingweb") + await expect(thingwebPage).toHaveURL("https://www.thingweb.io") + }) + + test("Check Eclipse footer link", async ({ page }) => { + await page.locator('#settings-btn').click() + const eclipsePromise = page.waitForEvent('popup') + await page.locator("#eclipse-link").click() + const eclipsePage = await eclipsePromise + await expect(eclipsePage).toHaveTitle("The Community for Open Collaboration and Innovation | The Eclipse Foundation") + await expect(eclipsePage).toHaveURL("https://www.eclipse.org") + }) + + test("Check privacy policy footer link", async ({ page }) => { + await page.locator('#settings-btn').click() + const privacyPromise = page.waitForEvent('popup') + await page.locator("#privacy-link").click() + const privacyPage = await privacyPromise + await expect(privacyPage).toHaveTitle("Eclipse Foundation Website Privacy Policy | The Eclipse Foundation") + await expect(privacyPage).toHaveURL("https://www.eclipse.org/legal/privacy.php") + }) + + test("Check terms of use footer link", async ({ page }) => { + await page.locator('#settings-btn').click() + const termsPromise = page.waitForEvent('popup') + await page.locator("#terms-link").click() + const termsPage = await termsPromise + await expect(termsPage).toHaveTitle("Eclipse.org Terms of Use | The Eclipse Foundation") + await expect(termsPage).toHaveURL("https://www.eclipse.org/legal/termsofuse.php") + }) + + test("Check copyright agent footer link", async ({ page }) => { + await page.locator('#settings-btn').click() + const copyrightPromise = page.waitForEvent('popup') + await page.locator("#copyright-link").click() + const copyrightPage = await copyrightPromise + await expect(copyrightPage).toHaveTitle("Copyright Agent | The Eclipse Foundation") + await expect(copyrightPage).toHaveURL("https://www.eclipse.org/legal/copyright.php") + }) + + test("Check legal footer link", async ({ page }) => { + await page.locator('#settings-btn').click() + const legalPromise = page.waitForEvent('popup') + await page.locator("#legal-link").click() + const legalPage = await legalPromise + await expect(legalPage).toHaveTitle("Eclipse Foundation Legal Resources | The Eclipse Foundation") + await expect(legalPage).toHaveURL("https://www.eclipse.org/legal/") + }) +}) + +test.describe("Editors and Tabs creation and deletion", () => { + test("Adding a new editor and closing it", async ({ page }) => { + const editorTabs = page.locator("#tab") + const editors = page.locator(".editor") + await expect(editorTabs).toHaveCount(1) + await expect(editors).toHaveCount(1) + + const initialTab = page.locator("#tab").nth(0) + await expect(initialTab).toHaveAttribute('data-tab-id', "1") + await expect(initialTab).toHaveText("TDThing TemplateCloseCancel") + await expect(initialTab).toHaveClass("active") + + const initialEditor = page.locator("#editor1") + await expect(initialEditor).toHaveAttribute('data-ide-id', "1") + await expect(initialEditor).toHaveClass("editor active") + + await page.locator("#ide-tab-add").click() + await expect(editorTabs).toHaveCount(2) + await expect(editors).toHaveCount(2) + + await expect(initialTab).toHaveClass("") + await expect(initialEditor).toHaveClass("editor") + + const secondTab = page.locator("#tab").nth(1) + await expect(secondTab).toHaveAttribute('data-tab-id', "2") + await expect(secondTab).toHaveText("TDThing TemplateCloseCancel") + await expect(secondTab).toHaveClass("active") + + const secondEditor = page.locator("#editor2") + await expect(secondEditor).toHaveAttribute('data-ide-id', "2") + await expect(secondEditor).toHaveClass("editor active") + + await page.locator("#tab").nth(1).locator(".close-tab").click() + await page.locator('#tab').nth(1).locator(".confirm-btns > .confirm-tab-close").click() + + await expect(editorTabs).toHaveCount(1) + await expect(editors).toHaveCount(1) + + await expect(initialTab).toHaveClass("active") + await expect(initialEditor).toHaveClass("editor active") + }) + + test("Opening an example and closing initial editor", async ({ page }) => { + const editorTabs = page.locator("#tab") + const editors = page.locator(".editor") + await expect(editorTabs).toHaveCount(1) + await expect(editors).toHaveCount(1) + + const initialTab = page.locator("#tab").nth(0) + await expect(initialTab).toHaveAttribute('data-tab-id', "1") + await expect(initialTab).toHaveText("TDThing TemplateCloseCancel") + await expect(initialTab).toHaveClass("active") + + const initialEditor = page.locator("#editor1") + await expect(initialEditor).toHaveAttribute('data-ide-id', "1") + await expect(initialEditor).toHaveClass("editor active") + + await page.locator("#examples-btn").click() + await page.locator(".example").nth(0).click() + await page.locator(".example").nth(0).getByRole("button", { name: /Apply/ }).click() + + await expect(editorTabs).toHaveCount(2) + await expect(editors).toHaveCount(2) + + await expect(initialTab).toHaveClass("") + await expect(initialEditor).toHaveClass("editor") + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveClass("editor active") + + await page.locator("#tab").nth(0).locator(".close-tab").click() + await page.locator('#tab').nth(0).locator(".confirm-btns > .confirm-tab-close").click() + + await expect(editorTabs).toHaveCount(1) + await expect(editors).toHaveCount(1) + }) +}) + +test.describe("JSON and YAML conversion", () => { + test("JSON to YAML and YAML to JSON", async ({ page }) => { + const editorTabs = page.locator("#tab") + const editors = page.locator(".editor") + await expect(editorTabs).toHaveCount(1) + await expect(editors).toHaveCount(1) + + const jsonYamlPopup = page.locator('.json-yaml-warning') + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + + const initialEditor = page.locator("#editor1") + const jsonBtn = page.locator('#file-type-json') + const yamlBtn = page.locator('#file-type-yaml') + + await expect(initialEditor).toHaveAttribute('data-mode-id', "json") + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + + await yamlBtn.click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning") + + await page.locator('#yaml-confirm-btn').click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + await expect(initialEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(jsonBtn).toBeChecked({ checked: false }) + await expect(yamlBtn).toBeChecked({ checked: true }) + + await jsonBtn.click() + await expect(initialEditor).toHaveAttribute('data-mode-id', "json") + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + }) + + test("Cancel YAML conversion", async ({ page }) => { + const editorTabs = page.locator("#tab") + const editors = page.locator(".editor") + await expect(editorTabs).toHaveCount(1) + await expect(editors).toHaveCount(1) + + const jsonYamlPopup = page.locator('.json-yaml-warning') + const initialEditor = page.locator("#editor1") + const jsonBtn = page.locator('#file-type-json') + const yamlBtn = page.locator('#file-type-yaml') + + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + await expect(initialEditor).toHaveAttribute('data-mode-id', "json") + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + + await yamlBtn.click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning") + + await page.locator('#yaml-cancel-btn').click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + await expect(initialEditor).toHaveAttribute('data-mode-id', "json") + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + }) +}) + + +test.describe("Examples menu functionality", () => { + test("Open and close examples menu", async ({ page }) => { + + await expect(page.getByRole('heading', { name: 'Simple Default' })).toBeVisible({ visible: false }) + await page.locator("#examples-btn").click() + + await expect(page.getByRole('heading', { name: 'Simple Default' })).toBeVisible({ visible: true }) + await page.locator(".examples-menu-container__close > i").click() + + await expect(page.getByRole('heading', { name: 'Simple Default' })).toBeVisible({ visible: false }) + }) + + test("Open Basic TD from quick access", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const basicExample = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0) + await expect(basicExample).toHaveClass("example") + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveClass("editor active") + + }) + + test("Open Basic TD from apply button", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const basicExample = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0) + await basicExample.click() + await expect(basicExample).toHaveClass("example open") + + const applyBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0).getByRole("button").filter({ hasText: "Apply" }) + await applyBtn.click() + await expect(basicExample).toHaveClass("example") + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveClass("editor active") + }) + + test("Open Basic TD and close with cancel button", async ({ page }) => { + await page.locator("#examples-btn").click() + + const basicTDExample = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0) + await basicTDExample.click() + await expect(basicTDExample).toHaveClass("example open") + + const cancelBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0).getByRole("button").filter({ hasText: "Cancel" }) + await cancelBtn.click() + await expect(basicTDExample).toHaveClass("example") + }) + + test("Toggle between TD and TM examples", async ({ page }) => { + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await expect(thingTypeToggle).toBeChecked({ checked: false }) + + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + }) + + test("Open Basic TM and check for icon change in tab", async ({ page }) => { + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const tabIcon = page.locator("#tab").nth(1).locator(".tab-icon") + await expect(tabIcon).toHaveText("TM") + }) + + test("Go to versioning in TD category and open example from quick access", async ({ page }) => { + await page.locator("#examples-btn").click() + + const categoryDropDown = page.locator("#thing-category") + await categoryDropDown.selectOption('9-versioning') + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Versioning' }).nth(0).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + }) + + test("Go to Tm Optional in TM category and open example from quick access", async ({ page }) => { + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const categoryDropDown = page.locator("#thing-category") + await categoryDropDown.selectOption('4-tm-optional') + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Optional Interaction Affordances' }).nth(0).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + }) + + test("Search for uriVariable in the TDs and open Combined URI variables in href example", async ({ page }) => { + await page.locator("#examples-btn").click() + + const searchInput = page.locator(".search-input") + searchInput.fill('uriVariables') + + const searchBtn = page.locator(".search-btn") + await searchBtn.click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Combined URI variables in href' }).nth(0).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyWeatherThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + }) + + test("Search for overwrite in the TMs and open Overwrite Existing Definitions example", async ({ page }) => { + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const searchInput = page.locator(".search-input") + searchInput.fill('overwrite') + + const searchBtn = page.locator(".search-btn") + await searchBtn.click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Overwrite Existing Definitions' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMSmart Lamp ControlCloseCancel") + await expect(exampleTab).toHaveClass("active") + }) +}) + +test.describe("Save menu functionality", () => { + test("Open and close save menu", async ({ page }) => { + const saveMenu = page.locator(".save-menu") + await expect(saveMenu).toHaveClass("save-menu closed") + + await page.locator("#save-btn").click() + await expect(saveMenu).toHaveClass("save-menu") + + const closeMenu = page.locator(".save-menu-close > i") + await closeMenu.click() + await expect(saveMenu).toHaveClass("save-menu closed") + }) + + test("Open save menu with template thing and check for TD in menu title", async ({ page }) => { + const saveMenu = page.locator(".save-menu") + + await page.locator("#save-btn").click() + await expect(saveMenu).toHaveClass("save-menu") + + const titleThingType = page.locator(".save-menu-title > p > #thing-type-text") + await expect(titleThingType).toHaveText("TD") + }) + + test("Open TM examples check for TM in the save menu title", async ({ page }) => { + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const saveMenu = page.locator(".save-menu") + + await page.locator("#save-btn").click() + await expect(saveMenu).toHaveClass("save-menu") + + const titleThingType = page.locator(".save-menu-title > p > #thing-type-text") + await expect(titleThingType).toHaveText("TM") + }) + + test("Share and open in new tab functionality with an example", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const basicExample = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0) + await expect(basicExample).toHaveClass("example") + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).nth(0).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const saveMenu = page.locator(".save-menu") + + await page.locator("#save-btn").click() + await expect(saveMenu).toHaveClass("save-menu") + + const openNewTab = page.locator("#open-url-tab") + await expect(openNewTab).toBeDisabled() + + const shareUrlInput = page.locator("#share-url-input") + await expect(shareUrlInput).toHaveText("") + + const shareUrlBtn = page.locator("#share-url-btn") + await shareUrlBtn.click() + + const newPlaygroundPromise = page.waitForEvent('popup') + await openNewTab.click() + const newPlaygroundPage = await newPlaygroundPromise + + await expect(newPlaygroundPage).toHaveTitle("TD Playground") + + const newPlaygroundTab = newPlaygroundPage.locator("#tab").nth(0) + await expect(newPlaygroundTab).toHaveAttribute('data-tab-id', "1") + await expect(newPlaygroundTab).toHaveText("TDMyLampThingCloseCancel") + await expect(newPlaygroundTab).toHaveClass("active") + + }) + + test("Open in ediTDor functionality", async ({ page }) => { + const saveMenu = page.locator(".save-menu") + + await page.locator("#save-btn").click() + await expect(saveMenu).toHaveClass("save-menu") + + const shareUrlInput = page.locator("#share-url-input") + await expect(shareUrlInput).toHaveText("") + + const openEditdorBtn = page.locator("#open-editdor-btn") + + const editdorPromise = page.waitForEvent('popup') + await openEditdorBtn.click() + const editdorPage = await editdorPromise + + await expect(editdorPage).toHaveTitle("ediTDor") + + const linkedTd = editdorPage.locator("#linkedTd > option") + await expect(linkedTd).toHaveText("Thing Template") + }) + + test("Download functionality", async ({ page }) => { + const saveMenu = page.locator(".save-menu") + + const exampleTab = page.locator("#tab").nth(0) + await expect(exampleTab).toHaveAttribute('data-tab-id', "1") + await expect(exampleTab).toHaveText("TDThing TemplateCloseCancel") + await expect(exampleTab).toHaveClass("active") + + await page.locator("#save-btn").click() + await expect(saveMenu).toHaveClass("save-menu") + + const downloadTdBtn = page.locator(".save-td__download") + + // Start waiting for download before clicking. + const downloadPromise = page.waitForEvent('download') + await downloadTdBtn.click() + const download = await downloadPromise + const expectedFilename = 'Thing-Template.json' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + //* The "Save as" functionality cannot be tested because it requires to open and interact with the file system wich Playwright cannot do +}) + +test.describe("Settings menu functionality", () => { + test("Opening and closing the settings menu", async ({ page }) => { + const settingsMenu = page.locator(".settings-menu") + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + const closeMenu = page.locator(".settings__close > i") + await closeMenu.click() + await expect(settingsMenu).toHaveClass("settings-menu closed") + }) + + test("Checking settings toggle buttons", async ({ page }) => { + const settingsMenu = page.locator(".settings-menu") + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + const autoValidate = page.locator("#auto-validate") + const validateJsonld = page.locator("#validate-jsonld") + const tmConformance = page.locator("#tm-conformance") + + await expect(autoValidate).toBeChecked({ checked: false }) + await expect(validateJsonld).toBeChecked({ checked: true }) + await expect(tmConformance).toBeChecked({ checked: true }) + }) + + test("Changing page theme", async ({ page }) => { + const playgroundSite = page.locator("html") + await expect(playgroundSite).toHaveClass("light-mode") + + const settingsMenu = page.locator(".settings-menu") + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + const themePicker = page.locator("#theme-picker") + await themePicker.selectOption('monochrome-mode') + await expect(playgroundSite).toHaveClass("monochrome-mode") + + await themePicker.selectOption('dark-mode') + await expect(playgroundSite).toHaveClass("dark-mode") + + await page.reload({ waitUntil: 'domcontentloaded' }) + await expect(playgroundSite).toHaveClass("dark-mode") + }) + + test("Changing font size", async ({ page }) => { + const settingsMenu = page.locator(".settings-menu") + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + const editorFontSize = page.locator(".editor-font-size") + await expect(editorFontSize).toHaveText("14") + + const fontSizeSlider = page.locator('#font-size') + await fontSizeSlider.click() + + await expect(editorFontSize).toHaveText("23") + + await page.reload({ waitUntil: 'domcontentloaded' }) + + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + await expect(editorFontSize).toHaveText("23") + }) + + test("Utilizing default settings", async ({ page }) => { + const playgroundSite = page.locator("html") + await expect(playgroundSite).toHaveClass("light-mode") + + const settingsMenu = page.locator(".settings-menu") + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + const themePicker = page.locator("#theme-picker") + await themePicker.selectOption('dark-mode') + await expect(playgroundSite).toHaveClass("dark-mode") + + const editorFontSize = page.locator(".editor-font-size") + await expect(editorFontSize).toHaveText("14") + + const fontSizeSlider = page.locator('#font-size') + await fontSizeSlider.click() + + await expect(editorFontSize).toHaveText("23") + + await page.reload({ waitUntil: 'domcontentloaded' }) + + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + await expect(playgroundSite).toHaveClass("dark-mode") + await expect(editorFontSize).toHaveText("23") + + const resetSettings = page.locator('.reset-settings') + await resetSettings.click() + + await expect(playgroundSite).toHaveClass("light-mode") + await expect(editorFontSize).toHaveText("14") + + await page.reload({ waitUntil: 'domcontentloaded' }) + + await expect(settingsMenu).toHaveClass("settings-menu closed") + + await page.locator("#settings-btn").click() + await expect(settingsMenu).toHaveClass("settings-menu") + + await expect(playgroundSite).toHaveClass("light-mode") + await expect(editorFontSize).toHaveText("14") + }) +}) + +test.describe("Validation view functionality", () => { + + test("Starting the validation with the main valiation button", async ({ page }) => { + + const validationTab = page.locator('#validation-tab') + const validationView = page.locator('#validation-view') + + await expect(validationTab).toBeChecked() + await expect(validationView).toHaveClass("console-view validation-view") + + const stateIcon = page.locator(".json-validation-section > .section-header > i").nth(0) + await expect(stateIcon).toHaveClass("fa-solid fa-circle") + + const validationBtn = page.locator("#validate-btn") + await validationBtn.click() + + //TODO: Find a better way to wait for this event to happen + await page.waitForTimeout(5000) + await expect(stateIcon).toHaveClass("fa-solid fa-circle-check") + }) + + test("Closing the default validation view and opening it again with the validation view tab", async ({ page }) => { + + const validationTab = page.locator('#validation-tab') + const validationView = page.locator('#validation-view') + + await expect(validationTab).toBeChecked() + await expect(validationView).toHaveClass("console-view validation-view") + + const trashBtn = page.locator(".trash") + await trashBtn.click() + + await expect(validationTab).toBeChecked({checked: false}) + await expect(validationView).toHaveClass("console-view validation-view hidden") + + await validationTab.click() + + await expect(validationTab).toBeChecked({checked: true}) + await expect(validationView).toHaveClass("console-view validation-view") + + const stateIcon = page.locator(".json-validation-section > .section-header > i").nth(0) + await expect(stateIcon).toHaveClass("fa-solid fa-circle-check") + }) + + test("Validating the 'All Defaults TD'", async ({ page }) => { + const validationTab = page.locator('#validation-tab') + const validationView = page.locator('#validation-view') + + await expect(validationTab).toBeChecked() + await expect(validationView).toHaveClass("console-view validation-view") + + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'All Default Values' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + await expect(validationTab).toBeChecked({checked: false}) + await expect(validationView).toHaveClass("console-view validation-view hidden") + + const validationBtn = page.locator("#validate-btn") + await validationBtn.click() + + await expect(validationTab).toBeChecked({checked: true}) + await expect(validationView).toHaveClass("console-view validation-view") + + //validation section + const jsonValidationSection = page.locator(".json-validation-section") + const jsonValidationSectionIcon = page.locator(".json-validation-section > .section-header > i").nth(0) + const jsonValidationSectionTxt = page.locator(".json-validation-section > .section-content > li") + + await jsonValidationSection.click() + await expect(jsonValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonSchemaValidationSection = page.locator(".json-schema-validation-section") + const jsonSchemaValidationSectionIcon = page.locator(".json-schema-validation-section > .section-header > i").nth(0) + const jsonSchemaValidationSectionTxt = page.locator(".json-schema-validation-section > .section-content > li") + + await jsonSchemaValidationSection.click() + await expect(jsonSchemaValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonSchemaValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonSchemaDefaultsSection = page.locator(".json-schema-defaults-section") + const jsonSchemaDefaultsSectionIcon = page.locator(".json-schema-defaults-section > .section-header > i").nth(0) + const jsonSchemaDefaultsSectionTxt = page.locator(".json-schema-defaults-section > .section-content > li") + + await jsonSchemaDefaultsSection.click() + await expect(jsonSchemaDefaultsSectionTxt).toHaveText("Validated Successfully") + await expect(jsonSchemaDefaultsSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonlsValidationSection = page.locator(".jsonls-validation-section") + const jsonlsValidationSectionIcon = page.locator(".jsonls-validation-section > .section-header > i").nth(0) + const jsonlsValidationSectionTxt = page.locator(".jsonls-validation-section > .section-content > li") + + await jsonlsValidationSection.click() + await expect(jsonlsValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonlsValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const additionalChecksSection = page.locator(".additional-checks-section") + const additionalChecksSectionIcon = page.locator(".additional-checks-section > .section-header > i").nth(0) + const additionalChecksSectionTxt = page.locator(".additional-checks-section > .section-content > li") + + await additionalChecksSection.click() + await expect(additionalChecksSectionTxt).toHaveText("Validated Successfully") + await expect(additionalChecksSectionIcon).toHaveClass("fa-solid fa-circle-check") + }) + + test("Validating the 'Basic TD'", async ({ page }) => { + const validationTab = page.locator('#validation-tab') + const validationView = page.locator('#validation-view') + + await expect(validationTab).toBeChecked() + await expect(validationView).toHaveClass("console-view validation-view") + + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + await expect(validationTab).toBeChecked({checked: false}) + await expect(validationView).toHaveClass("console-view validation-view hidden") + + const validationBtn = page.locator("#validate-btn") + await validationBtn.click() + + await expect(validationTab).toBeChecked({checked: true}) + await expect(validationView).toHaveClass("console-view validation-view") + + + //Validation section + const jsonValidationSection = page.locator(".json-validation-section") + const jsonValidationSectionIcon = page.locator(".json-validation-section > .section-header > i").nth(0) + const jsonValidationSectionTxt = page.locator(".json-validation-section > .section-content > li") + + await jsonValidationSection.click() + await expect(jsonValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonSchemaValidationSection = page.locator(".json-schema-validation-section") + const jsonSchemaValidationSectionIcon = page.locator(".json-schema-validation-section > .section-header > i").nth(0) + const jsonSchemaValidationSectionTxt = page.locator(".json-schema-validation-section > .section-content > li") + + await jsonSchemaValidationSection.click() + await expect(jsonSchemaValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonSchemaValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonSchemaDefaultsSection = page.locator(".json-schema-defaults-section") + const jsonSchemaDefaultsSectionIcon = page.locator(".json-schema-defaults-section > .section-header > i").nth(0) + const jsonSchemaDefaultsSectionTxt = page.locator(".json-schema-defaults-section > .section-content > li").nth(0) + + await jsonSchemaDefaultsSection.click() + await expect(jsonSchemaDefaultsSectionTxt).toHaveText("Optional validation failed:") + await expect(jsonSchemaDefaultsSectionIcon).toHaveClass("fa-solid fa-circle-exclamation") + + const jsonlsValidationSection = page.locator(".jsonls-validation-section") + const jsonlsValidationSectionIcon = page.locator(".jsonls-validation-section > .section-header > i").nth(0) + const jsonlsValidationSectionTxt = page.locator(".jsonls-validation-section > .section-content > li") + + await jsonlsValidationSection.click() + await expect(jsonlsValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonlsValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const additionalChecksSection = page.locator(".additional-checks-section") + const additionalChecksSectionIcon = page.locator(".additional-checks-section > .section-header > i").nth(0) + const additionalChecksSectionTxt = page.locator(".additional-checks-section > .section-content > li") + + await additionalChecksSection.click() + await expect(additionalChecksSectionTxt).toHaveText("Validated Successfully") + await expect(additionalChecksSectionIcon).toHaveClass("fa-solid fa-circle-check") + }) + + test("Validating the 'Basic TM'", async ({ page }) => { + + const validationTab = page.locator('#validation-tab') + const validationView = page.locator('#validation-view') + + await expect(validationTab).toBeChecked() + await expect(validationView).toHaveClass("console-view validation-view") + + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + await expect(validationTab).toBeChecked({checked: false}) + await expect(validationView).toHaveClass("console-view validation-view hidden") + + const validationBtn = page.locator("#validate-btn") + await validationBtn.click() + + await expect(validationTab).toBeChecked({checked: true}) + await expect(validationView).toHaveClass("console-view validation-view") + + //Validation section + const jsonValidationSection = page.locator(".json-validation-section") + const jsonValidationSectionIcon = page.locator(".json-validation-section > .section-header > i").nth(0) + const jsonValidationSectionTxt = page.locator(".json-validation-section > .section-content > li") + + await jsonValidationSection.click() + await expect(jsonValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonSchemaValidationSection = page.locator(".json-schema-validation-section") + const jsonSchemaValidationSectionIcon = page.locator(".json-schema-validation-section > .section-header > i").nth(0) + const jsonSchemaValidationSectionTxt = page.locator(".json-schema-validation-section > .section-content > li") + + await jsonSchemaValidationSection.click() + await expect(jsonSchemaValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonSchemaValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const jsonSchemaDefaultsSection = page.locator(".json-schema-defaults-section") + const jsonSchemaDefaultsSectionIcon = page.locator(".json-schema-defaults-section > .section-header > i").nth(0) + const jsonSchemaDefaultsSectionTxt = page.locator(".json-schema-defaults-section > .section-content > li").nth(0) + + await jsonSchemaDefaultsSection.click() + await expect(jsonSchemaDefaultsSectionTxt).toHaveText("A previous validation has failed or it is only available for Thing Descriptions") + await expect(jsonSchemaDefaultsSectionIcon).toHaveClass("fa-solid fa-circle") + + const jsonlsValidationSection = page.locator(".jsonls-validation-section") + const jsonlsValidationSectionIcon = page.locator(".jsonls-validation-section > .section-header > i").nth(0) + const jsonlsValidationSectionTxt = page.locator(".jsonls-validation-section > .section-content > li") + + await jsonlsValidationSection.click() + await expect(jsonlsValidationSectionTxt).toHaveText("Validated Successfully") + await expect(jsonlsValidationSectionIcon).toHaveClass("fa-solid fa-circle-check") + + const additionalChecksSection = page.locator(".additional-checks-section") + const additionalChecksSectionIcon = page.locator(".additional-checks-section > .section-header > i").nth(0) + const additionalChecksSectionTxt = page.locator(".additional-checks-section > .section-content > li") + + await additionalChecksSection.click() + await expect(additionalChecksSectionTxt).toHaveText("Validated Successfully") + await expect(additionalChecksSectionIcon).toHaveClass("fa-solid fa-circle-check") + }) + +}) + + +/* +7. openapi +8. async api +9. aas conversion +10. defaults +11. visualize +*/ \ No newline at end of file From 3dd4cd5e79a31b3f3cf90449a41d40e36c5ad7eb Mon Sep 17 00:00:00 2001 From: Sergio Eduardo Castro Ceballos <72516762+SergioCasCeb@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:17:48 +0200 Subject: [PATCH 02/56] Ignored test results and Added test script --- .gitignore | 1 + packages/web-new/package.json | 3 ++- .../trace.zip | Bin 962 -> 0 bytes .../trace.zip | Bin 961 -> 0 bytes .../trace.zip | Bin 961 -> 0 bytes .../trace.zip | Bin 965 -> 0 bytes .../trace.zip | Bin 959 -> 0 bytes .../trace.zip | Bin 960 -> 0 bytes 8 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 packages/web-new/test-results/test-Load-initial-state-Has-TD-template-chromium/trace.zip delete mode 100644 packages/web-new/test-results/test-Load-initial-state-Has-editor-tab-chromium/trace.zip delete mode 100644 packages/web-new/test-results/test-Load-initial-state-Has-title-chromium/trace.zip delete mode 100644 packages/web-new/test-results/test-Load-initial-state-JSON-button-is-checked-chromium/trace.zip delete mode 100644 packages/web-new/test-results/test-Load-initial-state-Validation-tab-is-checked-chromium/trace.zip delete mode 100644 packages/web-new/test-results/test-Load-initial-state-Validation-view-is-opened-chromium/trace.zip diff --git a/.gitignore b/.gitignore index ab58cf437..9cfa1dd0e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules # test screenshots for web package test_results/ +test-results/ # dist directory should be included only in the Package but not Repository dist diff --git a/packages/web-new/package.json b/packages/web-new/package.json index e6d4ebcd1..9352d2768 100644 --- a/packages/web-new/package.json +++ b/packages/web-new/package.json @@ -18,7 +18,8 @@ "build": "node external-scripts/generate-paths.js && webpack --mode production", "dev": "webpack serve --mode development", "serve": "node server/server.js", - "examples": "node external-scripts/generate-paths.js" + "examples": "node external-scripts/generate-paths.js", + "test": "npx playwright test" }, "devDependencies": { "@babel/core": "^7.22.9", diff --git a/packages/web-new/test-results/test-Load-initial-state-Has-TD-template-chromium/trace.zip b/packages/web-new/test-results/test-Load-initial-state-Has-TD-template-chromium/trace.zip deleted file mode 100644 index 6d60317fcc127be4ad378b3c535014f126fa5639..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 962 zcmWIWW@Zs#VBp|jxLoENZYFS?--nrjp;3c@fs28Gp(M4qM6aYMF*)^ZRJ{Lf1A+Sc z%Qt-5Braw8clwrF%sC1UP8^wcFYjSD-)Y8pye}tR)2XK2S8A3?r~YyEn>$-C8J(KX z$Q0V=ms|Ah?%$f{f2vm1Jev8KY0o_KhJ_&y)>axmt}%D?)p~lds$mwF>0h1Wk&ery z&0aaG_uNV>K6|-M(^&SUiBz4oQ|y_U*D~(1=Uy;lpX~M8S6bu4OwpTmo7wIi_jK6Q z9B9HP;Uv?_Y1f+&#JagXywm3TK!N%A2KUIPaHZ>px(_y7B0vDK|X4 z6XsVO?z#PPe$|w^iwjJa{;>4YygQ|ErgFrUob^X}kvVl0n-Hyxa`YU9G0 zA>X$xYV^?azQFZ2P2l0Xsmj^?FU?+P&s9lS#jteArk|phwS2smm_B=OZPJ$$*CZZY z+Q7&@$>YMKy^03swkV#NP=9%Epvdeq243G)l$M%Y-};&*NNTy)v&fm(o2stts%eRu z+PS(~{+Pqjqc_)gZ1VXuzf)t!j?mY6O&qL?4%zgDF6|s#%F`HT*r0q}Qy{pW9 z{mjGSSZ+R7L$&L(A7%Oa7yMYmVQ(VdeejdI<)6>Ds^7Xky)%2`)a|J=Q@=Ssv3SyY zw6NpxgsBsXwf0=zZ8i6&TgkesoqzH!l&n1`E$$xNw=B#lX7%T+M;1p4Pk5c!yY}3h z`-gVgEq`6UxbJoGy&V>PMKW839{rjVE___E&pFIV?%Hz}?pnXy@7fbz{F-B~*SA>4 zeQnDQyXRMrKrEVFdv20)$y-(R6;9P5>Hk zmv8vANnFbG@BJ+P4UG((ic3oUKg->Da*IXAdehvc93N%PGBYlz?30r%fxqLM4F+mu zOGP)F-;;Rg?H7Mrul*STvx5G}9G#MP+Q45>C#y_&^K^cVvliB}nlrmO-d|*tX6zF) zSizy8VcOy8zrSX#;|uxQ86RC9F!8qNRnFsDf8A=ob;RM6oFdlQUsXS@TH6)AJ+do& z^~JBzj=u#z?uy&$&gLa1(e(dRaoCp&kJA?S)D$|OKCr!M0nff()?0jXliz4QvwQT( z^0cdj{-N(lYD#?bzn6dK|1HM<_|~Dm#)VazngVxTl{o5j;dW=$v91*w7c95C?VB6B zB1L32SDu;VrVB5;8ZN7ye)Q|4M}o`t#1j{iynA&_zVJG)S(stB?`UP^sT^m8ebafu zp7ipbRoQ>~5}VR4Kd0sIuCFRx6K}ccn?zpozDJ%6%eVr(w4~z=&mK~7jY{U3wrq)e z*)f4z<$so+g_tO@k5bNI8 z?khw(XWad5z^1iMuP!$BPelCB-0eRm%S7a<*;q0bneYp3)aRR+6&PyZ+gBW-&XnC; z-0`Nxrh7)?3H2A*uRe4zUv>!5>*#FcQGG7dY^}7=C%9&Q$HW;&oC;1VH668k%zIaP zY4*DhJJ(Hep4fZRH}K52FD&inyFNJYox?ND?&QPy*Vk@k>a?H!6CY0y z7dx)l=X}jcZ{>$`?_ZUOMPCeBeL2@OX7%S|M=wrUymG6+^;dglS@0FgY!WNVUv2z< zf5F1@nZM>nJ@_@pT(57jjQiTw9d^&J9x3d2JYnmE_OF(XJI`nS-rAR4d~b(ESCPn8 zu}8P&gbPD#$=hzJeeQy3xa`7B>5s+w14?(*U7g2S{XuY*?(Oiq#Yf)j2Y53w*)!wL gbijNE23s0I6e0@-c(byBL>Ph40!SAFGb#fE0D?fgQvd(} diff --git a/packages/web-new/test-results/test-Load-initial-state-Has-title-chromium/trace.zip b/packages/web-new/test-results/test-Load-initial-state-Has-title-chromium/trace.zip deleted file mode 100644 index 64695147e8a234e6a4a13110a746ab0f4b82db00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 961 zcmWIWW@Zs#VBp|jxLoENUb6PLzBe-iLz4yr0~Z4WLrH3JiC#%jVsh%+sCfU|1_Jf> zmv8vANnFbG@APfAm~#{yoH#P?Uf#oQzSE5HcwbJsrc+J3uhcA)PW|KRH+QyPGB`D# zktwv#FSqF1-M=-@|5UB2c{KB}%$|MbEfYf?tgRG$Tx0I$tMv3@Rl_VH(`J*yk&es7 z&0aaGzuC6?tf{~BvNJhLg5Upeyx>@TZj0M%#*F4|k~3VQ@^3lxo!9aIKGXDrogecg z*`7s(3h7;`85KoVU!`R$|E|C9cYp4k=Jkfgtch|BJFl-x;)|-&uV8s1*`_O|dW0>i z>DLkIrFZ=PUs?X8n{BD)(es5)FPHUn@oZd_W^HPHbi$=Mn;&nS)Y|b;PIiOggAC5Y zvl=D^HP86+=Ja(-mwyX=#r#>>G89WrcKbXC@_T>os>a+IP6w+#Pb)E;B}mQPzB(sXB(N|3jbcd9(QV*D%qakDBsW@4pQ>(C&DdKYHzPk?OX}h8;EM zxCB+ZKkRMkoN@U1-M4rDHXc2^W7`JdgcbAL3|4KBS{%VrWgL2bhjJEI$-%V~^V6qm z$*M1F>-KfmG1?V&JoEAf342-YGcVM7B%*RwY;0}Ym)KIRF|R+rAZ~8aRt16k+HBsh zj=7~p-M@W`O=+KwlktaYMX|Qi8@C=Wk^VB(N7x{^At>nPpRP#JWvZ8?iVLzmf2CwI z1t#8@z}%^t@$sI(j3u`O(oXDudGEw$-!zG()j|`4X1%;s%B0yVq`G;_i7dyxw|CXF zM9u74T`jNXaP;WS_1&B0S8MNoD^x$p*86PBa(4&5XP!#mjw%M}uJT%TGO_Vh$b)+i zWRk2Go=8qp_{RBbmZi;u1118Y97#e7$|rXodD7>pvYF?;dXkFRMv<6JGajVvf5dxN zeQNf*4?EX&IZyOI@pajbsLR4KcG`#d&t@4$d{b$!kE>q4cg39Q;%%R{>1;kz-zC$& zXM+V_q0Ad)G-(Rrs z{L7zT7d-zp$6T*(v5foLmK}D_uO2Dvcsyb1g!ZqNj!VyHw$=%>tUF)%_>sk_!Yf`K zuZ!b+W!f$HA~|>7e6C~Zd_AtHO)KY~h4aXAHzSihGww_W f%y(e0r4d9SvS5HWD;r3J5eO}SbTKfaGB5xDe3iY3 diff --git a/packages/web-new/test-results/test-Load-initial-state-JSON-button-is-checked-chromium/trace.zip b/packages/web-new/test-results/test-Load-initial-state-JSON-button-is-checked-chromium/trace.zip deleted file mode 100644 index 374c1e6f9c34b1313d723b22eee026fea9288878..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 965 zcmWIWW@Zs#VBp|jxKidD{##3RvOhBeL$d}00~Z4WLrH3JiC#%jVsh%+sKD&o1_E{W z*9+9$^iGyBFMPD2y(~MEd$GthTi@z{H{NeTr}e0umt6Wkv3csj1@(FRQCY*JhgqJTle(oSeqHXZq!a zCjyHz_5>Ooq)5M9>b7lcRq!e1}Q=Uj>fc zXKPB6>|cDjcH(;J6-G&|$Yid6E6=6cI`mu5Rr_?5QaK)*to+Qo}dt+=LbY*B>5Z&&!Pd0XS z&77HHerEC;kGu#IZ}&Z%^ruG0U~#oUQpU#B$Hb(5wF$0USW;I%{qwU4vpE}o+%Sj; zG&eK4{7X+;y5q|(4#9N`1m;`l9ls`bIrl=inePD~Mla9Q&)R9BGp2cDpE-DG63>Z$ zER#-cP-LIvb>Y!YMT3)D70*n#e|c~8wCXbkUh&>8UYQG{w{tErIXOk=)2fWE&2`Uz z2}PCa<(;dY!60g{xBuUcKYMn5I_vk5yE1p@%nyHfPMoyyJYr|zvdT5|tjW)Sg;wG_ z%q-fk@U1vCMbe|TXOK8&!o)aELdWJibC!JVy;CZJ+r|TNl={l-AZsb=u z^Lsp=VO_Ig@xy>A!bQ6^@}8COxAS*>I9j$@V$F`}hu`<_z4mW)Ol9%5Pv3MmpQ-PX zY5$X6DD%i7Mfph=*ZW8QbI&DdSKWT~g~@(XeMijd&r6P8oU(XjufX+JHnS}F3S~A4 z7NxH?u8-ew;rW)oE97_EJ@4#(tZ_V0T5;X^N)xC_?|;oH+kBq$uiuk<&uvNzWu97O zDIfW2*{{~;EYqIT^5@p`H8)(Y$8K$3_4~Bi{&xO9KQH000OG0Mm9&SAI&emq`Nv0D&j~015yA0CZ(@bS`vqVPj?OT3=7w zFc5#=r?B#}7aBGFm$upiY#=~FXwulzyazYAHUY++YC%1tv78T$7hzO`^*}6?`HwY4o1;9 zkTbM@Bqveh%FW+#70^I`@|ck z+)n>6r1Y}}r76YFNkZwSjEW4wqGmfaJH?37oU`MJl7)!z9v!d=;Ajb>hJcb%gP3&n z~tPd>%qWod84iEP_#m)fmMh(3`1x!X432pbKt|d^@{T=_D}?Tx>dKkNU zJ*L~BuVj{hN&!kqW%DblD$GixHRj;fk_^e#6r#eg5eE`W(BiEjFio`~%#gp+y^-ge z%rHv#BqF6W(~au{QW_;nW@(W%f@Z&S`3Q|N6<7B@Oo57vv!54d-&a?D*(LrUdzPCC zPmh3noF|Fc7l%l-s4AHzhXtxrfqR2lwCKvW@!Nq~$c=Ms}U zA(6~7e4mJsSj19r$zp<={famAkkqcZ!>77x4n;mC*PG&MO^&0N%qa6Nz z>Am)>a_-I9%Gr^4cl1V zbHeWrP)h*+5-Ra z2&^b7$(p?R{h!ZwpI#4sx-s3a_(N5kJX=uX_Ghj=pZ7|bc1}^3X3X-sBC}NT9M_?| z-GTgv%C=u#v%d0{L28=vTDQ~uQjD{TmzhS%H=1S4ZuDI8bs6uIA7?&&X^3Qg|G30) zQ}^l&nG-XUB&GV)gZE$Ty#D)F?x(yO{(Z;Jh_qC4JS!6|-rPCkcK-nz=8b0;wcMCG z?SNc$^OV~!=T}XsySTt)=?_aEjk}WqCn`oLnDaIs3Cjec}BLTvqp;NEbF zA78^B3x3=cv(^2V*EETy|EG%MzFl~HtV;CfqqaQO`+Tb(+>Th__}uX1yhJ;v7`yb= zj!CXR;tsi-dHDI>xqAmE9zDEc+Xmr;74z05ge01}ZRGe8wrbu+r7W(JgKH<|r%%_C zRa@3J+m~I(XxFyB%gatb`t>p(!DV~GfeT5&yt*b|c$wEMtgzd6vaY9mbh;_*7`)kK_q@0JvBvR0 zZN+uxD@~#Hq|M*_L?AZ%q~xl+zsG>YaenE3ONMQk(yOb_{rJlo;LXTn&x||I0ka(# bY-t2hh#VN;&B_K6VFW@8AYBB^rwj}LgCMjf From 28e3c51114b36b60cbd1d5838c441dd93bf4b77a Mon Sep 17 00:00:00 2001 From: Sergio Eduardo Castro Ceballos <72516762+SergioCasCeb@users.noreply.github.com> Date: Fri, 13 Oct 2023 23:04:03 +0200 Subject: [PATCH 03/56] Added remaining tests and fixed template.html --- packages/web-new/src/template.html | 16 +- packages/web-new/tests/test.spec.js | 1345 ++++++++++++++++++++++++++- 2 files changed, 1339 insertions(+), 22 deletions(-) diff --git a/packages/web-new/src/template.html b/packages/web-new/src/template.html index b20974e92..b501d3851 100644 --- a/packages/web-new/src/template.html +++ b/packages/web-new/src/template.html @@ -565,13 +565,17 @@

Preferences

diff --git a/packages/web-new/tests/test.spec.js b/packages/web-new/tests/test.spec.js index d59559c94..1aad96ed2 100644 --- a/packages/web-new/tests/test.spec.js +++ b/packages/web-new/tests/test.spec.js @@ -1,4 +1,4 @@ -const { test, expect } = require('@playwright/test') +const { test, expect } = require('@playwright/test'); //Open the playground app before any test is runned test.beforeEach(async ({ page }) => { @@ -712,12 +712,12 @@ test.describe("Validation view functionality", () => { const trashBtn = page.locator(".trash") await trashBtn.click() - await expect(validationTab).toBeChecked({checked: false}) + await expect(validationTab).toBeChecked({ checked: false }) await expect(validationView).toHaveClass("console-view validation-view hidden") await validationTab.click() - await expect(validationTab).toBeChecked({checked: true}) + await expect(validationTab).toBeChecked({ checked: true }) await expect(validationView).toHaveClass("console-view validation-view") const stateIcon = page.locator(".json-validation-section > .section-header > i").nth(0) @@ -741,13 +741,13 @@ test.describe("Validation view functionality", () => { await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") await expect(exampleTab).toHaveClass("active") - await expect(validationTab).toBeChecked({checked: false}) + await expect(validationTab).toBeChecked({ checked: false }) await expect(validationView).toHaveClass("console-view validation-view hidden") const validationBtn = page.locator("#validate-btn") await validationBtn.click() - await expect(validationTab).toBeChecked({checked: true}) + await expect(validationTab).toBeChecked({ checked: true }) await expect(validationView).toHaveClass("console-view validation-view") //validation section @@ -809,13 +809,13 @@ test.describe("Validation view functionality", () => { await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") await expect(exampleTab).toHaveClass("active") - await expect(validationTab).toBeChecked({checked: false}) + await expect(validationTab).toBeChecked({ checked: false }) await expect(validationView).toHaveClass("console-view validation-view hidden") const validationBtn = page.locator("#validate-btn") await validationBtn.click() - await expect(validationTab).toBeChecked({checked: true}) + await expect(validationTab).toBeChecked({ checked: true }) await expect(validationView).toHaveClass("console-view validation-view") @@ -883,13 +883,13 @@ test.describe("Validation view functionality", () => { await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") await expect(exampleTab).toHaveClass("active") - await expect(validationTab).toBeChecked({checked: false}) + await expect(validationTab).toBeChecked({ checked: false }) await expect(validationView).toHaveClass("console-view validation-view hidden") const validationBtn = page.locator("#validate-btn") await validationBtn.click() - await expect(validationTab).toBeChecked({checked: true}) + await expect(validationTab).toBeChecked({ checked: true }) await expect(validationView).toHaveClass("console-view validation-view") //Validation section @@ -936,11 +936,1324 @@ test.describe("Validation view functionality", () => { }) +test.describe("OpenAPI view functionality", () => { + test("Trying to open the OpenAPI view with a TD with no protocols and closing it", async ({ page }) => { -/* -7. openapi -8. async api -9. aas conversion -10. defaults -11. visualize -*/ \ No newline at end of file + const initialTab = page.locator("#tab").nth(0) + await expect(initialTab).toHaveAttribute('data-tab-id', "1") + await expect(initialTab).toHaveText("TDThing TemplateCloseCancel") + await expect(initialTab).toHaveClass("active") + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("Please insert a TD which uses HTTP!") + + const trashBtn = page.locator(".trash") + await trashBtn.click() + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + }) + + test("Trying to open the OpenAPI view with a TM", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("This function is only allowed for Thing Descriptions!") + + }) + + test("Open the OpenAPI view with the 'Basic TD' example", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const openAPIEditor = page.locator('#open-api-container') + const openAPIContainer = openAPIEditor.getByRole('code').locator('div').filter({ hasText: '"openapi": "3.0.3",' }).nth(4) + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "json") + await expect(openAPIContainer).toHaveText('\"openapi\": \"3.0.3\",') + + const openAPIJsonBtn = page.locator('#open-api-json') + + await expect(openAPIJsonBtn).toBeDisabled() + + }) + + test("Open the OpenAPI view with the 'Basic TD' example as YAML", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + + const jsonYamlPopup = page.locator('.json-yaml-warning') + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + + const jsonBtn = page.locator('#file-type-json') + const yamlBtn = page.locator('#file-type-yaml') + + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + + await yamlBtn.click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning") + + await page.locator('#yaml-confirm-btn').click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(jsonBtn).toBeChecked({ checked: false }) + await expect(yamlBtn).toBeChecked({ checked: true }) + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const openAPIEditor = page.locator('#open-api-container') + const openAPIContainer = openAPIEditor.getByRole('code').locator('div').filter({ hasText: 'openapi: "3.0.3"' }).nth(4) + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(openAPIContainer).toHaveText('openapi: "3.0.3"') + + const openAPIYamlBtn = page.locator('#open-api-yaml') + await expect(openAPIYamlBtn).toBeDisabled() + + }) + + test("Open the OpenAPI view and change form JSON to YAML and from YAML to JSON", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const openAPIEditor = page.locator('#open-api-container') + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "json") + + const openAPIJsonBtn = page.locator('#open-api-json') + const openAPIYamlBtn = page.locator('#open-api-yaml') + + await expect(openAPIJsonBtn).toBeDisabled() + + await openAPIYamlBtn.click() + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(openAPIYamlBtn).toBeDisabled() + + await openAPIJsonBtn.click() + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "json") + await expect(openAPIJsonBtn).toBeDisabled() + }) + + test("Open the OpenAPI view and downloading it as JSON", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const openAPIEditor = page.locator('#open-api-container') + const openAPIContainer = openAPIEditor.getByRole('code').locator('div').filter({ hasText: '"openapi": "3.0.3",' }).nth(4) + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "json") + await expect(openAPIContainer).toHaveText('\"openapi\": \"3.0.3\",') + + const openAPIJsonBtn = page.locator('#open-api-json') + await expect(openAPIJsonBtn).toBeDisabled() + + // Start waiting for download before clicking. + const openAPIDownload = page.locator('#open-api-download') + const downloadPromise = page.waitForEvent('download') + await openAPIDownload.click() + const download = await downloadPromise + const expectedFilename = 'MyLampThing-OpenAPI.json' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + test("Open the OpenAPI view and downloading it as YAML", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const openAPIView = page.locator('#open-api-view') + const consoleError = page.locator('#console-error') + const openAPITab = page.locator("#open-api-tab") + + await expect(openAPIView).toHaveClass("console-view open-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(openAPITab).toBeChecked({ checked: false }) + + await openAPITab.click() + + await expect(openAPITab).toBeChecked({ checked: true }) + await expect(openAPIView).toHaveClass("console-view open-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const openAPIEditor = page.locator('#open-api-container') + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "json") + + const openAPIJsonBtn = page.locator('#open-api-json') + const openAPIYamlBtn = page.locator('#open-api-yaml') + + await expect(openAPIJsonBtn).toBeDisabled() + + await openAPIYamlBtn.click() + + await expect(openAPIEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(openAPIYamlBtn).toBeDisabled() + + const openAPIContainer = openAPIEditor.getByRole('code').locator('div').filter({ hasText: 'openapi: 3.0.3' }).nth(4) + await expect(openAPIContainer).toHaveText('openapi: 3.0.3') + + // Start waiting for download before clicking. + const openAPIDownload = page.locator('#open-api-download') + const downloadPromise = page.waitForEvent('download') + await openAPIDownload.click() + const download = await downloadPromise + const expectedFilename = 'MyLampThing-OpenAPI.yaml' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) +}) + +test.describe("AsyncAPI view functionality", () => { + test("Trying to open the AsyncAPI view with a TD with no protocols and closing it", async ({ page }) => { + + const initialTab = page.locator("#tab").nth(0) + await expect(initialTab).toHaveAttribute('data-tab-id', "1") + await expect(initialTab).toHaveText("TDThing TemplateCloseCancel") + await expect(initialTab).toHaveClass("active") + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("Please insert a TD which uses MQTT!") + + const trashBtn = page.locator(".trash") + await trashBtn.click() + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + }) + + test("Trying to open the AsyncAPI view with a TM", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("This function is only allowed for Thing Descriptions!") + + }) + + /** + * TODO: Do to a lack of examples that include the mqtt protocol this cannot be tested, nonetheless once + * TODO: this is added the code below should sufice with minimal adjustments + test("Open the AsyncAPI view with the '---' example", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: '---' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TD---CloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const AsyncAPIEditor = page.locator('#async-api-container') + const AsyncAPIContainer = AsyncAPIEditor.getByRole('code').locator('div').filter({ hasText: '"asyncapi": "2.0.0",' }).nth(4) + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "json") + await expect(AsyncAPIContainer).toHaveText('"asyncapi": "2.0.0",') + + const AsyncAPIJsonBtn = page.locator('#async-api-json') + + await expect(AsyncAPIJsonBtn).toBeDisabled() + + }) + + test("Open the AsyncAPI view with the '---' example as YAML", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: '---' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TD---CloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + + const jsonYamlPopup = page.locator('.json-yaml-warning') + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + + const jsonBtn = page.locator('#file-type-json') + const yamlBtn = page.locator('#file-type-yaml') + + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + + await yamlBtn.click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning") + + await page.locator('#yaml-confirm-btn').click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(jsonBtn).toBeChecked({ checked: false }) + await expect(yamlBtn).toBeChecked({ checked: true }) + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const AsyncAPIEditor = page.locator('#async-api-container') + const AsyncAPIContainer = AsyncAPIEditor.getByRole('code').locator('div').filter({ hasText: 'asyncapi: 2.0.0' }).nth(4) + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(AsyncAPIContainer).toHaveText('asyncapi: 2.0.0') + + const AsyncAPIYamlBtn = page.locator('#async-api-yaml') + await expect(AsyncAPIYamlBtn).toBeDisabled() + + }) + + test("Open the AsyncAPI view and change form JSON to YAML and from YAML to JSON", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: '---' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TD---CloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const AsyncAPIEditor = page.locator('#async-api-container') + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "json") + + const AsyncAPIJsonBtn = page.locator('#async-api-json') + const AsyncAPIYamlBtn = page.locator('#async-api-yaml') + + await expect(AsyncAPIJsonBtn).toBeDisabled() + + await AsyncAPIYamlBtn.click() + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(AsyncAPIYamlBtn).toBeDisabled() + + await AsyncAPIJsonBtn.click() + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "json") + await expect(AsyncAPIJsonBtn).toBeDisabled() + }) + + test("Open the AsyncAPI view and downloading it as JSON", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: '---' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TD---CloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const AsyncAPIEditor = page.locator('#async-api-container') + const AsyncAPIContainer = AsyncAPIEditor.getByRole('code').locator('div').filter({ hasText: '"asyncapi": "2.0.0",' }).nth(4) + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "json") + await expect(AsyncAPIContainer).toHaveText('\"asyncapi\": \"2.0.0\",') + + const AsyncAPIJsonBtn = page.locator('#async-api-json') + await expect(AsyncAPIJsonBtn).toBeDisabled() + + // Start waiting for download before clicking. + const AsyncAPIDownload = page.locator('#async-api-download') + const downloadPromise = page.waitForEvent('download') + await AsyncAPIDownload.click() + const download = await downloadPromise + const expectedFilename = 'MyLampThing-AsyncAPI.json' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + test("Open the AsyncAPI view and downloading it as YAML", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: '---' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TD---CloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const AsyncAPIView = page.locator('#async-api-view') + const consoleError = page.locator('#console-error') + const AsyncAPITab = page.locator("#async-api-tab") + + await expect(AsyncAPIView).toHaveClass("console-view async-api-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AsyncAPITab).toBeChecked({ checked: false }) + + await AsyncAPITab.click() + + await expect(AsyncAPITab).toBeChecked({ checked: true }) + await expect(AsyncAPIView).toHaveClass("console-view async-api-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const AsyncAPIEditor = page.locator('#async-api-container') + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "json") + + const AsyncAPIJsonBtn = page.locator('#async-api-json') + const AsyncAPIYamlBtn = page.locator('#async-api-yaml') + + await expect(AsyncAPIJsonBtn).toBeDisabled() + + await AsyncAPIYamlBtn.click() + + await expect(AsyncAPIEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(AsyncAPIYamlBtn).toBeDisabled() + + const AsyncAPIContainer = AsyncAPIEditor.getByRole('code').locator('div').filter({ hasText: 'asyncapi: 2.0.0' }).nth(4) + await expect(AsyncAPIContainer).toHaveText('asyncapi: 2.0.0') + + // Start waiting for download before clicking. + const AsyncAPIDownload = page.locator('#async-api-download') + const downloadPromise = page.waitForEvent('download') + await AsyncAPIDownload.click() + const download = await downloadPromise + const expectedFilename = 'MyLampThing-AsyncAPI.yaml' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + */ +}) + + +test.describe("AAS AID view functionality", () => { + test("Trying to open the AAS view with a TD with no protocols and closing it", async ({ page }) => { + + const initialTab = page.locator("#tab").nth(0) + await expect(initialTab).toHaveAttribute('data-tab-id', "1") + await expect(initialTab).toHaveText("TDThing TemplateCloseCancel") + await expect(initialTab).toHaveClass("active") + + const AASView = page.locator('#aas-view') + const consoleError = page.locator('#console-error') + const AASTab = page.locator("#aas-tab") + + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AASTab).toBeChecked({ checked: false }) + + await AASTab.click() + + await expect(AASTab).toBeChecked({ checked: true }) + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("Please insert a TD which uses HTTP, MQTT, CoAP or Modbus!") + + const trashBtn = page.locator(".trash") + await trashBtn.click() + + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AASTab).toBeChecked({ checked: false }) + + }) + + test("Trying to open the AAS view with a TM", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const AASView = page.locator('#aas-view') + const consoleError = page.locator('#console-error') + const AASTab = page.locator("#aas-tab") + + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AASTab).toBeChecked({ checked: false }) + + await AASTab.click() + + await expect(AASTab).toBeChecked({ checked: true }) + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("This function is only allowed for Thing Descriptions!") + + }) + + test("Open the AAS AID view with the 'Basic TD' example", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const AASView = page.locator('#aas-view') + const consoleError = page.locator('#console-error') + const AASTab = page.locator("#aas-tab") + + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AASTab).toBeChecked({ checked: false }) + + await AASTab.click() + + await expect(AASTab).toBeChecked({ checked: true }) + await expect(AASView).toHaveClass("console-view aas-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const ASSEditor = page.locator('#aas-container') + const ASSContainer = ASSEditor.getByRole('code').locator('div').filter({ hasText: '"idShort": "AssetInterfacesDescription",' }).nth(4) + + await expect(ASSEditor).toHaveAttribute('data-mode-id', "json") + await expect(ASSContainer).toHaveText('"idShort": "AssetInterfacesDescription",') + + }) + + test("Open the AAS AID view with the 'Basic TD' example and downloading it", async ({ page }) => { + await page.locator("#examples-btn").click() + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TD' }).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TDMyLampThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const exampleEditor = page.locator("#editor2") + await expect(exampleEditor).toHaveAttribute('data-ide-id', "2") + await expect(exampleEditor).toHaveAttribute('data-mode-id', "json") + await expect(exampleEditor).toHaveClass("editor active") + + const AASView = page.locator('#aas-view') + const consoleError = page.locator('#console-error') + const AASTab = page.locator("#aas-tab") + + await expect(AASView).toHaveClass("console-view aas-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(AASTab).toBeChecked({ checked: false }) + + await AASTab.click() + + await expect(AASTab).toBeChecked({ checked: true }) + await expect(AASView).toHaveClass("console-view aas-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const ASSEditor = page.locator('#aas-container') + const ASSContainer = ASSEditor.getByRole('code').locator('div').filter({ hasText: '"idShort": "AssetInterfacesDescription",' }).nth(4) + + await expect(ASSEditor).toHaveAttribute('data-mode-id', "json") + await expect(ASSContainer).toHaveText('"idShort": "AssetInterfacesDescription",') + + // Start waiting for download before clicking. + const AASDownload = page.locator('#aas-download') + const downloadPromise = page.waitForEvent('download') + await AASDownload.click() + const download = await downloadPromise + const expectedFilename = 'MyLampThing-AAS.json' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) +}) + +test.describe("Defaults view functionality", () => { + test("Opening the Defaults view with the Thing Template and closing it", async ({ page }) => { + + const initialTab = page.locator("#tab").nth(0) + await expect(initialTab).toHaveAttribute('data-tab-id', "1") + await expect(initialTab).toHaveText("TDThing TemplateCloseCancel") + await expect(initialTab).toHaveClass("active") + + const DefaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const DefaultsTab = page.locator("#defaults-tab") + + await expect(DefaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(DefaultsTab).toBeChecked({ checked: false }) + + await DefaultsTab.click() + + await expect(DefaultsTab).toBeChecked({ checked: true }) + await expect(DefaultsView).toHaveClass("console-view defaults-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const defaultsEditor = page.locator('#defaults-container') + const defaultsContainer = defaultsEditor.getByRole('code').locator('div').filter({ hasText: '"description": "This is your customizable template. Edit it to fit your Thing Description or Thing Model needs!",' }).nth(4) + + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "json") + await expect(defaultsContainer).toHaveText('"description": "This is your customizable template. Edit it to fit your Thing Description or Thing Model needs!",') + + const defaultsJsonBtn = page.locator('#defaults-json') + const defaultsAddBtn = page.locator('#defaults-add') + + await expect(defaultsJsonBtn).toBeDisabled() + await expect(defaultsAddBtn).toBeDisabled() + + const trashBtn = page.locator(".trash") + await trashBtn.click() + + await expect(DefaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(DefaultsTab).toBeChecked({ checked: false }) + }) + + test("Trying to open the Defaults view with a TM", async ({ page }) => { + + await page.locator("#examples-btn").click() + + const thingTypeToggle = page.locator('#thing-type-btn') + await thingTypeToggle.click() + await expect(thingTypeToggle).toBeChecked({ checked: true }) + + const quickAccessBtn = page.locator(".example").filter({ hasText: 'Basic TM' }).nth(1).getByRole("button").nth(0) + await quickAccessBtn.click() + + const exampleTab = page.locator("#tab").nth(1) + await expect(exampleTab).toHaveAttribute('data-tab-id', "2") + await expect(exampleTab).toHaveText("TMLamp ThingCloseCancel") + await expect(exampleTab).toHaveClass("active") + + const DefaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const DefaultsTab = page.locator("#defaults-tab") + + await expect(DefaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(DefaultsTab).toBeChecked({ checked: false }) + + await DefaultsTab.click() + + await expect(DefaultsTab).toBeChecked({ checked: true }) + await expect(DefaultsView).toHaveClass("console-view defaults-view hidden") + await expect(page.locator(".console-error__txt")).toHaveText("This function is only allowed for Thing Descriptions!") + + }) + + test("Open the Defaults view as YAML", async ({ page }) => { + + const templateEditor = page.locator("#editor1") + await expect(templateEditor).toHaveAttribute('data-ide-id', "1") + await expect(templateEditor).toHaveAttribute('data-mode-id', "json") + await expect(templateEditor).toHaveClass("editor active") + + const jsonYamlPopup = page.locator('.json-yaml-warning') + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + + const jsonBtn = page.locator('#file-type-json') + const yamlBtn = page.locator('#file-type-yaml') + + await expect(jsonBtn).toBeChecked({ checked: true }) + await expect(yamlBtn).toBeChecked({ checked: false }) + + await yamlBtn.click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning") + + await page.locator('#yaml-confirm-btn').click() + await expect(jsonYamlPopup).toHaveClass("json-yaml-warning closed") + await expect(templateEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(jsonBtn).toBeChecked({ checked: false }) + await expect(yamlBtn).toBeChecked({ checked: true }) + + const defaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const defaultsTab = page.locator("#defaults-tab") + + await expect(defaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(defaultsTab).toBeChecked({ checked: false }) + + await defaultsTab.click() + + await expect(defaultsTab).toBeChecked({ checked: true }) + await expect(defaultsView).toHaveClass("console-view defaults-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const defaultsEditor = page.locator('#defaults-container') + const defaultsContainer = defaultsEditor.getByRole('code').locator('div').filter({ hasText: 'description: >-' }).nth(4) + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(defaultsContainer).toHaveText('description: >-') + + const defaultsYamlBtn = page.locator('#defaults-yaml') + await expect(defaultsYamlBtn).toBeDisabled() + }) + + test("Open the Defaults view and change form JSON to YAML and from YAML to JSON", async ({ page }) => { + const templateEditor = page.locator("#editor1") + await expect(templateEditor).toHaveAttribute('data-ide-id', "1") + await expect(templateEditor).toHaveAttribute('data-mode-id', "json") + await expect(templateEditor).toHaveClass("editor active") + + const defaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const defaultsTab = page.locator("#defaults-tab") + + await expect(defaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(defaultsTab).toBeChecked({ checked: false }) + + await defaultsTab.click() + + await expect(defaultsTab).toBeChecked({ checked: true }) + await expect(defaultsView).toHaveClass("console-view defaults-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const defaultsEditor = page.locator('#defaults-container') + + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "json") + + const defaultsJsonBtn = page.locator('#defaults-json') + const defaultsYamlBtn = page.locator('#defaults-yaml') + + await expect(defaultsJsonBtn).toBeDisabled() + + await defaultsYamlBtn.click() + + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(defaultsYamlBtn).toBeDisabled() + + await defaultsJsonBtn.click() + + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "json") + await expect(defaultsJsonBtn).toBeDisabled() + }) + + test("Open the Defaults view and removing and adding default values", async ({ page }) => { + + const templateEditor = page.locator("#editor1") + await expect(templateEditor).toHaveAttribute('data-ide-id', "1") + await expect(templateEditor).toHaveClass("editor active") + + const defaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const defaultsTab = page.locator("#defaults-tab") + + await expect(defaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(defaultsTab).toBeChecked({ checked: false }) + + await defaultsTab.click() + + await expect(defaultsTab).toBeChecked({ checked: true }) + await expect(defaultsView).toHaveClass("console-view defaults-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const defaultsAddBtn = page.locator('#defaults-add') + const defaultsRemoveBtn = page.locator('#defaults-remove') + + await expect(defaultsAddBtn).toBeDisabled() + + await defaultsRemoveBtn.click() + await expect(defaultsRemoveBtn).toBeDisabled() + + await defaultsAddBtn.click() + await expect(defaultsAddBtn).toBeDisabled() + }) + + test("Open the Defaults view and downloading it as JSON with defaults", async ({ page }) => { + + const templateEditor = page.locator("#editor1") + await expect(templateEditor).toHaveAttribute('data-ide-id', "1") + await expect(templateEditor).toHaveAttribute('data-mode-id', "json") + await expect(templateEditor).toHaveClass("editor active") + + const DefaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const DefaultsTab = page.locator("#defaults-tab") + + await expect(DefaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(DefaultsTab).toBeChecked({ checked: false }) + + await DefaultsTab.click() + + await expect(DefaultsTab).toBeChecked({ checked: true }) + await expect(DefaultsView).toHaveClass("console-view defaults-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const defaultsEditor = page.locator('#defaults-container') + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "json") + + const DefaultsJsonBtn = page.locator('#defaults-json') + await expect(DefaultsJsonBtn).toBeDisabled() + + // Start waiting for download before clicking. + const DefaultsDownload = page.locator('#defaults-download') + const downloadPromise = page.waitForEvent('download') + await DefaultsDownload.click() + const download = await downloadPromise + const expectedFilename = 'Thing-Template-with-Defaults.json' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + test("Open the OpenAPI view and downloading it as YAML", async ({ page }) => { + const templateEditor = page.locator("#editor1") + await expect(templateEditor).toHaveAttribute('data-ide-id', "1") + await expect(templateEditor).toHaveAttribute('data-mode-id', "json") + await expect(templateEditor).toHaveClass("editor active") + + const DefaultsView = page.locator('#defaults-view') + const consoleError = page.locator('#console-error') + const DefaultsTab = page.locator("#defaults-tab") + + await expect(DefaultsView).toHaveClass("console-view defaults-view hidden") + await expect(consoleError).toHaveClass("console-view console-error hidden") + await expect(DefaultsTab).toBeChecked({ checked: false }) + + await DefaultsTab.click() + + await expect(DefaultsTab).toBeChecked({ checked: true }) + await expect(DefaultsView).toHaveClass("console-view defaults-view") + await expect(consoleError).toHaveClass("console-view console-error hidden") + + const defaultsEditor = page.locator('#defaults-container') + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "json") + + const defaultsJsonBtn = page.locator('#defaults-json') + const defaultsYamlBtn = page.locator('#defaults-yaml') + + await expect(defaultsJsonBtn).toBeDisabled() + + await defaultsYamlBtn.click() + + await expect(defaultsEditor).toHaveAttribute('data-mode-id', "yaml") + await expect(defaultsYamlBtn).toBeDisabled() + + const defaultsAddBtn = page.locator('#defaults-add') + const defaultsRemoveBtn = page.locator('#defaults-remove') + + await expect(defaultsAddBtn).toBeDisabled() + + await defaultsRemoveBtn.click() + await expect(defaultsRemoveBtn).toBeDisabled() + + // Start waiting for download before clicking. + const defaultsDownload = page.locator('#defaults-download') + const downloadPromise = page.waitForEvent('download') + await defaultsDownload.click() + const download = await downloadPromise + const expectedFilename = 'Thing-Template-without-Defaults.yaml' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) +}) + +test.describe("Visualization view functionality", () => { + + test("Open the visualization view with the thing template and closing it", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + const graphVisTitle = page.locator('#visualized').getByText('Thing Template', { exact: true }) + await expect(graphVisTitle).toHaveText("Thing Template") + + const trashBtn = page.locator(".trash") + await trashBtn.click() + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + }) + + test("Open the visualization view with the thing template and expand and collapse the graph view", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + const collapseAllBtn = page.locator('#collapse-all') + const expandAllBtn = page.locator('#expand-all') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + const svgPaths = page.locator("svg > g > path") + await expect(svgPaths).toHaveCount(9) + + await expandAllBtn.click() + await expect(expandAllBtn).toBeDisabled() + + await expect(svgPaths).toHaveCount(12) + + await collapseAllBtn.click() + await expect(collapseAllBtn).toBeDisabled() + + await expect(svgPaths).toHaveCount(0) + }) + + test("Open the visualization view with the thing template download the graph view as SVG", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + // Start waiting for download before clicking. + const svgDownload = page.locator('#download-svg') + const downloadPromise = page.waitForEvent('download') + await svgDownload.click() + const download = await downloadPromise + const expectedFilename = 'Graph-visualization.svg' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + test("Open the visualization view with the thing template and download the graph view as PNG", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + // Start waiting for download before clicking. + const pngDownload = page.locator('#download-png') + const downloadPromise = page.waitForEvent('download') + await pngDownload.click() + const download = await downloadPromise + const expectedFilename = 'Graph-visualization.png' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + test("Open the tree visualization view with the thing template and modified the input values", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + await treeViewBtn.click() + await expect(graphViewBtn).toBeChecked({ checked: false }) + await expect(treeViewBtn).toBeChecked({ checked: true }) + + const labelBtn = page.getByLabel('labels') + const radiusSlider = page.getByLabel('radius') + const extentSlider = page.getByLabel('extent') + const rotateSlider = page.getByLabel('rotate') + const dragSlider = page.getByLabel('drag precision') + const tidyBtn = page.getByLabel('tidy') + const clusterBtn = page.getByLabel('cluster') + const linksDropDown = page.getByLabel('links') + + await expect(labelBtn).toBeChecked({checked: true}) + await expect(radiusSlider).toHaveValue("350") + await expect(extentSlider).toHaveValue("360") + await expect(rotateSlider).toHaveValue("0") + await expect(dragSlider).toHaveValue("100") + await expect(tidyBtn).toBeChecked({checked: true}) + await expect(clusterBtn).toBeChecked({checked: false}) + await expect(linksDropDown).toHaveValue("line") + + await labelBtn.click() + await radiusSlider.click() + await extentSlider.click() + await rotateSlider.click() + await dragSlider.click() + await clusterBtn.click() + await linksDropDown.selectOption("diagonal") + + await expect(labelBtn).toBeChecked({checked: false}) + await expect(radiusSlider).toHaveValue("410") + await expect(extentSlider).toHaveValue("180") + await expect(rotateSlider).toHaveValue("180") + await expect(dragSlider).toHaveValue("50") + await expect(tidyBtn).toBeChecked({checked: false}) + await expect(clusterBtn).toBeChecked({checked: true}) + await expect(linksDropDown).toHaveValue("diagonal") + + }) + + test("Open the tree visualization view with the thing template and download as SVG", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + await treeViewBtn.click() + await expect(graphViewBtn).toBeChecked({ checked: false }) + await expect(treeViewBtn).toBeChecked({ checked: true }) + + // Start waiting for download before clicking. + const svgDownload = page.locator('#download-svg') + const downloadPromise = page.waitForEvent('download') + await svgDownload.click() + const download = await downloadPromise + const expectedFilename = 'Tree-visualization.svg' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) + + test("Open the tree visualization view with the thing template and download as PNG", async ({ page }) => { + + const visualizeView = page.locator('#visualize-view') + const visualizeTab = page.locator("#visualize-tab") + + await expect(visualizeView).toHaveClass("console-view visualize-view hidden") + await expect(visualizeTab).toBeChecked({ checked: false }) + + await visualizeTab.click() + + await expect(visualizeTab).toBeChecked({ checked: true }) + await expect(visualizeView).toHaveClass("console-view visualize-view") + + const graphViewBtn = page.locator('#graph-view') + const treeViewBtn = page.locator('#tree-view') + + await expect(graphViewBtn).toBeChecked({ checked: true }) + await expect(treeViewBtn).toBeChecked({ checked: false }) + + await treeViewBtn.click() + await expect(graphViewBtn).toBeChecked({ checked: false }) + await expect(treeViewBtn).toBeChecked({ checked: true }) + + // Start waiting for download before clicking. + const pngDownload = page.locator('#download-png') + const downloadPromise = page.waitForEvent('download') + await pngDownload.click() + const download = await downloadPromise + const expectedFilename = 'Tree-visualization.png' + expect(download.suggestedFilename()).toBe(expectedFilename) + }) +}) \ No newline at end of file From d49e9da7995413b3f7c1c1e73576a9eeb39c1263 Mon Sep 17 00:00:00 2001 From: Sergio Eduardo Castro Ceballos <72516762+SergioCasCeb@users.noreply.github.com> Date: Fri, 13 Oct 2023 23:37:32 +0200 Subject: [PATCH 04/56] Adding the test description in the readme file --- .gitignore | 1 + packages/web-new/README.md | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 9cfa1dd0e..95d50dc10 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules # test screenshots for web package test_results/ test-results/ +playwright-report/ # dist directory should be included only in the Package but not Repository dist diff --git a/packages/web-new/README.md b/packages/web-new/README.md index 464b528de..2f60e13fc 100644 --- a/packages/web-new/README.md +++ b/packages/web-new/README.md @@ -74,7 +74,7 @@ The `webpack.config.js` file is used to set up Webpack for the project. It manag - `optimization`: Contains settings for optimizing the build, including minimizing CSS using `CssMinimizerPlugin` -## Deployment +### 4. Deployment Requires [Lerna](https://www.npmjs.com/package/lerna) to be installed globally (`npm install -g lerna`). @@ -108,4 +108,19 @@ npm run dev ```sh npm run build npm run serve -``` \ No newline at end of file +``` + +### 5. Testing with Playwright + +To utilize the Playwright package for testing the application, you need to install it using `npm install` since it's not intended for production use. Additionally, to set up the supported browsers required for Playwright to run tests, you should execute the command `npx playwright install`. + +You can assess the visual appearance and functionality of the package in all browsers by running the command `npm run test`. This will execute all the tests in the supported browsers, and once the tests have finished, Playwright will host the reports at `http://localhost:9323`. + +If the reports aren't displayed automatically, you can also use the command `npx playwright show-report` to view the test results. + +For a more visual approach to writing and visualizing tests, you can use the command `npx playwright test --ui`. This command provides a visual interface that allows you to step through each part of the test and observe what occurs before, during, and after each step. + +Debugging can also be accomplished by running the Playwright test command with the `--debug` flag, like this: `npx playwright test --debug`. + +For additional information on how to run and debug tests, please refer to the [official Playwright website](https://playwright.dev/docs/running-tests). + From 6c8ae5806c778669b150d8bc471a10f6cde96f33 Mon Sep 17 00:00:00 2001 From: Sergio Eduardo Castro Ceballos <72516762+SergioCasCeb@users.noreply.github.com> Date: Sat, 14 Oct 2023 00:26:13 +0200 Subject: [PATCH 05/56] Adding error handling for AAS conversion --- packages/web-new/src/scripts/aas.js | 3 +-- packages/web-new/src/scripts/console.js | 21 ++++++++++++++------- packages/web-new/src/scripts/util.js | 6 ++---- packages/web-new/src/template.html | 15 --------------- 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/packages/web-new/src/scripts/aas.js b/packages/web-new/src/scripts/aas.js index 7184761f9..abcc1d2b1 100644 --- a/packages/web-new/src/scripts/aas.js +++ b/packages/web-new/src/scripts/aas.js @@ -22,7 +22,7 @@ import { editor } from 'monaco-editor' import { setFontSize, editorForm, fontSizeSlider } from './settings-menu' -import { generateTD, offerFileDownload } from './util' +import { offerFileDownload } from './util' import { getEditorData } from './editor' /******************************************************************/ @@ -31,7 +31,6 @@ import { getEditorData } from './editor' //AAS Elements export const AASTab = document.querySelector(".aas-tab-btn") -export const AASJsonBtn = document.querySelector("#aas-json") export const AASView = document.querySelector("#aas-view") const AASDownload = document.querySelector("#aas-download") diff --git a/packages/web-new/src/scripts/console.js b/packages/web-new/src/scripts/console.js index 55857730f..83b128e83 100644 --- a/packages/web-new/src/scripts/console.js +++ b/packages/web-new/src/scripts/console.js @@ -21,7 +21,7 @@ import { openApiTab, openApiJsonBtn, openApiYamlBtn, openApiView } from './open-api' import { asyncApiTab, asyncApiJsonBtn, asyncApiYamlBtn, asyncApiView } from './async-api' -import { AASJsonBtn, AASView } from './aas' +import { AASView, AASTab } from './aas' import { defaultsView, defaultsJsonBtn, defaultsYamlBtn, defaultsAddBtn } from './defaults' import { visualize } from './visualize' import { validationView } from './validation' @@ -117,8 +117,8 @@ visualizationOptions.forEach(option => { break; case "aas-tab": - AASView.classList.remove("hidden") - generateAAS(fileType, editorInstance) + + enableAPIConversionWithProtocol(editorInstance) break; @@ -172,10 +172,8 @@ visualizationOptions.forEach(option => { * @param {object} editor - currently active monaco editor */ function enableAPIConversionWithProtocol(editorInstance) { - let td = editorInstance.getValue() - if (editorInstance["_domElement"].dataset.modeId === "yaml") { - td = convertTDYamlToJson(td) - } + + let td = editorInstance["_domElement"].dataset.modeId === "yaml" ? convertTDYamlToJson(editorInstance.getValue()) : editorInstance.getValue() const protocolSchemes = detectProtocolSchemes(td) @@ -198,6 +196,15 @@ function enableAPIConversionWithProtocol(editorInstance) { showConsoleError("Please insert a TD which uses MQTT!") } } + + if (AASTab.checked === true) { + if (["mqtt", "mqtts", "http", "https", "coap", "modbus"].some(p => protocolSchemes.includes(p))) { + generateAAS(editorInstance["_domElement"].dataset.modeId, editorInstance) + AASView.classList.remove("hidden") + } else { + showConsoleError("Please insert a TD which uses HTTP, MQTT, CoAP or Modbus!") + } + } } } diff --git a/packages/web-new/src/scripts/util.js b/packages/web-new/src/scripts/util.js index 0a584a3b2..2db6cd790 100644 --- a/packages/web-new/src/scripts/util.js +++ b/packages/web-new/src/scripts/util.js @@ -174,11 +174,9 @@ export function generateAAS(fileType, editorInstance){ const AASInstance = assetInterfaceDescriptionUtil.transformTD2SM(tdToConvert) try { - const content = fileType === "json" - ? JSON.stringify(JSON.parse(AASInstance), undefined, 4) - : convertTDJsonToYaml(AASInstance) + const content = JSON.stringify(JSON.parse(AASInstance), undefined, 4) - editor.setModelLanguage(window.AASEditor.getModel(), fileType) + editor.setModelLanguage(window.AASEditor.getModel(), 'json') window.AASEditor.getModel().setValue(content) } catch (err) { console.error(err); diff --git a/packages/web-new/src/template.html b/packages/web-new/src/template.html index 7c1491cff..af8a15c42 100644 --- a/packages/web-new/src/template.html +++ b/packages/web-new/src/template.html @@ -241,10 +241,6 @@

Thing Description Playground - BETA Version

title="Conversion to Asset Administration Shell/Asset Interface Description"> - @@ -443,9 +439,6 @@

Thing Description Playground - BETA Version

- -