~singpolyma/sgx-jmp

75d1042bbb7e495bc026ef08372633f944dbde89 — Stephen Paul Weber 3 years ago d8cb729
Easy DSL for adding XEP-0122 validation to fields
2 files changed, 92 insertions(+), 2 deletions(-)

M lib/form_template.rb
M test/test_form_template.rb
M lib/form_template.rb => lib/form_template.rb +24 -2
@@ 48,8 48,30 @@ class FormTemplate
			@__form.instructions = s
		end

		def field(**kwargs)
			@__form.fields = @__form.fields + [kwargs]
		def validate(f, datatype: nil, **kwargs)
			Nokogiri::XML::Builder.with(f) do |x|
				x.validate(
					xmlns: "http://jabber.org/protocol/xdata-validate",
					datatype: datatype || "xs:string"
				) do
					x.basic unless validation_type(x, **kwargs)
				end
			end
		end

		def validation_type(x, open: false, regex: nil, range: nil)
			x.open if open
			x.range(min: range.first, max: range.last) if range
			x.regex(regex.source) if regex
			open || regex || range
		end

		def field(datatype: nil, open: false, regex: nil, range: nil, **kwargs)
			f = Blather::Stanza::X::Field.new(kwargs)
			if datatype || open || regex || range
				validate(f, datatype: datatype, open: open, regex: regex, range: range)
			end
			@__form.fields += [f]
		end

		def xml

M test/test_form_template.rb => test/test_form_template.rb +68 -0
@@ 46,6 46,74 @@ class FormTemplateTest < Minitest::Test
		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"