2024-02-16 09:35:16 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
RSpec.describe ThemeSettingsObjectValidator do
|
|
|
|
describe "#validate" do
|
2024-02-19 13:19:35 +08:00
|
|
|
it "should return the right hash of error messages when properties are required but missing" do
|
2024-02-16 09:35:16 +08:00
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
title: {
|
|
|
|
type: "string",
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
description: {
|
|
|
|
type: "string",
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
links: {
|
|
|
|
type: "objects",
|
|
|
|
schema: {
|
|
|
|
name: "link",
|
|
|
|
properties: {
|
|
|
|
name: {
|
|
|
|
type: "string",
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
child_links: {
|
|
|
|
type: "objects",
|
|
|
|
schema: {
|
|
|
|
name: "child_link",
|
|
|
|
properties: {
|
|
|
|
title: {
|
|
|
|
type: "string",
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
not_required: {
|
|
|
|
type: "string",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
errors = described_class.new(schema:, object: {}).validate
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
expect(errors[:description].full_messages).to contain_exactly("must be present")
|
|
|
|
expect(errors[:title].full_messages).to contain_exactly("must be present")
|
2024-02-16 09:35:16 +08:00
|
|
|
|
|
|
|
errors =
|
|
|
|
described_class.new(
|
|
|
|
schema: schema,
|
|
|
|
object: {
|
|
|
|
links: [{ child_links: [{}, {}] }, {}],
|
|
|
|
},
|
|
|
|
).validate
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
expect(errors[:title].full_messages).to contain_exactly("must be present")
|
|
|
|
expect(errors[:description].full_messages).to contain_exactly("must be present")
|
|
|
|
expect(errors[:links][0][:name].full_messages).to contain_exactly("must be present")
|
|
|
|
|
|
|
|
expect(errors[:links][0][:child_links][0][:title].full_messages).to contain_exactly(
|
|
|
|
"must be present",
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(errors[:links][0][:child_links][1][:title].full_messages).to contain_exactly(
|
|
|
|
"must be present",
|
2024-02-16 09:35:16 +08:00
|
|
|
)
|
2024-02-21 15:27:42 +08:00
|
|
|
|
|
|
|
expect(errors[:links][1][:name].full_messages).to contain_exactly("must be present")
|
2024-02-16 09:35:16 +08:00
|
|
|
end
|
2024-02-19 13:19:35 +08:00
|
|
|
|
|
|
|
context "for enum properties" do
|
|
|
|
let(:schema) do
|
|
|
|
{
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
enum_property: {
|
|
|
|
type: "enum",
|
|
|
|
choices: ["choice 1", 2, false],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should not return any error messages when the value of the property is in the enum" do
|
|
|
|
expect(
|
|
|
|
described_class.new(schema: schema, object: { enum_property: "choice 1" }).validate,
|
|
|
|
).to eq({})
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not in the enum" do
|
2024-02-21 15:27:42 +08:00
|
|
|
errors =
|
|
|
|
described_class.new(schema: schema, object: { enum_property: "random_value" }).validate
|
|
|
|
|
|
|
|
expect(errors[:enum_property].full_messages).to contain_exactly(
|
|
|
|
"must be one of the following: [\"choice 1\", 2, false]",
|
|
|
|
)
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when enum property is not present" do
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: {}).validate
|
|
|
|
|
|
|
|
expect(errors[:enum_property].full_messages).to contain_exactly(
|
|
|
|
"must be one of the following: [\"choice 1\", 2, false]",
|
2024-02-19 13:19:35 +08:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "for boolean properties" do
|
|
|
|
let(:schema) { { name: "section", properties: { boolean_property: { type: "boolean" } } } }
|
|
|
|
|
|
|
|
it "should not return any error messages when the value of the property is of type boolean" do
|
|
|
|
expect(
|
|
|
|
described_class.new(schema: schema, object: { boolean_property: true }).validate,
|
|
|
|
).to eq({})
|
|
|
|
|
|
|
|
expect(
|
|
|
|
described_class.new(schema: schema, object: { boolean_property: false }).validate,
|
|
|
|
).to eq({})
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not of type boolean" do
|
2024-02-21 15:27:42 +08:00
|
|
|
errors =
|
|
|
|
described_class.new(schema: schema, object: { boolean_property: "string" }).validate
|
|
|
|
|
|
|
|
expect(errors[:boolean_property].full_messages).to contain_exactly("must be a boolean")
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "for float properties" do
|
|
|
|
let(:schema) { { name: "section", properties: { float_property: { type: "float" } } } }
|
|
|
|
|
|
|
|
it "should not return any error messages when the value of the property is of type integer or float" do
|
|
|
|
expect(described_class.new(schema: schema, object: { float_property: 1.5 }).validate).to eq(
|
|
|
|
{},
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(described_class.new(schema: schema, object: { float_property: 1 }).validate).to eq(
|
|
|
|
{},
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not of type float" do
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { float_property: "string" }).validate
|
|
|
|
|
|
|
|
expect(errors[:float_property].full_messages).to contain_exactly("must be a float")
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
2024-02-20 09:17:27 +08:00
|
|
|
|
|
|
|
it "should return the right hash of error messages when integer property does not satisfy min or max validations" do
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
float_property: {
|
|
|
|
type: "float",
|
|
|
|
validations: {
|
|
|
|
min: 5.5,
|
|
|
|
max: 11.5,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { float_property: 4.5 }).validate
|
|
|
|
|
|
|
|
expect(errors[:float_property].full_messages).to contain_exactly(
|
|
|
|
"must be larger than or equal to 5.5",
|
2024-02-20 09:17:27 +08:00
|
|
|
)
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { float_property: 12.5 }).validate
|
|
|
|
|
|
|
|
expect(errors[:float_property].full_messages).to contain_exactly(
|
|
|
|
"must be smaller than or equal to 11.5",
|
|
|
|
)
|
2024-02-20 09:17:27 +08:00
|
|
|
end
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
context "for integer properties" do
|
|
|
|
let(:schema) { { name: "section", properties: { integer_property: { type: "integer" } } } }
|
|
|
|
|
|
|
|
it "should not return any error messages when the value of the property is of type integer" do
|
|
|
|
expect(described_class.new(schema: schema, object: { integer_property: 1 }).validate).to eq(
|
|
|
|
{},
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not of type integer" do
|
2024-02-21 15:27:42 +08:00
|
|
|
errors =
|
|
|
|
described_class.new(schema: schema, object: { integer_property: "string" }).validate
|
2024-02-19 13:19:35 +08:00
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
expect(errors[:integer_property].full_messages).to contain_exactly("must be an integer")
|
|
|
|
|
|
|
|
errors = described_class.new(schema: schema, object: { integer_property: 1.0 }).validate
|
|
|
|
|
|
|
|
expect(errors[:integer_property].full_messages).to contain_exactly("must be an integer")
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
2024-02-20 09:17:27 +08:00
|
|
|
|
|
|
|
it "should not return any error messages when the value of the integer property satisfies min and max validations" do
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
integer_property: {
|
|
|
|
type: "integer",
|
|
|
|
validations: {
|
|
|
|
min: 5,
|
|
|
|
max: 10,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(described_class.new(schema: schema, object: { integer_property: 6 }).validate).to eq(
|
|
|
|
{},
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when integer property does not satisfy min or max validations" do
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
integer_property: {
|
|
|
|
type: "integer",
|
|
|
|
validations: {
|
|
|
|
min: 5,
|
|
|
|
max: 10,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { integer_property: 4 }).validate
|
|
|
|
|
|
|
|
expect(errors[:integer_property].full_messages).to contain_exactly(
|
|
|
|
"must be larger than or equal to 5",
|
2024-02-20 09:17:27 +08:00
|
|
|
)
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { integer_property: 11 }).validate
|
|
|
|
|
|
|
|
expect(errors[:integer_property].full_messages).to contain_exactly(
|
|
|
|
"must be smaller than or equal to 10",
|
|
|
|
)
|
2024-02-20 09:17:27 +08:00
|
|
|
end
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
context "for string properties" do
|
|
|
|
let(:schema) { { name: "section", properties: { string_property: { type: "string" } } } }
|
|
|
|
|
|
|
|
it "should not return any error messages when the value of the property is of type string" do
|
|
|
|
expect(
|
|
|
|
described_class.new(schema: schema, object: { string_property: "string" }).validate,
|
|
|
|
).to eq({})
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not of type string" do
|
2024-02-20 09:17:27 +08:00
|
|
|
schema = { name: "section", properties: { string_property: { type: "string" } } }
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { string_property: 1 }).validate
|
2024-02-20 09:17:27 +08:00
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
expect(errors[:string_property].full_messages).to contain_exactly("must be a string")
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
2024-02-20 09:17:27 +08:00
|
|
|
|
|
|
|
it "should return the right hash of error messages when string property does not statisfy url validation" do
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
string_property: {
|
|
|
|
type: "string",
|
|
|
|
validations: {
|
|
|
|
url: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors =
|
|
|
|
described_class.new(schema: schema, object: { string_property: "not a url" }).validate
|
|
|
|
|
|
|
|
expect(errors[:string_property].full_messages).to contain_exactly("must be a valid URL")
|
2024-02-20 09:17:27 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "should not return any error messages when the value of the string property satisfies min_length and max_length validations" do
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
string_property: {
|
|
|
|
type: "string",
|
|
|
|
validations: {
|
|
|
|
min_length: 5,
|
|
|
|
max_length: 10,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(
|
|
|
|
described_class.new(schema: schema, object: { string_property: "123456" }).validate,
|
|
|
|
).to eq({})
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when string property does not satisfy min_length or max_length validations" do
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
string_property: {
|
|
|
|
type: "string",
|
|
|
|
validations: {
|
|
|
|
min_length: 5,
|
|
|
|
max_length: 10,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors = described_class.new(schema: schema, object: { string_property: "1234" }).validate
|
2024-02-20 09:17:27 +08:00
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
expect(errors[:string_property].full_messages).to contain_exactly(
|
|
|
|
"must be at least 5 characters long",
|
|
|
|
)
|
|
|
|
|
|
|
|
errors =
|
|
|
|
described_class.new(schema: schema, object: { string_property: "12345678910" }).validate
|
|
|
|
|
|
|
|
expect(errors[:string_property].full_messages).to contain_exactly(
|
|
|
|
"must be at most 10 characters long",
|
|
|
|
)
|
2024-02-20 09:17:27 +08:00
|
|
|
end
|
2024-02-19 13:19:35 +08:00
|
|
|
end
|
2024-02-21 08:11:15 +08:00
|
|
|
|
|
|
|
context "for category properties" do
|
|
|
|
it "should not return any error message when the value of the property is a valid id of a category record" do
|
|
|
|
category = Fabricate(:category)
|
|
|
|
|
|
|
|
schema = { name: "section", properties: { category_property: { type: "category" } } }
|
|
|
|
|
|
|
|
expect(
|
|
|
|
described_class.new(schema: schema, object: { category_property: category.id }).validate,
|
|
|
|
).to eq({})
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not an integer" do
|
|
|
|
schema = { name: "section", properties: { category_property: { type: "category" } } }
|
|
|
|
|
2024-02-21 15:27:42 +08:00
|
|
|
errors =
|
|
|
|
described_class.new(schema: schema, object: { category_property: "string" }).validate
|
|
|
|
|
|
|
|
expect(errors[:category_property].full_messages).to contain_exactly(
|
|
|
|
"must be a valid category id",
|
|
|
|
)
|
2024-02-21 08:11:15 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "should return the right hash of error messages when value of property is not a valid id of a category record" do
|
|
|
|
category = Fabricate(:category)
|
|
|
|
|
|
|
|
schema = {
|
|
|
|
name: "section",
|
|
|
|
properties: {
|
|
|
|
category_property: {
|
|
|
|
type: "category",
|
|
|
|
},
|
|
|
|
category_property_2: {
|
|
|
|
type: "category",
|
|
|
|
},
|
|
|
|
child_categories: {
|
|
|
|
type: "objects",
|
|
|
|
schema: {
|
|
|
|
name: "child_category",
|
|
|
|
properties: {
|
|
|
|
category_property_3: {
|
|
|
|
type: "category",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
queries =
|
|
|
|
track_sql_queries do
|
2024-02-21 15:27:42 +08:00
|
|
|
errors =
|
2024-02-21 08:11:15 +08:00
|
|
|
described_class.new(
|
|
|
|
schema: schema,
|
|
|
|
object: {
|
|
|
|
category_property: 99_999_999,
|
|
|
|
category_property_2: 99_999_999,
|
|
|
|
child_categories: [
|
|
|
|
{ category_property_3: 99_999_999 },
|
|
|
|
{ category_property_3: category.id },
|
|
|
|
],
|
|
|
|
},
|
2024-02-21 15:27:42 +08:00
|
|
|
).validate
|
|
|
|
|
|
|
|
expect(errors[:category_property].full_messages).to contain_exactly(
|
|
|
|
"must be a valid category id",
|
2024-02-21 08:11:15 +08:00
|
|
|
)
|
2024-02-21 15:27:42 +08:00
|
|
|
|
|
|
|
expect(errors[:category_property_2].full_messages).to contain_exactly(
|
|
|
|
"must be a valid category id",
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(
|
|
|
|
errors[:child_categories][0][:category_property_3].full_messages,
|
|
|
|
).to contain_exactly("must be a valid category id")
|
|
|
|
|
|
|
|
expect(errors[:child_categories][1]).to eq({})
|
2024-02-21 08:11:15 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
# only 1 SQL query should be executed to check if category ids are valid
|
|
|
|
expect(queries.length).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
2024-02-16 09:35:16 +08:00
|
|
|
end
|
|
|
|
end
|