Files
kefu/deploy/knowledge-v2-tests-edit.py
T
2026-09-21 10:34:06 +08:00

147 lines
9.0 KiB
Python

from pathlib import Path
p=Path(r'C:\kefu\wechat_rpa\test_knowledge.py')
s=p.read_text(encoding='utf-8')
s=s.replace(''' def test_sample_limit_does_not_publish_half_answer(self):
self.archive.import_messages(self.payload(), self.actor, '')''',''' def test_sample_limit_does_not_publish_half_answer(self):
payload = self.payload(messages=[('inbound', '预约挂号需要什么材料?'),
('outbound', '请先确认就诊日期。'), ('outbound', '还需要确认就诊科室。')])
self.archive.import_messages(payload, self.actor, '')''')
s=s.replace(" item['valid_until'] = '2000-01-01'\n self.publish(item)\n self.assertFalse(KnowledgeRetriever(self.store).search('default', '预约挂号')['hits'])", """ item['valid_until'] = '2099-01-01'
self.publish(item)
with mock.patch.object(KnowledgeRetriever, '_today', return_value='2099-01-02'):
self.assertFalse(KnowledgeRetriever(self.store).search('default', '预约挂号')['hits'])""")
pos=s.index('\n\nclass KnowledgeApiTest')
s=s[:pos]+'''
def test_preview_is_read_only_scoped_and_counts_only_direct_conversations(self):
self.archive.import_messages(self.payload(), self.actor, '')
self.archive.import_messages(self.payload('tenant_b'), self.actor, '')
group = self.payload(conversation='R:group')
for row in group['messages']:
row['source_message_id'] = 'group-' + row['source_message_id']
row['conversation']['conversation_type'] = 'group'
self.archive.import_messages(group, self.actor, '')
with self.db.connect() as db:
source = db.execute("SELECT id FROM archive_source_account WHERE tenant_id='default'").fetchone()[0]
options = {'source_account_id': source, 'max_messages': 1}
preview = self.store.preview_job('default', options)
self.assertEqual((preview['available_messages'], preview['total_messages'], preview['conversations']), (2, 1, 1))
self.assertEqual(preview['eligible_text_messages'], 2)
self.assertTrue(preview['limited'])
self.assertEqual(self.store.jobs('default'), [])
with self.assertRaises(ValueError):
self.store.preview_job('tenant_b', options)
with self.assertRaises(ValueError):
self.store.preview_job('default', {**options, 'date_from': '2026-09-16', 'date_to': '2026-09-15'})
empty = self.store.preview_job('default', {**options, 'date_from': '2099-01-01'})
self.assertEqual(empty['total_messages'], 0)
def test_exact_limit_preserves_complete_final_answer_and_progress(self):
self.archive.import_messages(self.payload(), self.actor, '')
job = self.start_job(max_messages=2)
self.assertEqual((job['total_messages'], job['progress_percent']), (2, 0))
KnowledgeWorker(self.store).step()
finished = self.store.job('default', job['id'])
self.assertEqual((finished['processed'], finished['progress_percent'], finished['completion_reason']),
(2, 100, 'source_exhausted'))
self.assertEqual(finished['created_items'], 1)
def test_real_progress_and_limit_reason(self):
rows = [('unknown', '系统消息')] * 401
self.archive.import_messages(self.payload(messages=rows), self.actor, '')
job = self.start_job(max_messages=201)
worker = KnowledgeWorker(self.store)
worker.step()
partial = self.store.job('default', job['id'])
self.assertEqual((partial['processed'], partial['total_messages'], partial['progress_percent']), (200, 201, 99))
worker.step()
final = self.store.job('default', job['id'])
self.assertEqual((final['processed'], final['completion_reason']), (201, 'message_limit'))
def test_cancel_fences_an_inflight_batch_and_allows_replacement(self):
self.archive.import_messages(self.payload(), self.actor, '')
job = self.start_job()
with self.assertRaisesRegex(ValueError, '已有未完成任务'):
self.start_job()
worker = KnowledgeWorker(self.store)
original = worker.rows
def cancel_after_read(row, size):
rows = original(row, size)
self.store.job_action('default', job['id'], 'cancel', self.actor, '')
return rows
with mock.patch.object(worker, 'rows', side_effect=cancel_after_read):
worker.step()
self.assertEqual(self.store.job('default', job['id'])['status'], 'cancelled')
self.assertEqual(self.store.list_items('default')['total'], 0)
with self.assertRaises(ValueError):
self.store.job_action('default', job['id'], 'resume', self.actor, '')
replacement = self.start_job()
worker.step()
self.assertEqual(self.store.job('default', replacement['id'])['created_items'], 1)
def test_enabling_requires_current_unexpired_publication(self):
with self.assertRaises(ValueError):
self.store.set_enabled('default', True, self.actor, '')
self.process()
item = self.publish()
self.store.set_enabled('default', True, self.actor, '')
self.store.transition('default', item['id'], item['revision'], 'disable', self.actor, '')
self.store.set_enabled('default', False, self.actor, '')
with self.assertRaises(ValueError):
self.store.set_enabled('default', True, self.actor, '')
def test_review_and_publication_validate_expiry_and_state(self):
self.process()
item = self.first()
with self.assertRaises(ValueError):
self.store.transition('default', item['id'], item['revision'], 'disable', self.actor, '')
item['conditions'], item['valid_until'] = '通用预约流程', '2000-01-01'
item = self.store.save('default', item['id'], item, self.actor, '')
with self.assertRaisesRegex(ValueError, '有效期'):
self.store.transition('default', item['id'], item['revision'], 'approve', self.actor, '', True)
item['valid_until'] = '2099-01-01'
item = self.store.save('default', item['id'], item, self.actor, '')
self.store.transition('default', item['id'], item['revision'], 'approve', self.actor, '', True)
with mock.patch.object(KnowledgeRetriever, '_today', return_value='2099-01-02'):
with self.assertRaisesRegex(ValueError, '有效期'):
self.store.publish('default', item['id'], item['revision'], self.actor, '')
def test_preview_eligible_text_matches_worker_identity_checks(self):
payload = self.payload(messages=[('inbound', '预约挂号需要什么材料?'), ('outbound', '请先确认日期。'), ('unknown', '无法确认角色')])
payload['messages'][1]['sender']['external_id'] = 'other-person'
self.archive.import_messages(payload, self.actor, '')
with self.db.connect() as db:
source = db.execute('SELECT id FROM archive_source_account').fetchone()[0]
preview = self.store.preview_job('default', {'source_account_id': source})
self.assertEqual((preview['available_messages'], preview['eligible_text_messages']), (3, 1))
''' + s[pos:]
pos=s.index('\n\nclass KnowledgeGatewayTest')
s=s[:pos]+'''
def test_preview_auth_scope_and_enable_empty_library(self):
actor = self.db.authenticate('admin', 'ChangedAdmin@2026')['id']
ArchiveStore(self.db).import_messages(KnowledgeTest.payload(self), actor, '')
with self.db.connect() as db:
source = db.execute('SELECT id FROM archive_source_account').fetchone()[0]
body = {'source_account_id': source}
url = '/api/v2/knowledge/jobs/preview'
self.assertEqual(self.client.post(url, json=body).status_code, 401)
self.assertEqual(self.client.post(url + '?account_id=-1', json=body, headers=self.headers).status_code, 400)
response = self.client.post(url, json=body, headers=self.headers)
self.assertEqual(response.status_code, 200, response.text)
self.assertEqual(response.json()['total_messages'], 2)
enabled = self.client.put('/api/v2/knowledge/settings', json={'enabled': True}, headers=self.headers)
self.assertEqual(enabled.status_code, 400)
self.db.create_user('reviewer', 'InitialReader123', 'viewer', actor, '')
reader = self.db.authenticate('reviewer', 'InitialReader123')['id']
self.db.change_password(reader, 'InitialReader123', 'ChangedReader@2026', '')
with self.db.connect() as db:
db.execute("INSERT OR IGNORE INTO role_permissions VALUES ('viewer','knowledge:write')")
db.execute("DELETE FROM role_permissions WHERE role_code='viewer' AND permission_code='im:content:read'")
login = self.client.post('/api/v2/auth/login', json={'username': 'reviewer', 'password': 'ChangedReader@2026'})
headers = {'Authorization': 'Bearer ' + login.json()['access_token']}
self.assertEqual(self.client.post(url, json=body, headers=headers).status_code, 403)
''' + s[pos:]
p.write_text(s,encoding='utf-8',newline='\n')
print('Added workflow regression tests.')