DATE = "date" AUTOCOMPLETE = "autocomplete" RANGE = "range" STRING = "string" VALUE_LIST = "value-list" def get_registry(registry):
    """
    :rtype: MultiseekRegistry
    """

    if isinstance(registry, str):
        if registry not in _cached_registry:
            m = importlib.import_module(registry).registry
            _cached_registry[registry] = m
        return _cached_registry[registry]

    return registry class Language(models.Model):
    name = models.TextField()
    description = models.TextField()

    def __str__(self):
        return self.name class Author(models.Model):
    last_name = models.TextField()
    first_name = models.TextField()

    def __str__(self):
        return u"%s %s" % (self.first_name, self.last_name) class Book(models.Model):
    title = models.TextField()
    year = models.IntegerField()
    language = models.ForeignKey(Language, on_delete=models.CASCADE)
    authors = models.ManyToManyField(Author)
    no_editors = models.IntegerField()
    last_updated = models.DateField(auto_now=True)
    available = models.BooleanField(default=False)

    def __str__(self):
        return u"%s by %s" % (self.title, u", ".join(
            [str(author) for author in self.authors.all()])) class wait_for_page_load(object):
    def __init__(self, browser):
        self.browser = browser

    def __enter__(self):
        self.old_page = self.browser.find_by_tag("html")[0]._element

    def __exit__(self, *_):
        WebDriverWait(self.browser, 10).until(
            lambda driver: staleness_of(self.old_page)
        )
import json
import pytest
import datetime
from django.conf import settings
from django.urls import reverse
from model_bakery import baker
from selenium.webdriver.support.expected_conditions import staleness_of, \
    alert_is_present
from selenium.webdriver.support.ui import WebDriverWait
from splinter.exceptions import ElementDoesNotExist
from multiseek.logic import DATE, AUTOCOMPLETE, RANGE, STRING, VALUE_LIST, \
    get_registry
from .models import Language, Author, Book
from builtins import str as text
from django.utils.translation import gettext_lazy as _
from .testutil import wait_for_page_load
            self.browser.visit(url)


class MultiseekWebPage(SplinterLoginMixin):
    """Helper functions, that take care of the multiseek form web page
    """

    def __init__(self, registry, browser, live_server_url):
        self.browser = browser
        self.registry = registry
        self.live_server_url = live_server_url

    def get_frame(self, id):
        """Ta funkcja zwraca multiseekową "ramkę" po jej ID
        """
        frame = self.browser.find_by_id(id)
        ret = dict()
        ret['frame'] = frame[0]
        fieldset = frame.find_by_tag('fieldset')
        ret['add_field'] = fieldset.find_by_id("add_field")[0]
        ret['add_frame'] = fieldset.find_by_id("add_frame")[0]
        ret['fields'] = fieldset.find_by_id("field-list")[0]

        return ret

    def extract_field_data(self, element):
        """Ta funkcja zwraca słownik z wartościami dla danego pola w
        formularzu. Pole - czyli wiersz z kolejnymi selectami:

            pole przeszukiwane, operacja, wartość wyszukiwana,
            następna operacja, przycisk zamknięcia

        Z pomocniczych wartości, zwracanych w słowniku mamy 'type' czyli
        tekstowy typ, odpowiadający definicjom w bpp.multiseek.logic.fields.keys()

        Zwracana wartość słownika 'value' może być różna dla różnych typów
        pól (np dla multiseek.logic.RANGE jest to lista z wartościami z obu pól)
        """
        ret = {}

        for elem in ['type', 'op', 'prev-op', 'close-button']:
            try:
                e = element.find_by_id(elem, wait_time=0)[0]
            except ElementDoesNotExist as x:
                # prev-op may be None
                if elem != 'prev-op':
                    raise x
                e = None

            ret[elem] = e

        selected = ret['type'].value
        ret['selected'] = selected

        inner_type = self.registry.field_by_name.get(selected).type
        ret['inner_type'] = inner_type

        if inner_type in [STRING, VALUE_LIST]:
            ret['value_widget'] = element.find_by_id("value")

        elif inner_type == RANGE:
            ret['value_widget'] = [
                element.find_by_id("value_min"),
                element.find_by_id("value_max")]

        elif inner_type == DATE:
            ret['value_widget'] = [
                element.find_by_id("value"),
                element.find_by_id("value_max")]

        elif inner_type == AUTOCOMPLETE:
            ret['value_widget'] = element.find_by_id("value")

        else:
            raise NotImplementedError(inner_type)

        code = '$("#%s").multiseekField("getValue")' % element['id']
        ret['value'] = self.browser.evaluate_script(code)

        if ret['inner_type'] in (DATE, AUTOCOMPLETE, RANGE):
            if ret['value']:
                ret['value'] = json.loads(ret['value'])
        return ret

    def get_field(self, id):
        field = self.browser.find_by_id(id)
        if len(field) != 1:
            raise Exception("field not found")
        return self.extract_field_data(field[0])

    def serialize(self):
        """Zwraca wartość funkcji serialize() dla formularza, w postaci
        listy -- czyli obiekt JSON"""
        return self.browser.evaluate_script(
            "$('#frame-0').multiseekFrame('serialize')")

    def get_field_value(self, field):
        return self.browser.evaluate_script(
            '$("#%s").multiseekField("getValue")' % field)

    def add_frame(self, frame="frame-0", prev_op=None):
        if not prev_op:
            return self.execute_script(
                """$("#%s").multiseekFrame('addFrame');""" % frame)

        return self.execute_script("""
            $("#%s").multiseekFrame('addFrame', '%s');
        """ % (frame, prev_op))

    def add_field(self, frame, label, op, value):
        code = """
        $("#%(frame)s").multiseekFrame("addField", "%(label)s", "%(op)s", %(value)s);
        """ % dict(frame=frame,
                   label=text(label),
                   op=text(op),
                   value=json.dumps(value))

        self.browser.execute_script(code)

    def load_form_by_name(self, name):

        with wait_for_page_load(self.browser):