Release v0.1.29: media previews, clean composer, regional profiles and cloud retention

This commit is contained in:
Codex
2026-10-04 20:03:44 +08:00
parent 67709832c5
commit 693dd2a10a
17 changed files with 359 additions and 46 deletions
+43
View File
@@ -190,3 +190,46 @@ class JournalTests(unittest.TestCase):
self.assertEqual(self.request('/api/households',self.root,data)[0],200)
self.assertEqual(self.request('/api/households',self.root,data)[0],409)
self.assertEqual(app.get_object('households',self.aid)['name'],'第一次修改')
def test_attachment_trash_restore_and_existing_reference_remain_visible(self):
m=dict(id=secrets.token_hex(8),familyId=self.aid,ownerId=self.actor['id'],status='ready',size=8,name='x.png',mime='image/png',at='now')
app.save_object('journal_media',m)
key=app.JOURNAL.save(self.actor,dict(self.note(),visibility='household',mediaIds=[m['id']]))['id']
self.assertEqual(self.request('/api/journal/remove-upload',self.actor,{'id':m['id']})[0],200)
snap=app.JOURNAL.snapshot(self.actor,{'mode':'mine'});self.assertEqual(snap['uploads'],[]);self.assertEqual(snap['trash'][0]['id'],m['id'])
self.assertEqual(app.JOURNAL.media(self.owner,m['id'])['id'],m['id'])
self.assertEqual(self.request('/api/journal',self.actor,dict(self.note(),mediaIds=[m['id']]))[0],409)
self.assertEqual(self.request('/api/journal',self.actor,app.get_object('journal_entries',key))[0],200)
for user in (self.owner,self.other):
self.assertIn(self.request('/api/journal/restore-upload',user,{'id':m['id']})[0],(403,404))
self.assertEqual(app.JOURNAL.snapshot(user,{})['trash'],[])
self.assertEqual(self.request('/api/journal/restore-upload',self.actor,{'id':m['id']})[0],200)
self.assertEqual(app.JOURNAL.snapshot(self.actor,{})['trash'],[])
def test_deleted_partial_upload_rejects_chunk_and_finish_and_can_restore(self):
m=dict(id=secrets.token_hex(8),familyId=self.aid,ownerId=self.actor['id'],status='receiving',size=8,name='x.png',mime='image/png',at='now',received=0)
app.save_object('journal_media',m);app.JOURNAL.remove_upload(self.actor,m['id'])
for action in (lambda:app.JOURNAL.chunk(self.actor,m['id'],0,b'123'),lambda:app.JOURNAL.finish_upload(self.actor,m['id'])):
with self.assertRaises(app.Problem):action()
app.JOURNAL.restore_upload(self.actor,m['id']);self.assertFalse(app.get_object('journal_media',m['id'])['trashedAt'])
def test_backup_readback_hash_check_and_constrained_cloud_delete(self):
data=b'fixture sqlite';stream=io.BytesIO(data)
with patch.object(app.BAIDU,'open_file',return_value=stream):
app.BAIDU.verify_backup('/test','1',len(data),hashlib.sha256(data).hexdigest())
with patch.object(app.BAIDU,'open_file',return_value=io.BytesIO(b'wrong')):
with self.assertRaises(app.Problem):app.BAIDU.verify_backup('/test','1',len(data),'wrong')
root='/apps/测试/数据库备份/'+'a'*16;name='vision-'+'a'*16+'-20260801T120000000000Z.sqlite';valid=root+'/'+name
with patch.object(app.BAIDU,'public_config',return_value={'appFolder':'测试'}),patch.object(app.BAIDU,'request',return_value={'info':[{'path':valid,'errno':0}]}) as request:
app.BAIDU.delete_backup_file(valid)
for path in (root,root+'/../'+name,root+'/other.png',root+'/'+name+'/private.png','/apps/测试/资料/'+name):
with self.assertRaises(app.Problem):app.BAIDU.delete_backup_file(path)
self.assertEqual(request.call_count,1)
def test_person_structured_places_preserve_legacy_and_survive_old_clients(self):
data=dict(name='测试人物',birthplace='旧称原记录',nativeProvince='山东省',nativeCity='烟台市',nativeDistrict='莱阳市',nativeTown='测试镇',nativeCommunity='测试村',birthCountry='中国',birthCity='济南市')
person=app.FAMILY.person(data,None)
self.assertEqual(person['nativeCity'],'烟台市');self.assertEqual(person['birthplace'],'旧称原记录')
saved=app.FAMILY.person({'name':'新姓名','birthplace':'旧称原记录'},person)
self.assertEqual(saved['nativeCommunity'],'测试村');self.assertEqual(saved['birthCity'],'济南市')
with self.assertRaises(app.Problem):app.FAMILY.person(dict(data,nativeCity=[]),person)