mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-23 19:49:43 +01:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request As title <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Tests should be picked up and run and pass
284 lines
9.6 KiB
C++
284 lines
9.6 KiB
C++
#include "pch.h"
|
|
#include "TestHelpers.h"
|
|
#include <json.h>
|
|
|
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
|
using namespace winrt::Windows::Data::Json;
|
|
|
|
namespace UnitTestsCommonUtils
|
|
{
|
|
TEST_CLASS(JsonTests)
|
|
{
|
|
public:
|
|
// from_file tests
|
|
TEST_METHOD(FromFile_NonExistentFile_ReturnsNullopt)
|
|
{
|
|
auto result = json::from_file(L"C:\\NonExistent\\File\\Path.json");
|
|
Assert::IsFalse(result.has_value());
|
|
}
|
|
|
|
TEST_METHOD(FromFile_ValidJsonFile_ReturnsJsonObject)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
tempFile.write("{\"key\": \"value\"}");
|
|
|
|
auto result = json::from_file(tempFile.path());
|
|
Assert::IsTrue(result.has_value());
|
|
}
|
|
|
|
TEST_METHOD(FromFile_InvalidJson_ReturnsNullopt)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
tempFile.write("not valid json {{{");
|
|
|
|
auto result = json::from_file(tempFile.path());
|
|
Assert::IsFalse(result.has_value());
|
|
}
|
|
|
|
TEST_METHOD(FromFile_EmptyFile_ReturnsNullopt)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
// File is empty
|
|
|
|
auto result = json::from_file(tempFile.path());
|
|
Assert::IsFalse(result.has_value());
|
|
}
|
|
|
|
TEST_METHOD(FromFile_ValidComplexJson_ParsesCorrectly)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
tempFile.write("{\"name\": \"test\", \"value\": 42, \"enabled\": true}");
|
|
|
|
auto result = json::from_file(tempFile.path());
|
|
Assert::IsTrue(result.has_value());
|
|
|
|
auto& obj = *result;
|
|
Assert::IsTrue(obj.HasKey(L"name"));
|
|
Assert::IsTrue(obj.HasKey(L"value"));
|
|
Assert::IsTrue(obj.HasKey(L"enabled"));
|
|
}
|
|
|
|
// to_file tests
|
|
TEST_METHOD(ToFile_ValidObject_WritesFile)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"key", JsonValue::CreateStringValue(L"value"));
|
|
json::to_file(tempFile.path(), obj);
|
|
|
|
// Read back and verify
|
|
auto result = json::from_file(tempFile.path());
|
|
Assert::IsTrue(result.has_value());
|
|
Assert::IsTrue(result->HasKey(L"key"));
|
|
}
|
|
|
|
TEST_METHOD(ToFile_ComplexObject_WritesFile)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"name", JsonValue::CreateStringValue(L"test"));
|
|
obj.SetNamedValue(L"value", JsonValue::CreateNumberValue(42));
|
|
obj.SetNamedValue(L"enabled", JsonValue::CreateBooleanValue(true));
|
|
json::to_file(tempFile.path(), obj);
|
|
|
|
auto result = json::from_file(tempFile.path());
|
|
Assert::IsTrue(result.has_value());
|
|
Assert::AreEqual(std::wstring(L"test"), std::wstring(result->GetNamedString(L"name")));
|
|
Assert::AreEqual(42.0, result->GetNamedNumber(L"value"));
|
|
Assert::IsTrue(result->GetNamedBoolean(L"enabled"));
|
|
}
|
|
|
|
// has tests
|
|
TEST_METHOD(Has_ExistingKey_ReturnsTrue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"key", JsonValue::CreateStringValue(L"value"));
|
|
Assert::IsTrue(json::has(obj, L"key", JsonValueType::String));
|
|
}
|
|
|
|
TEST_METHOD(Has_NonExistingKey_ReturnsFalse)
|
|
{
|
|
JsonObject obj;
|
|
Assert::IsFalse(json::has(obj, L"key", JsonValueType::String));
|
|
}
|
|
|
|
TEST_METHOD(Has_WrongType_ReturnsFalse)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"key", JsonValue::CreateStringValue(L"value"));
|
|
Assert::IsFalse(json::has(obj, L"key", JsonValueType::Number));
|
|
}
|
|
|
|
TEST_METHOD(Has_NumberType_ReturnsTrue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"key", JsonValue::CreateNumberValue(42));
|
|
Assert::IsTrue(json::has(obj, L"key", JsonValueType::Number));
|
|
}
|
|
|
|
TEST_METHOD(Has_BooleanType_ReturnsTrue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"key", JsonValue::CreateBooleanValue(true));
|
|
Assert::IsTrue(json::has(obj, L"key", JsonValueType::Boolean));
|
|
}
|
|
|
|
TEST_METHOD(Has_ObjectType_ReturnsTrue)
|
|
{
|
|
JsonObject obj;
|
|
JsonObject nested;
|
|
obj.SetNamedValue(L"key", nested);
|
|
Assert::IsTrue(json::has(obj, L"key", JsonValueType::Object));
|
|
}
|
|
|
|
// value function tests
|
|
TEST_METHOD(Value_IntegerType_CreatesNumberValue)
|
|
{
|
|
auto val = json::value(42);
|
|
Assert::IsTrue(val.ValueType() == JsonValueType::Number);
|
|
Assert::AreEqual(42.0, val.GetNumber());
|
|
}
|
|
|
|
TEST_METHOD(Value_DoubleType_CreatesNumberValue)
|
|
{
|
|
auto val = json::value(3.14);
|
|
Assert::IsTrue(val.ValueType() == JsonValueType::Number);
|
|
Assert::AreEqual(3.14, val.GetNumber());
|
|
}
|
|
|
|
TEST_METHOD(Value_BooleanTrue_CreatesBooleanValue)
|
|
{
|
|
auto val = json::value(true);
|
|
Assert::IsTrue(val.ValueType() == JsonValueType::Boolean);
|
|
Assert::IsTrue(val.GetBoolean());
|
|
}
|
|
|
|
TEST_METHOD(Value_BooleanFalse_CreatesBooleanValue)
|
|
{
|
|
auto val = json::value(false);
|
|
Assert::IsTrue(val.ValueType() == JsonValueType::Boolean);
|
|
Assert::IsFalse(val.GetBoolean());
|
|
}
|
|
|
|
TEST_METHOD(Value_String_CreatesStringValue)
|
|
{
|
|
auto val = json::value(L"hello");
|
|
Assert::IsTrue(val.ValueType() == JsonValueType::String);
|
|
Assert::AreEqual(std::wstring(L"hello"), std::wstring(val.GetString()));
|
|
}
|
|
|
|
TEST_METHOD(Value_JsonObject_ReturnsJsonValue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"key", JsonValue::CreateStringValue(L"value"));
|
|
auto val = json::value(obj);
|
|
Assert::IsTrue(val.ValueType() == JsonValueType::Object);
|
|
}
|
|
|
|
TEST_METHOD(Value_JsonValue_ReturnsIdentity)
|
|
{
|
|
auto original = JsonValue::CreateStringValue(L"test");
|
|
auto result = json::value(original);
|
|
Assert::AreEqual(std::wstring(L"test"), std::wstring(result.GetString()));
|
|
}
|
|
|
|
// get function tests
|
|
TEST_METHOD(Get_BooleanValue_ReturnsValue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"enabled", JsonValue::CreateBooleanValue(true));
|
|
|
|
bool result = false;
|
|
json::get(obj, L"enabled", result);
|
|
Assert::IsTrue(result);
|
|
}
|
|
|
|
TEST_METHOD(Get_IntValue_ReturnsValue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"count", JsonValue::CreateNumberValue(42));
|
|
|
|
int result = 0;
|
|
json::get(obj, L"count", result);
|
|
Assert::AreEqual(42, result);
|
|
}
|
|
|
|
TEST_METHOD(Get_DoubleValue_ReturnsValue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"ratio", JsonValue::CreateNumberValue(3.14));
|
|
|
|
double result = 0.0;
|
|
json::get(obj, L"ratio", result);
|
|
Assert::AreEqual(3.14, result);
|
|
}
|
|
|
|
TEST_METHOD(Get_StringValue_ReturnsValue)
|
|
{
|
|
JsonObject obj;
|
|
obj.SetNamedValue(L"name", JsonValue::CreateStringValue(L"test"));
|
|
|
|
std::wstring result;
|
|
json::get(obj, L"name", result);
|
|
Assert::AreEqual(std::wstring(L"test"), result);
|
|
}
|
|
|
|
TEST_METHOD(Get_MissingKey_UsesDefault)
|
|
{
|
|
JsonObject obj;
|
|
|
|
int result = 0;
|
|
json::get(obj, L"missing", result, 99);
|
|
Assert::AreEqual(99, result);
|
|
}
|
|
|
|
TEST_METHOD(Get_MissingKeyNoDefault_PreservesOriginal)
|
|
{
|
|
JsonObject obj;
|
|
|
|
int result = 42;
|
|
json::get(obj, L"missing", result);
|
|
// When key is missing and no default, original value is preserved
|
|
Assert::AreEqual(42, result);
|
|
}
|
|
|
|
TEST_METHOD(Get_JsonObject_ReturnsObject)
|
|
{
|
|
JsonObject obj;
|
|
JsonObject nested;
|
|
nested.SetNamedValue(L"inner", JsonValue::CreateStringValue(L"value"));
|
|
obj.SetNamedValue(L"nested", nested);
|
|
|
|
JsonObject result;
|
|
json::get(obj, L"nested", result);
|
|
Assert::IsTrue(result.HasKey(L"inner"));
|
|
}
|
|
|
|
// Roundtrip tests
|
|
TEST_METHOD(Roundtrip_ComplexObject_PreservesData)
|
|
{
|
|
TestHelpers::TempFile tempFile(L"", L".json");
|
|
|
|
JsonObject original;
|
|
original.SetNamedValue(L"string", JsonValue::CreateStringValue(L"hello"));
|
|
original.SetNamedValue(L"number", JsonValue::CreateNumberValue(42));
|
|
original.SetNamedValue(L"boolean", JsonValue::CreateBooleanValue(true));
|
|
|
|
JsonObject nested;
|
|
nested.SetNamedValue(L"inner", JsonValue::CreateStringValue(L"world"));
|
|
original.SetNamedValue(L"object", nested);
|
|
|
|
json::to_file(tempFile.path(), original);
|
|
auto loaded = json::from_file(tempFile.path());
|
|
|
|
Assert::IsTrue(loaded.has_value());
|
|
Assert::AreEqual(std::wstring(L"hello"), std::wstring(loaded->GetNamedString(L"string")));
|
|
Assert::AreEqual(42.0, loaded->GetNamedNumber(L"number"));
|
|
Assert::IsTrue(loaded->GetNamedBoolean(L"boolean"));
|
|
Assert::AreEqual(std::wstring(L"world"), std::wstring(loaded->GetNamedObject(L"object").GetNamedString(L"inner")));
|
|
}
|
|
};
|
|
}
|