SourceFlow.cpp (6466B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "WorkflowCommon.h" 5 #include "TestHooks.h" 6 #include "TestSettings.h" 7 #include <Commands/SourceCommand.h> 8 #include <Workflows/PromptFlow.h> 9 #include <Workflows/SourceFlow.h> 10 11 using namespace TestCommon; 12 using namespace AppInstaller::CLI; 13 using namespace AppInstaller::CLI::Workflow; 14 using namespace AppInstaller::Repository; 15 using namespace AppInstaller::Settings; 16 17 void OverrideForSourceAddWithAgreements(TestContext& context, bool isAddExpected = true) 18 { 19 context.Override({ EnsureRunningAsAdmin, [](TestContext&) 20 { 21 } }); 22 23 if (isAddExpected) 24 { 25 context.Override({ AddSource, [](TestContext&) 26 { 27 } }); 28 } 29 30 context.Override({ CreateSourceForSourceAdd, [](TestContext& context) 31 { 32 auto testSource = std::make_shared<TestSource>(); 33 testSource->Information.SourceAgreementsIdentifier = "AgreementsIdentifier"; 34 testSource->Information.SourceAgreements.emplace_back("Agreement Label", "Agreement Text", "https://test"); 35 testSource->Information.RequiredPackageMatchFields.emplace_back("Market"); 36 testSource->Information.RequiredQueryParameters.emplace_back("Market"); 37 context << Workflow::HandleSourceAgreements(Source{ testSource }); 38 } }); 39 } 40 41 TEST_CASE("SourceAddFlow_Agreement", "[SourceAddFlow][workflow]") 42 { 43 std::ostringstream sourceAddOutput; 44 TestContext context{ sourceAddOutput, std::cin }; 45 auto previousThreadGlobals = context.SetForCurrentThread(); 46 OverrideForSourceAddWithAgreements(context); 47 context.Args.AddArg(Execution::Args::Type::SourceName, "TestSource"sv); 48 context.Args.AddArg(Execution::Args::Type::SourceType, "Microsoft.Test"sv); 49 context.Args.AddArg(Execution::Args::Type::SourceArg, "TestArg"sv); 50 context.Args.AddArg(Execution::Args::Type::AcceptSourceAgreements); 51 52 SourceAddCommand sourceAdd({}); 53 sourceAdd.Execute(context); 54 INFO(sourceAddOutput.str()); 55 56 // Verify agreements are shown 57 REQUIRE(sourceAddOutput.str().find("Agreement Label") != std::string::npos); 58 REQUIRE(sourceAddOutput.str().find("Agreement Text") != std::string::npos); 59 REQUIRE(sourceAddOutput.str().find("https://test") != std::string::npos); 60 REQUIRE(sourceAddOutput.str().find(Resource::LocString(Resource::String::SourceAgreementsMarketMessage).get()) != std::string::npos); 61 62 // Verify Installer is called. 63 REQUIRE(context.GetTerminationHR() == S_OK); 64 } 65 66 TEST_CASE("SourceAddFlow_Agreement_Prompt_Yes", "[SourceAddFlow][workflow]") 67 { 68 // Accept the agreements by saying "Yes" at the prompt 69 std::istringstream sourceAddInput{ "y" }; 70 std::ostringstream sourceAddOutput; 71 TestContext context{ sourceAddOutput, sourceAddInput }; 72 auto previousThreadGlobals = context.SetForCurrentThread(); 73 OverrideForSourceAddWithAgreements(context); 74 context.Args.AddArg(Execution::Args::Type::SourceName, "TestSource"sv); 75 context.Args.AddArg(Execution::Args::Type::SourceType, "Microsoft.Test"sv); 76 context.Args.AddArg(Execution::Args::Type::SourceArg, "TestArg"sv); 77 78 SourceAddCommand sourceAdd({}); 79 sourceAdd.Execute(context); 80 INFO(sourceAddOutput.str()); 81 82 // Verify agreements are shown 83 REQUIRE(sourceAddOutput.str().find("Agreement Label") != std::string::npos); 84 REQUIRE(sourceAddOutput.str().find("Agreement Text") != std::string::npos); 85 REQUIRE(sourceAddOutput.str().find("https://test") != std::string::npos); 86 REQUIRE(sourceAddOutput.str().find(Resource::LocString(Resource::String::SourceAgreementsMarketMessage).get()) != std::string::npos); 87 88 // Verify Installer is called. 89 REQUIRE(context.GetTerminationHR() == S_OK); 90 } 91 92 TEST_CASE("SourceAddFlow_Agreement_Prompt_No", "[SourceAddFlow][workflow]") 93 { 94 // Accept the agreements by saying "No" at the prompt 95 std::istringstream sourceAddInput{ "n" }; 96 std::ostringstream sourceAddOutput; 97 TestContext context{ sourceAddOutput, sourceAddInput }; 98 auto previousThreadGlobals = context.SetForCurrentThread(); 99 OverrideForSourceAddWithAgreements(context, false); 100 context.Args.AddArg(Execution::Args::Type::SourceName, "TestSource"sv); 101 context.Args.AddArg(Execution::Args::Type::SourceType, "Microsoft.Test"sv); 102 context.Args.AddArg(Execution::Args::Type::SourceArg, "TestArg"sv); 103 104 SourceAddCommand sourceAdd({}); 105 sourceAdd.Execute(context); 106 INFO(sourceAddOutput.str()); 107 108 // Verify agreements are shown 109 REQUIRE(sourceAddOutput.str().find("Agreement Label") != std::string::npos); 110 REQUIRE(sourceAddOutput.str().find("Agreement Text") != std::string::npos); 111 REQUIRE(sourceAddOutput.str().find("https://test") != std::string::npos); 112 REQUIRE(sourceAddOutput.str().find(Resource::LocString(Resource::String::SourceAgreementsMarketMessage).get()) != std::string::npos); 113 114 // Verify Installer is called. 115 REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); 116 } 117 118 TEST_CASE("OpenSource_WithCustomHeader", "[OpenSource][CustomHeader]") 119 { 120 SetSetting(Stream::UserSources, R"(Sources:)"sv); 121 TestHook_ClearSourceFactoryOverrides(); 122 123 SourceDetails details; 124 details.Name = "restsource"; 125 details.Type = "Microsoft.Rest"; 126 details.Arg = "thisIsTheArg"; 127 details.Data = "thisIsTheData"; 128 129 std::string customHeader = "Test custom header in Open source Flow"; 130 131 bool receivedCustomHeader = false; 132 TestSourceFactory factory{ 133 [&](const SourceDetails& sd, std::optional<std::string> header) 134 { 135 receivedCustomHeader = header.value() == customHeader; 136 return std::shared_ptr<ISource>(new TestSource(sd)); 137 } }; 138 TestHook_SetSourceFactoryOverride(details.Type, factory); 139 140 TestProgress progress; 141 AddSource(details, progress); 142 143 std::ostringstream output; 144 TestContext context{ output, std::cin }; 145 auto previousThreadGlobals = context.SetForCurrentThread(); 146 context.Args.AddArg(Execution::Args::Type::Query, "TestQuery"sv); 147 context.Args.AddArg(Execution::Args::Type::CustomHeader, customHeader); 148 context.Args.AddArg(Execution::Args::Type::Source, details.Name); 149 150 AppInstaller::CLI::Workflow::OpenSource()(context); 151 REQUIRE(receivedCustomHeader); 152 }