Обновил структуру проекта
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import copy
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from parser_lab.admin import config_from_payload
|
||||
from parser_lab.repository import Repository, Conflict, NotFound
|
||||
from parser_lab.views import default_view, project_record, validate_view
|
||||
from parser_lab.web import public_page
|
||||
|
||||
|
||||
def test_detail_fields_are_independent_and_old_views_keep_their_fields():
|
||||
row = {'name': 'Alice', 'bio': 'Detailed biography', 'secret': 'PRIVATE'}
|
||||
view = default_view('table', ['/name'])
|
||||
view['detail_columns'] = [{'pointer': '/bio', 'label': 'Biography'}]
|
||||
publication = {'title': 'Study', 'description': '', 'version': 1,
|
||||
'records': [row], 'views': {'table': view}}
|
||||
listing = public_page(publication, 'table', '/collection')
|
||||
detail = public_page(publication, 'table', '/collection', record_id='1')
|
||||
assert 'Detailed biography' not in listing
|
||||
assert 'Detailed biography' in detail and 'Biography' in detail
|
||||
assert 'PRIVATE' not in detail
|
||||
assert [f['pointer'] for f in project_record(row, view, 1)['fields']] == ['/name']
|
||||
del view['detail_columns']
|
||||
legacy = public_page(publication, 'table', '/collection', record_id='1')
|
||||
assert 'Alice' in legacy and 'Detailed biography' not in legacy
|
||||
|
||||
|
||||
def test_detail_config_survives_save_and_validates_fields():
|
||||
draft = {'revision': 1, 'records': [{'name': 'Alice', 'bio': 'About'}]}
|
||||
view = default_view('table', ['/name'])
|
||||
view['detail_columns'] = [{'pointer': '/bio', 'label': 'About'}]
|
||||
result = config_from_payload(copy.deepcopy(draft), {'revision': 1, 'views': {'table': view}})
|
||||
assert result['views']['table']['detail_columns'] == [{'pointer': '/bio', 'label': 'About'}]
|
||||
view['detail_columns'] = [{'pointer': '/unknown', 'label': 'Unknown'}]
|
||||
assert validate_view(view, draft['records'])
|
||||
view['detail_columns'] = []
|
||||
assert validate_view(view, draft['records'])
|
||||
view['detail_columns'] = 'bad'
|
||||
with pytest.raises(ValueError):
|
||||
config_from_payload(copy.deepcopy(draft), {'revision': 1, 'views': {'table': view}})
|
||||
|
||||
|
||||
def test_questionnaire_detail_fields_do_not_replace_answers():
|
||||
row = {'name': 'Alice', 'bio': 'About Alice', 'answers': [{'question': 'Sleep?', 'answer': 7}]}
|
||||
view = default_view('questionnaire', ['/name'])
|
||||
view.update(questionnaire_mode='pairs', questions_pointer='/answers',
|
||||
detail_columns=[{'pointer': '/bio', 'label': 'Bio'}])
|
||||
fields = project_record(row, view, 1, detail=True)['fields']
|
||||
assert [(f['label'], f['text']) for f in fields] == [('Bio', 'About Alice'), ('Sleep?', '7')]
|
||||
|
||||
|
||||
def test_delete_removes_versions_and_sources_but_preserves_other_datasets(tmp_path):
|
||||
repo = Repository(tmp_path)
|
||||
d = repo.create('Delete me', b'old', 'old.json', [{'name': 'Alice'}])
|
||||
other = repo.create('Keep me', b'keep', 'keep.json', [{'name': 'Bob'}])
|
||||
d['views'] = {'table': default_view('table', ['/name'])}
|
||||
d = repo.save(d, d['revision'])
|
||||
repo.publish(d['id'], d['revision'])
|
||||
repo.unpublish(d['slug'], 1)
|
||||
for name in ('middle', 'latest'):
|
||||
d = repo.replace_source(d['id'], d['revision'], name.encode(), name + '.json', [{'name': name}])
|
||||
with pytest.raises(Conflict):
|
||||
repo.delete(d['id'], d['revision'] - 1)
|
||||
assert len(list((tmp_path / 'sources').iterdir())) == 4
|
||||
repo.delete(d['id'], d['revision'])
|
||||
with pytest.raises(NotFound):
|
||||
repo.get(d['id'])
|
||||
assert repo.versions(d['slug']) == []
|
||||
assert repo.get(other['id'])['title'] == 'Keep me'
|
||||
assert [p.read_bytes() for p in (tmp_path / 'sources').iterdir()] == [b'keep']
|
||||
with pytest.raises(NotFound):
|
||||
repo.delete(d['id'], d['revision'])
|
||||
|
||||
|
||||
def test_delete_retries_failed_source_cleanup_on_restart(tmp_path, monkeypatch):
|
||||
repo = Repository(tmp_path)
|
||||
d = repo.create('Delete', b'old', 'old.json', [{'name': 'Alice'}])
|
||||
d = repo.replace_source(d['id'], d['revision'], b'new', 'new.json', [{'name': 'Bob'}])
|
||||
unlink = Path.unlink
|
||||
|
||||
def blocked_source(path, *args, **kwargs):
|
||||
if path.name == d['source']:
|
||||
raise PermissionError('File temporarily unavailable')
|
||||
return unlink(path, *args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(Path, 'unlink', blocked_source)
|
||||
assert repo.delete(d['id'], d['revision']) is False
|
||||
with pytest.raises(NotFound):
|
||||
repo.get(d['id'])
|
||||
assert (tmp_path / 'sources' / d['source']).read_bytes() == b'new'
|
||||
monkeypatch.undo()
|
||||
restarted = Repository(tmp_path)
|
||||
assert restarted.list() == []
|
||||
assert not list((tmp_path / 'sources').iterdir())
|
||||
Reference in New Issue
Block a user