From 46be69cbf01c129f0cb5bf3043795dbef0f5ced1 Mon Sep 17 00:00:00 2001 From: jhuerta Date: Tue, 3 Jun 2025 15:35:00 -0700 Subject: [PATCH] Added split row validation fix --- editItemAddConceptResults.xlsx | Bin 258653 -> 259993 bytes tests/ExACT_editItemAddConcept.js | 1466 +++++++++++++++++++++++------ 2 files changed, 1159 insertions(+), 307 deletions(-) diff --git a/editItemAddConceptResults.xlsx b/editItemAddConceptResults.xlsx index 23cb80a0bd88717057e8069178011606048882a0..029be91f0517c63e9739d0347e99102a4b966402 100644 GIT binary patch delta 29758 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

>aTMdpCBm#n`dM#MnnUme@7cD7w+L z#1>1`*flREHZ0ND(b!@v-+yLV**o+5z31ay&bg=DbI&>V+%uO&PyMgm@z0rEIpC)* z)5|s6Dg2-E-!lLAfB#3O=Rz6TRrx+|wL4c;*~kT2;ze_7lPyuQCtB)8}&zTua2GL@1){QU1a3Pru zHjCBS!BEy~*pX;78|-$;IW-}e9kv*Z4zqKk(MLNhS|#TZlb?3jB3hicL|=ATGT3c) z=XDG@6c3xl2BzkR|7}v=R(7 zhAj?<^KFZ8#;P!Eqm`Q=Vq#0y4DlO>+2L%{stk)D8cdWDjs>05x(rJ}G?+!Byt~b7 zYJQIkk&m_w@wN_=NG&>I=l<6=oiZPAk#g_PW@&z()d{~3$#~~2yh$|JO%7*Ny9g~Y zhh22GYG0O7w8?BRnJIl3ALN|ff!!wfmDy}^uJ2f$SxJ+5!8QnUr&Doue(Zb6xV?)O zm?Hj%Wl!p=fwmY-qUg-%R-Wa?0+PLvq8xC8+BY zK1Tkozk^v9Dfy-YSFGd98Hw9VX5iR9{XSkSZ4*Tt_}Qppx8ou-)73nc&^1Tc{8uA0FI5 zo-)uNTQhSQ!d8RXVRF9Cw6R*Y8YCDZm?OMHM6R+0@+n7mcNP7-sSx62%l-SI4{T*SWd+3)?g%Hfgd}E zXpoG~`0Oy2plGn#jn4MO>KjwrZ6@be3t2}cnw3x-?EHC=Mki+E3Kr+>#gQy0W-<-J zI#m9SHF42wkR+?K;nGShFK~`VqjT)CcN9I)ENa%hnwc7!+&tkKA0ftz+XbJtq6lQ=}1GiF^Kb{HNLnbnx}Rkg#S(d68@ zAx=ANmdtYA#(&-M?8Bx|@1QM82&i)O=Fi>HZ0+VX-kS-(wL%x|e_*`;hHWsi@3!cM z9pK>lR*gcD@*!CZ+oqAuYA_*<>9M^Dt0F7qHpQBsb=GC&uo^6|oai0(7^fjx4OTh* zNRac}oz*q-$P-?LIR9{IHlNkt5aGafC$Y2J3?}%2=6f1xhef-^xqh$47LeVEX6N5O z8Ca5VvAhs0+xFjg>smSx%4pLDgR{sT5A=2``|1H!*)});$vO9+Myoc1!|rfiJfs8B!CEjeh20HX3~b`zM9!&%MFAJ4FIV%Py)zdFm#Vix6R zA468#&olCv<+;N`ob4{KIiT5QkPvT%U#!B2gJB!8+)bBQwlVB5nVmO&i(m}RjI3Ku zzZ~q0`kl?;@C(sqm0Ml@;9m6Je=v)VUn2;}Gymw}UUc6-=X)mx__bBOxj4vq@K1qJ zli5xybK%VHTq(njJJf{3S>akBD~$s_(devoopt*L}Q8cqw^Xqb~>S)9kE$haI*Uk;7V?U;M@LgJBWdc*EUDhImpBa+30G{iack;vGJMZVcT z#F_h;4Sj&Mn6^J!Y5ozzzdOOPBe&; zeEv<4v)4;Df?7la1by~zkaNK+f9+I~)#Tjqnmrr=!3N)U;f+7D))=$>ECP zIM%8y7MfF=4|a9nIW~u~SYXyx*9d_t$EwW&<+zp?;@CtK;F8_wx?PxS!^(sRYcshT z73I2W#~o&yYfmw*89Oc+M61nJ#+PG#h6N`Lo6(h4oMX!r7`K~U(@Jp3>@)~{VCOeK zt_I6Jf|*EM5RS@bf6g75DK&r#^)1LYDSkIsn!XI+x~PtWo&|6}c%Nu2RypTPi0fb= z$2v?4LYc|p;)A&6EH6m(jiRetFxOT)Zn4>2$3wV|+HtGh=8{TtpJ~VK7PD(<87__8 zeRdl1hzoZ4mE+jN1SK$&Lv%GP51o03LyVg(4%fsmj*YGumrRoDPz6r2uiz>j)}0kO zo>M(7m5$&TR|`bD)lM}dxWR6f{Sv|bz)(bmLXuolBe~ivC-9x3(RDcrDq~cPP~{J+ zY!J=W*CI%g*|n@Pbmr~NEe_Nn(i6ELS6GZ5#cs8_hQ&f{-U%3Lenz9~LL6A~CM_8$ zuN@ac)@s}@^17e>$hSJz*jpChnJp6as?K$#q~<~lJ*v*FWB^PCtI_U4cFPuqL*&?O8{=l!UxryfZZX?kV=Ve{ z33j$j(vRCrHrF95#u?3E&?4ZCtP=0lXR%W;~QFOIR)Y8B~!fJGV zf!)c<3}5FkyC{h(&ys+%qpUix^52pRRtS1YAgSbvEWj;(uP9Lc>) zOx2P=@s+yufE0sk!_pa3fiEIQ{+L&YOl#+z=qRI7R z6OIiH7#D43*PW*NaSIGKxVe5@GMij=)AZw3$>JK`0^^LDa5}NOR;P1po(8fGquF(- zrFI(lXwl&+)LJ_Y&LI0vg8gpElE z8=+IULiwyGO#PHUxTi!ajx$8tsoX#}@7Jbsn-~p?O8q(5wc#sHWYvOVmt=Q6ng-?> zVUdv|x~F`@rFsm)L&@&mv#X~UWU%gEDM`7>b?;lQk;hOx<0d=JoeoQFHS<#n)NhtX z1OzUWBj?WYh)`xWw<+HgJ=0j+l>eFyjpm!8=T}x(HZF=>j=5TGBZ}Frt}*i<2%`~H z=(->rUXwWsE4g}?;EGxRF&G4kTDNq~$j)DeQ2L&@ko+pEn-2~~$4`)idPVFp6Xx&pI zJ|Tm9;VL+fc*aEp0?TghQ&qq-Zbp8Sxd*uwLsL1wxK{4vqFKwg%PH}}uDd@WoH15{ z@FdS|5ag<~p9|Lh#zCnYU_b2+zXyTO-TJxU^zHdYWHroI{)k2;CWIiESDmBWr=qfofN?WyXxuT4o4~jQq5r@yoRMMI z1ebIUlmkv+*}R1Zg3T>rlard2#;+U*|6ly7ageytMdO2Oi=xtk|cd0=_ZP9rVw zR+Y&lr;Z7B#hfij*xm5R%itAip3_(ouIg-NntK6iAAO$tbY0}ZQF6$67qmFY!ECO* z7qR5tTgn9EMpmA8NwaG)ZZS))=>HXDNbc!j#Mo--ziYN2;B5}OYvN`7xC0iu?GI$$ zjL3ErM}u8?e->0V-195NVG}jK%Du=g!4;vY*SV@R@*3x0m`1@8CUoc;*NAH0;A&9g z>zqU@TJSz}a64aw%(u93+In4wgnKml_d1Y<=5lr#cLPW_aycvAxS<1eVE(vVu2JD$ zL;Lm~MS6Bx8c3i z39@e^Qry1@s&n>1v`)7<3#H%E;hH5oExGlH^x(g^a&)Q?Uzs9rgLK!e#pwGx*#9uf zdt4>jahnTabc5Z6OQ|cjA!eVy@K4`6Aed8xD@u?5;$q}&Eu!h)J31VzO`?hb_fh5T zlG<|^Mc(HUDCaNeXU;ah7*)8(Me$bbc7>|_u5JdL2&nU25WIMgOQzhroFq@^TtrUT zTa2>rb0z8FzmTKWJT*avHBP{p75AsP;_(Lw(+l>Jc#SK#)j=F6gVm0!x{v6pRePmqiBf5633@)M77?RpCO;!rHrar{;@0}g5Q^a*H>$ph_iPr7a$>u6h`wJp!VdHf5Qi1bgsw$J^`6{f8( zI1?@Y2Pz+I455AhXv9`(O-8!&50Hnw`=w8rvlH70BjH4WTBlbY#)oLqlI-hGK8HdQ{|fzImxs zXTQN}k9e)2s+8f)bl^2`n*IwTRH-(7gWZoEMWAY>-EXi${yY~#SKnwT;)sCgAp8sL zMQws>UrK6@JSlGDd+yzEz?YZ-I34KaZd{-YV;&_$tsWLIdA% z25SBv2zR-KiH82i`T*RJTjBN={)agX?;&dSclm||Q4?s%JDrp^hmHPv2k@aEJW>vQ z50da!Md;NB&P+GnL$3!~l%_%-ICjUQlBVwX#1F8dpFVPRXwQdyD_W4u$5ZS_jf6O~ zpz=EGBiCrb2RKtzryoB8{6ZZb5%uwVegCcy`C21ZT1=*uf*(@O&+*&+%^0 zMEiL@j<#~Vr{6{mVWL@n)+?BNc-}#y1wO(}DvRgcM)OACtI<6k%{p5*LyN@)p4}fx z{Z8o&5BHMALow#+V8~@g=a}fyH^78mZ(tPXZM@AFAfdhtlNYI%Kqeohr^Z zmM48tR>Ae5@qTjdwp7`2yoJtQ6MSewd93=VavEt-*He2n>9=ycRi%&uj^sgN5&AD2 zYrLvFYlLQWQd#L?dA?EMIs^Ll=ubDw@@42=1HL@<3&U2KZO*53I!uFz%U>gW@sd)tJj(~M&iV#feBe3vuVu4z|3SXSg zMq^z5^tMDN_N=-;b zqv&oF>#c!nMi}y|#P_1>uMk(3RKmtv)=@~HkZ8UJqaOGXB-`Dh`5v?>7LN99G@nKj zszNDmldu!|S7t2^Q`>MUy0bFiw^RqzxJrCQs$T`_59ok%hpH5y$J3T78l_lhr3j@I zi-9rCjm284_~mOsDdS>*pCWU`+-steSGDp!hTS1%iTwQ(D~^R`S0(f1lt~P9FBbB} z$791}#38CEEx|M1kCa4WdrfG2bJTMWl zxRnxM)L04}h{HrSqsLN?8X?8ffxMAYOd3ikR>4xfH9;#^v$;fy5&_!P%7;_7s99>O za+s$)5$>{@4f(+kGj^uOK7whr4ZiHMS)&J>^c^BaSs+O_JKXnr3y?k;MYaP@CsxuD zqKT0Za1zGd;-7QC90IN2EG-e{Fy87hhm}^HS`Oj@#*#}wW>7*hbAY6=ypXQD>MN|&#R zwkCQ^0dv^MQlr2Wg6U}zJPGzjDD9}BBQ4SU8hjH)6ETXfh@@pnVDwH345wr=@9(w& zFj`A)4yef{ai4 za(;Y-L|@cFcDbvTW_^{yokV;J-_T!m_+9D@9@L{(=I|~OCDnz&$tm!xo&Xa?|EBPX z-r-c~;G$;}LAp(9eh52`A3j+~Fx{;OTWnmLC9C!AdMqr;F8nf|K7w*|=62GHezy1Yg1TpJaS>F`!7zTpee;D!+WR9zja9eX6S9zsUT z>2OhLjj#v{>LEc&X{gwIBhV{UUxS2FnbAVc>qDVqrs1C}^k`@6y8j+nU+EgI@}CNmkR$r9m~prm+@{UMdrEyk}`(Z+m;89L;GX6n9@1^=$!-W{yHJCvPkw=j9d}MwPY* zJ4L7S8B}vLp!SdB;wdK`b~bnj98kt*LIg#()FD}L+{|nV6Pw&ms6@sLp&D_m;KMd$ z2$9sk6}yYTp4B8rwhN*Y3e4zsLUpRy8hqt+1I2L}NOf~s>l9+M+30O+@U@~nVrPqi zLS>rP1{*;M63|B=rFFnQz9R(BJX$y(eGiKfbl%u{= z#@c+w*YLjOuuw@q*!cF(V8;+EB)cQl*qFgLqbF0iFj|-42`Z;D*hq`^F;S%F8GJV? z(N!o(LmqGu^mRMFIo0d}<9OFjqdwe**+gpCp6{x_$I~C}`KENRFEF#F0kdrf9lQi% zTGfH?Oa~XkIQn;kx|2FWm4mxtjn;S6=ng#}Sf1w{`R-J+8^XhwPGBW`Iu}d#J886K zR=?PwdYutE=X8hpAL)#LCQQHyE1`!FKnLgJyqeTS!;o?`w9waGu>L*A0(4e)s3vzL zmcC+F=sDmj5+ha5U3>Con%9-hAiSy4KU9?1a8B&o6r+Au2hKi=>;qbnrHus^fb@*?Ik8*gy8hx-=gE&ho}% zCq{p+gLlCBWquC$h=G7o4g3A)&;tser734V($|rFG)TA-gquCw2MRwjk1MNSny6!6 zUMY8~s!pL_`|5B+qm@ecb8pfRdOTQ2qP6|_=GlW0HY%d<;SP_r`}3jR2PgQsLo)p0 zsQ!w9ErPwND*n)4#l+cRA(G9Z19a3RlvMW*fQEq+PiX@^HtjPEF67ie9lRCi`7(pt zYIe}}L7>)gI7}#PunyE_w^5(L&{(w*(D2j205uMW8||8@S!X1NV1H94Ko2Yf=c;n; zL!eya60U6aNH~n`Lp0MPBgE~)hau3@#VoAAxsmV<3x)zG?}J;p{?zPCj1?KC!xXXa zTMh$e&?q6Da)-eRpNZn%)Ha&&1xg{R(>OgEd6~~h%_hSa2okj%$#-%4jIeR=8IMOo za}i_VGunNr@fo;YvfF9(m(bkPvG5tyNAY#t{yBHNP?Z*s(l`z)MP9?<=G7>KoUTi8 zkf}8uOpO@r@gBg+_a2W&Yfx>i8ewH|7N1HTrlX94OecaOC%O^TOs71ppQyuH zF&rWlnuK#WQk|BxXc9uYe+QIMkm}T<*ON2?py^1oQ|-ynDpH*cIyf2dwPYOL!B&Dh z>4}=6LsAqpa0-x+gms~(Q}{maq$hJKpU8$dqln%6>r{S#JLT!{6~spU#D@;dLM-ky zMF^woUuokb&M|Zb3QoA%c)wrz2PDYJi)o`K<;N2UVnZ)4xTUwB#GXmm(5y!DO9* zRQ!emIs%d}eVhZ0&!52>9TM??=2*YH88Dl9-w0;vFcVm_w?T3hD`hL_?VhQlhYzEv z@GP(fq+mKb9obISEMU%2YKUWJ;Q#iM`9QilOQQrFa#4D&G8>qk7a)Q-<|7kcJ{uVY zknHqwwvG}$s;1OAknHmXu#8=E+)ArPA#>T~mfT0!u5(JsN(gOKQ0IS(>3t>4OY0}M@1e&?d4O@*~ zuk#MP5FMZLIVfd4L$gH=Ac>Ta!`IBt7H}c41K4wNbl`Zags$WO z{I?x2w)Wc!z>8D!oglG$oA=>fVGPB2emlxnzzCoK7c!(t+adRgU4Y)ZUpcO9*P+;H z+aj1nk`t2m*$qHQ(@sH&r;OZRp|sfjyu;1;nN&JGc6lNBDGO7YPVZtd(c6T_PN?*5HzqdtZXj*g561XC>@ET*K8|X- z2aum1fPT*GaYL3;)}u7p_v&Uw3lUA)3v~g$6z%yDlluMyq+*9)ll^{T*BsN^(08)q zC(M885FD*#A2ywuk2n4qCa`3mjvd@RPTY&td$SMw!RIj6dcc1CGx;!l$Ep3^`Ls!S z#=}S}k1Hk418@O#j=*&+IDo*Slx$_=m%g;?2%PJG2Q*SBuYVY+-a)wk{zv&5bn;;S z3GC)kT=>`zu{#OTW#v}n9P=^F)r^`oJf26$eVW-HWd?PhmSaTF5l-Z+v zY2ryF#Kn$j^p1N-oK9OEgM{L*VB^v;HAGh>=@;*s4pfL#43*KN(75~y;(x4J%07-Y z^5l78lyO|MM(FS~(yHT_8j;yZWlpG57m+(QkD!q!_!#Cna@I3mfMvbThBU|u4g$yYr9cQXj zij^q^H`PA^rzCxT9zN;sQ#wQkc8YjfMXVqP{1#0cPD2f~T!Hl61%$YwXEYe72BX@a zeg+szT3P7i8IU^I7^x7zedyFhP^ofOha+MaWS&)V%E{MTN7KEtFmI*6BG+hRp+@J} zaBfmAF(q1Xj&C%tZ9NJ;&)1T(+D1~=dCyUF?RoFhJ``=IJQs}g>Ulm@PW-HtJHcpk z0oy|D4a)o-v0%pq)>ndzjpkm(>I7coQ{>hem1*onFO0%8=Q4C~_o8Nr@L2^=Xd*=`Ps z=m1If{|~`v+ZEKUm#3TRUYs)h_SEJj1uu;+EkTWj^Q_Vm5`m*tsM7!_|@f9Qrv{xwW0-GZ+j zdyQQjrMu0&buM4SUdX!zPh0ysUq?>rQI&G8vr7VC36*yj|E+l!bn}2fc26ii1ex-x^RHzOV}i z{0$?Bdy00X(9DYTUCeESX8+cTR(6gt|4ha3Z*{44+jTC(b@;zMQu}} zNdC=n;^!X1z^4q1r=brqag*n`8+)CHnDykLjv0I}NRCHXHH(in>D;BJUI;pHJg8GAmz78mU4aXtW-YOsn#+3d&U}Qm)Dr{!9mr*Cwdn zGpz8WFYF{dhZ~&pBvdXwvMddHt^>9};yuq{aP8l~AJzSbuYnw(9-YPy1+4>6CF<(f zD`j6GM*H}10dm+VbXUB9^`yMT9!q|yu^y$a0lmD0^|TmWjly4nXXSz%lb52A|H1!H zex*?*KBYu4`OGU=4Z55{>9cq62Q6OXP*ZVi6zzM>21yZRZB)sj%5rbuhW{KJPxIfv zS!VweC>w@_Q|P}M0dP1*n$-PYTvR;$fK-HkiS<9mtrA$>k>o)7y7!(tsCQP)?a!NC={g_gItT z6JzMe`~0OuTO10-bw6kb;42nfPR{xOmFyP;GgbQtAA%}IS(^HhO)!-AUo5n(FlN8? z5woL`v7n)VY-bmm0T%J)7W^W3H928DQ7uL@Q7KMnB#U2_Q)?MNaDrO-D5caf!pN5w zyt>eUq8wBykOPU{yif}z5VVykKSaC_n)eRcnVZfo56)E=b<^bww&tSg3_lQ8e`~teeydLAMvir1z%>%HyYnQ$i6H7=;xy zjM3sEIt)8j>247f!$^aQ3aS$;N?jJ>g6d*X4KwO{UE#%q##GHuu+r*cLNYD$L#@ll zNAT)<1lzdB=^=zrPah$L8Z1U}{(nA#O}&)JSq#=4z8Xew;SZHh^%WY?cz-Zav^b`| zwggP{Ev^HVP`%nw96S%79Z%L007tuYAXN!ODSKfF!K>{_;Y4}GhHjO>%-wvsdep^F zNRcDvhSLE*-NbggnTnT$t}oAxqpwTCMiTn@0Jsp1TP}pt{gMKcjEczJDBTB&Z2+F- zym@HG_QyhIE-p?vD_|zU0XhWuuu?!68UVO`tBcctP-KIjnzu+UJBSQth(g9WdaI_TK__zNY62u1Lq{xymbhgGawx&SpWR3Sqjb?G8Kj4TIAVR@9|OVL}rs9|aY(tiaBU zem^6+s+Lv|I#F&En1~1m6G>aa#ME$h@c@cP+@ci66)rT%&Vd$MSA=XSYkX*SG!XVy zWc?5jaBe9SfvLxD7kuPq`*1lP0mj`QPb@AD)F^r#!SW6)yjw$cBEfr|l|c$>Je`YF z4CGibdHmW?vPJ1I@B|o5j)Hw``oWjBI)#cTXQG`JGG@*v_s*xOwxAEkJl zP>*Ux3k9EsjNgH){0-3>N;s0^?*3&obkwXWyvfAMLb6)@+qV;S=!cbc;3n)4TNPZp zjd2MUI#>mWe$@dQ9wT@)nVJ&KCgmNxP#O~hhy%OeJ8t7A`M@R|A!3F6KCy3N1+V^Z z1qsdZ_%JP2=pbip&hMpY9tREQI*@fJRmrY<;I($e>G-mmEmWu~Xx;fyC`C0B;1p+6 z#WmN`y;#8S|Z%s#8&P}VSjj7dUMs&50K%pJI_J(vVHvCF36 z$*er6MS>ls^=xlVnrC>5hEg`)MQJbU^TgUy%&eOw@^EQ$CnV zgjHr9u11Aw0CGYK9K_5TU`%ZT&8Z=TG6sYfJtTSC;2^rMK&PY%`PMup2}_vb3ZTuY zh}8FzG;4w;4QyjmGH`m-hMM*yV?U;x@TVuW0UlFRqr=xaEj}dZmK?mimH$&ZcVA zhx;4Ud&<>@5uCdu6qY|6HPedP0Dp2(K$WeIMs*grB@1<|;|8x!_vmd|3s&IjF*AqcBr=G@-Bfq7*M%bZG086ue$4=>0 zA3sGjg%`M1U!!7_&|tRcJ+p`AF2ZzNbeJ>-$}eIqt@;?{IqaU^O&V+f;k!%uGvbH>ehHG0>W1+|#euVN{q z33m0w7K%q`0y!SHfCx>SvLYybZfKCqZi}8TqZ{1RL_v+i(_u2T z+u%r_tNi3?m5ZYEmKp`&^+dd+v7{x8z|$%hPjRh~G_22n8(G>)U~YCSbRz-B_1CS0 zwCoHN#=mSWw4ezYIH})itwzuqV&=1<)!pWz*$BkF-uCZRc{fma4R^0{fzPFp*-I!|M8@>|g!BSFQ z@j{?q+ry0%Pl-J})_SHdc+Ba^t~ucGcox0w>9*DuG_x1nQrc{^MySni#d_=J$CJs_ zx;Nm_%2S%2^he-++8fc{(*akW+I`MC0T5B#*P73vE>8zs6{_CHjTB8w`sj$*aHV~( zj~hOLhWCZdeq6wr;J1f@+bzu9g60M-hDgJRT;0YW!-uiJ=$&}wE^<$OF0T75WB@cJ&wln8L# zO)1%Z{Xy`is^Okl49|OP5b#jNDoyQ&BPFgkScfOM@m355p4yxiHv;KhwM?u!8sK6{ z&eSMCd94)9FqzPmrvWa8`V4_IBjIf>4-p&%4^Eimyv#CW9*Ptiu;{xP3caG!4K^)MsDSeNpw|?^tf5H zyHzLtOCYHg>fF(|XhGv!B#r-4vzF@h*oiOUQC?2MN<3DY-+GS1hVMTP3O+N6btY&X znCOcDP;E4{<~I?$6)lEUXw_&iS|bZT1&z_DPI(lXhD?SugU4W2;F##q7?AsVA~fB5 ztY!x)y}^)lEG+mz7GFmB*q{nE8ixRU<1}A{u1tc`_l(maN%)km(0D|)J(Gbse>~tl zH*soLS2&fJph1E|0cUL|00~`PiS&2^5(wq%HFR}FQI{-l4U1@fL0f}`HYp8z=;|_4 z(nKiNLjxa3Pt?F8xxtDQo&~#f@pEdQ*X{mU{#byfqj?Q>G)CQ#!kzPX~F_M9WZ*Z`nC<`>Qk* zZv7UA45hOxc?KZS*;R>l&hWMeF%giWUCN#bKs0t`&qEj2f|%pEn4+v3 zIJ(c8gOZk~F8XYaTI#G!E$4bC6N&`x5AJ@LE2JugQ5rNKXQ;4wLNdyzYGpK(rp?nx zt$ZSmr>EvY?EBO4QIHImtbVxFc_Cc#L0JcmC*H|-KKx974sUtPm=Aqk=eS6E4nYcT z3&0I_GKwuV7r;@VGHRg13lK|DSgK0V**Z`Of5Id)8?){g@C{C0HfBXt6d(SQjsd0J zdAdeQvcHnF|%3~ZM-PID!Orz_t6FH;=D(u-?8(GE{6J) z!sxKYFfV*+9vS@|u?{v@>WD8Bc z1Mm4&O|>LikxqVBfTos2L#W159Wws%1AVo$06CU|m*p2XQ4$TO;mb6-a(}wHe_1{X z>Y;H|W4TgRLKPMD(DJloxkg`jlM9P>Z+Sin>Y-Jr_X?EalzQl?6&h%ztvbdVwncFk9z$~bl%67x%|VEd?thEw8d4cEBvfF(~^?XHK$kFNY?s%`bn?}J(BSXED9WMb>C*Q?je?9o zl$Yn0CgVDUc+^5;X!SbyDmChE-3-_0v)=oRjOB+fv{I|}Agh!@e_!t|g@#em1`Pwa z20@MY>kaNwXbkyo1Oq6AhSSiE-bs%-C&J})*x~7oYAH01Qa3>X`K8cuv}TiTZu}Vq z%G(6tK9x|0Zgyu@sMO`xLT_!>q1kbJVfX=O`utib9M=!-nxk3^joPBYz^w>Apd7RX zwvk^8jieV_@~f1ng(gzQRvn6n&$`xZ%|}5kv<}7OC@x0n;85PlK`}IjQ1SJ;%zzSb zO@fZ@+#KvH6hmuLzis&?R}@2|==W`!y@A#j+?hvhhpS1ppe=fFHMHz++74_~L?ft} zQ^%GKH@2;vC_JDbTAj{1p<$&Unx>Sy)Ff{BkKRd~%90(e3QKg*ltt~gstf#}2rAN6m$0Uw?^c;e zeZ`c9?-CAtDuaen+HT!E%C|d;VLTDSLF_%Ek4WJzizd)_dJ3 ziF9nQ4%&eXCE%xmGN_f7{{)}@X)RF)wNjCN8fBx41uZ!(_hDkxL0ixt`>^#<2aTh; z`*olq{K=gCZat`VP$QK)0C?0vtJ1dzbnr@N+BgE~knwyOD% zyAFyE77u|{tXwIj23nJv{_LF~Hb#r%HZ2tvaj; zB6!e=y3GdG$HM|%`$8Rb+!3}8T8{FLu)LuKMX59<9nJT-pEmKSqfi;@pixxq7`qlg z5z)0X;#hti^yx7`q7GV)zWBvsz)OB%4H!5|3+B(iKv@Mv(B8)p<7V$FMO#v_QO+IL zv4+RkDC`8LM-eocR-b@0`9;tu3OLC+WE=`7-auY9@FeapK9xc5p7bt*iiu!Ei7`ul zb(cXa(UemfsyLD&Jvw&^(kV627NjrN~|2vz%m^Xf@Ny+DQlPd-MZ_dF(D&(tjsC`zYV;6Lw_|r^O>LNf<`?S%zi=HD+vpY0eeE-~XRxYNac}LgwG0wkB7B zboh5@ML7uVzlzGb^)egu&~$+wHts5nT)qq$2VTR%l==fGgVTKI@-^I74EjT(cNA>l z!gl`w=CiL0wMts;Q8kl#L<~)iO2t await driver.findElement(By.linkText('Biology - QA')).click() }, //Wait page to load @@ -405,11 +405,34 @@ const steps = [ { description: 'Validate Biology - QA count', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(1)')).getText(); - if (elementText !== 'Biology - QA (1046)') { - throw new Error(`Expected: "Biology - QA (1046)"; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Biology - QA (1046)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Biology - QA (1046) label matched as expected'); } }, @@ -617,30 +640,6 @@ const steps = [ } }, - //Subject: Mathematics checkbox - { - description: 'Verify Subject: Mathematics checkbox icon is present', - action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#metasubjectsMathematics')), 5000).catch(() => false); - if (!expectedIcon) { - throw new Error('Subject: Mathematics checkbox icon not found'); - } - console.log('Passed: Subject Mathematics checkbox icon present'); - } - }, - - //Subject: Mathematics label - { - description: 'Validate Subject: Mathematics label', - action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(7)')).getText(); - if (elementText !== 'Mathematics') { - throw new Error(`Expected: Subject: "Mathematics" label; Actual: "${elementText}"`); - } - console.log('Passed: Subject Mathematics label matched as expected'); - } - }, - //Subject: Language Arts checkbox { description: 'Verify Subject: Language Arts checkbox icon is present', @@ -657,7 +656,7 @@ const steps = [ { description: 'Validate Subject: Language Arts label', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(10)')).getText(); + const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(7)')).getText(); if (elementText !== 'Language Arts') { throw new Error(`Expected: Subject: "Language Arts" label; Actual: "${elementText}"`); } @@ -665,6 +664,30 @@ const steps = [ } }, + //Subject: Mathematics checkbox + { + description: 'Verify Subject: Mathematics checkbox icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#metasubjectsMathematics')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Subject: Mathematics checkbox icon not found'); + } + console.log('Passed: Subject Mathematics checkbox icon present'); + } + }, + + //Subject: Mathematics label + { + description: 'Validate Subject: Mathematics label', + action: async () => { + const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(10)')).getText(); + if (elementText !== 'Mathematics') { + throw new Error(`Expected: Subject: "Mathematics" label; Actual: "${elementText}"`); + } + console.log('Passed: Subject Mathematics label matched as expected'); + } + }, + //Subject: Social Studies checkbox { description: 'Verify Subject: Social Studies checkbox icon is present', @@ -1260,11 +1283,34 @@ const steps = [ { description: 'Validate Content 1 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(8) .lo-descr')).getText(); - if (elementText !== 'Yes, it should work! Perhaps') { - throw new Error(`Expected: Content 1 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Biology - QA (1046)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Content 1 description "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Content 1 description "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Content 1 description text matched as expected'); } }, @@ -1440,11 +1486,34 @@ const steps = [ { description: 'Validate Content 2 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(9) .lo-descr')).getText(); - if (elementText !== 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.') { - throw new Error(`Expected: Content 2 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(9) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Content 2 description text located in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Content 2 description text located within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Content 2 description text matched as expected'); } }, @@ -1653,11 +1722,34 @@ const steps = [ { description: 'Validate Biology - QA count', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(1)')).getText(); - if (elementText !== 'Biology - QA (1046)') { - throw new Error(`Expected: "Biology - QA (1046)"; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Biology - QA (4)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Biology - QA (1046) label matched as expected'); } }, @@ -1701,11 +1793,34 @@ const steps = [ { description: 'Validate Grade: 9 label', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(3) > label:nth-child(4)')).getText(); - if (elementText !== '9') { - throw new Error(`Expected: Grade: "9" label; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(3)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = '9 (4)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Grade 9 label matched as expected'); } }, @@ -1857,11 +1972,34 @@ const steps = [ { description: 'Validate Subject: Science label', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label')).getText(); - if (elementText !== 'Science') { - throw new Error(`Expected: Subject: "Science" label; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(6)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science (4)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Subject Science label matched as expected'); } }, @@ -1929,11 +2067,34 @@ const steps = [ { description: 'Validate Pending label', action: async () => { - const elementText = await driver.findElement(By.css('label:nth-child(6)')).getText(); - if (elementText !== 'Pending') { - throw new Error(`Expected: "Pending"; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(8)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Pending (4)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Pending label matched as expected'); } }, @@ -2196,11 +2357,34 @@ const steps = [ { description: 'Validate Filtered Content 1 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(1) .lo-descr')).getText(); - if (elementText !== `This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.`) { - throw new Error(`Expected: Filtered Content 1 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(1) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Filtered Content 1 description text located in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Filtered Content 1 description text located within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Filtered Content 1 description text matched as expected'); } }, @@ -2340,11 +2524,34 @@ const steps = [ { description: 'Validate Filtered Content 2 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(2) .lo-descr')).getText(); - if (elementText !== 'An exploration of physics. Calculating the acceleration of a Porsche. This video with commentary focuses on the study of mechanics.') { - throw new Error(`Expected: Filtered Content 2 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(2) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'An exploration of physics. Calculating the acceleration of a Porsche. This video with commentary focuses on the study of mechanics.'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Filtered Content 2 description text located in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Filtered Content 2 description text located within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Filtered Content 2 description text matched as expected'); } }, @@ -2444,8 +2651,8 @@ const steps = [ } }, - //NEXT ACTION - Click Filtered content 2 Edit button - { description: 'Click filtered countent 2 Edit button', action: async () => await driver.findElement(By.css('.card:nth-child(1) .ml-3')).click() }, + //NEXT ACTION - Click Filtered content 1 Edit button (abrupt climate change) + { description: 'Click filtered countent 1 Edit button', action: async () => await driver.findElement(By.css('.card:nth-child(1) .ml-3')).click() }, //Wait for page to load - Edit Item { @@ -3238,11 +3445,34 @@ const steps = [ { description: 'Validate Tagged Concept 1 header text', action: async () => { - const elementText = await driver.findElement(By.css('#k749')).getText(); - if (elementText !== 'Science | Earth Science | Climate') { - throw new Error(`Expected: Tagged Concept 1 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#k786')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Habits of the Mind | Curiosity'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 1 header text matched as expected'); } }, @@ -3250,7 +3480,7 @@ const steps = [ { description: 'Validate Tagged concept 1 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k786')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 1 header text color did not match; Actual: "${elementStyle}"`); } @@ -3262,7 +3492,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 1 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k749 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k786 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 1 "Remove" button icon not found'); } @@ -3274,7 +3504,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k749 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k786 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 1 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -3286,7 +3516,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k786 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 1 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -3298,7 +3528,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k786 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 1 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -3310,7 +3540,7 @@ const steps = [ { description: 'Verify Tagged Concept 1 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k749 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k786 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 1 "Primary" toggle button icon not found'); } @@ -3322,11 +3552,34 @@ const steps = [ { description: 'Validate Tagged Concept 2 header text', action: async () => { - const elementText = await driver.findElement(By.css('#k937')).getText(); - if (elementText !== `Science | Physical Science | Physics | Force and Motion | Newton's Laws`) { - throw new Error(`Expected: Tagged Concept 2 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#k933')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Physical Science | Physics | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 2 header text matched as expected'); } }, @@ -3334,7 +3587,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k933')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 2 header text color did not match; Actual: "${elementStyle}"`); } @@ -3346,7 +3599,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 2 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k937 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k933 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 2 "Remove" button icon not found'); } @@ -3358,7 +3611,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k937 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k933 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 2 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -3370,7 +3623,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k933 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 2 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -3382,7 +3635,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k933 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 2 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -3394,7 +3647,7 @@ const steps = [ { description: 'Verify Tagged Concept 2 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k937 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k933 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 2 "Primary" toggle button icon not found'); } @@ -3406,11 +3659,34 @@ const steps = [ { description: 'Validate Tagged Concept 3 header text', action: async () => { - const elementText = await driver.findElement(By.css('#k37785095')).getText(); - if (elementText !== 'Science | Earth Science | Topography | Influence on Climate / Weather / etc.') { - throw new Error(`Expected: Tagged Concept 3 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#k26613360')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Habits of the Mind | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 2 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 2 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 3 header text matched as expected'); } }, @@ -3418,7 +3694,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k26613360')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 3 header text color did not match; Actual: "${elementStyle}"`); } @@ -3430,7 +3706,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 3 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785095 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k26613360 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 3 "Remove" button icon not found'); } @@ -3442,7 +3718,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k37785095 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k26613360 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 3 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -3454,7 +3730,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k26613360 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 3 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -3466,7 +3742,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k26613360 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 3 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -3478,7 +3754,7 @@ const steps = [ { description: 'Verify Tagged Concept 3 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785095 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k26613360 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 3 "Primary" toggle button icon not found'); } @@ -3490,11 +3766,34 @@ const steps = [ { description: 'Validate Tagged Concept 4 header text', action: async () => { - const elementText = await driver.findElement(By.css('#k425604099')).getText(); - if (elementText !== 'Science | General') { - throw new Error(`Expected: Tagged Concept 4 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#k37785094')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Earth Science | Topography | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 3 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 3 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 4 header text matched as expected'); } }, @@ -3502,7 +3801,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k37785094')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 4 header text color did not match; Actual: "${elementStyle}"`); } @@ -3514,7 +3813,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 4 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k425604099 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785094 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 4 "Remove" button icon not found'); } @@ -3526,7 +3825,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k425604099 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k37785094 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 4 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -3538,7 +3837,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k37785094 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 4 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -3550,7 +3849,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k37785094 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 4 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -3562,7 +3861,7 @@ const steps = [ { description: 'Verify Tagged Concept 4 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k425604099 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785094 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 4 "Primary" toggle button icon not found'); } @@ -4015,7 +4314,7 @@ const steps = [ } }, - //NEXT ACTION - AutoAlign link + //NEXT ACTION - AutoAlign tab { description: 'Click AutoAlign tab link', action: async () => await driver.findElement(By.linkText('AutoAlign')).click() }, { description: 'Wait for action to complete', action: async () => await driver.sleep(5000) }, @@ -4151,17 +4450,40 @@ const steps = [ } }, - /*Base Suggestion On sub-title + //Base Suggestion On sub-title KRYS { description: 'Validate Base Suggestion On sub-title', action: async () => { - const elementText = await driver.findElement(By.xpath('//*[@id="suggest_form"]/*[1]')).getText(); - if (elementText !== 'Base Suggestion On:') { - throw new Error(`Expected: "Base Suggestion On:" sub-title text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggest_form')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Base Suggestion On:'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Base Suggestion On: sub-title text matched as expected'); } - },*/ + }, //Title checkbox { @@ -4619,17 +4941,40 @@ const steps = [ } }, - /*# of Concepts label + //# of Concepts label KRYS { description: 'Validate # of Concepts label', action: async () => { - const elementText = await driver.findElement(By.xpath('//*[@id="suggest_form"]/*[2]')).getText(); - if (elementText !== '# of Concepts') { - throw new Error(`Expected: "# of Concepts" label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggest_form')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = '# of Concepts'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[3].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: # of Concepts label matched as expected'); } - },*/ + }, //Subject Areas label { @@ -4643,17 +4988,40 @@ const steps = [ } }, - /*Subject Areas label + //Subject Areas label KRYS { description: 'Validate Subject Areas label', action: async () => { - const elementText = await driver.findElement(By.xpath('//*[@id="suggest_form"]/*[3]')).getText(); - if (elementText !== 'Subject Areas') { - throw new Error(`Expected: 33"Subject Areas" label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggest_form')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Subject Areas'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[3].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed:44 Subject Areas label matched as expected'); } - },*/ + }, //Subject Area value -Language Arts { @@ -4800,11 +5168,34 @@ const steps = [ { description: 'Validate Suggested Concept 1 label', action: async () => { - const elementText = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(1)')).getText(); - if (elementText !== 'History / Technology / Social Perspectives | Advancement of Science') { - throw new Error(`Expected: Suggested Concept 1 label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | History / Technology / Social Perspectives | Advancement of Science'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Suggested Concept 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Suggested Concept 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Suggested Concept 1 label matched as expected'); } }, @@ -4860,11 +5251,34 @@ const steps = [ { description: 'Validate Suggested Concept 2 label', action: async () => { - const elementText = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(2)')).getText(); - if (elementText !== 'History / Technology / Social Perspectives | Advancement of Science') { - throw new Error(`Expected: Suggested Concept 2 label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(2)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | History / Technology / Social Perspectives | Nature of Science'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Suggested Concept 2 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Suggested Concept 2 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Suggested Concept 2 label matched as expected'); } }, @@ -4884,7 +5298,7 @@ const steps = [ { description: 'Validate Suggested Concept 3 Add button text', action: async () => { - const elementText = await driver.findElement(By.css('.list-group-item:nth-child(3) > .btn')).getText(); + const elementText = await driver.findElement(By.css('.list-group-item:nth-child(3) > .btn-success')).getText(); if (elementText !== 'Add') { throw new Error(`Expected: Suggested Concept 3 Add button text did not match; Actual: "${elementText}"`); } @@ -4908,7 +5322,7 @@ const steps = [ { description: 'Validate Suggested Concept 3 Add button color', action: async () => { - const elementValue = await driver.findElement(By.css('.list-group-item:nth-child(3) > .btn')).getCssValue('background-color'); + const elementValue = await driver.findElement(By.css('.list-group-item:nth-child(3) > .btn-success')).getCssValue('background-color'); if (elementValue !== 'rgba(40, 167, 69, 1)') { throw new Error(`Expected: Suggested Concept 3 Add button color did not match; Actual: "${elementValue}"`); } @@ -4920,11 +5334,34 @@ const steps = [ { description: 'Validate Suggested Concept 3 label', action: async () => { - const elementText = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(3)')).getText(); - if (elementText !== 'Science | History / Technology / Social Perspectives | Nature of Science') { - throw new Error(`Expected: Suggested Concept 3 label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(3)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = `Science | Earth Science | Earth History | Earth's Evolution | Climate Changes Over Time / Past Climates`; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Suggested Concept 3 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Suggested Concept 3 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Suggested Concept 3 label matched as expected'); } }, @@ -4980,11 +5417,34 @@ const steps = [ { description: 'Validate Suggested Concept 4 label', action: async () => { - const elementText = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(4)')).getText(); - if (elementText !== `Science | Earth Science | Earth History | Earth's Evolution | Climate Changes Over Time / Past Climates`) { - throw new Error(`Expected: Suggested Concept 4 label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(4)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = `Science | Earth Science | Earth History | Earth's Evolution | Theories`; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Suggested Concept 4 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Suggested Concept 4 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Suggested Concept 4 label matched as expected'); } }, @@ -5004,7 +5464,7 @@ const steps = [ { description: 'Validate Suggested Concept 5 Add button text', action: async () => { - const elementText = await driver.findElement(By.css('.list-group-item:nth-child(5) > .btn')).getText(); + const elementText = await driver.findElement(By.css('.list-group-item:nth-child(5) > .btn-success')).getText(); if (elementText !== 'Add') { throw new Error(`Expected: Suggested Concept 5 Add button text did not match; Actual: "${elementText}"`); } @@ -5028,7 +5488,7 @@ const steps = [ { description: 'Validate Suggested Concept 5 Add button color', action: async () => { - const elementValue = await driver.findElement(By.css('.list-group-item:nth-child(5) > .btn')).getCssValue('background-color'); + const elementValue = await driver.findElement(By.css('.list-group-item:nth-child(5) > .btn-success')).getCssValue('background-color'); if (elementValue !== 'rgba(40, 167, 69, 1)') { throw new Error(`Expected: Suggested Concept 5 Add button color did not match; Actual: "${elementValue}"`); } @@ -5040,11 +5500,34 @@ const steps = [ { description: 'Validate Suggested Concept 5 label', action: async () => { - const elementText = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(5)')).getText(); - if (elementText !== 'Science | Life Science (Biology) | Environment | Human Factors | Global Warming') { - throw new Error(`Expected: Suggested Concept 5 label did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#suggested_concepts .list-group-item:nth-child(5)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Life Science (Biology) | Environment | Human Factors | Global Warming'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Suggested Concept 5 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Suggested Concept 5 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Suggested Concept 5 label matched as expected'); } }, @@ -5060,15 +5543,15 @@ const steps = [ } }, - //NEXT ACTION - Click concept 5 Primary toggle - { description: 'Click Concept 5 Primary toggle icon', action: async () => await driver.findElement(By.css('.list-group-item:nth-child(5) label')).click() }, + //NEXT ACTION - Click concept 2 Primary toggle + { description: 'Click Concept 2 Primary toggle icon', action: async () => await driver.findElement(By.css('.list-group-item:nth-child(2) label')).click() }, { description: 'Wait for action to complete', action: async () => await driver.sleep(2000) }, //Suggested Concept 5 Primary label { description: 'Validate Suggested Concept 5 Primary label', action: async () => { - const elementText = await driver.findElement(By.css('#suggested_concepts > ul > li:nth-child(5) > div > label > span')).getText(); + const elementText = await driver.findElement(By.css('.list-group-item:nth-child(2) .switch-primary')).getText(); if (elementText !== 'Primary') { throw new Error(`Expected: "Primary" toggle indicator; Actual: "${elementText}"`); } @@ -5076,8 +5559,8 @@ const steps = [ } }, - //NEXT ACTION - Click concept 5 Add button - { description: 'Click Concept 5 Add button', action: async () => await driver.findElement(By.css('.list-group-item:nth-child(5) > .btn')).click() }, + //NEXT ACTION - Click concept 2 Add button + { description: 'Click Concept 2 Add button', action: async () => await driver.findElement(By.css('.list-group-item:nth-child(2) > .btn')).click() }, //Added suggested concept confirmation alert title { @@ -5120,8 +5603,8 @@ const steps = [ description: 'Validate Added suggested concept confirmation alert DIV description', action: async () => { const elementText = await driver.findElement(By.css('.toast-body')).getText(); - if (elementText !== 'Science | Life Science (Biology) | Environment | Human Factors | Global Warming') { - throw new Error(`Expected: "Science | Life Science (Biology) | Environment | Human Factors | Global Warming" Confirmation DIV description text did not match; Actual: "${elementText}"`); + if (elementText !== 'Science | History / Technology / Social Perspectives | Nature of Science') { + throw new Error(`Expected: "Science | History / Technology / Social Perspectives | Nature of Science" Confirmation DIV description text did not match; Actual: "${elementText}"`); } console.log('Passed: Confirmation DIV description text displayed as expected'); } @@ -5178,19 +5661,42 @@ const steps = [ { description: 'Validate Tagged Concept 1 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li')).getText(); - if (elementText !== 'Science | Earth Science | Climate') { - throw new Error(`Expected: Tagged Concept 1 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Habits of the Mind | Curiosity'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 1 header text matched as expected'); } }, - + //Tagged concept 1 header text color -gray { description: 'Validate Tagged concept 1 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k786')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 1 header text color did not match; Actual: "${elementStyle}"`); } @@ -5202,7 +5708,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 1 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k749 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k786 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 1 "Remove" button icon not found'); } @@ -5214,7 +5720,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k749 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k786 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 1 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -5226,7 +5732,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k786 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 1 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -5238,7 +5744,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k786 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 1 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -5250,7 +5756,7 @@ const steps = [ { description: 'Verify Tagged Concept 1 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k749 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k786 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 1 "Primary" toggle button icon not found'); } @@ -5262,11 +5768,34 @@ const steps = [ { description: 'Validate Tagged Concept 2 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[2]')).getText(); - if (elementText !== `Science | Physical Science | Physics | Force and Motion | Newton's Laws`) { - throw new Error(`Expected: Tagged Concept 2 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[2]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Physical Science | Physics | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 2 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 2 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 2 header text matched as expected'); } }, @@ -5274,7 +5803,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k933')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 2 header text color did not match; Actual: "${elementStyle}"`); } @@ -5286,7 +5815,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 2 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k937 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k933 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 2 "Remove" button icon not found'); } @@ -5298,7 +5827,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k937 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k933 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 2 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -5310,7 +5839,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k933 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 2 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -5322,7 +5851,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k933 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 2 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -5334,7 +5863,7 @@ const steps = [ { description: 'Verify Tagged Concept 2 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k937 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k933 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 2 "Primary" toggle button icon not found'); } @@ -5346,11 +5875,34 @@ const steps = [ { description: 'Validate Tagged Concept 3 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[3]')).getText(); - if (elementText !== 'Science | Earth Science | Topography | Influence on Climate / Weather / etc.') { - throw new Error(`Expected: Tagged Concept 3 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[3]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Habits of the Mind | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 3 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 3 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 3 header text matched as expected'); } }, @@ -5358,7 +5910,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k26613360')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 3 header text color did not match; Actual: "${elementStyle}"`); } @@ -5370,7 +5922,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 3 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785095 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k26613360 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 3 "Remove" button icon not found'); } @@ -5382,7 +5934,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k37785095 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k26613360 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 3 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -5394,7 +5946,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k26613360 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 3 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -5406,7 +5958,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k26613360 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 3 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -5418,7 +5970,7 @@ const steps = [ { description: 'Verify Tagged Concept 3 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785095 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k26613360 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 3 "Primary" toggle button icon not found'); } @@ -5430,11 +5982,34 @@ const steps = [ { description: 'Validate Tagged Concept 4 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[4]')).getText(); - if (elementText !== 'Science | General') { - throw new Error(`Expected: Tagged Concept 4 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[4]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Earth Science | Topography | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 4 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 4 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 4 header text matched as expected'); } }, @@ -5442,7 +6017,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k37785094')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 4 header text color did not match; Actual: "${elementStyle}"`); } @@ -5454,7 +6029,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 4 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k425604099 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785094 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 4 "Remove" button icon not found'); } @@ -5466,7 +6041,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k425604099 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k37785094 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 4 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -5478,7 +6053,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k37785094 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 4 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -5490,7 +6065,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k37785094 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 4 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -5502,7 +6077,7 @@ const steps = [ { description: 'Verify Tagged Concept 4 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k425604099 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785094 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 4 "Primary" toggle button icon not found'); } @@ -5514,11 +6089,34 @@ const steps = [ { description: 'Validate Tagged Concept 5 header text', action: async () => { - const elementText = await driver.findElement(By.css('#k11532278')).getText(); - if (elementText !== 'Science | Life Science (Biology) | Environment | Human Factors | Global Warming') { - throw new Error(`Expected: Tagged Concept 5 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[5]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | History / Technology / Social Perspectives | Nature of Science'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged Concept 5 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged Concept 5 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 5 header text matched as expected'); } }, @@ -5526,7 +6124,7 @@ const steps = [ { description: 'Validate Tagged concept 5 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k11532278')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k806')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 51 header text color did not match; Actual: "${elementStyle}"`); } @@ -5586,7 +6184,7 @@ const steps = [ { description: 'Validate Tagged Concept 5 primary toggle button text', action: async () => { - const elementText = await driver.findElement(By.css('#k11532278 > div > label > span')).getText(); + const elementText = await driver.findElement(By.css('#k806 > div > label > span')).getText(); if (elementText !== 'Primary') { throw new Error(`Expected: Tagged Concept 5 "Primary" toggle button text did not match; Actual: "${elementText}"`); } @@ -5598,7 +6196,7 @@ const steps = [ { description: 'Validate Tagged Concept 5 active primary toggle button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k11532278 > div > label > span')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k806 > div > label > span')).getCssValue('color'); if (elementStyle !== 'rgba(255, 255, 255, 1)') { throw new Error(`Expected: Tagged Concept 5 active "Primary" toggle button color did not match; Actual: "${elementStyle}"`); } @@ -5606,8 +6204,9 @@ const steps = [ } }, - //NEXT ACTION - Click concept 2 Add button {ECS-2852 Update the "Add" icon after selecting item} - { description: 'Click Concept 2 Add button', action: async () => await driver.findElement(By.css('.list-group-item:nth-child(2) > .btn-success')).click() }, + //NEXT ACTION - Click concept 2 Add button (second time){ECS-2852 Update the "Add" icon after selecting item} + { description: 'Click Concept 2 Add button', action: async () => await driver.findElement(By.css('.list-group-item:nth-child(2) > .btn')).click() }, + { description: 'Wait for page to redirect back', action: async () => await driver.sleep(2000) }, //Added suggested concept confirmation alert title { @@ -5670,8 +6269,8 @@ const steps = [ }, //NEXT ACTION - Click Save Changes button - { description: 'Wait for page to redirect back', action: async () => await driver.sleep(5000) }, { description: 'Click Save Changes button', action: async () => await driver.findElement(By.css('.submit-content-button')).click() }, + { description: 'Wait for page to redirect', action: async () => await driver.sleep(2000) }, //Wait for confirmation bannter to load { @@ -5839,11 +6438,34 @@ const steps = [ { description: 'Validate Data range text handle', action: async () => { - const elementText = await driver.findElement(By.css('#get_report')).getText(); //.form-group:nth-child(1) > .form-label - if (elementText !== 'Data range:') { - throw new Error(`Expected: "Data range: Start"; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('#get_report')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Data range:'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Data range: Start text handle matched as expected'); } }, @@ -6322,11 +6944,34 @@ const steps = [ { description: 'Validate Biology - QA count', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(1)')).getText(); - if (elementText !== 'Biology - QA (1046)') { - throw new Error(`Expected: "Biology - QA (1046)"; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.form-group:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Biology - QA (1046)'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[1].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Biology - QA (1046) label matched as expected'); } }, @@ -6534,30 +7179,6 @@ const steps = [ } }, - //Subject: Mathematics checkbox - { - description: 'Verify Subject: Mathematics checkbox icon is present', - action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#metasubjectsMathematics')), 5000).catch(() => false); - if (!expectedIcon) { - throw new Error('Subject: Mathematics checkbox icon not found'); - } - console.log('Passed: Subject Mathematics checkbox icon present'); - } - }, - - //Subject: Mathematics label - { - description: 'Validate Subject: Mathematics label', - action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(7)')).getText(); - if (elementText !== 'Mathematics') { - throw new Error(`Expected: Subject: "Mathematics" label; Actual: "${elementText}"`); - } - console.log('Passed: Subject Mathematics label matched as expected'); - } - }, - //Subject: Language Arts checkbox { description: 'Verify Subject: Language Arts checkbox icon is present', @@ -6574,7 +7195,7 @@ const steps = [ { description: 'Validate Subject: Language Arts label', action: async () => { - const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(10)')).getText(); + const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(7)')).getText(); if (elementText !== 'Language Arts') { throw new Error(`Expected: Subject: "Language Arts" label; Actual: "${elementText}"`); } @@ -6582,6 +7203,30 @@ const steps = [ } }, + //Subject: Mathematics checkbox + { + description: 'Verify Subject: Mathematics checkbox icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#metasubjectsMathematics')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Subject: Mathematics checkbox icon not found'); + } + console.log('Passed: Subject Mathematics checkbox icon present'); + } + }, + + //Subject: Mathematics label + { + description: 'Validate Subject: Mathematics label', + action: async () => { + const elementText = await driver.findElement(By.css('.form-group:nth-child(6) > label:nth-child(10)')).getText(); + if (elementText !== 'Mathematics') { + throw new Error(`Expected: Subject: "Mathematics" label; Actual: "${elementText}"`); + } + console.log('Passed: Subject Mathematics label matched as expected'); + } + }, + //Subject: Social Studies checkbox { description: 'Verify Subject: Social Studies checkbox icon is present', @@ -7177,11 +7822,34 @@ const steps = [ { description: 'Validate Content 1 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(8) .lo-descr')).getText(); - if (elementText !== 'Yes, it should work! Perhaps') { - throw new Error(`Expected: Content 1 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(8) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Yes, it should work! Perhaps'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Content 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Content 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Content 1 description text matched as expected'); } }, @@ -7357,11 +8025,34 @@ const steps = [ { description: 'Validate Content 2 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(9) .lo-descr')).getText(); - if (elementText !== 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.') { - throw new Error(`Expected: Content 2 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(9) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Content 2 description text located in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Content 2 description text located within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Content 2 description text matched as expected'); } }, @@ -7508,11 +8199,34 @@ const steps = [ { description: 'Validate Tagged Concept 1 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li')).getText(); - if (elementText !== 'Science | Earth Science | Climate') { - throw new Error(`Expected: Tagged Concept 1 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Habits of the Mind | Curiosity'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged concept 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged concept 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 1 header text matched as expected'); } }, @@ -7520,7 +8234,7 @@ const steps = [ { description: 'Validate Tagged concept 1 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k786')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 1 header text color did not match; Actual: "${elementStyle}"`); } @@ -7532,7 +8246,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 1 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k749 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k786 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 1 "Remove" button icon not found'); } @@ -7544,7 +8258,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k749 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k786 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 1 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -7556,7 +8270,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k786 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 1 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -7568,7 +8282,7 @@ const steps = [ { description: 'Validate Tagged Concept 1 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k749 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k786 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 1 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -7580,7 +8294,7 @@ const steps = [ { description: 'Verify Tagged Concept 1 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k749 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k786 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 1 "Primary" toggle button icon not found'); } @@ -7592,11 +8306,34 @@ const steps = [ { description: 'Validate Tagged Concept 2 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[2]')).getText(); - if (elementText !== `Science | Physical Science | Physics | Force and Motion | Newton's Laws`) { - throw new Error(`Expected: Tagged Concept 2 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[2]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | History / Technology / Social Perspectives | Nature of Science | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged concept 2 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged concept 2 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 2 header text matched as expected'); } }, @@ -7604,7 +8341,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k806')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 2 header text color did not match; Actual: "${elementStyle}"`); } @@ -7616,7 +8353,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 2 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k937 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k806 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 2 "Remove" button icon not found'); } @@ -7628,7 +8365,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k937 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k806 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 2 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -7640,7 +8377,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k806 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 2 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -7652,7 +8389,7 @@ const steps = [ { description: 'Validate Tagged Concept 2 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k937 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k806 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 2 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -7664,7 +8401,7 @@ const steps = [ { description: 'Verify Tagged Concept 2 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k937 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k806 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 2 "Primary" toggle button icon not found'); } @@ -7676,11 +8413,34 @@ const steps = [ { description: 'Validate Tagged Concept 3 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[3]')).getText(); - if (elementText !== 'Science | Earth Science | Topography | Influence on Climate / Weather / etc.') { - throw new Error(`Expected: Tagged Concept 3 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[3]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Physical Science | Physics | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged concept 3 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged concept 3 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 3 header text matched as expected'); } }, @@ -7688,7 +8448,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k11532278')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k933')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 3 header text color did not match; Actual: "${elementStyle}"`); } @@ -7700,7 +8460,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 3 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k11532278 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k933 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 3 "Remove" button icon not found'); } @@ -7712,7 +8472,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k11532278 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k933 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 3 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -7724,7 +8484,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k11532278 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k933 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 3 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -7736,7 +8496,7 @@ const steps = [ { description: 'Validate Tagged Concept 3 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k11532278 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k933 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 3 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -7748,7 +8508,7 @@ const steps = [ { description: 'Verify Tagged Concept 3 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k11532278 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k933 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 3 "Primary" toggle button icon not found'); } @@ -7760,11 +8520,34 @@ const steps = [ { description: 'Validate Tagged Concept 4 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[4]')).getText(); - if (elementText !== 'Science | Earth Science | Topography | Influence on Climate / Weather / etc.') { - throw new Error(`Expected: Tagged Concept 4 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[4]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Habits of the Mind | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged concept 4 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged concept 4 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 4 header text matched as expected'); } }, @@ -7772,7 +8555,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k26613360')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 4 header text color did not match; Actual: "${elementStyle}"`); } @@ -7784,7 +8567,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 4 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785095 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k26613360 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 4 "Remove" button icon not found'); } @@ -7796,7 +8579,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k37785095 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k26613360 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 4 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -7808,7 +8591,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k26613360 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 4 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -7820,7 +8603,7 @@ const steps = [ { description: 'Validate Tagged Concept 4 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k37785095 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k26613360 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 4 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -7832,7 +8615,7 @@ const steps = [ { description: 'Verify Tagged Concept 4 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785095 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k26613360 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 4 "Primary" toggle button icon not found'); } @@ -7844,11 +8627,34 @@ const steps = [ { description: 'Validate Tagged Concept 5 header text', action: async () => { - const elementText = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[5]')).getText(); - if (elementText !== 'Science | General') { - throw new Error(`Expected: Tagged Concept 5 header text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.xpath('//div[2]/div/div/ul/li[5]')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Science | Earth Science | Topography | General'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Tagged concept 5 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Tagged concept 5 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Tagged Concept 5 header text matched as expected'); } }, @@ -7856,7 +8662,7 @@ const steps = [ { description: 'Validate Tagged Concept 5 header text color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099')).getCssValue('color'); + const elementStyle = await driver.findElement(By.css('#k37785094')).getCssValue('color'); if (elementStyle !== 'rgba(99, 99, 99, 1)') { throw new Error(`Expected: Tagged Concept 5 header text color did not match; Actual: "${elementStyle}"`); } @@ -7868,7 +8674,7 @@ const steps = [ { description: 'Verify Tagged Concept remove button 5 icon is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k425604099 .glyphicon')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785094 .glyphicon')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 5 "Remove" button icon not found'); } @@ -7880,7 +8686,7 @@ const steps = [ { description: 'Validate Tagged Concept 5 delete button text', action: async () => { - const elementText = await driver.findElement(By.css('#k425604099 > .btn')).getText(); + const elementText = await driver.findElement(By.css('#k37785094 > .btn')).getText(); if (elementText !== 'Remove') { throw new Error(`Expected: Tagged Concept 5 "Remove" button text did not match; Actual: "${elementText}"`); } @@ -7892,7 +8698,7 @@ const steps = [ { description: 'Validate Tagged Concept 5 remove button label color', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099 > .btn')).getCssValue('background-color'); + const elementStyle = await driver.findElement(By.css('#k37785094 > .btn')).getCssValue('background-color'); if (elementStyle !== 'rgba(246, 60, 40, 1)') { throw new Error(`Expected: Tagged Concept 5 "Remove" button color did not match; Actual: "${elementStyle}"`); } @@ -7904,7 +8710,7 @@ const steps = [ { description: 'Validate Tagged Concept 5 remove button tooltip', action: async () => { - const elementStyle = await driver.findElement(By.css('#k425604099 > .btn')).getAttribute('title'); + const elementStyle = await driver.findElement(By.css('#k37785094 > .btn')).getAttribute('title'); if (elementStyle !== 'Remove Concept') { throw new Error(`Expected: Tagged Concept 5 "Remove Concept" button tooltip did not match; Actual: "${elementStyle}"`); } @@ -7916,7 +8722,7 @@ const steps = [ { description: 'Verify Tagged Concept 5 primary toggle button is present', action: async () => - { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k425604099 .switch-primary')), 5000).catch(() => false); + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#k37785094 .switch-primary')), 5000).catch(() => false); if (!expectedIcon) { throw new Error('Tagged Concept 5 "Primary" toggle button icon not found'); } @@ -7932,7 +8738,7 @@ const steps = [ await driver.sleep(2000); const removeButton = await driver.wait( - until.elementLocated(By.css('#k11532278 > .btn')), + until.elementLocated(By.css('#k806 > .btn')), 5000 ); await removeButton.click(); @@ -8075,7 +8881,7 @@ const steps = [ action: async () => { const elementStyle = await driver.findElement(By.css('.breadcrumb-item:nth-child(2)')).getCssValue('color'); if (elementStyle !== 'rgba(48, 200, 172, 1)') { - throw new Error(`"C"ontent" breadcrumb text color did not match; Actual: "${elementStyle}"`); + throw new Error(`"Content" breadcrumb text color did not match; Actual: "${elementStyle}"`); } console.log('Passed: Content breadcrumb text color matched as expected'); } @@ -8118,7 +8924,7 @@ const steps = [ } }, - //Edit View button color -green + //Edit View button color -clear { description: 'Validate Edit View button color', action: async () => { @@ -8460,11 +9266,34 @@ const steps = [ { description: 'Validate Content 1 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(8) .lo-descr')).getText(); - if (elementText !== 'Yes, it should work! Perhaps') { - throw new Error(`Expected: Content 1 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(8) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Yes, it should work! Perhaps'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Content 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Content 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Content 1 description text matched as expected'); } }, @@ -8640,11 +9469,34 @@ const steps = [ { description: 'Validate Content 2 description', action: async () => { - const elementText = await driver.findElement(By.css('.card:nth-child(9) .lo-descr')).getText(); - if (elementText !== 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.') { - throw new Error(`Expected: Content 2 description text did not match; Actual: "${elementText}"`); + try { + const element = await driver.findElement(By.css('.card:nth-child(9) .lo-descr')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'This Science NetLinks lesson focuses on a current issue in science in order to help students understand the process by which scientific knowledge is developed and refined. In this lesson, students are introduced to some recent ideas about abrupt climate change. This gives them a glimpse into how scientific theories are formed and refined by new data.'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Content 2 description text located in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Content 2 description text located within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging } - console.log('Passed: Content 2 description text matched as expected'); } },