# (c) cavaliba.com - tests - helper_export.py

"""Exporter view helpers: every export is a DataTask, so a test that wants the
exported bytes has to run the task and read its attachment instead of reading the
POST response. A calling class needs CELERY_TASK_ALWAYS_EAGER=True (the task then
runs inside the POST) and isolate_filestore() in its setUp."""

import shutil
import tempfile

from django.test import override_settings
from django.urls import reverse

from app_data.models import DataFile, DataTask


def isolate_filestore(testcase):
    """Point CAVALIBA_FILESTORE at a throwaway directory for one test.

    An export writes a real blob, and the test DB is dropped at the end of the run
    while the blob is not - so without this every run would leave orphans behind in
    the shared filestore."""

    rootdir = tempfile.mkdtemp(prefix="cavaliba_test_filestore_")
    override = override_settings(CAVALIBA_FILESTORE=rootdir)
    override.enable()
    testcase.addCleanup(override.disable)
    testcase.addCleanup(shutil.rmtree, rootdir, ignore_errors=True)
    return rootdir


def export_post(testcase, **data):
    """POST the Exporter form and return the response, asserting nothing."""

    return testcase.client.post(reverse("app_data:data_exporter"), data)


def export_submit(testcase, **data):
    """POST the Exporter form and return the submitted DataTask.

    Asserts the page re-rendered (200) with a task handle - which is also what opens
    the progress modal. Says nothing about the task's state, so a failing export can
    use this too."""

    response = export_post(testcase, **data)
    testcase.assertEqual(response.status_code, 200)
    handle = response.context["task_handle"]
    testcase.assertTrue(handle, "no export task was submitted")
    return DataTask.objects.get(handle=handle)


def export_bytes(testcase, **data):
    """Run one export through the view and return its result file's raw bytes."""

    task = export_submit(testcase, **data)
    testcase.assertEqual(task.state, "DONE", task.output)
    datafile = DataFile.objects.get(fileid=task.attachment["fileid"])
    with open(datafile.filepath, "rb") as f:
        return f.read()


def export_text(testcase, **data):
    """Run one export through the view and return its result file as text, decoded
    with the encoding the export was asked for (utf-8 by default)."""

    return export_bytes(testcase, **data).decode(data.get("encoding") or "utf-8")
