From 7d65782728db3a3abeb907bfd4dae0ad6859aef4 Mon Sep 17 00:00:00 2001 From: fangchen <2027002340@qq.com> Date: Mon, 20 May 2024 18:31:40 +0800 Subject: [PATCH 1/9] fixbug555 --- app/templates/userpage_get.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 68997ef..fe812a6 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -157,6 +157,7 @@ update(data['today_article']); check_pre(data['visited_articles']); check_next(data['result_of_generate_article']); + toggleHighlighting(); } } }); @@ -170,6 +171,7 @@ if(data['today_article']){ update(data['today_article']); check_pre(data['visited_articles']); + toggleHighlighting(); } } }); -- 2.17.1 From 6500eeca8412ea4faed66b1761b06560ca84e9f4 Mon Sep 17 00:00:00 2001 From: fangchen <2027002340@qq.com> Date: Mon, 20 May 2024 19:03:33 +0800 Subject: [PATCH 2/9] test bug --- app/test/test_bug555_fangchen.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/test/test_bug555_fangchen.py diff --git a/app/test/test_bug555_fangchen.py b/app/test/test_bug555_fangchen.py new file mode 100644 index 0000000..e69de29 -- 2.17.1 From a42e63dc277b87b4ad2d240617b2d4068a3f6883 Mon Sep 17 00:00:00 2001 From: fangchen <2027002340@qq.com> Date: Mon, 20 May 2024 19:23:31 +0800 Subject: [PATCH 3/9] test bug555 --- .../conftest.cpython-312-pytest-8.2.1.pyc | Bin 0 -> 832 bytes ...g555_fangchen.cpython-312-pytest-8.2.1.pyc | Bin 0 -> 2603 bytes app/test/test_bug555_fangchen.py | 45 ++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc create mode 100644 app/test/__pycache__/test_bug555_fangchen.cpython-312-pytest-8.2.1.pyc diff --git a/app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc b/app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e9f8cacbfa3f7568903180c0243b5bd35e38e4a GIT binary patch literal 832 zcmZ`$L2DC16n?XtY&L0A0;Xawq39`>Z7PTmM5?t1QGyt9Sr)=3J4vVAO_rIBbwwd! z(X*%EPY{2K7r~1x6bpLsmXcdfzM1W&_24Y~=6i46d-LY|zLv`+!1by2WDpa8U((5z zb^#Xe5zN2?kN98{wQGUi*9ZhTJ5SOR!#40l^9zA#n<}RJ#h_%D2vFnTde-!E_j1SZ z<-)aB|C5uyl2eXJ-S{IbT6K~Xk7&>1>;>iMTzf|{s%pIYT4MGl%#YYeB&$1N++BJb-7r=!bOrJg zvGK^_^oS!dNpTrU3R$d##WKC?^2A7CVhZZh5t{_*;8x~ZOKGkCI0&$_m&)7iU(uIK zDU$*!5KTB$1glpm_0;t0#pmX|VC+qNdY|9G0!f9~K{MA0AwL0*;a&LzYA4V-C4~>Q ex3x2kkXs8Kw8~tfxe1z?#x=68;%6Enb;Dowe#DIc literal 0 HcmV?d00001 diff --git a/app/test/__pycache__/test_bug555_fangchen.cpython-312-pytest-8.2.1.pyc b/app/test/__pycache__/test_bug555_fangchen.cpython-312-pytest-8.2.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3958c610e92d3bd1a5bf6e23c85d963d754a90c2 GIT binary patch literal 2603 zcmbUjOKTfPcvjDmCE1P?%XS>wN*X6t+9-Cx4Y;Mm4+Tn!2~ADNqDEb5NA@baT6K2U zwu}vd=HNgfIW;+^P-sE|`3)_lE%ag|6`P4o1Eq)D0zS0l)R|e0*LjpcR@(XAkNIZi zoBcf=Zv*rhK6$=;JqW;Gj1Z5nh3wv=$ZenkRnmbhap*JrC7%S0fE<)uNk|THNmveZ z2xUm2PmdUFavRt2>ro>n$2cC)<3_vO&hen$VRXu!91rOSjD(!zcvwGZbje*tN=_Nw za<|bV_i#ScdyPZ#A&y5V-Y54_yzM%W57(tk^eIbwCL@u^A}Xp_TR@l+v5AtcnboOz zMXOqr_D$C57{7#y(_H0}qS=&@L`yYPvXNRSnN?L|CRQdu24|~6Frg!CU%<#hRXev- zLN%sCx@XMS3sN)YMW-~M(~4mEEd;#b4237)u$bB`q5`4p)y;`@u6!(}nBZ2L!m1h_A?CRhhcZa`)?IKw6Uj~a(CN{I& zHE-Ls@zbYA-#?Qbp}*1bv5}Dx5>~LSm2{;2M0fPl-)L6L{TC1}o7g~VTHzhVN}JVm zOD{_f=%%6;XtS^jE#6aha7ZWT*Dw<7<-=3DR=P^vFlFH&U36^QtY(+fLP|{*G}EzO z(P(%3R=T8{7E-gBBxe1A1aj&eA{~aZq#4>WDlBSM)m$X8GKB@?b|FkVJs`eMrZH;_ zRM}iW1=|#2(q3Yz6%=YQZ|W*(=L*Go!7P_8WRozajuZ=#aLp|S3D&SywMmd0V%A7V z(5c#*PJFp3(%p*7ViZw#A+m@^hMvlzh>dD{D*nTy;*@toaLyo>ywM zyp1fI57gb<*w|R1tW@Vp^QfAw)k%~|TLL^xy~~ZnnYHkCV&Kj~BXN8! zyahWp;ot@wyc=%9VNMALOv3Ox*4-&rcC+I~M-%o^troTo10LCgCpO@ThrZ3>$&KO3pC^CK z{g_)n|Hb;$mBw(P3BTli-)q8Cukkz8NKL=&mu4~2griSjaxHW-dL#NxoO>Af0}lTC z%nu?5UtvGD*lK^9OP&jXUqS=tj`=hFbnP8Yx9QDHVrOf0TK5*!Td399N@Nv_E-t%i zvluO6x~e3y$71`@<+V{`zHkaA0h?a1B;+zkz;QH{K#T6gs^%E(SxE>oyZ5Ewo`}P* z3bG~BFlhK<-90`1uTim_TFu0E*3sM}aOnSaaF`YWr|CdEtyTymzA7xtu3sEs1M4C< z%Jd=qGAXlJ@?(S9y~}s#eXvVWfKSljIsC{lRYyl3;}0px?qll%Iz01BlJqA4*TL7( q#~}U~M0dcz4tSUU&+LG+|M(=SYZuVrZ_u{`dUgXnQW}p_)BgbPk8R@s literal 0 HcmV?d00001 diff --git a/app/test/test_bug555_fangchen.py b/app/test/test_bug555_fangchen.py index e69de29..f7cee42 100644 --- a/app/test/test_bug555_fangchen.py +++ b/app/test/test_bug555_fangchen.py @@ -0,0 +1,45 @@ +import time +import pytest +import uuid +from selenium import webdriver +from selenium.webdriver import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.common.exceptions import UnexpectedAlertPresentException, NoAlertPresentException, NoSuchElementException, \ + TimeoutException +from conftest import driver +from conftest import URL + +def test_bug555(): + driver = webdriver.Edge() + try: + driver.maximize_window() + base_url = "http://127.0.0.1:5000" + driver.get(base_url) + article = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'article'))) + perform_actions_on_article(driver, article) + + next_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'load_next_article'))) + next_button.click() + print("Clicked next article button.") + + prev_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'load_pre_article'))) + prev_button.click() + print("Clicked previous article button.") + + except (TimeoutException, NoSuchElementException) as e: + print(f"An error occurred: {e}") + + finally: + driver.quit() + print("Driver closed.") + +def perform_actions_on_article(driver, article): + actions = ActionChains(driver) + actions.move_to_element(article) + actions.click_and_hold() + actions.move_by_offset(450, 200) + actions.release() + actions.perform() + print("Performed actions on article.") \ No newline at end of file -- 2.17.1 From 35a6f1c82886174f2ebfae3a290ccf8af3bac146 Mon Sep 17 00:00:00 2001 From: fangchen <2027002340@qq.com> Date: Mon, 20 May 2024 21:25:51 +0800 Subject: [PATCH 4/9] fix --- .../conftest.cpython-312-pytest-8.2.1.pyc | Bin 832 -> 836 bytes ...g555_fangchen.cpython-312-pytest-8.2.1.pyc | Bin 2603 -> 3028 bytes app/test/conftest.py | 2 +- app/test/test_bug555_fangchen.py | 4 +--- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc b/app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc index 7e9f8cacbfa3f7568903180c0243b5bd35e38e4a..21d8cb176631685df758554721eacd7a2a23d60a 100644 GIT binary patch delta 57 zcmX@Wc7%=hG%qg~0}veb^-eS0$a|cTjmjDZF1r#m| LC~X#I(q#ky#aItt delta 53 zcmX@Yc7TodG%qg~0}#xV^G>VW$a|cTg~c@`eex|vZ2=LWa09~=0mO18AMWg$ z#8FbEEmDJo)ZRd?SUI2NUh+~nO(0a*0q_TH*o7@KyWbP$3J`(F$UtCB$|{Z|%K(KFoQ$P$ z2`*FP7ThM~1)fk=_9$M#YuY$upHe5(nLH=^m4Fa1d8b^jGzbkQ?~?Z@jY5;jyXCz~ zv(T&rg`myO)r`n1!86smEK^>~bD zEq^2i4F33vIpMOT;=uu!wc^-;kDh-#V;Y7wTG&PDF z%noS;EB0aAo(L~UT1J1i&sx)%8iojID6A!u8HAuX8eR)n87G{SH64o4NC3O6G=&|D z&_ERQ*qKocNyhBtIBtPf?uZ#$ECFLl8e=>`vJgc#X5X8@ZE1*78d73$Gso#MO|@gh zPSYMc(@0VcxenaN8Itgvm`}uY7|S3T)l+vqb3v>rV;`MYtlVIrP6rIr@_1@| zbYV`1NM9J6ots^lfckkuOD`-+28=HxGK(o`bzxFnlqG#>Ixa87)9D2R>V{bnhl|6* z!?9FcT}&=PHJZ+1AJvu>XdfBIPd>emWU@{0fZgj1|K8NM#qaQeFTIz%U%gr6J9Zko zue)xrg~mgr#=(5!;H{q0(5d{;sh<r=@~^*ykMp@Ra$!U%1l1Zo28#UPqdMTJ|I&BKciC_H?Yhl(|MSQP{GG+F zH*&t=hk$WLsHUO!+Ss)txxj%Ee=yGU_mMUGY@&D43AUZ}lZPGK zdjpdP9NRt4$$qeXz)2;C9hC3iccOt@?Zn(J9AV6h=2ya80Y>=>0ib%FY|u1W>%w8G zsexEjt{mGn0M&#-^ffLWk*Quv3?Md@OXvkY=qY}tRL3yr(J_nYs796r5pGKQj?C-+ z4@9}vIc-6PfV~Wwu%_DZjYiyvt_ZGIvs z9nM$c+Vfod)ssbTzu9Wbb8SVgqrzW3a?N4szBv8q=_1!mG-Ymw^W?md+g#r+aSI~d z1oIh5Hpn{&*Bwh|3GB+PP%NFLK#az9f^GV)i6Xdy2&l2ABBFD&WM0zQ#BCg5&LGbj z?6L%y%VZ=G^Ez1!Rmv!cP8B!W&1mIaX039^^NMIvQxr0MB5P&2&Kf3qCY{!h5zRt;$0{`wgcfo?6kvXQoIqSz?~N15YkUc53bgi_rS5g oS%zue1*G~5wBGTAwn8OODDMdsJnfsVhio$w-i^AML*_{T0;y`b+yDRo delta 1229 zcmah}%}X0W6rbJfZYGIIG|^~``S2r}wQAc#TWCv5H3^E~U7@BiyD6LI!*14(mIOU` zh)_^js2(j8R22Fj6bhw1^pcR2gvEl_LJxu$@zj~bbxR9&VCVhbd%yY3o7uNpX+LbW zd^4Mk0FA)lWPFX@vUCvpTLarR4seE~Gv%6b5r8wUftjwYUmx`hCkl(aDDM$&+msG~ zZ6FbNF&+t0KGAg=^S}T|kOK({xm_NP$P;y!X|VpBB`A-OUE>^iNH)TGQZlQA95}p` z&g*izgjJ1eHb<%q0w6{U-YEs!$GadNrT$s!`2K-6~G>s7SMon+bC;esxBzE=jA_phf>zEmW(?(>c0P ztxFR!{w36hPvh0{CN2L8^fq4bHJl}|teXZ)1luH^QXK|G9~C7bmgHrlf$dRRl9?zM zN%PB6T>kqUfP*Bz?BVNKV3B|KJk1m(QG{qYI37nlvxy6KI%zQFSxde2XFz|i_n_#%t1 z`fbP_X22K56YkToZn?#HPWWV_Y4nDOzkLzk@BuhOGY|*RbO9fxGTcIve Date: Mon, 3 Jun 2024 00:02:19 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=20app/templates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/templates/login.html | 11 ++++---- app/templates/reset.html | 13 +++++---- app/templates/signup.html | 20 +++++++------ app/templates/test_bug536_QianLetao.py | 39 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 app/templates/test_bug536_QianLetao.py diff --git a/app/templates/login.html b/app/templates/login.html index b0806b6..b001cb0 100644 --- a/app/templates/login.html +++ b/app/templates/login.html @@ -11,12 +11,14 @@ function login(){ let username = $("#username").val(); let password = $("#password").val(); + let regex = /^[a-zA-Z0-9_]*$/; + if (username === "" || password === ""){ alert('输入不能为空!'); return false; } - if (password.includes(' ')) { - alert('输入不能包含空格!'); + if (!regex.test(username) || !regex.test(password)) { + alert('用户名和密码只能包含英文字母和数字!'); return false; } $.post( @@ -29,7 +31,7 @@ window.location.href = "/"+username+"/userpage"; } } - ) + ); return false; } @@ -46,5 +48,4 @@ {% endif %} -{% endblock %} - +{% endblock %} \ No newline at end of file diff --git a/app/templates/reset.html b/app/templates/reset.html index 408e001..741a7f9 100644 --- a/app/templates/reset.html +++ b/app/templates/reset.html @@ -8,14 +8,12 @@ let old_password = $("#old-password").val(); let new_password = $("#new-password").val(); let re_new_password = $("#re-new-password").val(); + let regex = /^[a-zA-Z0-9_]*$/; + if (old_password === "" || new_password === "" || re_new_password === ""){ alert('输入不能为空!'); return false; } - if (old_password.includes(' ') || new_password.includes(' ')) { - alert('输入不能包含空格!'); - return false; - } if (new_password !== re_new_password) { alert('新密码不匹配,请重新输入'); return false; @@ -24,6 +22,11 @@ alert('密码过于简单。(密码长度至少4位)'); return false; } + if (!regex.test(new_password)) { + alert('新密码只能包含英文字母和数字!'); + return false; + } + $.post("/reset", {'old-password': old_password, 'new-password': new_password}, function (response) { if (response.status === '1') { @@ -34,7 +37,7 @@ window.location.href = "/reset"; } } - ) + ); return false; } diff --git a/app/templates/signup.html b/app/templates/signup.html index 6b5db6e..660e924 100644 --- a/app/templates/signup.html +++ b/app/templates/signup.html @@ -12,14 +12,12 @@ You're logged in already! Logout. let username = $("#username").val(); let password = $("#password").val(); let password2 = $("#password2").val(); + let regex = /^[a-zA-Z0-9_]*$/; + if (username === "" || password === "" || password2 === ""){ alert('输入不能为空!'); return false; } - if (password.includes(' ') || password2.includes(' ')) { - alert('输入不能包含空格!'); - return false; - } if (password !== password2) { alert('确认密码与输入密码不一致!'); return false; @@ -28,6 +26,11 @@ You're logged in already! Logout. alert('密码过于简单。(密码长度至少4位)'); return false; } + if (!regex.test(username) || !regex.test(password)) { + alert('用户名和密码只能包含英文字母和数字!'); + return false; + } + $.post("/signup", {'username': username, 'password': password}, function (response) { if (response.status === '0') { @@ -47,7 +50,7 @@ You're logged in already! Logout. alert(response.warn); } } - ) + ); return false; } @@ -60,13 +63,12 @@ You're logged in already! Logout.

Sign up

-

+

- -{% endif %} -{% endblock %} +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/app/templates/test_bug536_QianLetao.py b/app/templates/test_bug536_QianLetao.py new file mode 100644 index 0000000..cce0fe6 --- /dev/null +++ b/app/templates/test_bug536_QianLetao.py @@ -0,0 +1,39 @@ +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities +from selenium.webdriver.common.keys import Keys + +import time + +# 初始化WebDriver +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + + +# 测试注册页面输入密码包含空格的情况 +def test_signup_password_with_space(): + try: + driver.get("http://127.0.0.1:5000/signup") + + # 输入用户名 + username_elem = driver.find_element_by_name('username') + username_elem.send_keys("阿萨德") + + # 输入包含空格的密码 + password_elem = driver.find_element_by_name('password') + password_elem.send_keys("阿萨德阿萨德") + + # 再次输入密码 + password2_elem = driver.find_element_by_name('password2') + password2_elem.send_keys("阿萨德阿萨德") + + # 提交注册表单 + password2_elem.send_keys(Keys.RETURN) + + # 等待一段时间确保页面加载完成 + time.sleep(2) + + # 检查是否弹出警告框 + alert = driver.switch_to.alert + assert "用户名和密码只能包含英文字母和数字!" in alert.text + finally: + driver.quit() -- 2.17.1 From 35751c2c5f27c527c86b10a18ec0fe69002d81d2 Mon Sep 17 00:00:00 2001 From: fangchen <2027002340@qq.com> Date: Tue, 4 Jun 2024 11:48:22 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=8F=8F=E8=BF=B0=E4=BD=A0=E7=9A=84?= =?UTF-8?q?=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnglishPal | 1 + .../conftest.cpython-312-pytest-8.2.1.pyc | Bin 836 -> 0 bytes ...bug555_fangchen.cpython-312-pytest-8.2.1.pyc | Bin 3028 -> 0 bytes mintty.2024-06-04_11-12-32.png | Bin 0 -> 20329 bytes 4 files changed, 1 insertion(+) create mode 160000 EnglishPal delete mode 100644 app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc delete mode 100644 app/test/__pycache__/test_bug555_fangchen.cpython-312-pytest-8.2.1.pyc create mode 100644 mintty.2024-06-04_11-12-32.png diff --git a/EnglishPal b/EnglishPal new file mode 160000 index 0000000..8cbc7c9 --- /dev/null +++ b/EnglishPal @@ -0,0 +1 @@ +Subproject commit 8cbc7c9a0ce543db48f80a743c4168ca847ca500 diff --git a/app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc b/app/test/__pycache__/conftest.cpython-312-pytest-8.2.1.pyc deleted file mode 100644 index 21d8cb176631685df758554721eacd7a2a23d60a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 836 zcmZ`$L2DC16n?WwHk-7OfUVd|2=$c9HZ2q(h*YBoQG*zASr)=3J4vVRW|x_bHKGu) z=ugOR5Pyd!FNz0cp;*w1x0Kv^^37~Ftp{h>dEa~U-kUey_qkLm01zc1td%3liEin5qIr4WunZN;cm=;`6$w!N;9A=B!n)Zb z_;~JGtN+Q#UCJp@9hI-%2J9*Y-7)7b(txP&h9oFc1KVy>^tpF+s132ML}o} zSwtPXHy#ey3;X_P=rOVX#PMt=4DE=D$nFQDfdpnai8Gz2k9YyQshnzr+*o8lE6*jG8=x6UTqEl$eySl-H~aO18AMWg$ z#8FbEEmDJo)ZRd?SUI2NUh+~nO(0a*0q_TH*o7@KyWbP$3J`(F$UtCB$|{Z|%K(KFoQ$P$ z2`*FP7ThM~1)fk=_9$M#YuY$upHe5(nLH=^m4Fa1d8b^jGzbkQ?~?Z@jY5;jyXCz~ zv(T&rg`myO)r`n1!86smEK^>~bD zEq^2i4F33vIpMOT;=uu!wc^-;kDh-#V;Y7wTG&PDF z%noS;EB0aAo(L~UT1J1i&sx)%8iojID6A!u8HAuX8eR)n87G{SH64o4NC3O6G=&|D z&_ERQ*qKocNyhBtIBtPf?uZ#$ECFLl8e=>`vJgc#X5X8@ZE1*78d73$Gso#MO|@gh zPSYMc(@0VcxenaN8Itgvm`}uY7|S3T)l+vqb3v>rV;`MYtlVIrP6rIr@_1@| zbYV`1NM9J6ots^lfckkuOD`-+28=HxGK(o`bzxFnlqG#>Ixa87)9D2R>V{bnhl|6* z!?9FcT}&=PHJZ+1AJvu>XdfBIPd>emWU@{0fZgj1|K8NM#qaQeFTIz%U%gr6J9Zko zue)xrg~mgr#=(5!;H{q0(5d{;sh<r=@~^*ykMp@Ra$!U%1l1Zo28#UPqdMTJ|I&BKciC_H?Yhl(|MSQP{GG+F zH*&t=hk$WLsHUO!+Ss)txxj%Ee=yGU_mMUGY@&D43AUZ}lZPGK zdjpdP9NRt4$$qeXz)2;C9hC3iccOt@?Zn(J9AV6h=2ya80Y>=>0ib%FY|u1W>%w8G zsexEjt{mGn0M&#-^ffLWk*Quv3?Md@OXvkY=qY}tRL3yr(J_nYs796r5pGKQj?C-+ z4@9}vIc-6PfV~Wwu%_DZjYiyvt_ZGIvs z9nM$c+Vfod)ssbTzu9Wbb8SVgqrzW3a?N4szBv8q=_1!mG-Ymw^W?md+g#r+aSI~d z1oIh5Hpn{&*Bwh|3GB+PP%NFLK#az9f^GV)i6Xdy2&l2ABBFD&WM0zQ#BCg5&LGbj z?6L%y%VZ=G^Ez1!Rmv!cP8B!W&1mIaX039^^NMIvQxr0MB5P&2&Kf3qCY{!h5zRt;$0{`wgcfo?6kvXQoIqSz?~N15YkUc53bgi_rS5g oS%zue1*G~5wBGTAwn8OODDMdsJnfsVhio$w-i^AML*_{T0;y`b+yDRo diff --git a/mintty.2024-06-04_11-12-32.png b/mintty.2024-06-04_11-12-32.png new file mode 100644 index 0000000000000000000000000000000000000000..72ccafeddcde90a32a8f06c07f626d4a0c0ecca2 GIT binary patch literal 20329 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 Date: Tue, 4 Jun 2024 16:00:10 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=20app/templates/test=5Fb?= =?UTF-8?q?ug536=5FQianLetao.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/templates/test_bug536_QianLetao.py | 39 -------------------------- 1 file changed, 39 deletions(-) delete mode 100644 app/templates/test_bug536_QianLetao.py diff --git a/app/templates/test_bug536_QianLetao.py b/app/templates/test_bug536_QianLetao.py deleted file mode 100644 index cce0fe6..0000000 --- a/app/templates/test_bug536_QianLetao.py +++ /dev/null @@ -1,39 +0,0 @@ -from selenium import webdriver -from selenium.webdriver.common.desired_capabilities import DesiredCapabilities -from selenium.webdriver.common.keys import Keys - -import time - -# 初始化WebDriver -driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) -driver.implicitly_wait(10) - - -# 测试注册页面输入密码包含空格的情况 -def test_signup_password_with_space(): - try: - driver.get("http://127.0.0.1:5000/signup") - - # 输入用户名 - username_elem = driver.find_element_by_name('username') - username_elem.send_keys("阿萨德") - - # 输入包含空格的密码 - password_elem = driver.find_element_by_name('password') - password_elem.send_keys("阿萨德阿萨德") - - # 再次输入密码 - password2_elem = driver.find_element_by_name('password2') - password2_elem.send_keys("阿萨德阿萨德") - - # 提交注册表单 - password2_elem.send_keys(Keys.RETURN) - - # 等待一段时间确保页面加载完成 - time.sleep(2) - - # 检查是否弹出警告框 - alert = driver.switch_to.alert - assert "用户名和密码只能包含英文字母和数字!" in alert.text - finally: - driver.quit() -- 2.17.1 From 97ddee0ccff466569a23cde628f2a2826a7aaf35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=B1=E4=B9=90=E6=B6=9B?= <1215891603@qq.com> Date: Tue, 4 Jun 2024 16:01:51 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前的pytest文件上传位置错误,现在更改上传到test文件夹中 --- app/test/test_bug536_QianLetao.py | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 app/test/test_bug536_QianLetao.py diff --git a/app/test/test_bug536_QianLetao.py b/app/test/test_bug536_QianLetao.py new file mode 100644 index 0000000..cce0fe6 --- /dev/null +++ b/app/test/test_bug536_QianLetao.py @@ -0,0 +1,39 @@ +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities +from selenium.webdriver.common.keys import Keys + +import time + +# 初始化WebDriver +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + + +# 测试注册页面输入密码包含空格的情况 +def test_signup_password_with_space(): + try: + driver.get("http://127.0.0.1:5000/signup") + + # 输入用户名 + username_elem = driver.find_element_by_name('username') + username_elem.send_keys("阿萨德") + + # 输入包含空格的密码 + password_elem = driver.find_element_by_name('password') + password_elem.send_keys("阿萨德阿萨德") + + # 再次输入密码 + password2_elem = driver.find_element_by_name('password2') + password2_elem.send_keys("阿萨德阿萨德") + + # 提交注册表单 + password2_elem.send_keys(Keys.RETURN) + + # 等待一段时间确保页面加载完成 + time.sleep(2) + + # 检查是否弹出警告框 + alert = driver.switch_to.alert + assert "用户名和密码只能包含英文字母和数字!" in alert.text + finally: + driver.quit() -- 2.17.1 From 7b29f8d652eda6d3e27e3c386b223ae087856733 Mon Sep 17 00:00:00 2001 From: mponeja Date: Mon, 10 Jun 2024 18:20:37 +0800 Subject: [PATCH 9/9] Test case scripts --- app/pickle_idea.py | 17 +++-- app/test/helper.py | 55 +++++++++----- app/test/test_bug518_mponeja.py | 121 +++++++++++++++++++++++++++++++ app/test/test_bug555_fangchen.py | 43 ----------- 4 files changed, 168 insertions(+), 68 deletions(-) create mode 100644 app/test/test_bug518_mponeja.py delete mode 100644 app/test/test_bug555_fangchen.py diff --git a/app/pickle_idea.py b/app/pickle_idea.py index 45bd19a..c172c32 100644 --- a/app/pickle_idea.py +++ b/app/pickle_idea.py @@ -54,12 +54,19 @@ def save_frequency_to_pickle(d, pickle_fname): pickle.dump(d2, f) f.close() -def unfamiliar(path,word): - f = open(path,"rb") +def unfamiliar(path, word): + f = open(path, "rb") dic = pickle.load(f) - dic[word] += [datetime.now().strftime('%Y%m%d%H%M')] - fp = open(path,"wb") - pickle.dump(dic,fp) + if word in dic: + if len(dic[word]) <= 16: # Check if the length of the list is less than 16 + dic[word].append(datetime.now().strftime('%Y%m%d%H%M')) + else: + dic[word].append(datetime.now().strftime('%Y%m%d%H%M')) + else: + dic[word] = [datetime.now().strftime('%Y%m%d%H%M')] + f.close() + with open(path, "wb") as fp: + pickle.dump(dic, fp) def familiar(path,word): f = open(path,"rb") diff --git a/app/test/helper.py b/app/test/helper.py index 2b0deec..a6991d0 100644 --- a/app/test/helper.py +++ b/app/test/helper.py @@ -2,32 +2,47 @@ import uuid from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import UnexpectedAlertPresentException, NoAlertPresentException +from selenium.webdriver.common.by import By def signup(URL, driver): username = 'TestUser' + str(uuid.uuid1()).split('-')[0].title() password = '[Abc+123]' driver.get(URL) - - elem = driver.find_element_by_link_text('注册') - elem.click() - elem = driver.find_element_by_id('username') - elem.send_keys(username) - - elem = driver.find_element_by_id('password') - elem.send_keys(password) - - elem = driver.find_element_by_id('password2') - elem.send_keys(password) - - elem = driver.find_element_by_class_name('btn') # 找到"注册"按钮 - elem.click() - try: - WebDriverWait(driver, 1).until(EC.alert_is_present()) - driver.switch_to.alert.accept() - except (UnexpectedAlertPresentException, NoAlertPresentException): - pass + # Click the register link + register_link = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.LINK_TEXT, '注册')) + ) + register_link.click() + + # Fill the registration form + username_field = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, 'username')) + ) + username_field.send_keys(username) + + password_field = driver.find_element(By.ID, 'password') + password_field.send_keys(password) + + confirm_password_field = driver.find_element(By.ID, 'password2') + confirm_password_field.send_keys(password) + + # Click the register button + register_button = driver.find_element(By.CLASS_NAME, 'btn') + register_button.click() + + # Handle possible alert + try: + WebDriverWait(driver, 1).until(EC.alert_is_present()) + alert = driver.switch_to.alert + alert.accept() + except (UnexpectedAlertPresentException, NoAlertPresentException): + pass + + return username, password - return username, password + except Exception as e: + print(f"An error occurred: {e}") + return None, None \ No newline at end of file diff --git a/app/test/test_bug518_mponeja.py b/app/test/test_bug518_mponeja.py new file mode 100644 index 0000000..27bc19b --- /dev/null +++ b/app/test/test_bug518_mponeja.py @@ -0,0 +1,121 @@ +import random +import string +import time + +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +from helper import signup + +def has_punctuation(s): + return any(c in string.punctuation for c in s) + +def login(driver, home, uname, password): + driver.get(home) + WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, '登录'))).click() + driver.find_element(By.ID, 'username').send_keys(uname) + driver.find_element(By.ID, 'password').send_keys(password) + driver.find_element(By.XPATH, '//button[text()="登录"]').click() + WebDriverWait(driver, 10).until(EC.title_is(f"EnglishPal Study Room for {uname}")) + + +def select_valid_word(driver): + elem = driver.find_element(By.ID, 'text-content') + essay_content = elem.text + valid_word = random.choice([word for word in essay_content.split() if len(word) >= 6 and not has_punctuation( + word) and 'font>' not in word and 'br>' not in word and 'p>' not in word]) + driver.find_element(By.ID, 'selected-words').send_keys(valid_word) + return valid_word + + +def select_more_words(driver): + elem = driver.find_element(By.ID, 'text-content') + essay_content = elem.text + valid_words = [word for word in essay_content.split() if len(word) >= 6 and not has_punctuation( + word) and 'font>' not in word and 'br>' not in word and 'p>' not in word] + words_to_send = ', '.join(valid_words[:7]) + driver.find_element(By.ID, 'selected-words').send_keys(words_to_send) + + +def test_unfamiliar_button(driver, URL): + try: + username, password = signup(URL, driver) + time.sleep(5) + + word = select_valid_word(driver) + + # Wait for the button to be clickable + time.sleep(8) + # Add selected word to the list of unfamiliar words + add_to_unfamiliar_button = driver.find_element(By.XPATH, '//button[text()="把生词加入我的生词库"]') + add_to_unfamiliar_button.click() + # Wait for the page to update + time.sleep(3) + + add_words_button = driver.find_element(By.XPATH, '//button[text()="加入我的生词簿"]') # Replace with actual ID or selector + add_words_button.click() + # Wait for the page to update again + time.sleep(2) + + # Check if the added word appears in the word container + word_container = driver.find_element(By.CLASS_NAME, 'word-container') + words = word_container.find_elements(By.TAG_NAME, 'p') + added_word_exists = any(word.text == word for word in words) + time.sleep(2) + + # Mark word as unfamiliar + time.sleep(5) + for _ in range(16): + time.sleep(1) + unfamiliar_btn = driver.find_element(By.XPATH, '//a[contains(@class, "btn-warning") and text()="不熟悉"]') + unfamiliar_btn.click() + # Wait for the page to updatec + time.sleep(5) + + # # Keep track of the unfamiliar word count + # counter = 0 + # freq_count = driver.find_element(By.ID, 'freq_'+ word).text + # # counter = freq_count + # print(f"Unfamiliar word count: {freq_count}") + # time.sleep(3) + + #add new words + word = select_more_words(driver) + add_to_unfamiliar_button = driver.find_element(By.XPATH, '//button[text()="把生词加入我的生词库"]') + add_to_unfamiliar_button.click() + + time.sleep(5) + + #add the words to the list of words + add_words_again = driver.find_element(By.XPATH, '//button[text()="加入我的生词簿"]') # Replace with actual ID or selector + add_words_again.click() + # Wait for the page to update again + time.sleep(3) + + + #current count after adding new words + current_unfamiliar_count = driver.find_element(By.XPATH, '//a[contains(@class, "btn-warning") and text()="不熟悉"]') + current_unfamiliar_count = int(unfamiliar_btn.text.split('(')[1].split(')')[0]) + print(f"Unfamiliar word count: {current_unfamiliar_count}") + time.sleep(3) + + + # Verify that the number of unfamiliar words has decreased + # current_unfamiliar_count = driver.find_element(By.ID, 'freq_'+word).text + # print(f"Unfamiliar word second count: {current_unfamiliar_count}") + # time.sleep(3) + + # # Verify that the number of unfamiliar words remains the same + # assert current_unfamiliar_count == freq_count, "Unfamiliar word count did not increase as expected" + # time.sleep(3) + + # Log out and close the browser + driver.find_element(By.XPATH, '//a[contains(@class, "btn-secondary") and text()="退出"]') + driver.execute_script("window.open('');window.close();") + WebDriverWait(driver, 2) + driver.execute_script("window.open('');") + driver.switch_to.window(driver.window_handles[-1]) + + finally: + driver.quit() \ No newline at end of file diff --git a/app/test/test_bug555_fangchen.py b/app/test/test_bug555_fangchen.py deleted file mode 100644 index d1edfb5..0000000 --- a/app/test/test_bug555_fangchen.py +++ /dev/null @@ -1,43 +0,0 @@ -import time -import pytest -import uuid -from selenium import webdriver -from selenium.webdriver import ActionChains -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.common.exceptions import UnexpectedAlertPresentException, NoAlertPresentException, NoSuchElementException, \ - TimeoutException -from conftest import URL -driver = webdriver.Chrome() -def test_bug555(): - try: - driver.maximize_window() - base_url = "http://127.0.0.1:5000" - driver.get(base_url) - article = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'article'))) - perform_actions_on_article(driver, article) - - next_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'load_next_article'))) - next_button.click() - print("Clicked next article button.") - - prev_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'load_pre_article'))) - prev_button.click() - print("Clicked previous article button.") - - except (TimeoutException, NoSuchElementException) as e: - print(f"An error occurred: {e}") - - finally: - driver.quit() - print("Driver closed.") - -def perform_actions_on_article(driver, article): - actions = ActionChains(driver) - actions.move_to_element(article) - actions.click_and_hold() - actions.move_by_offset(450, 200) - actions.release() - actions.perform() - print("Performed actions on article.") \ No newline at end of file -- 2.17.1