"""
Tests form async behaviour of gavo.formal.
"""

#c Copyright 2008-2024, the GAVO project <gavo@ari.uni-heidelberg.de>
#c
#c This program is free software, covered by the GNU GPL.  See the
#c COPYING file in the source distribution.


from twisted.web import template
from twisted.web.template import tags as T

from gavo import formal
from gavo.formal import validation
from gavo.helpers import trialhelpers

FK = formal.FORMS_KEY

class FormalTestResource(formal.ResourceWithForm):
	isLeaf = True
	result = None

	def form_borken(self, request):
		if request.args.get(b"input")==[b"break early"]:
			raise ValueError("Broken")

		form = formal.Form()
		form.addField("anint", formal.Integer(),
			label="A test integer input")
		form.addField("input", formal.String(),
			label="A test text input")
		form.addAction(self.evaluateBroken)
		return form
	
	def evaluateBroken(self, request, form, data):
		if data["input"]=="break late":
			return 1/0
		if data["input"]=="invalid":
			raise validation.FieldValidationError("Don't like that input",
				fieldName="input")
		self.result = "Ok: "+data["input"]

	@template.renderer
	def insertResult(self, request, tag):
		if self.result is None:
			return ""
		else:
			return tag[self.result]

	loader = template.TagLoader(T.html[
		T.body[T.p["Before form"],
			T.p(class_="result")(render="insertResult"),
			T.transparent(render="form borken"),
			T.p["After form"]]])


class BasicFormalTests(trialhelpers.RenderTest):
	@property
	def renderer(self):
		return FormalTestResource()

	def testFormEvaluationWoks(self):
		return self.assertPOSTHasStrings("/",
			{FK: ["borken"], "input": ["123"]}, [
			'<p class="result">Ok: 123'])

	def testGETDoesNotEvaluate(self):
		return self.assertGETLacksStrings("/",
			{FK: ["borken"], "input": ["123"]}, [
			"Ok: 123"])

	def testFormEvaluationErrorReported(self):
		return self.assertPOSTHasStrings("/",
			{FK: ["borken"], "input": ["invalid"]}, [
			'<p>Please correct the following error(s):',
			"Don't like that input</li>",
			'class="field string textinput error"',
			'value="invalid"'])

	def testFormRender(self):
		return self.assertGETHasStrings("/", {}, [
			'<form',
			'class="nevow-form"',
			'id="borken"',
			'action=""', 'method="post"',
			' id="borken-input-field" ',
			'<label', 'for="borken-input">',
			'A test text input</label>',
			'id="borken-action-submit"',
			'<p>Before form</p>',
			'<p>After form</p>'])

	def testBrokenHandlerTerminates(self):
		return self.assertPOSTHasStrings("/",
			{FK: ["borken"], "input": ["break late"]}, [
			"Unhandled exception while handling the form:"])

	def testBrokenFormMakerTerminates(self):
		return self.assertPOSTHasStrings("/",
			{FK: ["borken"], "input": ["break early"]}, [
			  "\n\nBroken", "Unhandled exception while handling the form:"])

	def testGETFillsEvenBrokenValues(self):
		return self.assertGETHasStrings("/honk",
			{FK: ["borken"], "input": ["break late"]}, [
			'action="honk"', 'value="break late"'])

	def testFormErrorInline(self):
		return self.assertPOSTHasStrings("/",
			{FK: ["borken"], "anint": ["invalid"]}, [
			"<p>Please correct the following error(s):",
			'<div class="message">Not a valid number</div>',
			'value="invalid"'])


class GettableTestResource(FormalTestResource):
	processOnGET = True


class ExtraGETTests(trialhelpers.RenderTest):
	@property
	def renderer(self):
		return GettableTestResource()

	def testFormEvaluationOnGET(self):
		return self.assertPOSTHasStrings("/",
			{FK: ["borken"], "input": ["123"]}, [
			"Ok: 123"])

	def testGETErrors(self):
		return self.assertGETHasStrings("/",
			{FK: ["borken"], "anint": ["invalid"]}, [
			"<p>Please correct the following error(s):",
			'<div class="message">Not a valid number</div>',
			'value="invalid"'])
