testing stuff
This commit is contained in:
parent
c90629ed3d
commit
97f88f9df8
|
@ -155,10 +155,10 @@ args._validation_errors # => {"age" => ["must be an integer"]}
|
||||||
|
|
||||||
ArgParser is designed to be configurable so it can handle a wide variety of use cases. As such, it includes several overridable methods which can be used to modify its behavior. These are:
|
ArgParser is designed to be configurable so it can handle a wide variety of use cases. As such, it includes several overridable methods which can be used to modify its behavior. These are:
|
||||||
|
|
||||||
- `on_validation_error` - called when a validation error occurs
|
- `on_validation_error` - called when a validation error occurs; by default calls `add_validation_error` and then raises `ArgParser::ValidationError`
|
||||||
- `on_unknown_attribute` - called when an unknown attribute is encountered
|
- `on_unknown_attribute` - called when an unknown attribute is encountered; by default raises `ArgParser::UnknownAttributeError`
|
||||||
- `on_missing_attribute` - called when a required attribute is missing
|
- `on_missing_attribute` - called when a required attribute is missing; by default raises `ArgParser::MissingAttributeError`
|
||||||
- `on_conversion_error` - called when a value isn't able to be converted to the specified type
|
- `on_conversion_error` - called when a value isn't able to be converted to the specified type; by default raises `ArgParser::ConversionError`
|
||||||
|
|
||||||
In addition, the way keys are parsed can be modified by overriding the `parse_key` method. By default, it simply removes one or two dashes from the beginning of the key. For example, `--name` becomes `name`, and `-n` becomes `n`.
|
In addition, the way keys are parsed can be modified by overriding the `parse_key` method. By default, it simply removes one or two dashes from the beginning of the key. For example, `--name` becomes `name`, and `-n` becomes `n`.
|
||||||
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
require "./spec_helper"
|
|
||||||
|
|
||||||
Spectator.describe ArgParser do
|
|
||||||
context "supported arguments" do
|
|
||||||
let(args) { ["--name", "John Doe", "--age", "32", "--height", "163.2", "--is_human", "true", "--website", "https://example.com", "--id", "39aacd14-9e1b-11ed-91ad-b44506ca30d5"] }
|
|
||||||
let(parser) { TestSupportedArgs.new(args) }
|
|
||||||
|
|
||||||
it "parses name" do
|
|
||||||
expect(parser.name).to eq("John Doe")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "parses age" do
|
|
||||||
expect(parser.age).to be_a(Int32)
|
|
||||||
expect(parser.age).to eq(32)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "parses height" do
|
|
||||||
expect(parser.height).to be_a(Float64)
|
|
||||||
expect(parser.height).to eq(163.2)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "parses is_human" do
|
|
||||||
expect(parser.is_human).to be_a(Bool)
|
|
||||||
expect(parser.is_human).to eq(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "parses website" do
|
|
||||||
expect(parser.website).to be_a(URI)
|
|
||||||
expect(parser.website.to_s).to eq("https://example.com")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "parses id" do
|
|
||||||
expect(parser.id).to be_a(UUID)
|
|
||||||
expect(parser.id.to_s).to eq("39aacd14-9e1b-11ed-91ad-b44506ca30d5")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -19,3 +19,28 @@ struct TestSupportedArgs
|
||||||
|
|
||||||
getter id : UUID
|
getter id : UUID
|
||||||
end
|
end
|
||||||
|
|
||||||
|
enum Color
|
||||||
|
Red
|
||||||
|
Green
|
||||||
|
Blue
|
||||||
|
end
|
||||||
|
|
||||||
|
struct TestConverters
|
||||||
|
include ArgParser
|
||||||
|
|
||||||
|
@[ArgParser::Field(converter: ArgParser::CommaSeparatedArrayConverter(Int32))]
|
||||||
|
getter ids : Array(Int32)
|
||||||
|
|
||||||
|
@[ArgParser::Field(converter: ArgParser::EpochConverter)]
|
||||||
|
getter unix : Time
|
||||||
|
|
||||||
|
@[ArgParser::Field(converter: ArgParser::EpochMillisConverter, key: "unix-ms")]
|
||||||
|
getter unix_ms : Time
|
||||||
|
|
||||||
|
@[ArgParser::Field(converter: ArgParser::EnumNameConverter(Color))]
|
||||||
|
getter color : Color
|
||||||
|
|
||||||
|
@[ArgParser::Field(converter: ArgParser::EnumValueConverter(Color))]
|
||||||
|
getter ncolor : Color
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
require "../spec_helper"
|
||||||
|
|
||||||
|
Spectator.describe ArgParser do
|
||||||
|
let(args) { ["--name", "John Doe", "--age", "32", "--height", "163.2", "--is_human", "--website", "https://example.com", "--id", "39aacd14-9e1b-11ed-91ad-b44506ca30d5"] }
|
||||||
|
let(parser) { TestSupportedArgs.new(args) }
|
||||||
|
|
||||||
|
it "parses string values" do
|
||||||
|
expect(parser.name).to eq("John Doe")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "parses int32 values" do
|
||||||
|
expect(parser.age).to be_a(Int32)
|
||||||
|
expect(parser.age).to eq(32)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "parses float64 value" do
|
||||||
|
expect(parser.height).to be_a(Float64)
|
||||||
|
expect(parser.height).to eq(163.2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "parses boolean values" do
|
||||||
|
expect(parser.is_human).to be_a(Bool)
|
||||||
|
expect(parser.is_human).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "parses uri values" do
|
||||||
|
expect(parser.website).to be_a(URI)
|
||||||
|
expect(parser.website.to_s).to eq("https://example.com")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "parses uuid values" do
|
||||||
|
expect(parser.id).to be_a(UUID)
|
||||||
|
expect(parser.id.to_s).to eq("39aacd14-9e1b-11ed-91ad-b44506ca30d5")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
require "../spec_helper"
|
||||||
|
|
||||||
|
Spectator.describe "ArgParser converters" do
|
||||||
|
let(args) { ["--ids", "1,2,3,4", "--unix", "1674843165", "--unix-ms", "1674843241159", "--color", "red", "--ncolor", "2"] }
|
||||||
|
let(parser) { TestConverters.new(args) }
|
||||||
|
|
||||||
|
it "converts comma separated list to array" do
|
||||||
|
expect(parser.ids).to eq [1, 2, 3, 4]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts unix time to time" do
|
||||||
|
expect(parser.unix).to eq Time.unix(1674843165)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts unix time to time" do
|
||||||
|
expect(parser.unix_ms).to eq Time.unix_ms(1674843241159)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts string to color" do
|
||||||
|
expect(parser.color).to eq Color::Red
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts string to color" do
|
||||||
|
expect(parser.ncolor).to eq Color::Blue
|
||||||
|
end
|
||||||
|
end
|
|
@ -84,7 +84,7 @@ module ArgParser
|
||||||
{% elsif value[:type] < Array %}
|
{% elsif value[:type] < Array %}
|
||||||
%var{name} ||= [] of {{value[:type].type_vars[0]}}
|
%var{name} ||= [] of {{value[:type].type_vars[0]}}
|
||||||
{% if value[:converter] %}
|
{% if value[:converter] %}
|
||||||
%var{name} << {{ value[:converter] }}.from_arg(value)
|
%var{name}.concat {{ value[:converter] }}.from_arg(value)
|
||||||
{% else %}
|
{% else %}
|
||||||
%var{name} << ::Union({{value[:type].type_vars[0]}}).from_arg(value)
|
%var{name} << ::Union({{value[:type].type_vars[0]}}).from_arg(value)
|
||||||
{% end %}
|
{% end %}
|
||||||
|
@ -146,8 +146,6 @@ module ArgParser
|
||||||
|
|
||||||
%validator{name} = {{ validator.name(generic_args: false) }}.new({{ args.join(", ").id }})
|
%validator{name} = {{ validator.name(generic_args: false) }}.new({{ args.join(", ").id }})
|
||||||
if %found{name} && !%validator{name}.validate({{name.id.stringify}}, @{{name}})
|
if %found{name} && !%validator{name}.validate({{name.id.stringify}}, @{{name}})
|
||||||
@_validation_errors[{{name.stringify}}] ||= [] of String
|
|
||||||
@_validation_errors[{{name.stringify}}] += %validator{name}.errors
|
|
||||||
on_validation_error({{name.stringify}}, @{{name}}, %validator{name}.errors)
|
on_validation_error({{name.stringify}}, @{{name}}, %validator{name}.errors)
|
||||||
end
|
end
|
||||||
{% end %}
|
{% end %}
|
||||||
|
@ -189,7 +187,8 @@ module ArgParser
|
||||||
#
|
#
|
||||||
# Note: You can override this method to change the way validation errors are handled.
|
# Note: You can override this method to change the way validation errors are handled.
|
||||||
def on_validation_error(key : String, value, errors : Array(String))
|
def on_validation_error(key : String, value, errors : Array(String))
|
||||||
raise ValidationError.new(key, errors)
|
add_validation_error(key, erorrs)
|
||||||
|
raise ValidationError.new(key, value, errors)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Called when a value cannot be converted to the expected type.
|
# Called when a value cannot be converted to the expected type.
|
||||||
|
@ -199,6 +198,11 @@ module ArgParser
|
||||||
raise ConversionError.new(key, value, type)
|
raise ConversionError.new(key, value, type)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_validation_error(key : String, value, errors : Array(String))
|
||||||
|
@errors[key] ||= [] of String
|
||||||
|
@errors[key].concat errors
|
||||||
|
end
|
||||||
|
|
||||||
# https://en.wikipedia.org/wiki/Quotation_mark#Summary_table
|
# https://en.wikipedia.org/wiki/Quotation_mark#Summary_table
|
||||||
QUOTE_CHARS = {'"' => '"', '“' => '”', '‘' => '’', '«' => '»', '‹' => '›', '❛' => '❜', '❝' => '❞', '❮' => '❯', '"' => '"'}
|
QUOTE_CHARS = {'"' => '"', '“' => '”', '‘' => '’', '«' => '»', '‹' => '›', '❛' => '❜', '❝' => '❞', '❮' => '❯', '"' => '"'}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module ArgParser::EnumValueConverter(E)
|
module ArgParser::EnumValueConverter(E)
|
||||||
def self.from_arg(arg)
|
def self.from_arg(arg)
|
||||||
E.new(arg)
|
E.from_value(arg.to_i64)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module ArgParser::EpochConverter
|
module ArgParser::EpochConverter
|
||||||
def self.from_arg(arg)
|
def self.from_arg(arg)
|
||||||
Time.epoch(arg.to_i64)
|
Time.unix(arg.to_i64)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module ArgParser::EpochMillisConverter
|
module ArgParser::EpochMillisConverter
|
||||||
def self.from_arg(arg)
|
def self.from_arg(arg)
|
||||||
Time.epoch_ms(arg.to_i64)
|
Time.unix_ms(arg.to_i64)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,8 +18,9 @@ module ArgParser
|
||||||
end
|
end
|
||||||
|
|
||||||
class ValidationError < Error
|
class ValidationError < Error
|
||||||
def initialize(name, errors)
|
def initialize(name, value, errors)
|
||||||
super("Validation failed for #{name}: #{errors.join(", ")}")
|
super("Validation failed for field :#{name} with value #{value.inspect}:\n" +
|
||||||
|
errors.map { |e| " - #{e}" }.join("\n"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue