Добавлены все базовые файлы для запуска проекта
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import asyncio
|
||||
import io
|
||||
from types import SimpleNamespace
|
||||
|
||||
import rio
|
||||
import components
|
||||
from n8n_client import WebhookError
|
||||
|
||||
|
||||
def view():
|
||||
return SimpleNamespace(collection_name='my-store', pending_files=(), upload_error='',
|
||||
upload_status='', upload_progress='', is_uploading=False,
|
||||
force_refresh=lambda: None)
|
||||
|
||||
|
||||
def pick(state, name, data=b'# Notes'):
|
||||
file = rio.FileInfo(name, len(data), 'text/markdown', io.BytesIO(data))
|
||||
components.KnowledgeApp.pick_file(state, rio.FilePickEvent(file))
|
||||
return file
|
||||
|
||||
|
||||
def test_partial_failure_retries_only_failed_file_and_retains_bytes(monkeypatch):
|
||||
state = view()
|
||||
pick(state, 'first.md')
|
||||
pick(state, 'second.md')
|
||||
pick(state, 'third.md')
|
||||
calls = []
|
||||
|
||||
async def upload(name, contents, collection):
|
||||
calls.append(name)
|
||||
assert contents == b'# Notes'
|
||||
assert collection == 'my-store'
|
||||
if name == 'second.md' and calls.count(name) == 1:
|
||||
raise WebhookError('Временная ошибка')
|
||||
|
||||
monkeypatch.setattr(components, 'client', SimpleNamespace(upload=upload))
|
||||
asyncio.run(components.KnowledgeApp.upload_file(state))
|
||||
assert calls == ['first.md', 'second.md', 'third.md']
|
||||
assert len(state.pending_files) == 1
|
||||
assert state.pending_files[0].contents == b'# Notes'
|
||||
assert 'second.md' in state.upload_error
|
||||
assert '2 из 3' in state.upload_status
|
||||
asyncio.run(components.KnowledgeApp.upload_file(state))
|
||||
assert calls == ['first.md', 'second.md', 'third.md', 'second.md']
|
||||
assert not state.pending_files
|
||||
assert not state.upload_error
|
||||
assert not state.is_uploading
|
||||
|
||||
|
||||
def test_invalid_files_do_not_remove_valid_selection():
|
||||
state = view()
|
||||
good = pick(state, 'good.md')
|
||||
pick(state, 'bad.txt')
|
||||
pick(state, 'empty.md', b'')
|
||||
pick(state, 'another.md')
|
||||
assert len(state.pending_files) == 2
|
||||
assert 'bad.txt' in state.upload_error and 'empty.md' in state.upload_error
|
||||
components.KnowledgeApp.remove_file(state, rio.FilePickEvent(good))
|
||||
assert len(state.pending_files) == 1
|
||||
assert state.pending_files[0].file.name == 'another.md'
|
||||
|
||||
|
||||
def test_busy_queue_is_immutable_and_duplicate_submission_is_ignored(monkeypatch):
|
||||
state = view()
|
||||
first = pick(state, 'first.md')
|
||||
calls = []
|
||||
|
||||
async def upload(*args):
|
||||
calls.append(args)
|
||||
pick(state, 'late.md')
|
||||
components.KnowledgeApp.remove_file(state, rio.FilePickEvent(first))
|
||||
assert len(state.pending_files) == 1
|
||||
await components.KnowledgeApp.upload_file(state)
|
||||
|
||||
monkeypatch.setattr(components, 'client', SimpleNamespace(upload=upload))
|
||||
asyncio.run(components.KnowledgeApp.upload_file(state))
|
||||
assert len(calls) == 1
|
||||
assert not state.pending_files
|
||||
|
||||
|
||||
def test_read_error_does_not_block_remaining_files(monkeypatch):
|
||||
state = view()
|
||||
broken = pick(state, 'broken.md')
|
||||
state.pending_files[0].file = SimpleNamespace(name='broken.md', read_bytes=broken_read)
|
||||
pick(state, 'good.md')
|
||||
calls = []
|
||||
|
||||
async def upload(name, *_):
|
||||
calls.append(name)
|
||||
|
||||
monkeypatch.setattr(components, 'client', SimpleNamespace(upload=upload))
|
||||
asyncio.run(components.KnowledgeApp.upload_file(state))
|
||||
assert calls == ['good.md']
|
||||
assert not state.pending_files
|
||||
assert 'Выберите его заново' in state.upload_error
|
||||
|
||||
|
||||
async def broken_read():
|
||||
raise OSError('closed stream')
|
||||
Reference in New Issue
Block a user