Compare commits

..

1 Commits

Author SHA1 Message Date
邓博 513fe125bf FIX Bug 347 2025-06-18 12:24:29 +08:00
10 changed files with 148 additions and 9 deletions

View File

@ -18,7 +18,7 @@ picked from articles selected for him to read according his vocabulary level. E
`python3 main.py`
Make sure you have put the SQLite database file in the path `app/db` (see below).
Make sure you have put the SQLite database file in the path `app/static` (see below).
## Run it as a Docker container
@ -214,5 +214,5 @@ Bug report: http://118.25.96.118/bugzilla/show_bug.cgi?id=215
Bug report: http://118.25.96.118/bugzilla/show_bug.cgi?id=489
*Last modified on 2026-03-12*
*Last modified on 2023-01-30*

View File

@ -106,7 +106,7 @@ def get_today_article(user_word_list, visited_articles):
text_level = text_difficulty_level(d['text'], d3)
result_of_generate_article = "found"
today_article = {}
today_article = None
if d:
oxford_words = load_oxford_words(oxford_words_path)
oxford_word_count, total_words = count_oxford_words(d['text'],oxford_words)

View File

@ -79,6 +79,8 @@ class UserName:
def validate(self):
if len(self.username) > 20:
return f'{self.username} is too long. The user name cannot exceed 20 characters.'
if len(self.username) == 0: # 用户名必须不为空
return 'You can`t use an empty user name.'
if self.username.startswith('.'): # a user name must not start with a dot
return 'Period (.) is not allowed as the first letter in the user name.'
if ' ' in self.username: # a user name must not include a whitespace

View File

@ -144,8 +144,8 @@ if __name__ == '__main__':
运行程序
'''
# app.secret_key = os.urandom(16)
app.run(debug=True, port=5000)
# app.run(debug=True)
# app.run(debug=False, port='6000')
app.run(debug=True)
# app.run(debug=True, port='6000')
# app.run(host='0.0.0.0', debug=True, port='6000')
# print(mod5('123'))

View File

@ -31,7 +31,7 @@
<p><a href="/login">登录</a> <a href="/signup">注册</a> <a href="/static/usr/instructions.html">使用说明</a></p >
<p><b> {{ random_ads }}。 <a href="/signup">试试</a>吧!</b></p>
{% endif %}
<div class="alert alert-success" role="alert">共有文章 <span class="badge bg-success"> {{ number_of_essays }} </span> 篇,Oxford 5000 单词占比 <span class="badge bg-success"> {{ (ratio * 100) | int }}% </span> </div>
<div class="alert alert-success" role="alert">共有文章 <span class="badge bg-success"> {{ number_of_essays }} </span> 篇,覆盖 <span class="badge bg-success"> {{ (ratio * 100) | int }}% </span> 的 Oxford5000 单词</div>
<p>粘贴1篇文章 (English only)</p>
<form method="post" action="/">
<textarea name="content" id="article" rows="10" cols="120"></textarea><br/>

View File

@ -29,8 +29,8 @@
password2 = $("#password2").val().trim();
// 基本表单验证
if (username === "" || password === "" || password2 === "") {
alert('输入不能为空!');
if (password === "" || password2 === "") {
alert('输入密码不能为空!');
return false;
}
if (password.includes(' ') || password2.includes(' ')) {

View File

@ -87,7 +87,7 @@
<div id="text-content">
<div id="found">
<div class="alert alert-success" role="alert">According to your word list, your level is <span class="text-decoration-underline" id="user_level">{{ today_article["user_level"] }}</span> and we have chosen an article with a difficulty level of <span class="text-decoration-underline" id="text_level">{{ today_article["text_level"] }}</span> for you. <span class="text-decoration-underline" id="ratio">{{ (today_article["ratio"] * 100) | int }}%</span> of the words in this article are in Oxford Word 5000.</div>
<div class="alert alert-success" role="alert">According to your word list, your level is <span class="text-decoration-underline" id="user_level">{{ today_article["user_level"] }}</span> and we have chosen an article with a difficulty level of <span class="text-decoration-underline" id="text_level">{{ today_article["text_level"] }}</span> for you. The Oxford word coverage is <span class="text-decoration-underline" id="ratio">{{ (today_article["ratio"] * 100) | int }}%.</span></div>
<p class="text-muted" id="date">Article added on: {{ today_article["date"] }}</p><br/>
<button onclick="saveArticle()" >标记文章</button>

View File

@ -0,0 +1,74 @@
# test_integration_username.py
import pytest
import sys
import os
# 获取文件所在目录的上两级目录EnglishPal
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
sys.path.append(project_root)
from app.Login import add_user, check_username_availability
# 模拟数据库行为
class MockUserDB:
def __init__(self):
self.users = {}
def insert_user(self, username, password, start_date, expiry_date):
if username in self.users:
return False
self.users[username] = {
'password': password,
'start_date': start_date,
'expiry_date': expiry_date
}
return True
def get_user_by_username(self, username):
return self.users.get(username)
original_insert_user = None
original_get_user_by_username = None
@pytest.fixture(autouse=True)
def setup_and_teardown():
global original_insert_user, original_get_user_by_username
from app.Login import insert_user as original_iu, get_user_by_username as original_gubu
original_insert_user = original_iu
original_get_user_by_username = original_gubu
mock_db = MockUserDB()
def mock_insert_user(**kwargs):
return mock_db.insert_user(**kwargs)
def mock_get_user_by_username(username):
return mock_db.get_user_by_username(username)
from app.Login import insert_user, get_user_by_username
insert_user = mock_insert_user
get_user_by_username = mock_get_user_by_username
yield
from app.Login import insert_user, get_user_by_username
insert_user = original_insert_user
get_user_by_username = original_get_user_by_username
def test_add_user_with_empty_username_fails():
with pytest.raises(ValueError) as exc_info:
add_user('', 'Password123')
assert "Attribute User.name is required" in str(exc_info.value)
def test_add_user_with_valid_username_succeeds():
result = add_user('validuser', 'Password123')
assert result is None # 如果 add_user 不返回值,则断言无异常即可
assert check_username_availability('validuser') is False # 用户已存在

63
app/test_login.py Normal file
View File

@ -0,0 +1,63 @@
# test_username.py
import pytest
from app.Login import UserName
def test_username_too_long():
username = 'a' * 21
result = UserName(username).validate()
assert username in result
assert 'too long' in result
def test_username_empty():
username = ''
result = UserName(username).validate()
assert 'empty user name' in result
def test_username_starts_with_dot():
username = '.startwithdot'
result = UserName(username).validate()
assert 'Period (.) is not allowed' in result
def test_username_contains_space():
username = 'has space'
result = UserName(username).validate()
assert 'Whitespace is not allowed' in result
def test_username_contains_invalid_punctuation():
invalid_chars = ['@', '#', '$', '!', '{', '}', '[', ']']
for c in invalid_chars:
username = f'bad{c}name'
result = UserName(username).validate()
assert f'{c} is not allowed' in result, f"Failed on char: {c}"
def test_username_uses_restricted_word():
restricted_words = ['signup', 'login', 'logout', 'reset', 'mark', 'back',
'unfamiliar', 'familiar', 'del', 'admin']
for word in restricted_words:
result = UserName(word).validate()
assert 'restricted word' in result, f"Failed on word: {word}"
def test_username_contains_chinese():
username = '用户名'
result = UserName(username).validate()
assert 'Chinese characters are not allowed' in result
def test_valid_username():
valid_usernames = [
'valid_user',
'valid.user',
'user123',
'A_veryValidName',
]
for username in valid_usernames:
result = UserName(username).validate()
assert result == 'OK', f"Failed on valid username: {username}"

Binary file not shown.