text: # pylint: disable=missing-docstring
  import datetime
  from typing import Tuple, Optional, FrozenSet
  
  import pytest
  from beancount.core.amount import A, Amount
  from beancount.core.data import Balance
  from beancount.core.data import CostSpec
  from beancount.core.data import create_simple_posting
  from beancount.core.data import Note
  from beancount.core.data import Posting
  from beancount.core.data import Transaction
  from beancount.core.number import D
  from beancount.core.number import MISSING
  from flask.json import loads
  
  from fava.core.file import _format_entry
  from fava.core.charts import dumps
  from fava.helpers import FavaAPIException
  from fava.serialisation import deserialise
  from fava.serialisation import deserialise_posting
  from fava.serialisation import extract_tags_links
  from fava.serialisation import serialise
  
  
  def test_serialise() -> None:
      assert serialise(None) is None
      txn = Transaction(
          {},
          datetime.date(2017, 12, 12),
          "*",
          "Test3",
          "asdfasd",
          frozenset(["tag"]),
          frozenset(["link"]),
          [],
      )
      create_simple_posting(txn, "Assets:ETrade:Cash", "100", "USD")
      create_simple_posting(txn, "Assets:ETrade:GLD", None, None)
  
      json_txn = {
          "date": "2017-12-12",
          "flag": "*",
          "meta": {},
          "narration": "asdfasd #tag ^link",
          "payee": "Test3",
          "type": "Transaction",
          "postings": [
              {"account": "Assets:ETrade:Cash", "amount": "100 USD"},
              {"account": "Assets:ETrade:GLD", "amount": ""},
          ],
      }
  
      serialised = loads(dumps(serialise(txn)))
      assert serialised == json_txn
  
      txn = txn._replace(payee="")
      json_txn["payee"] = ""
      serialised = loads(dumps(serialise(txn)))
      assert serialised == json_txn
  
      txn = txn._replace(payee=None)
      serialised = loads(dumps(serialise(txn)))
      assert serialised == json_txn
  
  
  @pytest.mark.parametrize(
      "amount_cost_price,amount_string",
      [
          ((A("100 USD"), None, None), "100 USD"),
          (
              (
                  A("100 USD"),
                  CostSpec(D("10"), None, "EUR", None, None, False),
                  None,
              ),
              "100 USD {10 EUR}",
          ),
          (
              (
                  A("100 USD"),
                  CostSpec(D("10"), None, "EUR", None, None, False),
                  A("11 EUR"),
              ),
              "100 USD {10 EUR} @ 11 EUR",
          ),
          ((A("100 USD"), None, A("11 EUR")), "100 USD @ 11 EUR"),
          (
              (
                  A("100 USD"),
                  CostSpec(MISSING, None, MISSING, None, None, False),
                  None,
              ),
              "100 USD {}",
          ),
      ],
  )
  def test_serialise_posting(
      amount_cost_price: Tuple[Amount, Optional[CostSpec], Amount],
      amount_string: str,
  ) -> None:
      pos = Posting("Assets", *amount_cost_price, None, None)
      json = {"account": "Assets", "amount": amount_string}
      assert loads(dumps(serialise(pos))) == json
      assert deserialise_posting(json) == pos
  
  
  @pytest.mark.parametrize(
      "amount_cost_price,amount_string",
      [
          ((A("100 USD"), None, None), "10*10 USD"),
          ((A("130 USD"), None, None), "100+50 - 20 USD"),
          ((A("-140 USD"), None, None), "-1400 / 10 USD"),
          ((A("10 USD"), None, A("1 EUR")), "10 USD @@ 10 EUR"),
          (
              (A("7 USD"), None, A("1.428571428571428571428571429 EUR")),
              "7 USD @@ 10 EUR",
          ),
          ((A("0 USD"), None, A("0 EUR")), "0 USD @@ 0 EUR"),
      ],
  )
  def test_deserialise_posting(
      amount_cost_price: Tuple[Amount, Optional[CostSpec], Amount],
      amount_string: str,
  ) -> None:
      """Roundtrip is not possible here due to total price or calculation."""
      pos = Posting("Assets", *amount_cost_price, None, None)
      json = {"account": "Assets", "amount": amount_string}
      assert deserialise_posting(json) == pos
  
  
  def test_deserialise_posting_and_format(snapshot) -> None:
      txn = Transaction(
          {},
          datetime.date(2017, 12, 12),
          "*",
          "Test3",
          "asdfasd",
          frozenset(["tag"]),
          frozenset(["link"]),
          [
              deserialise_posting({"account": "Assets", "amount": "10"}),
              deserialise_posting({"account": "Assets", "amount": "10 EUR @"}),
          ],
      )
      snapshot(_format_entry(txn, 61))
  
  
  def test_serialise_balance() -> None:
      bal = Balance(
          {},
          datetime.date(2019, 9, 17),
          "Assets:ETrade:Cash",
          A("0.1234567891011121314151617 CHF"),
          None,
          None,
      )
  
      json = {
          "date": "2019-09-17",
          "amount": {"currency": "CHF", "number": "0.1234567891011121314151617"},
          "diff_amount": None,
          "meta": {},
          "tolerance": None,
          "account": "Assets:ETrade:Cash",
          "type": "Balance",
      }
  
      serialised = loads(dumps(serialise(bal)))
  
      assert serialised == json
  
  
  def test_deserialise() -> None:
      postings = [
          {"account": "Assets:ETrade:Cash", "amount": "100 USD"},
          {"account": "Assets:ETrade:GLD"},
      ]
      json_txn = {
          "type": "Transaction",
          "date": "2017-12-12",
          "flag": "*",
          "payee": "Test3",
          "narration": "asdfasd #tag ^link",
          "meta": {},
          "postings": postings,
      }
  
      txn = Transaction(
          {},
          datetime.date(2017, 12, 12),
          "*",
          "Test3",
          "asdfasd",
          frozenset(["tag"]),
          frozenset(["link"]),
          [],
      )
      create_simple_posting(txn, "Assets:ETrade:Cash", "100", "USD")
      txn.postings.append(
          Posting("Assets:ETrade:GLD", MISSING, None, None, None, None)
      )
      assert deserialise(json_txn) == txn
  
      with pytest.raises(KeyError):
          deserialise({})
  
      with pytest.raises(FavaAPIException):
          deserialise({"type": "NoEntry"})
  
  
  def test_deserialise_balance() -> None:
      json_bal = {
          "type": "Balance",
          "date": "2017-12-12",
          "account": "Assets:ETrade:Cash",
          "amount": {"number": "100", "currency": "USD"},
          "meta": {},
      }
      bal = Balance(
          {},
          datetime.date(2017, 12, 12),
          "Assets:ETrade:Cash",
          A("100 USD"),
          None,
          None,
      )
      assert deserialise(json_bal) == bal
  
  
  def test_deserialise_note() -> None:
      json_note = {
          "type": "Note",
          "date": "2017-12-12",
          "account": "Assets:ETrade:Cash",
          "comment": 'This is some comment or note""',
          "meta": {},
      }
      note = Note(
          {},
          datetime.date(2017, 12, 12),
          "Assets:ETrade:Cash",
          "This is some comment or note",
      )
      assert deserialise(json_note) == note
  
  
  def test_extract_tags_links() -> None:
      assert extract_tags_links("notag") == ("notag", frozenset(), frozenset())
      extracted1: Tuple[str, FrozenSet[str], FrozenSet[str]] = (
          "Some text",
          frozenset(["tag"]),
          frozenset(),
      )
      assert extract_tags_links("Some text #tag") == extracted1
      assert extract_tags_links("Some text ^link") == (
          "Some text",
          frozenset(),
          frozenset(["link"]),
      )
  
      extracted2 = ("Some text", frozenset(["tag", "tag2"]), frozenset(["link"]))
      assert extract_tags_links("Some text #tag #tag2 ^link") == extracted2
      assert extract_tags_links("Some text#tag#tag2 ^link") == (
          "Some text#tag#tag2",
          frozenset(),
          frozenset(["link"]),
      )
      assert extract_tags_links("Some text#tag#tag2^link") == (
          "Some text#tag#tag2^link",
          frozenset(),
          frozenset(),
      )
      assert extract_tags_links("#tag") == ("", frozenset(["tag"]), frozenset())
  