Source code for timApp.tests.server.test_preamble

"""Server tests for preamble."""
from unittest.mock import patch, Mock

from lxml import html

from timApp.document.docinfo import DocInfo
from timApp.document.docparagraph import DocParagraph
from timApp.document.specialnames import (
    TEMPLATE_FOLDER_NAME,
    PREAMBLE_FOLDER_NAME,
    DEFAULT_PREAMBLE_DOC,
)
from timApp.document.yamlblock import YamlBlock
from timApp.tests.server.timroutetest import TimRouteTest
from timApp.timdb.sqa import db


[docs]class PreambleTestBase(TimRouteTest):
[docs] def create_doc_and_preamble(self, folder: str): d = self.create_doc(f"{folder}/a/b/test1") preamble_name = DEFAULT_PREAMBLE_DOC p1, p2, p3 = self.create_preambles(folder, preamble_name) p1.document.set_settings({"macros": {"a": "cat", "b": "dog", "d": "sheep"}}) p2.document.set_settings({"macros": {"b": "mouse", "c": "giraffe"}}) p3.document.set_settings({"macros": {"c": "elephant", "d": "fly"}}) return d, p1, p2, p3
[docs] def create_preambles(self, folder: str, preamble_name: str): p1 = self.create_doc( f"{folder}/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{preamble_name}" ) p2 = self.create_doc( f"{folder}/a/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{preamble_name}" ) p3 = self.create_doc( f"{folder}/a/b/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{preamble_name}" ) return p1, p2, p3
[docs]class PreambleTest(PreambleTestBase):
[docs] def test_preamble_settings(self): self.login_test1() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) d.document.set_settings({"macros": {"e": "fox"}}) d_no_preamble = self.create_doc(f"{folder}/a/b/nopreamble") self.assertEqual( [p.path_without_lang for p in d.get_preamble_docs()], [ f"users/test-user-1/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{DEFAULT_PREAMBLE_DOC}", f"users/test-user-1/a/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{DEFAULT_PREAMBLE_DOC}", f"users/test-user-1/a/b/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{DEFAULT_PREAMBLE_DOC}", ], ) self.assertEqual( d.document.get_settings().get_dict()["macros"], {"a": "cat", "b": "mouse", "c": "elephant", "d": "fly", "e": "fox"}, ) d_no_preamble.document.set_settings({"preamble": None}) self.assertEqual( d_no_preamble.document.get_settings().get_dict(), {"preamble": None} ) self.assertEqual( p1.document.get_settings().get_dict()["macros"], {"a": "cat", "b": "dog", "d": "sheep"}, ) self.assertEqual( p2.document.get_settings().get_dict()["macros"], {"b": "mouse", "c": "giraffe"}, ) self.assertEqual( p3.document.get_settings().get_dict()["macros"], {"c": "elephant", "d": "fly"}, )
[docs] def test_preamble_content(self): self.login_test2() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) d.document.set_settings({"macros": {"e": "fox"}}) p1.document.add_text("p1") p2.document.add_text("p2") p3.document.add_text("p3 %%e%% s") d.document.add_text("own") elem = self.get(d.url, as_tree=True) self.assert_content(elem, ["p1", "p2", "p3 fox s", "", "own"])
[docs] def test_preamble_self(self): self.login_test3() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) p1.document.add_text("p1") p2.document.add_text("p2") p3.document.add_text("p3") self.get(p1.url)
[docs] def test_preamble_perf(self): self.login_test1() d = self.create_doc() with patch.object(DocInfo, "_get_preamble_docs_impl") as m: # type: Mock self.get(d.url) m.assert_called_once()
[docs]class PreambleTest2(PreambleTestBase):
[docs] def test_preamble_unique_ids(self): self.login_test1() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) par = p1.document.add_text("test")[0] d.document.add_paragraph("test", par_id=par.get_id()) self.get( d.url, expect_contains="The paragraphs in the main document must " "have distinct ids from the preamble documents. Conflicting ids:", ) p2.document.add_paragraph("test", par_id=par.get_id()) self.get( d.url, expect_contains="The paragraphs in preamble documents must have distinct ids among themselves.", )
[docs] def test_preamble_area_settings(self): self.login_test2() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) p1.document.add_text( """ #- {area=a settings=""} a: b #- {area_end=a} """ ) resp = self.get(d.url, as_tree=True) # There should not be warnings about missing areas. alert = resp.cssselect(".alert.alert-info") self.assertFalse(alert)
[docs] def test_preamble_heading_numbering(self): self.login_test3() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) p1.document.add_text("# a") p2.document.add_text("# b") p3.document.add_text("# c") p1.document.set_settings({"auto_number_headings": 1}) d.document.add_text("# d") doc = self.get(d.url, as_tree=True) self.assert_content(doc, ["1. a", "2. b", "3. c", "4. d"]) first_par = d.document.get_paragraphs()[0] e = self.post_preview( d, text="# d", par=first_par.get_id(), json_key="texts", as_tree=True ) self.assert_content(e, ["4. d"]) e = self.post_preview( d, text="# d", par_next=first_par.get_id(), json_key="texts", as_tree=True ) self.assert_content(e, ["4. d"]) e = self.post_par( d.document, "# x", first_par.get_id(), json_key="texts", as_tree=True ) self.assert_content(e, ["4. x"]) e = self.get_updated_pars(d) changed = e["changed_pars"] self.assert_content(html.fromstring(changed[first_par.get_id()]), ["4. x"]) p1.document.set_settings({}) d.document.set_settings({"auto_number_headings": 1}) self.get(d.url) e = self.post_par( d.document, "# z", first_par.get_id(), json_key="texts", as_tree=True ) self.assert_content(e, ["4. z"]) e = self.get_updated_pars(d) changed = e["changed_pars"] self.assert_content(html.fromstring(changed[first_par.get_id()]), ["4. z"])
[docs]class PreambleTest3(PreambleTestBase):
[docs] def test_preamble_translation(self): self.login_test1() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) p1.document.add_text("macro a is %%a%%") p2.document.add_text("macro b is %%b%%") p3.document.add_text("macro c is %%c%%") d.document.add_text("macro d is %%d%%") d.document.add_text("macro e is %%e%%") dt = self.create_translation(d, "test", "fi") p1t = self.create_translation(p1, "test", "fi") p2t = self.create_translation(p2, "test", "fi") p1tpars = p1t.document.get_paragraphs() p2tpars = p2t.document.get_paragraphs() p1tpars[0].set_markdown( YamlBlock( values={"macros": {"a": "kissa", "b": "koira", "d": "lammas"}} ).to_markdown() ) p1tpars[0].save() e = self.get(dt.url, as_tree=True) self.assert_content( e, [ "macro a is kissa", "macro b is mouse", "macro c is elephant", "macro d is fly", "macro e is", ], ) p1tpars[1].set_markdown("makro a on %%a%%") p1tpars[1].save() e = self.get(dt.url, as_tree=True) self.assert_content( e, [ "makro a on kissa", "macro b is mouse", "macro c is elephant", "macro d is fly", "macro e is", ], ) dt.document.set_settings({"macros": {"e": "jänis", "d": "kärpänen"}}) e = self.get(dt.url, as_tree=True) self.assert_content( e, [ "makro a on kissa", "macro b is mouse", "macro c is elephant", "", "macro d is kärpänen", "macro e is jänis", ], ) p2tpars[1].set_markdown("makro b on %%b%%") p2tpars[1].save() with patch.object( DocParagraph, "get", wraps=DocParagraph.get ) as m: # type: Mock e = self.get(dt.url, as_tree=True) # + 1 because of bookmark document expected_count = ( sum( map( len, (x.document.get_par_ids() for x in (p1, p2, p3, p1t, p2t, d, dt)), ) ) + 1 ) # TODO: Paragraphs of p1 and p2 are read twice. Delta should be 0 ideally. self.assertAlmostEqual(expected_count, m.call_count, delta=4) self.assert_content( e, [ "makro a on kissa", "makro b on mouse", "macro c is elephant", "", "macro d is kärpänen", "macro e is jänis", ], ) self.assertEqual(len(e.cssselect(".preamble")), 3) self.assertEqual(len(e.cssselect("tim-par-ref")), 0)
[docs] def test_multiple_preamble(self): self.login_test2() folder = self.current_user.get_personal_folder().path d, p1, p2, p3 = self.create_doc_and_preamble(folder) p1c, p2c, p3c = self.create_preambles(folder, "chat") d.document.set_settings({"preamble": "preamble, chat"}) p1.document.add_text("p1") p2.document.add_text("p2") p3.document.add_text("p3") p1c.document.add_text("p1c") p2c.document.add_text("p2c") p3c.document.add_text("p3c") e = self.get(d.url, as_tree=True) self.assert_content(e, ["p1", "p1c", "p2", "p2c", "p3", "p3c", ""]) d.document.set_settings({"preamble": "chat, preamble"}) e = self.get(d.url, as_tree=True) self.assert_content(e, ["p1c", "p1", "p2c", "p2", "p3c", "p3", ""]) dt = self.create_translation(d) p2ctr = self.create_translation(p2c) p = p2ctr.document.get_paragraphs()[0] p.set_markdown("p2ctr") p.save() e = self.get(dt.url, as_tree=True) self.assert_content(e, ["p1c", "p1", "p2ctr", "p2", "p3c", "p3", ""]) d.document.set_settings({"preamble": "chat, preamblez"}) e = self.get(d.url, as_tree=True) self.assert_content(e, ["p1c", "p2c", "p3c", ""])
[docs] def test_preamble_ref(self): self.login_test3() d = self.create_doc() d2 = self.create_doc() par = d2.document.add_text("from preamble")[0] p = self.create_preamble_for(d) p.document.add_text("""test""") p.document.add_paragraph_obj(par.create_reference(p.document)) t = self.get(d.url, as_tree=True) pars = t.cssselect(".par.preamble") for pr in pars: self.assertEqual(p.path, pr.attrib["data-from-preamble"])
[docs]class PreambleTest4(TimRouteTest):
[docs] def test_absolute_preamble(self): """User may refer to preambles located in an absolute path""" self.test_user_1.make_admin() db.session.commit() self.login_test1() folder = self.current_user.get_personal_folder().path preamble = self.create_doc(f"/{folder}/{PREAMBLE_FOLDER_NAME}/test") preamble.document.add_text("p1") document = self.create_doc("/kurssit/tie/document") document.document.add_text("p2") document.document.set_settings( {"preamble": f"/{folder}/{PREAMBLE_FOLDER_NAME}/test"} ) document_text = self.get(document.url, as_tree=True) self.assert_content(document_text, ["p1", "", "p2"])
[docs] def test_absolute_preamble_order(self): """Preambles located in an absolute path will be treated last""" self.test_user_2.make_admin() db.session.commit() self.login_test2() folder = self.current_user.get_personal_folder().path pt = self.create_doc( f"{folder}/{TEMPLATE_FOLDER_NAME}/{PREAMBLE_FOLDER_NAME}/{DEFAULT_PREAMBLE_DOC}" ) pt.document.add_text("templates") pa = self.create_doc( f"/kurssit/tie/{PREAMBLE_FOLDER_NAME}/{DEFAULT_PREAMBLE_DOC}" ) pa.document.add_text("absolute") document = self.create_doc(f"{folder}/document") document.document.add_text("document") path = f"{pt.short_name}, /{pa.path}" document.document.set_settings({"preamble": path}) document_text = self.get(document.url, as_tree=True) self.assert_content(document_text, ["templates", "absolute", "", "document"])
[docs] def test_preambles_self_reference(self): """Preamble shall not refer to itself""" self.test_user_3.make_admin() db.session.commit() self.login_test3() folder = self.current_user.get_personal_folder().path preamble = self.create_doc( f"{folder}/{PREAMBLE_FOLDER_NAME}/{DEFAULT_PREAMBLE_DOC}" ) preamble.document.add_text("test")[0] self.assertNotIn( "The paragraphs in the main document must " "have distinct ids from the preamble documents. " "Conflicting ids:", self.get(preamble.url), )