mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
Live testing surfaced three ways small models went wrong summarizing a library: they gave up after one empty search (misspelled channel names found nothing), so zero-result searches now carry a retry hint and the Research prompt requires list_collections before channel/site questions and search_videos(channel_id) before claiming a channel is summarized; they presented the familiar YouTube source URL instead of the WROLPi link, so listings omit the source URL (archive detail keeps it); and they invented links for channels, so channel collections now carry their real /videos/channel page link. Search descriptions state that search_str is optional for browsing the newest items. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
132 lines
4.7 KiB
Python
132 lines
4.7 KiB
Python
"""Tests for the /api/ai formatting helpers."""
|
|
from modules.ai import lib
|
|
|
|
|
|
def test_wrolpi_link_video():
|
|
fg = dict(id=123, model='video', video=dict(), mimetype='video/mp4')
|
|
assert lib.wrolpi_link(fg) == '/videos/123'
|
|
|
|
|
|
def test_wrolpi_link_doc():
|
|
fg = dict(id=5, model='doc', mimetype='application/pdf')
|
|
assert lib.wrolpi_link(fg) == '/docs/5'
|
|
|
|
|
|
def test_wrolpi_link_archive():
|
|
fg = dict(id=7, model='archive', mimetype='text/html')
|
|
assert lib.wrolpi_link(fg) == '/archives/7'
|
|
|
|
|
|
def test_wrolpi_link_epub(test_directory):
|
|
fg = dict(id=9, mimetype='application/epub+zip', primary_path=test_directory / 'books/foo.epub')
|
|
assert lib.wrolpi_link(fg) == '/epub/epub.html?url=/download/books/foo.epub'
|
|
|
|
|
|
def test_wrolpi_link_mobi(test_directory):
|
|
fg = dict(id=9, mimetype='application/x-mobipocket-ebook', primary_path=test_directory / 'books/foo.mobi')
|
|
assert lib.wrolpi_link(fg) == '/download/books/foo.mobi'
|
|
|
|
|
|
def test_wrolpi_link_media_fallback(test_directory):
|
|
fg = dict(id=2, mimetype='image/png', primary_path=test_directory / 'photos/a.png')
|
|
assert lib.wrolpi_link(fg) == '/media/photos/a.png'
|
|
|
|
|
|
def test_wrolpi_link_no_path():
|
|
assert lib.wrolpi_link(dict(mimetype='image/png')) is None
|
|
|
|
|
|
def test_format_file_group_video():
|
|
fg = dict(
|
|
id=42,
|
|
model='video',
|
|
title='Canning Basics',
|
|
mimetype='video/mp4',
|
|
size=1000,
|
|
length=4021,
|
|
published_datetime='2024-01-02',
|
|
tags=['food'],
|
|
video=dict(channel=dict(id=1, name='Homesteading'), description='x' * 500),
|
|
d_headline='pressure <b>canning</b>',
|
|
)
|
|
result = lib.format_file_group(fg)
|
|
assert result['id'] == 42
|
|
assert result['kind'] == 'video'
|
|
assert result['link'] == '/videos/42'
|
|
assert result['captions_link'] == '/api/ai/videos/42/captions'
|
|
assert result['channel'] == 'Homesteading'
|
|
assert result['duration'] == 4021
|
|
assert result['headline'] == 'pressure <b>canning</b>'
|
|
assert result['tags'] == ['food']
|
|
# Listing descriptions are truncated.
|
|
assert len(result['description']) == lib.LISTING_DESCRIPTION_LENGTH + 1
|
|
# Empty fields are omitted.
|
|
assert 'author' not in result and 'url' not in result
|
|
|
|
|
|
def test_format_file_group_archive():
|
|
fg = dict(id=8, model='archive', title='Some Page', mimetype='text/html', url='https://example.com/a')
|
|
result = lib.format_file_group(fg)
|
|
assert result['kind'] == 'archive'
|
|
assert result['link'] == '/archives/8'
|
|
assert result['text_link'] == '/api/ai/archives/8/text'
|
|
# Listings omit the source URL so small models present the WROLPi link instead.
|
|
assert 'url' not in result
|
|
assert lib.format_file_group(fg, include_url=True)['url'] == 'https://example.com/a'
|
|
|
|
|
|
def test_format_file_groups_total():
|
|
result = lib.format_file_groups([dict(id=1, model='archive')], 55)
|
|
assert result['total'] == 55
|
|
assert len(result['results']) == 1
|
|
|
|
|
|
def test_paginate_text():
|
|
text = 'a' * (lib.PAGE_SIZE + 100)
|
|
page = lib.paginate_text(text, 0)
|
|
assert len(page['content']) == lib.PAGE_SIZE
|
|
assert page['next_offset'] == lib.PAGE_SIZE
|
|
assert page['total_chars'] == lib.PAGE_SIZE + 100
|
|
|
|
page = lib.paginate_text(text, page['next_offset'])
|
|
assert len(page['content']) == 100
|
|
assert page['next_offset'] is None
|
|
|
|
# Exact boundary has no next page.
|
|
page = lib.paginate_text('a' * lib.PAGE_SIZE, 0)
|
|
assert page['next_offset'] is None
|
|
|
|
# Empty text.
|
|
page = lib.paginate_text(None, 0)
|
|
assert page == dict(content='', next_offset=None, total_chars=0)
|
|
|
|
|
|
def test_html_to_text():
|
|
html = '<html><head><style>.x{}</style><script>evil()</script></head>' \
|
|
'<body><nav>menu</nav><p>Hello</p><p></p><p>World</p></body></html>'
|
|
text = lib.html_to_text(html)
|
|
assert 'Hello' in text and 'World' in text
|
|
assert 'evil' not in text and 'menu' not in text and '.x{}' not in text
|
|
|
|
|
|
def test_format_caption_chunks():
|
|
chunks = [dict(start_seconds=0, text='hello'), dict(start_seconds=3671, text='goodbye')]
|
|
text = lib.format_caption_chunks(chunks)
|
|
assert text == '[00:00:00] hello\n[01:01:11] goodbye'
|
|
assert lib.format_caption_chunks(None) == ''
|
|
|
|
|
|
def test_format_zim_search():
|
|
zim_results = [dict(
|
|
metadata=dict(title='Test Zim'),
|
|
estimate=2,
|
|
search=[
|
|
dict(zim_id=1, path='one', title='One', headline='the first', rank=1),
|
|
dict(zim_id=1, path='two', title='Two', headline=None, rank=1),
|
|
],
|
|
)]
|
|
result = lib.format_zim_search(zim_results)
|
|
assert result['total'] == 2
|
|
assert result['results'][0]['link'] == '/api/zim/1/entry/one'
|
|
assert result['results'][0]['zim'] == 'Test Zim'
|
|
assert 'headline' not in result['results'][1]
|