Skip to content

Commit ae46e79

Browse files
committed
Coerce inputs from Int Value to Float Value
1 parent d608c56 commit ae46e79

File tree

3 files changed

+67
-58
lines changed

3 files changed

+67
-58
lines changed

src/GraphQLResponse.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,20 @@ void Value::set<BooleanType>(BooleanType value)
363363
template <>
364364
void Value::set<IntType>(IntType value)
365365
{
366-
if (type() != Type::Int)
366+
if (type() == Type::Float)
367367
{
368-
throw std::logic_error("Invalid call to Value::set for IntType");
368+
// Coerce IntType to FloatType
369+
*_data = { static_cast<FloatType>(value) };
369370
}
371+
else
372+
{
373+
if (type() != Type::Int)
374+
{
375+
throw std::logic_error("Invalid call to Value::set for IntType");
376+
}
370377

371-
*_data = { value };
378+
*_data = { value };
379+
}
372380
}
373381

374382
template <>
@@ -452,6 +460,12 @@ IntType Value::get<IntType>() const
452460
template <>
453461
FloatType Value::get<FloatType>() const
454462
{
463+
if (type() == Type::Int)
464+
{
465+
// Coerce IntType to FloatType
466+
return static_cast<FloatType>(std::get<IntType>(*_data));
467+
}
468+
455469
if (type() != Type::Float)
456470
{
457471
throw std::logic_error("Invalid call to Value::get for FloatType");

src/GraphQLService.cpp

Lines changed: 21 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,8 @@ response::IntType ModifiedArgument<response::IntType>::convert(const response::V
677677
template <>
678678
response::FloatType ModifiedArgument<response::FloatType>::convert(const response::Value& value)
679679
{
680-
if (value.type() != response::Type::Float)
680+
if (value.type() != response::Type::Float
681+
&& value.type() != response::Type::Int)
681682
{
682683
throw schema_exception { { "not a float" } };
683684
}
@@ -726,8 +727,7 @@ response::IdType ModifiedArgument<response::IdType>::convert(const response::Val
726727
return Base64::fromBase64(encoded.c_str(), encoded.size());
727728
}
728729

729-
template <>
730-
std::future<response::Value> ModifiedResult<response::IntType>::convert(FieldResult<response::IntType>&& result, ResolverParams&& params)
730+
void blockSubFields(const ResolverParams& params)
731731
{
732732
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
733733
if (params.selection != nullptr)
@@ -739,6 +739,12 @@ std::future<response::Value> ModifiedResult<response::IntType>::convert(FieldRes
739739

740740
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
741741
}
742+
}
743+
744+
template <>
745+
std::future<response::Value> ModifiedResult<response::IntType>::convert(FieldResult<response::IntType>&& result, ResolverParams&& params)
746+
{
747+
blockSubFields(params);
742748

743749
return resolve(std::move(result), std::move(params),
744750
[](response::IntType&& value, const ResolverParams&)
@@ -750,16 +756,7 @@ std::future<response::Value> ModifiedResult<response::IntType>::convert(FieldRes
750756
template <>
751757
std::future<response::Value> ModifiedResult<response::FloatType>::convert(FieldResult<response::FloatType>&& result, ResolverParams&& params)
752758
{
753-
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
754-
if (params.selection != nullptr)
755-
{
756-
auto position = params.selection->begin();
757-
std::ostringstream error;
758-
759-
error << "Field may not have sub-fields name: " << params.fieldName;
760-
761-
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
762-
}
759+
blockSubFields(params);
763760

764761
return resolve(std::move(result), std::move(params),
765762
[](response::FloatType&& value, const ResolverParams&)
@@ -771,16 +768,7 @@ std::future<response::Value> ModifiedResult<response::FloatType>::convert(FieldR
771768
template <>
772769
std::future<response::Value> ModifiedResult<response::StringType>::convert(FieldResult<response::StringType>&& result, ResolverParams&& params)
773770
{
774-
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
775-
if (params.selection != nullptr)
776-
{
777-
auto position = params.selection->begin();
778-
std::ostringstream error;
779-
780-
error << "Field may not have sub-fields name: " << params.fieldName;
781-
782-
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
783-
}
771+
blockSubFields(params);
784772

785773
return resolve(std::move(result), std::move(params),
786774
[](response::StringType&& value, const ResolverParams&)
@@ -792,16 +780,7 @@ std::future<response::Value> ModifiedResult<response::StringType>::convert(Field
792780
template <>
793781
std::future<response::Value> ModifiedResult<response::BooleanType>::convert(FieldResult<response::BooleanType>&& result, ResolverParams&& params)
794782
{
795-
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
796-
if (params.selection != nullptr)
797-
{
798-
auto position = params.selection->begin();
799-
std::ostringstream error;
800-
801-
error << "Field may not have sub-fields name: " << params.fieldName;
802-
803-
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
804-
}
783+
blockSubFields(params);
805784

806785
return resolve(std::move(result), std::move(params),
807786
[](response::BooleanType&& value, const ResolverParams&)
@@ -813,16 +792,7 @@ std::future<response::Value> ModifiedResult<response::BooleanType>::convert(Fiel
813792
template <>
814793
std::future<response::Value> ModifiedResult<response::Value>::convert(FieldResult<response::Value>&& result, ResolverParams&& params)
815794
{
816-
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
817-
if (params.selection != nullptr)
818-
{
819-
auto position = params.selection->begin();
820-
std::ostringstream error;
821-
822-
error << "Field may not have sub-fields name: " << params.fieldName;
823-
824-
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
825-
}
795+
blockSubFields(params);
826796

827797
return resolve(std::move(result), std::move(params),
828798
[](response::Value&& value, const ResolverParams&)
@@ -834,16 +804,7 @@ std::future<response::Value> ModifiedResult<response::Value>::convert(FieldResul
834804
template <>
835805
std::future<response::Value> ModifiedResult<response::IdType>::convert(FieldResult<response::IdType>&& result, ResolverParams&& params)
836806
{
837-
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
838-
if (params.selection != nullptr)
839-
{
840-
auto position = params.selection->begin();
841-
std::ostringstream error;
842-
843-
error << "Field may not have sub-fields name: " << params.fieldName;
844-
845-
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
846-
}
807+
blockSubFields(params);
847808

848809
return resolve(std::move(result), std::move(params),
849810
[](response::IdType&& value, const ResolverParams&)
@@ -852,8 +813,7 @@ std::future<response::Value> ModifiedResult<response::IdType>::convert(FieldResu
852813
});
853814
}
854815

855-
template <>
856-
std::future<response::Value> ModifiedResult<Object>::convert(FieldResult<std::shared_ptr<Object>>&& result, ResolverParams&& params)
816+
void requireSubFields(const ResolverParams& params)
857817
{
858818
// http://spec.graphql.org/June2018/#sec-Leaf-Field-Selections
859819
if (params.selection == nullptr)
@@ -865,6 +825,12 @@ std::future<response::Value> ModifiedResult<Object>::convert(FieldResult<std::sh
865825

866826
throw schema_exception { { schema_error{ error.str(), { position.line, position.column }, { params.errorPath } } } };
867827
}
828+
}
829+
830+
template <>
831+
std::future<response::Value> ModifiedResult<Object>::convert(FieldResult<std::shared_ptr<Object>>&& result, ResolverParams&& params)
832+
{
833+
requireSubFields(params);
868834

869835
return std::async(params.launch,
870836
[](FieldResult<std::shared_ptr<Object>>&& resultFuture, ResolverParams&& paramsFuture)

test/TodayTests.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,3 +1524,32 @@ TEST_F(TodayServiceCase, MutateSetFloat)
15241524
FAIL() << response::toJSON(ex.getErrors());
15251525
}
15261526
}
1527+
1528+
TEST_F(TodayServiceCase, MutateCoerceSetFloat)
1529+
{
1530+
auto query = R"(mutation {
1531+
coerceFloat: setFloat(value: 1)
1532+
})"_graphql;
1533+
response::Value variables(response::Type::Map);
1534+
auto state = std::make_shared<today::RequestState>(22);
1535+
auto result = _service->resolve(state, query, "", std::move(variables)).get();
1536+
1537+
try
1538+
{
1539+
ASSERT_TRUE(result.type() == response::Type::Map);
1540+
auto errorsItr = result.find("errors");
1541+
if (errorsItr != result.get<response::MapType>().cend())
1542+
{
1543+
FAIL() << response::toJSON(response::Value(errorsItr->second));
1544+
}
1545+
const auto data = service::ScalarArgument::require("data", result);
1546+
ASSERT_TRUE(data.type() == response::Type::Map);
1547+
const auto coerceFloat = service::FloatArgument::require("coerceFloat", data);
1548+
ASSERT_EQ(1.0, coerceFloat) << "should return the value that was coerced from an int";
1549+
ASSERT_EQ(1.0, today::Mutation::getFloat()) << "should save the value in the Mutation static member";
1550+
}
1551+
catch (service::schema_exception & ex)
1552+
{
1553+
FAIL() << response::toJSON(ex.getErrors());
1554+
}
1555+
}

0 commit comments

Comments
 (0)