# frozen_string_literal: true

require "test_helper"
require "form_template"

class FormTemplateTest < Minitest::Test
	def test_form_one_field
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			title "TITLE"
			instructions "INSTRUCTIONS"
			field(var: "thevar", label: "thelabel")
		TEMPLATE
		form = template.render
		assert_equal :form, form.type
		assert_equal "TITLE", form.title
		assert_equal "INSTRUCTIONS", form.instructions
		assert_equal 1, form.fields.length
		assert_equal "thevar", form.fields[0].var
		assert_equal "thelabel", form.fields[0].label
	end

	def test_form_two_fields
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			field(var: "thevar", label: "thelabel")
			field(var: "thevar2", label: "thelabel2")
		TEMPLATE
		form = template.render
		assert_equal 2, form.fields.length
		assert_equal "thevar", form.fields[0].var
		assert_equal "thelabel", form.fields[0].label
		assert_equal "thevar2", form.fields[1].var
		assert_equal "thelabel2", form.fields[1].label
	end

	def test_result_no_fields
		template = FormTemplate.new(<<~TEMPLATE)
			result!
			title "TITLE"
			instructions "INSTRUCTIONS"
		TEMPLATE
		form = template.render
		assert_equal :result, form.type
		assert_equal "TITLE", form.title
		assert_equal "INSTRUCTIONS", form.instructions
	end

	def test_form_validate_basic
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			field(var: "thevar", label: "thelabel", datatype: "xs:integer")
		TEMPLATE
		form = template.render
		assert_equal 1, form.fields.length
		assert_equal "thevar", form.fields[0].var
		assert_equal "thelabel", form.fields[0].label
		validate = form.fields[0].find(
			"ns:validate",
			ns: "http://jabber.org/protocol/xdata-validate"
		).first
		assert_equal "xs:integer", validate[:datatype]
		assert_equal "basic", validate.children.first.name
	end

	def test_form_validate_open
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			field(var: "thevar", label: "thelabel", open: true)
		TEMPLATE
		form = template.render
		assert_equal 1, form.fields.length
		assert_equal "thevar", form.fields[0].var
		assert_equal "thelabel", form.fields[0].label
		validate = form.fields[0].find(
			"ns:validate",
			ns: "http://jabber.org/protocol/xdata-validate"
		).first
		assert_equal ["open"], validate.children.map(&:name)
	end

	def test_form_validate_regex
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			field(var: "thevar", label: "thelabel", regex: /[A-Z]/)
		TEMPLATE
		form = template.render
		assert_equal 1, form.fields.length
		assert_equal "thevar", form.fields[0].var
		assert_equal "thelabel", form.fields[0].label
		validate = form.fields[0].find(
			"ns:validate",
			ns: "http://jabber.org/protocol/xdata-validate"
		).first
		assert_equal ["regex"], validate.children.map(&:name)
		assert_equal "[A-Z]", validate.children.first.content
	end

	def test_form_validate_range
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			field(var: "thevar", label: "thelabel", range: (10..22))
		TEMPLATE
		form = template.render
		assert_equal 1, form.fields.length
		assert_equal "thevar", form.fields[0].var
		assert_equal "thelabel", form.fields[0].label
		validate = form.fields[0].find(
			"ns:validate",
			ns: "http://jabber.org/protocol/xdata-validate"
		).first
		assert_equal ["range"], validate.children.map(&:name)
		assert_equal "10", validate.children.first[:min]
		assert_equal "22", validate.children.first[:max]
	end

	def test_no_type
		template = FormTemplate.new(<<~TEMPLATE)
			title "TITLE"
			instructions "INSTRUCTIONS"
		TEMPLATE
		assert_raises { template.render }
	end

	def test_custom_xml
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			xml.whoever @arg
		TEMPLATE
		form = template.render(arg: "abc")
		assert_equal "abc", form.at("whoever").content
	end

	def test_table
		template = FormTemplate.new(<<~TEMPLATE)
			form!
			table(
				@arg,
				one: "One",
				two: { label: "Two", datatype: "xs:integer" },
				three: { label: "Three", type: "jid-single" }
			)
		TEMPLATE
		form = template.render(arg: [OpenStruct.new(one: 1, two: 2, three: 3)])
		assert_equal 3, form.at("reported").children.length
		assert_equal "one", form.at("reported").children[0][:var]
		assert_equal "two", form.at("reported").children[1][:var]
		assert_equal(
			"xs:integer",
			form.at("reported").children[1].at_xpath(
				"./ns:validate", ns: "http://jabber.org/protocol/xdata-validate"
			)[:datatype]
		)
		assert_equal "three", form.at("reported").children[2][:var]
		assert_equal "jid-single", form.at("reported").children[2][:type]
	end
end
