"""
:Copyright: 2007-2021 Jochen Kupperschmidt
:License: MIT, see LICENSE for details.
"""

from pathlib import Path
from tempfile import mkstemp

import pytest

from chatrelater.serialization import save_data, load_data


class LoadSaveContext(object):
    """A context to create a temporary filename and remove the file afterwards."""

    def __init__(self, data):
        self.data = data

    def __enter__(self):
        _, tmp_filename = mkstemp()
        self.filename = Path(tmp_filename)
        save_data(self.data, filename=self.filename)
        return self.filename

    def __exit__(self, *exc_info):
        self.filename.unlink()


def test_load_save_data():
    """Test saving data and then loading it again.

    Also, KeyErrors are expected if required keys are missing.
    """
    # Assure that missing keys raise a ``KeyError``.
    required_keys = frozenset(['nicknames', 'relations', 'directed'])
    for key in required_keys:
        keys = set(required_keys)
        keys.remove(key)
        assert_required_keys(dict.fromkeys(keys), True)
    assert_required_keys({'nicknames': None}, True)
    assert_required_keys(dict.fromkeys(required_keys), False)

    # Assure the exact data saved will be loaded afterwards.
    data = {
        'nicknames': 123,
        'relations': 456,
        'directed': True,
    }
    with LoadSaveContext(data) as filename:
        assert load_data(filename) == (123, 456, True)


def assert_required_keys(data, should_raise=False):
    with LoadSaveContext(data) as filename:
        if should_raise:
            with pytest.raises(KeyError):
                load_data(filename)
        else:
            load_data(filename)

"""
:Copyright: 2007-2021 Jochen Kupperschmidt
:License: MIT, see LICENSE for details.
"""

from pathlib import Path
from tempfile import mkstemp

import pytest

from chatrelater.serialization import save_data, load_data


class LoadSaveContext(object):
    """A context to create a temporary filename."""

    def __init__(self, tmp_path, data):
        self.tmp_path = tmp_path
        self.data = data

    def __enter__(self):
        self.filename = generate_tmp_file(self.tmp_path)
        save_data(self.data, filename=self.filename)
        return self.filename

    def __exit__(self, *exc_info):
        self.filename.unlink()


def test_load_save_data(tmp_path):
    """Test saving data and then loading it again.

    Also, KeyErrors are expected if required keys are missing.
    """
    # Assure that missing keys raise a ``KeyError``.
    required_keys = frozenset(['nicknames', 'relations', 'directed'])
    for key in required_keys:
        keys = set(required_keys)
        keys.remove(key)
        assert_required_keys(tmp_path, dict.fromkeys(keys), True)
    assert_required_keys(tmp_path, {'nicknames': None}, True)
    assert_required_keys(tmp_path, dict.fromkeys(required_keys), False)

    # Assure the exact data saved will be loaded afterwards.
    data = {
        'nicknames': 123,
        'relations': 456,
        'directed': True,
    }
    with LoadSaveContext(tmp_path, data) as filename:
        assert load_data(filename) == (123, 456, True)


def generate_tmp_file(tmp_path: Path) -> Path:
    _, tmp_filename = mkstemp(dir=tmp_path)
    return Path(tmp_filename)


def assert_required_keys(tmp_path, data, should_raise=False):
    with LoadSaveContext(tmp_path, data) as filename:
        if should_raise:
            with pytest.raises(KeyError):
                load_data(filename)
        else:
            load_data(filename)

Put temporary files into path provided by pytest's `tmp_path` fixture