def test_image_update(fn_params, col_tuple):
    "Test that we can update an existing image."
    expected_initial_filename = \
        "tr-f53cec5dc23d10d91500c50d79ccb4e73df697f64fc2cd93a1b2fcf2698775c5.jpg"
    expected_modified_filename = \
        "tr-fecd805de369bbc6d59fdd673b7bec823a6a84fada25335835e71acae780dbc5.jpg"

    # Create the image.
    fn_params['filter_'] = "InternalDogImageTest"
    os.chdir(col_tuple.cwd)
    note = find_notes(**fn_params).pop()

    sync((note, ), col_tuple.col, "Default")
    answer = _get_only_note(col_tuple).fields[1]
    assert answer.startswith(f'<img src="{expected_initial_filename}"')

    # Update to a new image (DogUpdateTest uses the same TR ID for its question).
    fn_params['filter_'] = "DogUpdateTest"
    note = find_notes(**fn_params).pop()
    sync((note, ), col_tuple.col, "Default")
    answer = _get_only_note(col_tuple).fields[1]
    assert answer.startswith(f'<img src="{expected_modified_filename}')

    # The original image doesn't get removed, but it could be removed on media check.
    assert col_tuple.col.media.have(expected_initial_filename)

    # But the new one is there.
    assert col_tuple.col.media.have(expected_modified_filename)

    # And the initial filename is now shown as unused.
    r = col_tuple.col.media.check()
    assert not r.missing
    assert r.unused == [expected_initial_filename]
def test_import_invalid_scheduling(fn_params, col_tuple):
    "Test what happens when we import a note with invalid scheduling info."

    fn_params['filter_'] = "IllegalScheduledQuestionAndAnswer"
    os.chdir(col_tuple.cwd)

    with pytest.raises(ScheduleParsingError):
        find_notes(**fn_params)
示例#3
0
def test_doubleclosingbrace(fn_params):
    """
    Report: "Single '}' encountered in format string" error
    prevents syncing.

    https://github.com/sobjornstad/TiddlyRemember/issues/29
    """
    fn_params['filter_'] = "BadClosingBraceCloze"
    with pytest.raises(UnmatchedBracesError):
        find_notes(**fn_params)
def test_encrypted_wiki_without_password(fn_params):
    """
    Check that when we import from an encrypted wiki without a password,
    we get a useful error message.
    """
    fn_params['filter_'] = "TiddlyRememberTest"
    fn_params['wiki_path'] = "tests/encrypted_wiki.html"
    fn_params['wiki_type'] = "file"

    with pytest.raises(RenderingError, match="forget to give the password"):
        find_notes(**fn_params)
def test_encrypted_wiki_from_url(fn_params, file_requests_session):
    """
    Check that when we import from an encrypted wiki without a password,
    we get a useful error message.
    """
    fn_params['filter_'] = "TiddlyRememberTest"
    fn_params['wiki_path'] = (Path.cwd() / "tests" /
                              "encrypted_wiki.html").as_uri()
    fn_params['wiki_type'] = "url"
    fn_params['requests_session'] = file_requests_session

    with pytest.raises(RenderingError, match="forget to give the password"):
        find_notes(**fn_params)
def test_image_resync(fn_params, col_tuple):
    """
    Test that we can sync an unchanged image on an update and nothing untoward
    happens.
    """
    expected_initial_filename = \
        "tr-f53cec5dc23d10d91500c50d79ccb4e73df697f64fc2cd93a1b2fcf2698775c5.jpg"

    # sanity check
    assert not col_tuple.col.media.have(expected_initial_filename)

    fn_params['filter_'] = "InternalDogImageTest"
    os.chdir(col_tuple.cwd)
    note = find_notes(**fn_params).pop()

    sync((note, ), col_tuple.col, "Default")
    assert col_tuple.col.media.have(expected_initial_filename)

    # Resync; we have to change a field before it will try to resync the image.
    note.question = "A new question"
    sync((note, ), col_tuple.col, "Default")
    assert col_tuple.col.media.have(expected_initial_filename)

    r = col_tuple.col.media.check()
    assert not r.missing
    assert not r.unused
def test_escaped_cloze_import(fn_params):
    "The 'EscapedCloze' note imports with successful escaped braces."
    fn_params['filter_'] = "EscapedCloze"
    note = find_notes(**fn_params).pop()
    assert note.text == (
        r'In LaTeX, we create fractions with '
        r'{{c1::<code>\frac{numerator}{denominator}</code>}}.')
def test_import_qa_with_scheduling(fn_params, col_tuple):
    "Test that we can import a question and answer into Anki with scheduling info."

    fn_params['filter_'] = "ScheduledQuestionAndAnswer"
    os.chdir(col_tuple.cwd)
    notes = find_notes(**fn_params)

    # sanity check
    assert len(notes) == 1
    anki_notes = col_tuple.col.find_notes("")
    assert len(anki_notes) == 0

    userlog = sync(notes, col_tuple.col, 'Default')

    assert 'Added 1 note' in userlog
    anki_notes = col_tuple.col.find_notes("")
    assert len(anki_notes) == 1
    anki_note = col_tuple.col.getNote(anki_notes[0])
    assert anki_note.fields[0] == "What is TiddlyRemember good for?"

    card = col_tuple.col.get_card(
        col_tuple.col.find_cards(f"nid:{anki_note.id}")[0])
    assert card.factor == 1800
    assert card.lapses == 1
    assert card.ivl == 5
    # year=2200 on this test card so delta will be positive for the foreseeable future
    assert card.due == (datetime.date(year=2200, month=9, day=22) -
                        datetime.datetime.now().date()).days
def test_escaped_cloze_katex(fn_params):
    "KaTeX math markup within clozes often requires escaping."
    fn_params['filter_'] = "KatexClozeTest"
    note = find_notes(**fn_params).pop()

    assert (r'{{c1::<span class="tw-katex-inline">'
            r'\( x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} \)'
            r'</span>}}') in note.text
示例#10
0
def test_audio(fn_params):
    "An HTML5 audio tag should come across into a TwNote."
    expected_filename = \
        "tr-07d11170fe30596ca17307682d2745e09862a8dcdf90c76fa90b70d381eb4973.mp3"
    fn_params['filter_'] = "AudioTest"
    note = find_notes(**fn_params).pop()

    assert f'[sound:{expected_filename}]' in note.question
示例#11
0
def test_internal_image(fn_params):
    "Check that internal images come across into TwNotes, including sizing."
    fn_params['filter_'] = "InternalDogImageTest"
    notes = find_notes(**fn_params)
    note = notes.pop()

    # will have been replaced with an internal media file
    assert '<img src="tr-' in note.answer
    assert 'width="300"' in note.answer
示例#12
0
def test_inlinecloze(fn_params):
    """
    Report: Inline cloze with no other block cloze in the tiddler
    not recognized at all.
    """
    fn_params['filter_'] = "MultipleInlineCloze"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
示例#13
0
def test_invalid_image_format(fn_params):
    fn_params['filter_'] = "InvalidFormatImageTest"
    fn_params['warnings'] = []
    note = find_notes(**fn_params).pop()

    assert '<img src="tr-' in note.answer  # we still add it to Anki...
    assert '.xxx' in note.answer  # ...but we don't know what to call it
    assert len(fn_params['warnings']) == 1
    assert "Unknown media type for URL" in fn_params['warnings'][
        0]  # and warn user
示例#14
0
def test_bad_image_url(fn_params):
    "An image URL that returns 404 at sync time should render an explanatory message."
    warnings = []
    fn_params['filter_'] = "BadImageUrlTest"
    fn_params['warnings'] = warnings
    note = find_notes(**fn_params).pop()

    assert '<img src="https://example.com/missing.png"' in note.text
    assert warnings
    assert '404 Not Found' in warnings[0]
示例#15
0
def test_external_image(fn_params):
    "Check that image references come across into TwNotes, including sizing."
    fn_params['filter_'] = "ExternalCatImageTest"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert isinstance(note, QuestionNote)
    assert note.id_ == "20200926152139943"
    assert '<img src="https://upload.wikimedia.org' in note.answer
    assert 'width="400"' in note.answer
示例#16
0
def test_tiddlyremember_variable(fn_params):
    """
    Check that the variable "tr-rendering" is set to "yes" when TiddlyRemember
    is working. This will allow custom templates to be written to render or not
    render certain things. For instance, some UI elements won't work correctly
    when there is no browser, so they shouldn't appear.
    """
    fn_params['filter_'] = "TrVariableTest"
    notes = find_notes(**fn_params)
    assert len(notes) == 1
    note = notes.pop()
    assert note.answer == "yes"
示例#17
0
def test_canonical_uri_image(fn_params):
    """
    An image given a _canonical_uri with a relative path should come across
    into a TwNote.
    """
    fn_params['filter_'] = "RelativeCanonicalUriImageTest"
    fn_params['wiki_path'] = "tests/file_wiki.html"
    fn_params['wiki_type'] = "file"
    fn_params['warnings'] = []
    note = find_notes(**fn_params).pop()
    assert not fn_params['warnings']
    assert '<img src="tr-' in note.answer
示例#18
0
def test_katex(fn_params):
    "Check that KaTeX math markup comes across as MathJax entries."
    fn_params['filter_'] = "KatexTest"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert isinstance(note, QuestionNote)
    assert note.id_ == "20201220193519092"
    assert r'<span class="tw-katex-inline">\( x + 5 = 86 \)</span>' in note.question
    assert r'<span class="tw-katex-display">\[ 81 \]</span>' in note.answer
示例#19
0
def test_link(fn_params):
    "Check that internal links are removed and external links comes across."
    fn_params['filter_'] = "LinkTest"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert note.id_ == "20200926154719339"
    assert note.question == 'How do you get to Google?'
    assert note.answer == \
        'Browse to <a href="https://google.com">https://google.com</a>.'
示例#20
0
def test_encrypted_wiki_import(fn_params):
    """
    Check that we can import notes from an encrypted wiki.
    """
    fn_params['filter_'] = "TiddlyRememberTest"
    fn_params['wiki_path'] = "tests/encrypted_wiki.html"
    fn_params['wiki_type'] = "file"
    fn_params['password'] = "******"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()
    assert note.id_ == "20200925190437552"
示例#21
0
def test_external_image(fn_params):
    "Check that image references come across into TwNotes, including sizing."
    fn_params['filter_'] = "ExternalCatImageTest"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert isinstance(note, QuestionNote)
    assert note.id_ == "20200926152139943"
    # will have been replaced with an internal media file
    assert '<img src="tr-' in note.answer
    assert 'width="400"' in note.answer
示例#22
0
def test_image_import(fn_params, col_tuple):
    "Test importing an image embedded in a TiddlyWiki into Anki."
    expected_filename = \
        "tr-f53cec5dc23d10d91500c50d79ccb4e73df697f64fc2cd93a1b2fcf2698775c5.jpg"

    fn_params['filter_'] = "InternalDogImageTest"
    os.chdir(col_tuple.cwd)
    note = find_notes(**fn_params).pop()

    sync((note, ), col_tuple.col, "Default")
    answer = _get_only_note(col_tuple).fields[1]
    assert answer.startswith(f'<img src="{expected_filename}"')
    assert col_tuple.col.media.have(expected_filename)
示例#23
0
def _sync_note_with_edits(fn_params, col_tuple, from_tiddler: str,
                          edit_callable: Callable = None) -> str:
    fn_params['filter_'] = from_tiddler
    os.chdir(col_tuple.cwd)
    notes = find_notes(**fn_params)
    assert len(notes) == 1

    if edit_callable is not None:
        note = notes.pop()
        edit_callable(note)
        notes.add(note)

    return sync(notes, col_tuple.col, 'Default')
示例#24
0
def test_formatting(fn_params):
    "Check that basic HTML formatting comes across into TwNotes."
    fn_params['filter_'] = "FormattingTest"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert isinstance(note, ClozeNote)
    assert note.id_ == "20200926152545054"
    assert '<strong>' in note.text
    assert '<em>' in note.text
    assert '<strike>' in note.text
示例#25
0
def test_url_import(fn_params):
    """
    Check that the URL-to-folder conversion works.

    Note that the TiddlyRemember docs may not always have the latest copy of
    TiddlyRemember (e.g., during development, it will be one version behind).
    If this test starts failing, that should be the first thing you check.
    """
    fn_params['filter_'] = "TiddlyRemember"
    fn_params['wiki_path'] = "https://sobjornstad.github.io/TiddlyRemember/"
    fn_params['wiki_type'] = "url"
    notes = find_notes(**fn_params)
    assert notes  # don't want to make dependent on the summarized note options
示例#26
0
def test_file_wiki_embedded_image(fn_params):
    """
    An embedded image in a file wiki should come across into a TwNote.

    (Regression test: the prepending of a relative path to the URL to work with
    _canonical_uri tiddlers broke this in an earlier version.)
    """
    fn_params['filter_'] = "EmbeddedImageTest"
    fn_params['wiki_path'] = "tests/file_wiki.html"
    fn_params['wiki_type'] = "file"
    fn_params['warnings'] = []
    note = find_notes(**fn_params).pop()
    assert not fn_params['warnings']
    assert '<img src="tr-' in note.answer
示例#27
0
def test_recursive_link(fn_params):
    "Check that links are still cleaned up when inside another HTML element."

    fn_params['filter_'] = "RecursiveLinkTest"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert note.id_ == "20200926154719339"
    assert note.question == 'How do you get <strong>to Google</strong>?'
    assert note.answer == \
        ('Browse <span style="color: orange;">to '
         '<a href="https://google.com">https://google.com</a></span>.')
示例#28
0
def test_export(fn_params, col_tuple, tmp_path, test_case_name,
                include_scheduling, output):
    "Check that we can sync an item into Anki and then export it as a TiddlyWiki macro."
    fn_params['filter_'] = test_case_name
    os.chdir(col_tuple.cwd)
    notes = find_notes(**fn_params)
    sync(notes, col_tuple.col, "Default")

    exp = TiddlyRememberMacroExporter(col_tuple.col)
    if include_scheduling:
        exp.includeSched = True
    exp.exportInto(tmp_path / "output.txt")
    with open(tmp_path / "output.txt", "r") as f:  # pylint: disable=unspecified-encoding
        macros = f.read()
    assert macros == dedent(output).strip()
示例#29
0
def test_hardref(fn_params):
    """
    Although the note appears in 2 tiddlers, only one TwNote will be generated
    because it has been hard-referenced.
    """
    fn_params['filter_'] = "[tag[HardrefTest]]"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert isinstance(note, QuestionNote)
    assert note.id_ == "20200925183527082"
    assert note.tidref == "HardrefQaTarget"
    assert note.question == "Do hard references work in TiddlyRemember?"
示例#30
0
def test_nonascii(fn_params):
    """
    Reports: non-ASCII question text or tiddler names variously broken on some
    platforms.
    """
    fn_params['filter_'] = "[field:reference-name[NonAsciiQuestionText]]"
    notes = find_notes(**fn_params)

    assert len(notes) == 1
    note = notes.pop()

    assert isinstance(note, QuestionNote)
    assert note.id_ == "20200923152852640"
    assert note.question == "What 'élan vital' means?"
    assert note.tidref == "NonAsciiQuestionTéxt😀"