diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f3280c3e5..27446e3df 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -112,14 +112,14 @@ jobs: test-winapp: name: WinApp - #Disable until we get AppiumUpdate - if: ${{ false }} needs: waitOld runs-on: windows-latest steps: - uses: actions/checkout@v2 - - run: | - Start-Process -FilePath "C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe" + - name: Install Appium + run: npm install -g appium + - name: Run Appium + run: invoke-expression 'cmd /c start appium' shell: pwsh - id: builder uses: ./.github/workflows/buildtest-action @@ -137,8 +137,7 @@ jobs: test-appium: name: Appium # Skip when dependabot PR - Dependabot PRs cannot access action secrets - if: ${{ false }} - #Disable until we get AppiumUpdate if: github.actor != 'dependabot[bot]' + if: github.actor != 'dependabot[bot]' needs: waitOld runs-on: ubuntu-latest steps: @@ -436,8 +435,7 @@ jobs: # Skip when dependabot PR - Dependabot PRs cannot access action secrets if: github.actor != 'dependabot[bot]' runs-on: windows-latest - needs: [test-untils, test-mongo, test-database, test-webservice, test-base, test-email, test-framework, test-specflow, test-specflownunit, test-composite, test-selenpomlazy, test-selenutil, test-selengen, getVersion] - #Disable until we get AppiumUpdate needs: [test-appium, test-winapp, test-untils, test-mongo, test-database, test-webservice, test-base, test-email, test-framework, test-specflow, test-specflownunit, test-composite, test-selenpomlazy, test-selenutil, test-selengen, getVersion] + needs: [test-appium, test-winapp, test-untils, test-mongo, test-database, test-webservice, test-base, test-email, test-framework, test-specflow, test-specflownunit, test-composite, test-selenpomlazy, test-selenutil, test-selengen, getVersion] steps: - name: Set up JDK 11 uses: actions/setup-java@v1 diff --git a/Framework/AppiumUnitTests/App.config b/Framework/AppiumUnitTests/App.config index eb1cd3a31..0ec30804b 100644 --- a/Framework/AppiumUnitTests/App.config +++ b/Framework/AppiumUnitTests/App.config @@ -38,7 +38,8 @@ - + + @@ -73,10 +74,9 @@ + - - - - + + diff --git a/Framework/AppiumUnitTests/AppiumConfigTests.cs b/Framework/AppiumUnitTests/AppiumConfigTests.cs index 2a181419c..6262e48c7 100644 --- a/Framework/AppiumUnitTests/AppiumConfigTests.cs +++ b/Framework/AppiumUnitTests/AppiumConfigTests.cs @@ -7,14 +7,13 @@ using Magenic.Maqs.BaseAppiumTest; using Magenic.Maqs.Utilities.Helper; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Support.UI; using System; namespace AppiumUnitTests { - using OpenQA.Selenium; - /// /// Appium Config Unit Tests /// @@ -29,6 +28,7 @@ public class AppiumConfigTests public static void Initialize(TestContext testContext) { Config.UpdateWithVSTestContext(testContext); + Config.AddTestSettingValue("sauce:options", JsonConvert.SerializeObject(AppiumConfig.GetCapabilitiesAsStrings()), ConfigSection.AppiumCapsMaqs); } /// @@ -58,7 +58,7 @@ public void GetPlatformVersionTest() [TestCategory(TestCategories.Appium)] public void GetDeviceNameTest() { - Assert.AreEqual("Android GoogleAPI Emulator", AppiumConfig.GetDeviceName()); + Assert.AreEqual("Android Emulator", AppiumConfig.GetDeviceName()); } /// @@ -80,7 +80,7 @@ public void GetCommandTimeout() [TestCategory(TestCategories.Appium)] public void MobileDeviceTest() { - AppiumDriver driver = AppiumDriverFactory.GetDefaultMobileDriver(); + AppiumDriver driver = AppiumDriverFactory.GetDefaultMobileDriver(); try { @@ -110,7 +110,7 @@ public void GetMobileHubUrlTest() [TestCategory(TestCategories.Appium)] public void GetWaitDriverTest() { - AppiumDriver driver = AppiumDriverFactory.GetDefaultMobileDriver(); + AppiumDriver driver = AppiumDriverFactory.GetDefaultMobileDriver(); WebDriverWait wait = AppiumUtilities.GetDefaultWaitDriver(driver); try { diff --git a/Framework/AppiumUnitTests/AppiumIosUnitTests.cs b/Framework/AppiumUnitTests/AppiumIosUnitTests.cs index 49bf1a192..9e92c13c4 100644 --- a/Framework/AppiumUnitTests/AppiumIosUnitTests.cs +++ b/Framework/AppiumUnitTests/AppiumIosUnitTests.cs @@ -8,8 +8,10 @@ using Magenic.Maqs.Utilities.Helper; using Magenic.Maqs.Utilities.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; using OpenQA.Selenium; using OpenQA.Selenium.Appium; +using System.Collections.Generic; using System.IO; namespace AppiumUnitTests @@ -73,17 +75,23 @@ public void AssertFuncFailPath() /// Sets capabilities for testing the iOS Driver creation /// /// iOS instance of the Appium Driver - protected override AppiumDriver GetMobileDevice() + protected override AppiumDriver GetMobileDevice() { - AppiumOptions options = new AppiumOptions(); + AppiumOptions options = new AppiumOptions + { + DeviceName = "iPhone 13 Simulator", + PlatformName = "iOS", + PlatformVersion = "15.0", + BrowserName = "Safari" + }; - options.AddAdditionalCapability("deviceName", "iPhone 8 Simulator"); - options.AddAdditionalCapability("deviceOrientation", "portrait"); - options.AddAdditionalCapability("platformVersion", "12.2"); - options.AddAdditionalCapability("platformName", "iOS"); - options.AddAdditionalCapability("browserName", "Safari"); - options.AddAdditionalCapability("username", Config.GetValueForSection(ConfigSection.AppiumCapsMaqs, "userName")); - options.AddAdditionalCapability("accessKey", Config.GetValueForSection(ConfigSection.AppiumCapsMaqs, "accessKey")); + var sauceCreds = Config.GetValueForSection(ConfigSection.AppiumCapsMaqs, "sauce:options"); + + // Use Appium 1.22 for running iOS tests + sauceCreds = sauceCreds.Replace("1.20.2", "1.22.0"); + + options.AddAdditionalAppiumOption("sauce:options", JsonConvert.DeserializeObject>(sauceCreds)); + options.AddAdditionalAppiumOption("deviceOrientation", "portrait"); return AppiumDriverFactory.GetIOSDriver(AppiumConfig.GetMobileHubUrl(), options, AppiumConfig.GetMobileCommandTimeout()); } diff --git a/Framework/AppiumUnitTests/AppiumTestObjectTests.cs b/Framework/AppiumUnitTests/AppiumTestObjectTests.cs index a2bf6526b..bad887529 100644 --- a/Framework/AppiumUnitTests/AppiumTestObjectTests.cs +++ b/Framework/AppiumUnitTests/AppiumTestObjectTests.cs @@ -35,7 +35,7 @@ public void AppiumTestObjectTest() [TestCategory(TestCategories.Appium)] public void GetAndCloseDriverTest() { - AppiumDriver driver = AppiumDriverFactory.GetDefaultMobileDriver(); + AppiumDriver driver = AppiumDriverFactory.GetDefaultMobileDriver(); try { Assert.IsNotNull(driver); diff --git a/Framework/AppiumUnitTests/AppiumUtilitiesTests.cs b/Framework/AppiumUnitTests/AppiumUtilitiesTests.cs index 07aa65f37..755343510 100644 --- a/Framework/AppiumUnitTests/AppiumUtilitiesTests.cs +++ b/Framework/AppiumUnitTests/AppiumUtilitiesTests.cs @@ -19,13 +19,24 @@ namespace AppiumUnitTests /// Appium Utilities Unit Tests /// [TestClass] + [TestCategory(TestCategories.Appium)] public class AppiumUtilitiesTests : BaseAppiumTest { + /// + /// Verify we can create a Appium test object with a Appium driver + /// + [TestMethod] + public void CreateAppiumTestObjectWithDriver() + { + AppiumTestObject newObject = new AppiumTestObject(this.AppiumDriver, this.TestObject.Log, "test"); + Assert.AreEqual(this.AppiumDriver, newObject.AppiumDriver); + Assert.AreEqual(this.Log, newObject.Log); + } + /// /// Verify a bad create fails in the right way /// [TestMethod] - [TestCategory(TestCategories.Appium)] [ExpectedException(typeof(WebDriverException))] public void BadCreate() { @@ -36,7 +47,6 @@ public void BadCreate() /// Verify CaptureScreenshot works - Validating that the screenshot was created /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void CaptureScreenshotTest() { AppiumUtilities.CaptureScreenshot(this.TestObject.AppiumDriver, this.TestObject); @@ -49,7 +59,6 @@ public void CaptureScreenshotTest() /// Verify CaptureScreenshot works with console logger - Validating that the screenshot was not created /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void CaptureScreenshotWithConsoleLoggerTest() { // Create a console logger and calculate the file location @@ -67,7 +76,6 @@ public void CaptureScreenshotWithConsoleLoggerTest() /// Verify that CaptureScreenshot properly handles exceptions and returns false /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void CaptureScreenshotThrownException() { FileLogger tempLogger = new FileLogger @@ -84,7 +92,6 @@ public void CaptureScreenshotThrownException() /// Verify when a screenshot is captured it is associated to the test object /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void CaptureScreenshotTestObjectAssociation() { AppiumUtilities.CaptureScreenshot(this.TestObject.AppiumDriver, this.TestObject); @@ -97,7 +104,6 @@ public void CaptureScreenshotTestObjectAssociation() /// Verify SavePageSource works - Validating that the Page Source file was created /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void SavePageSourceTest() { AppiumUtilities.SavePageSource(this.TestObject.AppiumDriver, this.TestObject); @@ -112,7 +118,6 @@ public void SavePageSourceTest() /// Verify that SavePageSource properly handles exceptions and returns false /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void SavePageSourceThrownException() { FileLogger tempLogger = new FileLogger @@ -129,7 +134,6 @@ public void SavePageSourceThrownException() /// Verify that SavePageSource creates Directory if it does not exist already /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void SavePageSourceNoExistingDirectory() { string pageSourcePath = AppiumUtilities.SavePageSource(this.AppiumDriver, this.TestObject, "TempTestDirectory", "SavePSNoDir"); @@ -141,7 +145,6 @@ public void SavePageSourceNoExistingDirectory() /// Verify when a page source is saved it is associated to the test object /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void SavedPageSourceTestObjectAssociation() { string pageSourcePath = AppiumUtilities.SavePageSource(this.AppiumDriver, this.TestObject, "TempTestDirectory", "TestObjAssoc"); @@ -153,7 +156,6 @@ public void SavedPageSourceTestObjectAssociation() /// Test lazy element /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void AppiumLazyTest() { Assert.IsNotNull(this.TestObject.AppiumDriver); @@ -175,7 +177,6 @@ public void AppiumLazyTest() /// Test lazy parent element and finds /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void AppiumLazyParentTest() { this.AppiumDriver.Navigate().GoToUrl(Config.GetValueForSection(ConfigSection.AppiumMaqs, "WebSiteBase")); @@ -198,7 +199,6 @@ public void AppiumLazyParentTest() /// Test lazy element wait overrides /// [TestMethod] - [TestCategory(TestCategories.Appium)] public void AppiumLazyWaitOverride() { TimeSpan overrideTimeSpan = TimeSpan.FromSeconds(10); diff --git a/Framework/AppiumUnitTests/AppiumWinAppUnitTests.cs b/Framework/AppiumUnitTests/AppiumWinAppUnitTests.cs index 14453c53d..288aa9912 100644 --- a/Framework/AppiumUnitTests/AppiumWinAppUnitTests.cs +++ b/Framework/AppiumUnitTests/AppiumWinAppUnitTests.cs @@ -8,7 +8,6 @@ using Magenic.Maqs.Utilities.Helper; using Magenic.Maqs.Utilities.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using System; using System.IO; @@ -48,7 +47,7 @@ public void AppiumWinAppDriverTest() this.SoftAssert.Assert(() => Assert.IsTrue(NotepadApplication.TextEditor.Displayed, "Expect displayed")); this.SoftAssert.Assert(() => Assert.IsFalse(NotepadApplication.DontSave.ExistsNow, "Expect not to exist now")); - this.SoftAssert.Assert(() => Assert.AreEqual(testString, this.AppiumDriver.FindElementByName("Text Editor").Text)); + this.SoftAssert.Assert(() => Assert.AreEqual(testString, this.AppiumDriver.FindElement(MobileBy.Name("Text Editor")).Text)); NotepadApplication.OverrideDriver(null); this.SoftAssert.Assert(() => Assert.AreEqual(null, NotepadApplication.GetAppiumDriver())); @@ -97,11 +96,11 @@ protected override void BeforeCleanup(TestResultType resultType) /// Sets capabilities for testing the Windows application driver creation /// /// Windows application driver instance of the Appium Driver - protected override AppiumDriver GetMobileDevice() + protected override AppiumDriver GetMobileDevice() { AppiumOptions options = new AppiumOptions(); - options.AddAdditionalCapability("app", $"{Environment.SystemDirectory}\\notepad.exe"); - return AppiumDriverFactory.GetWindowsDriver(new Uri("http://127.0.0.1:4723"), options, TimeSpan.FromSeconds(30)); + options.App = $"{Environment.SystemDirectory}\\notepad.exe"; + return AppiumDriverFactory.GetWindowsDriver(new Uri("http://127.0.0.1:4723/wd/hub"), options, TimeSpan.FromSeconds(30)); } } } diff --git a/Framework/AppiumUnitTests/NotepadPageModel.cs b/Framework/AppiumUnitTests/NotepadPageModel.cs index 4a4f56a5a..dc1df3ce3 100644 --- a/Framework/AppiumUnitTests/NotepadPageModel.cs +++ b/Framework/AppiumUnitTests/NotepadPageModel.cs @@ -7,7 +7,6 @@ using Magenic.Maqs.BaseAppiumTest; using Magenic.Maqs.Utilities.Logging; using Magenic.Maqs.Utilities.Performance; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; namespace AppiumUnitTests @@ -31,7 +30,7 @@ public NotepadPageModel(IAppiumTestObject testObject) /// private LazyMobileElement Document { - get { return this.GetLazyElement(By.ClassName("Notepad"), "Document"); } + get { return this.GetLazyElement(MobileBy.ClassName("Notepad"), "Document"); } } /// @@ -39,7 +38,7 @@ private LazyMobileElement Document /// public LazyMobileElement TextEditor { - get { return this.GetLazyElement(Document, By.Name("Text Editor"), "Text Editor"); } + get { return this.GetLazyElement(Document, MobileBy.Name("Text Editor"), "Text Editor"); } } /// @@ -47,7 +46,7 @@ public LazyMobileElement TextEditor /// private LazyMobileElement Close { - get { return this.GetLazyElement(By.Name("Close"), "Close"); } + get { return this.GetLazyElement(MobileBy.Name("Close"), "Close"); } } /// @@ -55,7 +54,7 @@ private LazyMobileElement Close /// public LazyMobileElement DontSave { - get { return this.GetLazyElement(By.Name("Don't Save"), "Don't Save"); } + get { return this.GetLazyElement(MobileBy.Name("Don't Save"), "Don't Save"); } } public void CloseAndDontSave() @@ -77,7 +76,7 @@ public override bool IsPageLoaded() /// Get web driver /// /// The web driver - public AppiumDriver GetAppiumDriver() + public AppiumDriver GetAppiumDriver() { return this.AppiumDriver; } diff --git a/Framework/BaseAppiumTest/AppiumConfig.cs b/Framework/BaseAppiumTest/AppiumConfig.cs index 5a5493659..76aaf98c7 100644 --- a/Framework/BaseAppiumTest/AppiumConfig.cs +++ b/Framework/BaseAppiumTest/AppiumConfig.cs @@ -31,11 +31,10 @@ private static void CheckConfig() { var validator = new ConfigValidation() { - RequiredFields = new List() + RequiredOneOfFields = new List() { - "PlatformName", - "PlatformVersion", - "DeviceName" + "App", + "BrowserName" } }; Config.Validate(ConfigSection.AppiumMaqs, validator); @@ -60,7 +59,34 @@ public static string GetPlatformVersion() } /// - /// Get the Device Name + /// Get the application name or path + /// + /// Application name or path + public static string GetApp() + { + return Config.GetValueForSection(ConfigSection.AppiumMaqs, "App"); + } + + /// + /// Get the browser Name + /// + /// Browser Name + public static string GetBrowserName() + { + return Config.GetValueForSection(ConfigSection.AppiumMaqs, "BrowserName"); + } + + /// + /// Get the browser version + /// + /// Browser version + public static string GetBrowserVersion() + { + return Config.GetValueForSection(ConfigSection.AppiumMaqs, "BrowserVersion"); + } + + /// + /// Get the device Name /// /// Device Name public static string GetDeviceName() diff --git a/Framework/BaseAppiumTest/AppiumDriverFactory.cs b/Framework/BaseAppiumTest/AppiumDriverFactory.cs index edbf5af5f..40335626c 100644 --- a/Framework/BaseAppiumTest/AppiumDriverFactory.cs +++ b/Framework/BaseAppiumTest/AppiumDriverFactory.cs @@ -4,10 +4,10 @@ // // Factory for creating mobile drivers //-------------------------------------------------- +using Newtonsoft.Json; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Android; -using OpenQA.Selenium.Appium.Enums; using OpenQA.Selenium.Appium.iOS; using OpenQA.Selenium.Appium.Windows; using System; @@ -25,7 +25,7 @@ public static class AppiumDriverFactory /// Get the default Appium driver based on the test run configuration /// /// An AppiumDriver - public static AppiumDriver GetDefaultMobileDriver() + public static AppiumDriver GetDefaultMobileDriver() { return GetDefaultMobileDriver(AppiumConfig.GetDeviceType()); } @@ -35,9 +35,9 @@ public static AppiumDriver GetDefaultMobileDriver() /// /// The platform type we want to use /// An AppiumDriver - public static AppiumDriver GetDefaultMobileDriver(PlatformType deviceType) + public static AppiumDriver GetDefaultMobileDriver(PlatformType deviceType) { - AppiumDriver appiumDriver; + AppiumDriver appiumDriver; Uri mobileHub = AppiumConfig.GetMobileHubUrl(); TimeSpan timeout = AppiumConfig.GetMobileCommandTimeout(); @@ -83,11 +83,11 @@ public static AppiumDriver GetDefaultMobileDriver(PlatformType devi /// Appium options /// Command timeout /// The Appium driver - public static AppiumDriver GetAndroidDriver(Uri mobileHub, AppiumOptions options, TimeSpan timeout) + public static AppiumDriver GetAndroidDriver(Uri mobileHub, AppiumOptions options, TimeSpan timeout) { return CreateDriver(() => { - var driver = new AndroidDriver(mobileHub, options, timeout); + var driver = new AndroidDriver(mobileHub, options, timeout); return driver; }); } @@ -99,11 +99,11 @@ public static AppiumDriver GetAndroidDriver(Uri mobileHub, AppiumOp /// Appium options /// Command timeout /// The Appium driver - public static AppiumDriver GetIOSDriver(Uri mobileHub, AppiumOptions options, TimeSpan timeout) + public static AppiumDriver GetIOSDriver(Uri mobileHub, AppiumOptions options, TimeSpan timeout) { return CreateDriver(() => { - var driver = new IOSDriver(mobileHub, options, timeout); + var driver = new IOSDriver(mobileHub, options, timeout); return driver; }); } @@ -115,11 +115,11 @@ public static AppiumDriver GetIOSDriver(Uri mobileHub, AppiumOption /// Appium options /// Command timeout /// The Appium driver - public static AppiumDriver GetWindowsDriver(Uri mobileHub, AppiumOptions options, TimeSpan timeout) + public static AppiumDriver GetWindowsDriver(Uri mobileHub, AppiumOptions options, TimeSpan timeout) { return CreateDriver(() => { - var driver = new WindowsDriver(mobileHub, options, timeout); + var driver = new WindowsDriver(mobileHub, options, timeout); return driver; }); } @@ -129,9 +129,9 @@ public static AppiumDriver GetWindowsDriver(Uri mobileHub, AppiumOp /// /// Function for creating a driver /// An Appium driver - public static AppiumDriver CreateDriver(Func> createFunction) + public static AppiumDriver CreateDriver(Func createFunction) { - AppiumDriver appiumDriver = null; + AppiumDriver appiumDriver = null; try { @@ -166,7 +166,7 @@ public static AppiumDriver CreateDriver(Func /// Brings in an AppiumDriver - public static void SetDefaultTimeouts(this AppiumDriver driver) + public static void SetDefaultTimeouts(this AppiumDriver driver) { driver.SetTimeouts(AppiumConfig.GetMobileTimeout()); } @@ -176,7 +176,7 @@ public static void SetDefaultTimeouts(this AppiumDriver driver) /// /// Brings in an AppiumDriver /// The new timeout - public static void SetTimeouts(this AppiumDriver driver, TimeSpan timeout) + public static void SetTimeouts(this AppiumDriver driver, TimeSpan timeout) { driver.Manage().Timeouts().AsynchronousJavaScript = timeout; driver.Manage().Timeouts().PageLoad = timeout; @@ -203,10 +203,12 @@ public static AppiumOptions GetDefaultMobileOptions(Dictionary c public static AppiumOptions GetDefaultMobileOptions() { AppiumOptions options = new AppiumOptions(); - - options.AddAdditionalCapability(MobileCapabilityType.DeviceName, AppiumConfig.GetDeviceName()); - options.AddAdditionalCapability(MobileCapabilityType.PlatformVersion, AppiumConfig.GetPlatformVersion()); - options.AddAdditionalCapability(MobileCapabilityType.PlatformName, AppiumConfig.GetPlatformName().ToUpper()); + options.App = AppiumConfig.GetApp(); + options.BrowserName = AppiumConfig.GetBrowserName(); + options.BrowserVersion = AppiumConfig.GetBrowserVersion(); + options.DeviceName = AppiumConfig.GetDeviceName(); + options.PlatformVersion = AppiumConfig.GetPlatformVersion(); + options.PlatformName = AppiumConfig.GetPlatformName().ToUpper(); options.SetMobileOptions(AppiumConfig.GetCapabilitiesAsObjects()); return options; @@ -229,7 +231,17 @@ private static AppiumOptions SetMobileOptions(this AppiumOptions appiumOptions, { if (keyValue.Value != null && (!(keyValue.Value is string) || !string.IsNullOrEmpty(keyValue.Value as string))) { - appiumOptions.AddAdditionalCapability(keyValue.Key, keyValue.Value); + try + { + // Check if this is a Json string + var jsonDictionary = JsonConvert.DeserializeObject>(keyValue.Value as string); + appiumOptions.AddAdditionalAppiumOption(keyValue.Key, jsonDictionary); + } + catch + { + // Not Json string so add as a normal string + appiumOptions.AddAdditionalAppiumOption(keyValue.Key, keyValue.Value); + } } } diff --git a/Framework/BaseAppiumTest/AppiumDriverManager.cs b/Framework/BaseAppiumTest/AppiumDriverManager.cs index 7e22f67dd..4728c04f2 100644 --- a/Framework/BaseAppiumTest/AppiumDriverManager.cs +++ b/Framework/BaseAppiumTest/AppiumDriverManager.cs @@ -6,7 +6,6 @@ //-------------------------------------------------- using Magenic.Maqs.BaseTest; using Magenic.Maqs.Utilities.Logging; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using System; @@ -22,7 +21,7 @@ public class AppiumDriverManager : DriverManager /// /// Function for getting an Appium driver /// The associated test object - public AppiumDriverManager(Func> getDriver, ITestObject testObject) : base(getDriver, testObject) + public AppiumDriverManager(Func getDriver, ITestObject testObject) : base(getDriver, testObject) { } @@ -30,7 +29,7 @@ public AppiumDriverManager(Func> getDriver, ITestObjec /// Override the Appium driver /// /// The new Appium driver - public void OverrideDriver(AppiumDriver overrideDriver) + public void OverrideDriver(AppiumDriver overrideDriver) { this.OverrideDriverGet(() => overrideDriver); } @@ -39,7 +38,7 @@ public void OverrideDriver(AppiumDriver overrideDriver) /// Override the Appium driver /// /// The new Appium driver - public void OverrideDriver(Func> overrideDriver) + public void OverrideDriver(Func overrideDriver) { this.OverrideDriverGet(overrideDriver); } @@ -48,9 +47,9 @@ public void OverrideDriver(Func> overrideDriver) /// Get the Appium driver /// /// The Appium driver - public AppiumDriver GetAppiumDriver() + public AppiumDriver GetAppiumDriver() { - return GetBase() as AppiumDriver; + return GetBase() as AppiumDriver; } /// @@ -75,7 +74,7 @@ protected override void DriverDispose() try { - AppiumDriver driver = this.GetAppiumDriver(); + AppiumDriver driver = this.GetAppiumDriver(); driver?.KillDriver(); } catch (Exception e) diff --git a/Framework/BaseAppiumTest/AppiumDriverWaitExtensions.cs b/Framework/BaseAppiumTest/AppiumDriverWaitExtensions.cs index ce51f2bf8..982fc675a 100644 --- a/Framework/BaseAppiumTest/AppiumDriverWaitExtensions.cs +++ b/Framework/BaseAppiumTest/AppiumDriverWaitExtensions.cs @@ -21,7 +21,7 @@ public static class AppiumDriverWaitExtensions /// /// Wait collection for the Appium Driver /// - private static readonly ConcurrentDictionary, WebDriverWait> waitCollection; + private static readonly ConcurrentDictionary waitCollection; #pragma warning disable S3963 // "static" fields should be initialized inline /// @@ -29,7 +29,7 @@ public static class AppiumDriverWaitExtensions /// static AppiumDriverWaitExtensions() { - waitCollection = new ConcurrentDictionary, WebDriverWait>(); + waitCollection = new ConcurrentDictionary(); } #pragma warning restore S3963 // "static" fields should be initialized inline @@ -38,7 +38,7 @@ static AppiumDriverWaitExtensions() /// /// The appium driver /// The WebDriverWait - public static WebDriverWait GetWaitDriver(this AppiumDriver driver) + public static WebDriverWait GetWaitDriver(this AppiumDriver driver) { if (waitCollection.ContainsKey(driver)) { @@ -57,7 +57,7 @@ public static WebDriverWait GetWaitDriver(this AppiumDriver driver) /// /// The appium driver /// Web Driver Wait - public static void SetWaitDriver(this AppiumDriver driver, WebDriverWait waiter) + public static void SetWaitDriver(this AppiumDriver driver, WebDriverWait waiter) { waitCollection.AddOrUpdate(driver, waiter, (oldkey, oldvalue) => waiter); } @@ -67,7 +67,7 @@ public static void SetWaitDriver(this AppiumDriver driver, WebDrive /// /// The appium driver /// True if the wait driver was removed - public static bool RemoveWaitDriver(this AppiumDriver driver) + public static bool RemoveWaitDriver(this AppiumDriver driver) { return waitCollection.TryRemove(driver, out WebDriverWait _); } @@ -77,7 +77,7 @@ public static bool RemoveWaitDriver(this AppiumDriver driver) /// /// The appium driver /// 'by' selector for the element - public static void WaitForAbsentElement(this AppiumDriver driver, By by) + public static void WaitForAbsentElement(this AppiumDriver driver, By by) { if (!WaitUntilAbsentElement(driver, by)) { @@ -89,7 +89,7 @@ public static void WaitForAbsentElement(this AppiumDriver driver, B /// Wait for the page to load /// /// The appium driver - public static void WaitForPageLoad(this AppiumDriver driver) + public static void WaitForPageLoad(this AppiumDriver driver) { if (!WaitUntilPageLoad(driver)) { @@ -103,7 +103,7 @@ public static void WaitForPageLoad(this AppiumDriver driver) /// The appium driver /// 'by' selector for the element /// True if the element is not visible on the page - public static bool WaitUntilAbsentElement(this AppiumDriver driver, By by) + public static bool WaitUntilAbsentElement(this AppiumDriver driver, By by) { DateTime start = DateTime.Now; @@ -140,7 +140,7 @@ public static bool WaitUntilAbsentElement(this AppiumDriver driver, /// /// The appium driver /// True if the page finished loading - public static bool WaitUntilPageLoad(this AppiumDriver driver) + public static bool WaitUntilPageLoad(this AppiumDriver driver) { DateTime start = DateTime.Now; string source = string.Empty; diff --git a/Framework/BaseAppiumTest/AppiumTestObject.cs b/Framework/BaseAppiumTest/AppiumTestObject.cs index 945324f33..172e8553d 100644 --- a/Framework/BaseAppiumTest/AppiumTestObject.cs +++ b/Framework/BaseAppiumTest/AppiumTestObject.cs @@ -6,7 +6,6 @@ //-------------------------------------------------- using Magenic.Maqs.BaseTest; using Magenic.Maqs.Utilities.Logging; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using System; @@ -23,7 +22,7 @@ public class AppiumTestObject : BaseTestObject, IAppiumTestObject /// The test's Appium driver /// The test's logger /// The test's fully qualified test name - public AppiumTestObject(AppiumDriver appiumDriver, ILogger logger, string fullyQualifiedTestName) : base(logger, fullyQualifiedTestName) + public AppiumTestObject(AppiumDriver appiumDriver, ILogger logger, string fullyQualifiedTestName) : base(logger, fullyQualifiedTestName) { this.ManagerStore.Add(typeof(AppiumDriverManager).FullName, new AppiumDriverManager(() => appiumDriver, this)); this.SoftAssert = new AppiumSoftAssert(this); @@ -35,7 +34,7 @@ public AppiumTestObject(AppiumDriver appiumDriver, ILogger logger, /// Function for initializing a Appium driver /// The test's logger /// The test's fully qualified test name - public AppiumTestObject(Func> appiumDriver, ILogger logger, string fullyQualifiedTestName) : base(logger, fullyQualifiedTestName) + public AppiumTestObject(Func appiumDriver, ILogger logger, string fullyQualifiedTestName) : base(logger, fullyQualifiedTestName) { this.ManagerStore.Add(typeof(AppiumDriverManager).FullName, new AppiumDriverManager(appiumDriver, this)); this.SoftAssert = new AppiumSoftAssert(this); @@ -44,7 +43,7 @@ public AppiumTestObject(Func> appiumDriver, ILogger lo /// /// Gets the Appium driver /// - public AppiumDriver AppiumDriver + public AppiumDriver AppiumDriver { get { @@ -67,7 +66,7 @@ public AppiumDriverManager AppiumManager /// Override the Appium driver /// /// New Appium driver - public void OverrideAppiumDriver(AppiumDriver appiumDriver) + public void OverrideAppiumDriver(AppiumDriver appiumDriver) { this.AppiumManager.OverrideDriver(appiumDriver); } @@ -76,7 +75,7 @@ public void OverrideAppiumDriver(AppiumDriver appiumDriver) /// Override the Appium driver /// /// New function for initializing a Appium driver - public void OverrideAppiumDriver(Func> appiumDriver) + public void OverrideAppiumDriver(Func appiumDriver) { this.AppiumManager.OverrideDriver(appiumDriver); } diff --git a/Framework/BaseAppiumTest/AppiumUtilities.cs b/Framework/BaseAppiumTest/AppiumUtilities.cs index 5a40225c5..df9857f7f 100644 --- a/Framework/BaseAppiumTest/AppiumUtilities.cs +++ b/Framework/BaseAppiumTest/AppiumUtilities.cs @@ -25,7 +25,7 @@ public static class AppiumUtilities /// The TestObject to associate the screenshot with /// Appends a name to the end of a filename /// Boolean if the save of the image was successful - public static bool CaptureScreenshot(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string appendName = "") + public static bool CaptureScreenshot(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string appendName = "") { try { @@ -57,7 +57,7 @@ public static bool CaptureScreenshot(this AppiumDriver appiumDriver /// The TestObject to associate the screenshot with /// The directory file path /// Filename without extension - public static void CaptureScreenshot(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string directory, string fileNameWithoutExtension) + public static void CaptureScreenshot(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string directory, string fileNameWithoutExtension) { Screenshot screenshot = ((ITakesScreenshot)appiumDriver).GetScreenshot(); @@ -74,7 +74,7 @@ public static void CaptureScreenshot(this AppiumDriver appiumDriver /// The TestObject to associate the file and log with /// Appends a name to the end of a filename /// Boolean if the save of the page source was successful - public static bool SavePageSource(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string appendName = "") + public static bool SavePageSource(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string appendName = "") { try { @@ -114,7 +114,7 @@ public static bool SavePageSource(this AppiumDriver appiumDriver, I /// The directory file path /// Filename without extension /// Path to the log file - public static string SavePageSource(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string directory, string fileNameWithoutExtension) + public static string SavePageSource(this AppiumDriver appiumDriver, IAppiumTestObject testObject, string directory, string fileNameWithoutExtension) { // Save the current page source into a string string pageSource = appiumDriver.PageSource; @@ -146,7 +146,7 @@ public static string SavePageSource(this AppiumDriver appiumDriver, /// Make sure the driver is shut down /// /// The driver - public static void KillDriver(this AppiumDriver driver) + public static void KillDriver(this AppiumDriver driver) { try { @@ -163,7 +163,7 @@ public static void KillDriver(this AppiumDriver driver) /// /// Brings in an AppiumDriver /// An WebDriverWait - public static WebDriverWait GetDefaultWaitDriver(AppiumDriver driver) + public static WebDriverWait GetDefaultWaitDriver(AppiumDriver driver) { return GetWaitDriver(driver, AppiumConfig.GetMobileTimeout(), AppiumConfig.GetMobileWaitTime()); } @@ -175,7 +175,7 @@ public static WebDriverWait GetDefaultWaitDriver(AppiumDriver drive /// How long is the timeout /// How long to wait before rechecking /// A web driver wait - public static WebDriverWait GetWaitDriver(AppiumDriver driver, TimeSpan timeoutTime, TimeSpan waitTime) + public static WebDriverWait GetWaitDriver(AppiumDriver driver, TimeSpan timeoutTime, TimeSpan waitTime) { return new WebDriverWait(new SystemClock(), driver, timeoutTime, waitTime); } diff --git a/Framework/BaseAppiumTest/BaseAppiumPageModel.cs b/Framework/BaseAppiumTest/BaseAppiumPageModel.cs index 748b5545a..bfe086009 100644 --- a/Framework/BaseAppiumTest/BaseAppiumPageModel.cs +++ b/Framework/BaseAppiumTest/BaseAppiumPageModel.cs @@ -37,7 +37,7 @@ protected BaseAppiumPageModel(IAppiumTestObject testObject) /// /// Gets the webdriver from the test object /// - protected AppiumDriver AppiumDriver { get; private set; } + protected AppiumDriver AppiumDriver { get; private set; } /// /// Gets the log from the test object @@ -65,7 +65,7 @@ protected IPerfTimerCollection PerfTimerCollection /// This allows you to use something other than the default tests object driver. /// /// The override driver - public void OverrideDriver(AppiumDriver appiumDriver) + public void OverrideDriver(AppiumDriver appiumDriver) { this.AppiumDriver = appiumDriver; } diff --git a/Framework/BaseAppiumTest/BaseAppiumTest.cs b/Framework/BaseAppiumTest/BaseAppiumTest.cs index 826a81572..fa26575ec 100644 --- a/Framework/BaseAppiumTest/BaseAppiumTest.cs +++ b/Framework/BaseAppiumTest/BaseAppiumTest.cs @@ -6,7 +6,6 @@ //-------------------------------------------------- using Magenic.Maqs.BaseTest; using Magenic.Maqs.Utilities.Logging; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using System; @@ -28,7 +27,7 @@ public BaseAppiumTest() /// /// Gets or sets the AppiumDriver /// - public AppiumDriver AppiumDriver + public AppiumDriver AppiumDriver { get { @@ -45,7 +44,7 @@ public AppiumDriver AppiumDriver /// The default get appium driver function /// /// The appium driver - protected virtual AppiumDriver GetMobileDevice() + protected virtual AppiumDriver GetMobileDevice() { return AppiumDriverFactory.GetDefaultMobileDriver(); } diff --git a/Framework/BaseAppiumTest/BaseAppiumTest.csproj b/Framework/BaseAppiumTest/BaseAppiumTest.csproj index d94625352..4784d9eb1 100644 --- a/Framework/BaseAppiumTest/BaseAppiumTest.csproj +++ b/Framework/BaseAppiumTest/BaseAppiumTest.csproj @@ -41,7 +41,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Framework/BaseAppiumTest/IAppiumTestObject.cs b/Framework/BaseAppiumTest/IAppiumTestObject.cs index 4370ff59e..934a4c9b8 100644 --- a/Framework/BaseAppiumTest/IAppiumTestObject.cs +++ b/Framework/BaseAppiumTest/IAppiumTestObject.cs @@ -5,7 +5,6 @@ // Holds Appium test object interface //-------------------------------------------------- using Magenic.Maqs.BaseTest; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using System; @@ -19,7 +18,7 @@ public interface IAppiumTestObject : ITestObject /// /// Gets the Appium driver /// - AppiumDriver AppiumDriver { get; } + AppiumDriver AppiumDriver { get; } /// /// Gets the Appium driver manager @@ -30,12 +29,12 @@ public interface IAppiumTestObject : ITestObject /// Override the Appium driver /// /// New Appium driver - void OverrideAppiumDriver(AppiumDriver appiumDriver); + void OverrideAppiumDriver(AppiumDriver appiumDriver); /// /// Override the Appium driver /// /// New function for initializing a Appium driver - void OverrideAppiumDriver(Func> appiumDriver); + void OverrideAppiumDriver(Func appiumDriver); } } \ No newline at end of file diff --git a/Framework/BaseAppiumTest/LazyMobileElement.cs b/Framework/BaseAppiumTest/LazyMobileElement.cs index 40726e11b..f93bf97e8 100644 --- a/Framework/BaseAppiumTest/LazyMobileElement.cs +++ b/Framework/BaseAppiumTest/LazyMobileElement.cs @@ -36,7 +36,7 @@ public LazyMobileElement(IAppiumTestObject testObject, By locator, [CallerMember /// The Appium driver /// The 'by' selector for the element /// A user friendly name, for logging purposes - public LazyMobileElement(IAppiumTestObject testObject, AppiumDriver appiumDriver, By locator, [CallerMemberName] string userFriendlyName = null) : base(testObject, appiumDriver, () => appiumDriver.GetWaitDriver(), locator, userFriendlyName) + public LazyMobileElement(IAppiumTestObject testObject, AppiumDriver appiumDriver, By locator, [CallerMemberName] string userFriendlyName = null) : base(testObject, appiumDriver, () => appiumDriver.GetWaitDriver(), locator, userFriendlyName) { } diff --git a/Framework/BaseDatabaseTest/BaseDatabaseTest.csproj b/Framework/BaseDatabaseTest/BaseDatabaseTest.csproj index e04ff1189..e0f7068ee 100644 --- a/Framework/BaseDatabaseTest/BaseDatabaseTest.csproj +++ b/Framework/BaseDatabaseTest/BaseDatabaseTest.csproj @@ -41,7 +41,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Framework/BaseSeleniumTest/BaseSeleniumTest.csproj b/Framework/BaseSeleniumTest/BaseSeleniumTest.csproj index 1e065c722..5fc8c273d 100644 --- a/Framework/BaseSeleniumTest/BaseSeleniumTest.csproj +++ b/Framework/BaseSeleniumTest/BaseSeleniumTest.csproj @@ -41,14 +41,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/Framework/SeleniumUnitTests/App.config b/Framework/SeleniumUnitTests/App.config index 279ce52f6..6ddd51f4b 100644 --- a/Framework/SeleniumUnitTests/App.config +++ b/Framework/SeleniumUnitTests/App.config @@ -72,7 +72,9 @@ - - + + + + diff --git a/Framework/SpecFlowExtension/SpecFlowExtension.csproj b/Framework/SpecFlowExtension/SpecFlowExtension.csproj index 2e301995e..46a32dd60 100644 --- a/Framework/SpecFlowExtension/SpecFlowExtension.csproj +++ b/Framework/SpecFlowExtension/SpecFlowExtension.csproj @@ -41,7 +41,7 @@ - + diff --git a/Framework/SpecFlowExtension/TestSteps/BaseAppiumTestSteps.cs b/Framework/SpecFlowExtension/TestSteps/BaseAppiumTestSteps.cs index 2f93661c2..5079c8e24 100644 --- a/Framework/SpecFlowExtension/TestSteps/BaseAppiumTestSteps.cs +++ b/Framework/SpecFlowExtension/TestSteps/BaseAppiumTestSteps.cs @@ -5,7 +5,6 @@ // Base teststeps code for tests using appium //-------------------------------------------------- using Magenic.Maqs.BaseAppiumTest; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; using TechTalk.SpecFlow; using MaqsAppium = Magenic.Maqs.BaseAppiumTest.BaseAppiumTest; @@ -29,7 +28,7 @@ public BaseAppiumTestSteps(ScenarioContext context) : base(context) /// /// Gets the Appium driver from the test object /// - protected AppiumDriver AppiumDriver + protected AppiumDriver AppiumDriver { get { return this.TestObject.AppiumDriver; } } diff --git a/Framework/SpecFlowExtensionNUnitTests/Steps/AppiumUnitTestSteps.cs b/Framework/SpecFlowExtensionNUnitTests/Steps/AppiumUnitTestSteps.cs index 4db7ef477..ef86cdfc5 100644 --- a/Framework/SpecFlowExtensionNUnitTests/Steps/AppiumUnitTestSteps.cs +++ b/Framework/SpecFlowExtensionNUnitTests/Steps/AppiumUnitTestSteps.cs @@ -86,7 +86,7 @@ public void ThenAppiumDriverIsNotNull() [Then(@"AppiumDriver is type AppiumDriver")] public void AndAppiumDriverIsTypeEventFiringAppiumDriver() { - Assert.IsTrue(this.AppiumDriver.GetType().Equals(typeof(AppiumDriver)), $"AppiumDriver for BaseAppiumTestSteps class is the wrong type : {this.TestObject.AppiumDriver.GetType()}."); + Assert.IsTrue(this.AppiumDriver.GetType().Equals(typeof(AppiumDriver)), $"AppiumDriver for BaseAppiumTestSteps class is the wrong type : {this.TestObject.AppiumDriver.GetType()}."); } } } diff --git a/Framework/SpecFlowExtensionUnitTests/Steps/AppiumUnitTestSteps.cs b/Framework/SpecFlowExtensionUnitTests/Steps/AppiumUnitTestSteps.cs index d9081d7b9..0c6fec6fc 100644 --- a/Framework/SpecFlowExtensionUnitTests/Steps/AppiumUnitTestSteps.cs +++ b/Framework/SpecFlowExtensionUnitTests/Steps/AppiumUnitTestSteps.cs @@ -89,7 +89,7 @@ public void ThenAppiumDriverIsNotNull() [Then(@"AppiumDriver is type AppiumDriver")] public void AndAppiumDriverIsTypeEventFiringAppiumDriver() { - Assert.IsTrue(this.TestObject.AppiumDriver.GetType().Equals(typeof(AppiumDriver)), $"AppiumDriver for BaseAppiumTestSteps class is the wrong type : {this.TestObject.AppiumDriver.GetType()}."); + Assert.IsTrue(this.TestObject.AppiumDriver.GetType().Equals(typeof(AppiumDriver)), $"AppiumDriver for BaseAppiumTestSteps class is the wrong type : {this.TestObject.AppiumDriver.GetType()}."); } /// @@ -97,9 +97,9 @@ public void AndAppiumDriverIsTypeEventFiringAppiumDriver() /// /// THe by to search with /// The AppiumWebElement found - private AppiumWebElement FindElement(By by) + private AppiumElement FindElement(By by) { - return (AppiumWebElement)this.TestObject.AppiumDriver.FindElement(by); + return (AppiumElement)this.TestObject.AppiumDriver.FindElement(by); } } } diff --git a/Framework/Utilities/Helper/Config.cs b/Framework/Utilities/Helper/Config.cs index 7eae6a2f4..460441ffd 100644 --- a/Framework/Utilities/Helper/Config.cs +++ b/Framework/Utilities/Helper/Config.cs @@ -90,14 +90,26 @@ public static void Validate(ConfigSection configSection, ConfigValidation config var configSectionPassed = GetSectionDictionary(configSection); List exceptions = new List(); - foreach (var requiredField in configValidation.RequiredFields) + + // Check if we have any required fields + if (configValidation.RequiredFields != null && configValidation.RequiredFields.Count > 0) { - if (!configSectionPassed.ContainsKey(requiredField)) + foreach (var requiredField in configValidation.RequiredFields) { - exceptions.Add($"Key missing {requiredField}"); + if (!configSectionPassed.ContainsKey(requiredField)) + { + exceptions.Add($"Key missing: {requiredField}"); + } } } + // Check if we have any one of required fields + if (configValidation.RequiredOneOfFields != null && configValidation.RequiredOneOfFields.Count > 0 && !configValidation.RequiredOneOfFields.Any(x => configSectionPassed.ContainsKey(x))) + { + // We have one of fields and didn't find any of them + exceptions.Add($"Need at least one of the following keys: {string.Join(", ", configValidation.RequiredOneOfFields)}"); + } + if (exceptions.Count > 0) { StringBuilder message = new StringBuilder(); @@ -135,10 +147,7 @@ public static Dictionary GetSectionDictionary(string section) foreach (IConfigurationSection child in compositeConfig.GetSection(section).GetChildren()) { - if (!string.IsNullOrEmpty(child.Value)) - { - keyList.Add(child.Key); - } + keyList.AddRange(GetRecursiveKeys(child)); } // Loop over all the key value pairs @@ -228,18 +237,6 @@ public static void AddTestSettingValues(IDictionary configuratio AddTestSettingValues(configurations, section.ToString()); } - /// - /// Add configuration override values - /// - /// Key for the value you are adding or overriding - /// Value being added or overridden - /// What section it should be added to - public static void AddTestSettingValues(string key, string value, ConfigSection section = DEFAULTMAQSSECTION) - { - var newKeyValue = new Dictionary { { key, value } }; - AddTestSettingValues(newKeyValue, section); - } - /// /// Add configuration override values /// @@ -271,6 +268,18 @@ public static void AddTestSettingValues(string key, string value, string section AddTestSettingValues(newKeyValue, section); } + /// + /// Add configuration override values + /// + /// Key for the value you are adding or overriding + /// Value being added or overridden + /// What section it should be added to + public static void AddTestSettingValue(string key, string value, ConfigSection section = DEFAULTMAQSSECTION) + { + var newKeyValue = new Dictionary { { key, value } }; + AddTestSettingValues(newKeyValue, section); + } + /// /// Get value from the general (MAGENICMAQS) section of the config file /// @@ -467,6 +476,33 @@ private static bool TryGetSectionValue(string section, string key, out string va return result.found; } + /// + /// Recursively get keys with values + /// + /// Child node to get keys for + /// List of keys + private static List GetRecursiveKeys(IConfigurationSection child) + { + List keyList = new List(); + + // Add the current child key if it has a value + if (!string.IsNullOrEmpty(child.Value)) + { + keyList.Add(child.Key); + } + + // Recusively look for lower level children that have values + foreach (IConfigurationSection subchild in child.GetChildren()) + { + foreach (string key in GetRecursiveKeys(subchild)) + { + keyList.Add($"{child.Key}:{key}"); + } + } + + return keyList; + } + /// /// Create an empty configuration root /// diff --git a/Framework/Utilities/Helper/ConfigValidation.cs b/Framework/Utilities/Helper/ConfigValidation.cs index 53fa41210..27c4719e3 100644 --- a/Framework/Utilities/Helper/ConfigValidation.cs +++ b/Framework/Utilities/Helper/ConfigValidation.cs @@ -11,5 +11,10 @@ public class ConfigValidation /// Gets or sets the list of required fields for a config /// public List RequiredFields { get; set; } + + /// + /// Gets or sets the list of fields you need at least one of for a config + /// + public List RequiredOneOfFields { get; set; } } } diff --git a/Framework/UtilitiesUnitTests/ConfigUnitTests.cs b/Framework/UtilitiesUnitTests/ConfigUnitTests.cs index 1bc735d2b..387bced55 100644 --- a/Framework/UtilitiesUnitTests/ConfigUnitTests.cs +++ b/Framework/UtilitiesUnitTests/ConfigUnitTests.cs @@ -147,7 +147,7 @@ public void SimpleSingleConfig() string overrideValue = baseValue + "_Override"; // Override the configuration - Config.AddTestSettingValues(key, overrideValue); + Config.AddTestSettingValue(key, overrideValue); // Make sure it worked Assert.AreEqual(overrideValue, Config.GetGeneralValue(key)); @@ -185,7 +185,7 @@ public void SimpleSingleForConfigSection() string overrideValue = baseValue + "_Override"; // Override the configuration - Config.AddTestSettingValues(key, overrideValue, ConfigSection.MagenicMaqs); + Config.AddTestSettingValue(key, overrideValue, ConfigSection.MagenicMaqs); // Make sure it worked Assert.AreEqual(overrideValue, Config.GetGeneralValue(key)); @@ -377,5 +377,19 @@ public void ConfigFieldsNull() Config.Validate(ConfigSection.WebServiceMaqs, null); } + /// + /// Multilevel configuration hierarchy is respected + /// + /// Configuration key + /// Expected value for key + [DataTestMethod] + [DataRow("low:JSON", "lowerJson")] + [DataRow("compound:key", "compound")] + [DataRow("compound:key:lower", "compoundEvenLower")] + public void MultilevelSectionKeys(string key, string expected) + { + var value = Config.GetSectionDictionary("MagenicMaqs"); + Assert.AreEqual(expected, value[key]); + } } } diff --git a/Framework/UtilitiesUnitTests/appsettings.json b/Framework/UtilitiesUnitTests/appsettings.json index 14d88052b..fcfbee9f9 100644 --- a/Framework/UtilitiesUnitTests/appsettings.json +++ b/Framework/UtilitiesUnitTests/appsettings.json @@ -14,7 +14,10 @@ "ConfigJsonEnvRun": "JSON", "ConfigJsonEnv": "JSON", "ConfigJson": "JSON", - "JsonOnly": "JSON" + "JsonOnly": "JSON", + "low": { "JSON": "lowerJson" }, + "compound:key": "compound", + "compound:key:lower": "compoundEvenLower" }, "TopTest": { "MidTest": [