147 lines
9.0 KiB
Python
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.')
|