diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj index 2c11fac7..7b42a5aa 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj @@ -28,7 +28,9 @@ + + True @@ -65,6 +67,8 @@ + + @@ -72,7 +76,7 @@ - + diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml index 7f1ab861..a72405e3 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml @@ -362,6 +362,21 @@ Authentication parameters, such as URI matcher and credentials. A task to be awaited. + + + Enables HTTP Request/Response logging, and starts network monitoring. + + Browser instance. + Logging preferences. + A task to be awaited. + + + + Enables HTTP Request/Response logging. + + Browser instance. + Logging preferences. + Implementation of version-independent emulation DevTools commands as extensions for . @@ -2140,5 +2155,75 @@ horizontal coordinate vertical coordinate + + + HTTP Request/Response logging options. + + + + + Controls logging of general request info: Method, URL, Request ID. + + + + + Controls logging of request headers. + + + + + Controls logging of request POST data. + + + + + Controls logging of general response info: Status code, URL, Resource type, Request ID. + + + + + Controls logging of response headers. + + + + + Controls logging of response body. + + + + + Extensions for localized logger. + + + + + Logging of localized messages with a specific log level. + + Current instance of logger. + Logging level. + Localized message key. + Arguments for the localized message. + Thrown when specified log level is not supported. + + + + Logging parameters for specific features, such as HTTP Exchange. + + + + + Whether feature logging should be enabled or not. + + + + + Logging level for the specific feature. + + + + + Logging level for specific features, such as HTTP Exchange. + + diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNetworkExtensions.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNetworkExtensions.cs index d1233ff7..949b0f35 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNetworkExtensions.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNetworkExtensions.cs @@ -1,4 +1,7 @@ -using OpenQA.Selenium; +using Aquality.Selenium.Logging; +using OpenQA.Selenium; +using System; +using System.Linq; using System.Threading.Tasks; namespace Aquality.Selenium.Browsers @@ -35,5 +38,89 @@ public static async Task RegisterBasicAuthenticationAndStartMonitoring(this Brow networkHandling.AddAuthenticationHandler(handler); await networkHandling.StartMonitoring(); } + + /// + /// Enables HTTP Request/Response logging, and starts network monitoring. + /// + /// Browser instance. + /// Logging preferences. + /// A task to be awaited. + public static async Task EnableHttpExchangeLoggingAndStartMonitoring(this Browser browser, HttpExchangeLoggingOptions loggingOptions = null) + { + browser.EnableHttpExchangeLogging(loggingOptions); + await browser.Network.StartMonitoring(); + } + + /// + /// Enables HTTP Request/Response logging. + /// + /// Browser instance. + /// Logging preferences. + public static void EnableHttpExchangeLogging(this Browser browser, HttpExchangeLoggingOptions loggingOptions = null) + { + if (loggingOptions == null) + { + loggingOptions = new HttpExchangeLoggingOptions(); + } + browser.Network.NetworkRequestSent += GetRequestEventHandler(loggingOptions); + browser.Network.NetworkResponseReceived += GetResponseEventHandler(loggingOptions); + } + + private static EventHandler GetResponseEventHandler(HttpExchangeLoggingOptions loggingOptions) + { + return (object sender, NetworkResponseReceivedEventArgs args) => + { + if (loggingOptions.ResponseInfo.Enabled) + { + AqualityServices.LocalizedLogger.LogByLevel( + loggingOptions.ResponseInfo.LogLevel, + "loc.browser.network.event.responsereceived.log.info", + args.ResponseStatusCode, args.ResponseUrl, args.ResponseResourceType, args.RequestId); + } + if (loggingOptions.ResponseHeaders.Enabled && args.ResponseHeaders.Any()) + { + AqualityServices.LocalizedLogger.LogByLevel( + loggingOptions.ResponseHeaders.LogLevel, + "loc.browser.network.event.responsereceived.log.headers", + string.Join(",", args.ResponseHeaders.Select(header => $"{Environment.NewLine}\t{header.Key}: {header.Value}"))); + } + if (loggingOptions.ResponseBody.Enabled && !string.IsNullOrEmpty(args.ResponseBody)) + { + AqualityServices.LocalizedLogger.LogByLevel( + loggingOptions.ResponseBody.LogLevel, + "loc.browser.network.event.responsereceived.log.body", + args.ResponseBody); + } + }; + } + + private static EventHandler GetRequestEventHandler(HttpExchangeLoggingOptions loggingOptions) + { + return (object sender, NetworkRequestSentEventArgs args) => + { + if (loggingOptions.RequestInfo.Enabled) + { + AqualityServices.LocalizedLogger.LogByLevel( + loggingOptions.RequestInfo.LogLevel, + "loc.browser.network.event.requestsent.log.info", + args.RequestMethod, args.RequestUrl, args.RequestId); + + } + if (loggingOptions.RequestHeaders.Enabled && args.RequestHeaders.Any()) + { + AqualityServices.LocalizedLogger.LogByLevel( + loggingOptions.RequestHeaders.LogLevel, + "loc.browser.network.event.requestsent.log.headers", + string.Join(",", args.RequestHeaders.Select(header => $"{Environment.NewLine}\t{header.Key}: {header.Value}"))); + } + if (loggingOptions.RequestPostData.Enabled && !string.IsNullOrEmpty(args.RequestPostData)) + { + AqualityServices.LocalizedLogger.LogByLevel( + loggingOptions.RequestPostData.LogLevel, + "loc.browser.network.event.requestsent.log.data", + args.RequestPostData); + } + }; + } } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Logging/HttpExchangeLoggingOptions.cs b/Aquality.Selenium/src/Aquality.Selenium/Logging/HttpExchangeLoggingOptions.cs new file mode 100644 index 00000000..0d2110ac --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Logging/HttpExchangeLoggingOptions.cs @@ -0,0 +1,38 @@ +namespace Aquality.Selenium.Logging +{ + /// + /// HTTP Request/Response logging options. + /// + public class HttpExchangeLoggingOptions + { + /// + /// Controls logging of general request info: Method, URL, Request ID. + /// + public LoggingParameters RequestInfo { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Info }; + + /// + /// Controls logging of request headers. + /// + public LoggingParameters RequestHeaders { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Debug }; + + /// + /// Controls logging of request POST data. + /// + public LoggingParameters RequestPostData { get; set; } = new LoggingParameters { Enabled = false, LogLevel = LogLevel.Debug }; + + /// + /// Controls logging of general response info: Status code, URL, Resource type, Request ID. + /// + public LoggingParameters ResponseInfo { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Info }; + + /// + /// Controls logging of response headers. + /// + public LoggingParameters ResponseHeaders { get; set; } = new LoggingParameters { Enabled = true, LogLevel = LogLevel.Debug }; + + /// + /// Controls logging of response body. + /// + public LoggingParameters ResponseBody { get; set; } = new LoggingParameters { Enabled = false, LogLevel = LogLevel.Debug }; + } +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Logging/LocalizedLoggerExtensions.cs b/Aquality.Selenium/src/Aquality.Selenium/Logging/LocalizedLoggerExtensions.cs new file mode 100644 index 00000000..0760ac4e --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Logging/LocalizedLoggerExtensions.cs @@ -0,0 +1,43 @@ +using Aquality.Selenium.Core.Localization; +using System; + +namespace Aquality.Selenium.Logging +{ + /// + /// Extensions for localized logger. + /// + public static class LocalizedLoggerExtensions + { + /// + /// Logging of localized messages with a specific log level. + /// + /// Current instance of logger. + /// Logging level. + /// Localized message key. + /// Arguments for the localized message. + /// Thrown when specified log level is not supported. + public static void LogByLevel(this ILocalizedLogger logger, LogLevel logLevel, string messageKey, params object[] args) + { + switch (logLevel) + { + case LogLevel.Debug: + logger.Debug(messageKey, args: args); + break; + case LogLevel.Info: + logger.Info(messageKey, args); + break; + case LogLevel.Warn: + logger.Warn(messageKey, args); + break; + case LogLevel.Error: + logger.Error(messageKey, args); + break; + case LogLevel.Fatal: + logger.Fatal(messageKey, args: args); + break; + default: + throw new NotSupportedException($"Localized logging at level [{logLevel}] is not supported."); + } + } + } +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Logging/LogLevel.cs b/Aquality.Selenium/src/Aquality.Selenium/Logging/LogLevel.cs new file mode 100644 index 00000000..e598ecbb --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Logging/LogLevel.cs @@ -0,0 +1,14 @@ +namespace Aquality.Selenium.Logging +{ + /// + /// Logging level for specific features, such as HTTP Exchange. + /// + public enum LogLevel + { + Debug, + Info, + Warn, + Error, + Fatal + } +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Logging/LoggingParameters.cs b/Aquality.Selenium/src/Aquality.Selenium/Logging/LoggingParameters.cs new file mode 100644 index 00000000..a09ba2e0 --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Logging/LoggingParameters.cs @@ -0,0 +1,18 @@ +namespace Aquality.Selenium.Logging +{ + /// + /// Logging parameters for specific features, such as HTTP Exchange. + /// + public struct LoggingParameters + { + /// + /// Whether feature logging should be enabled or not. + /// + public bool Enabled { get; set; } + + /// + /// Logging level for the specific feature. + /// + public LogLevel LogLevel { get; set; } + } +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json index 57ffca7c..3b92ba20 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json @@ -1,6 +1,6 @@ { "loc.browser.arguments": "Атрымалі стартавыя аргументы браўзэра з settings файла: {0}", - "loc.browser.excludedArguments": "Выключэнне аргументаў браўзэра з settings файла: {0}", + "loc.browser.excludedArguments": "Атрымалі выключаныя аргументы браўзэра з settings файла: {0}", "loc.browser.back": "Вяртаемся да папярэдняй старонкі", "loc.browser.forward": "Пераходзім да наступнай старонкі", "loc.browser.capabilities": "Атрымалі capabilities браўзэра з settings файла: {0}", @@ -86,6 +86,12 @@ "loc.browser.devtools.command.execute.result": "Вынік DevTools каманды: [{0}]", "loc.browser.network.event.requestsent.add": "Падпісваемся на падзею адпраўкі сеткавага запыта", "loc.browser.network.event.requestsent.remove": "Адпісваемся ад падзеі адпраўкі сеткавага запыта", + "loc.browser.network.event.requestsent.log.info": "Адпраўлены HTTP запыт:\r\nМетад: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nID запыта: \t{2}", + "loc.browser.network.event.requestsent.log.headers": "Загалоўкі запыта:\r\n{{{0}\r\n}}", + "loc.browser.network.event.requestsent.log.data": "POST дадзеныя запыта:\r\n{0}", + "loc.browser.network.event.responsereceived.log.info": "Атрыманы HTTP адказ:\r\nСтатус-код: \t{0}, \r\nURL: \t\t\t{1}, \r\nТып рэсурса: \t{2}, \r\nID запыта: \t{3}", + "loc.browser.network.event.responsereceived.log.headers": "Загалоўкі адказа:\r\n{{{0}\r\n}}", + "loc.browser.network.event.responsereceived.log.body": "Цела адказа:\r\n{0}", "loc.browser.network.event.responsereceived.add": "Падпісваемся на падзею атрымання сеткавага адказа", "loc.browser.network.event.responsereceived.remove": "Адпісваемся ад падзеі атрымання сеткавага адказа", "loc.browser.network.handler.authentication.add": "Дадаем апрацоўшчык базавай аўтэнтыфікацыі", diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json index c25f96f9..4efb0c85 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json @@ -1,6 +1,6 @@ { "loc.browser.arguments": "Got browser start arguments from settings file: {0}", - "loc.browser.excludedArguments": "Exclude browser arguments from settings file: {0}", + "loc.browser.excludedArguments": "Got excluded browser arguments from settings file: {0}", "loc.browser.back": "Return to previous page", "loc.browser.forward": "Proceed to the next page", "loc.browser.capabilities": "Got browser capabilities from settings file: {0}", @@ -86,6 +86,12 @@ "loc.browser.devtools.command.execute.result": "DevTools command result: [{0}]", "loc.browser.network.event.requestsent.add": "Subscribing to Network Request Sent event", "loc.browser.network.event.requestsent.remove": "Unsubscribing from Network Request Sent event", + "loc.browser.network.event.requestsent.log.info": "Send HTTP Request:\r\nMethod: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nRequest ID: \t{2}", + "loc.browser.network.event.requestsent.log.headers": "Request headers:\r\n{{{0}\r\n}}", + "loc.browser.network.event.requestsent.log.data": "Request POST data:\r\n{0}", + "loc.browser.network.event.responsereceived.log.info": "Received HTTP Response:\r\nStatus code: \t{0}, \r\nURL: \t\t\t{1}, \r\nResource type: \t{2}, \r\nRequest ID: \t{3}", + "loc.browser.network.event.responsereceived.log.headers": "Response headers:\r\n{{{0}\r\n}}", + "loc.browser.network.event.responsereceived.log.body": "Response body:\r\n{0}", "loc.browser.network.event.responsereceived.add": "Subscribing to Network Response Received event", "loc.browser.network.event.responsereceived.remove": "Unsubscribing from Network Response Received event", "loc.browser.network.handler.authentication.add": "Adding Basic Authentication handler", diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/pl.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/pl.json new file mode 100644 index 00000000..3048ca88 --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/pl.json @@ -0,0 +1,131 @@ +{ + "loc.browser.arguments": "Pobrano argumenty uruchamiania przeglądarki z pliku ustawień: {0}", + "loc.browser.excludedArguments": "Pobrano wykluczone argumenty przeglądarki z pliku ustawień: {0}", + "loc.browser.back": "Powrót do poprzedniej strony", + "loc.browser.forward": "Przejście do następnej strony", + "loc.browser.capabilities": "Pobrano możliwości przeglądarki z pliku ustawień: {0}", + "loc.browser.options": "Pobrano opcje profilu przeglądarki z pliku ustawień: {0}", + "loc.browser.driver.quit": "Zamykanie przeglądarki", + "loc.browser.getUrl": "Pobieranie aktualnego adresu URL", + "loc.browser.url.value": "Aktualny adres URL: [{0}]", + "loc.browser.grid": "Ustawianie WebDriver z Selenium Grid hub", + "loc.browser.grid.fail": "Ustawienie sterownika z Selenium Grid hub nie powiodło się", + "loc.browser.maximize": "Maksymalizacja okna przeglądarki", + "loc.browser.navigate": "Przejdź do adresu URL - '{0}'", + "loc.browser.page.wait": "Oczekiwanie na załadowanie strony", + "loc.browser.page.timeout": "Przekroczono limit czasu ładowania strony", + "loc.browser.ready": "Przeglądarka '{0}' gotowa...", + "loc.browser.refresh": "Odświeżanie strony", + "loc.browser.alert.accept": "Akceptowanie alertu przeglądarki", + "loc.browser.alert.decline": "Odrzucanie alertu przeglądarki", + "loc.browser.alert.fail": "Niepowodzenie podczas obsługi alertu", + "loc.button": "Przycisk", + "loc.checkbox": "Pole wyboru", + "loc.checkable.get.state": "Uzyskiwanie stanu", + "loc.checkable.state": "Stan: [{0}]", + "loc.clicking": "Kliknięcie", + "loc.clicking.double": "Podwójne kliknięcie", + "loc.clicking.js": "Kliknięcie przez JavaScript", + "loc.clicking.right": "Kliknięcie w prawo", + "loc.combobox": "Pole kombi", + "loc.combobox.getting.selected.text": "Pobieranie zaznaczonego tekstu", + "loc.combobox.getting.selected.value": "Pobieranie wybranej wartości", + "loc.combobox.selected.text": "Wybrany tekst: [{0}]", + "loc.combobox.selected.value": "Wybrana wartość: [{0}]", + "loc.combobox.select.by.text": "Wybieranie wartości z tekstem '{0}'", + "loc.combobox.select.by.text.js": "Wybieranie wartości z tekstem '{0}' przez JavaScript", + "loc.combobox.get.texts": "Pobieranie listy tekstów opcji", + "loc.combobox.get.texts.js": "Pobieranie listy tekstów opcji przez JavaScript", + "loc.combobox.get.values": "Pobieranie listy wartości", + "loc.combobox.get.text.js": "Pobieranie wybranego tekstu przez JavaScript", + "loc.combobox.texts": "Lista tekstów opcji: [{0}]", + "loc.combobox.values": "Lista wartości: [{0}]", + "loc.el.getattr": "Pobieranie atrybutu '{0}'", + "loc.el.attr.value": "Wartość atrybutu '{0}': [{1}]", + "loc.el.attr.set": "Ustawienie wartości atrybutu '{0}': [{1}]", + "loc.el.cssvalue": "Pobieranie wartości css '{0}'", + "loc.el.execute.pinnedjs": "Wykonywanie przypiętego JavaScript", + "loc.el.execute.pinnedjs.result": "Wynik wykonania przypiętego JavaScript: [{0}]", + "loc.focusing": "Skupienie", + "loc.get.text": "Pobieranie tekstu z elementu", + "loc.text.value": "Tekst elementu: [{0}]", + "loc.get.text.js": "Pobieranie tekstu z elementu przez JavaScript", + "loc.hover.js": "Najedź kursorem na element przez JavaScript", + "loc.is.present.js": "Określ, czy element jest obecny na ekranie, przez JavaScript", + "loc.is.present.value": "Czy element jest obecny na ekranie: [{0}]", + "loc.get.xpath.js": "Pobieranie lokalizatora XPath elementu przez JavaScript", + "loc.xpath.value": "Lokalizator XPath: [{0}]", + "loc.label": "Etykieta", + "loc.link": "Link", + "loc.moving": "Przesuwanie myszy na element", + "loc.movingFrom": "Przesuwanie myszy z elementu", + "loc.radio": "RadioButton", + "loc.scrolling.center.js": "Przewijanie do centrum przez JavaScript", + "loc.scrolling.js": "Przewijanie przez JavaScript", + "loc.selecting.value": "Wybieranie wartości - '{0}'", + "loc.send.text": "Ustawianie tekstu - '{0}'", + "loc.setting.value": "Ustawienie wartości - '{0}'", + "loc.text.clearing": "Oczyszczenie", + "loc.text.submitting": "Przesyłanie", + "loc.text.field": "Pole tekstowe", + "loc.text.sending.key": "Wysyłanie klawisz '{0}'", + "loc.text.typing": "Wpisywanie '{0}'", + "loc.browser.switch.to.tab.handle": "Przełączanie na nową kartę według deskryptora '{0}'", + "loc.browser.switch.to.tab.index": "Przełączanie na nową kartę według indeksu '{0}'", + "loc.browser.switch.to.new.tab": "Przełączanie do nowej karty", + "loc.browser.get.tab.handles": "Pobieranie listy deskryptorów otwartych kart", + "loc.browser.get.tab.handle": "Pobieranie bieżącego deskryptora karty", + "loc.browser.tab.open.new": "Otwieranie nowej karty", + "loc.browser.tab.close": "Zamknięcie karty", + "loc.browser.devtools.session.isactive": "Sprawdzanie, czy sesja DevTools jest aktywna", + "loc.browser.devtools.session.isactive.result": "Czy sesja DevTools jest aktywna: [{0}]", + "loc.browser.devtools.session.close": "Zamykanie sesji DevTools", + "loc.browser.devtools.session.get": "Pobieranie sesji DevTools z wersją protokołu [{0}]", + "loc.browser.devtools.command.execute": "Wykonywanie polecenia DevTools [{0}]", + "loc.browser.devtools.command.execute.withparams": "Wykonywanie polecenia DevTools [{0}] z parametrami [{1}]", + "loc.browser.devtools.command.execute.result": "Wynik polecenia DevTools: [{0}]", + "loc.browser.network.event.requestsent.add": "Subskrybowanie do zdarzenia Wysłanie Żądania Sieciowego", + "loc.browser.network.event.requestsent.remove": "Anulowanie subskrypcji do zdarzenia Wysłane Żądanie Sieciowe", + "loc.browser.network.event.requestsent.log.info": "Wysłano żądanie HTTP:\r\nMetoda: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nID żądania: \t {2}", + "loc.browser.network.event.requestsent.log.headers": "Nagłówki żądania:\r\n{{{0}\r\n}}", + "loc.browser.network.event.requestsent.log.data": "POST dane żądania:\r\n{0}", + "loc.browser.network.event.responsereceived.log.info": "Otrzymana odpowiedź HTTP:\r\nKod stanu: \t{0}, \r\nURL: \t\t\t{1}, \r \nTyp zasobu: \t{2}, \r\nID żądania: \t{3}", + "loc.browser.network.event.responsereceived.log.headers": "Nagłówki odpowiedzi:\r\n{{{0}\r\n}}", + "loc.browser.network.event.responsereceived.log.body": "Treść odpowiedzi:\r\n{0}", + "loc.browser.network.event.responsereceived.add": "Subskrybowanie do zdarzenia Otrzymano odpowiedź sieciową", + "loc.browser.network.event.responsereceived.remove": "Anulowanie do subskrypcji zdarzenia Otrzymano odpowiedź sieciową", + "loc.browser.network.handler.authentication.add": "Dodawanie programu obsługi uwierzytelniania podstawowego", + "loc.browser.network.handler.authentication.clear": "Usuwanie programów obsługi uwierzytelniania podstawowego", + "loc.browser.network.handler.request.add": "Dodawanie programu obsługi żądań sieciowych", + "loc.browser.network.handler.request.clear": "Usuwanie programów obsługi żądań sieciowych", + "loc.browser.network.handler.response.add": "Dodawanie obsługi odpowiedzi sieciowej", + "loc.browser.network.handler.response.clear": "Czyszczenie obsługi odpowiedzi sieciowej", + "loc.browser.network.monitoring.start": "Uruchamianie monitorowania sieci", + "loc.browser.network.monitoring.stop": "Zatrzymywanie monitorowania sieci", + "loc.browser.javascript.initializationscripts.get": "Pobieranie inicjujących skryptów JavaScript", + "loc.browser.javascript.scriptcallbackbindings.get": "Pobieranie powiązań wywołań zwrotnych JavaScript", + "loc.browser.javascript.event.callbackexecuted.add": "Subskrybowanie do zdarzenia Wykonywane jest nazwane powiązanie wywołania zwrotnego", + "loc.browser.javascript.event.callbackexecuted.remove": "Rezygnacja z subskrypcji Wykonywane jest nazwane powiązanie wywołania zwrotnego", + "loc.browser.javascript.event.exceptionthrown.add": "Subskrybowanie do zdarzenia wyjątek JavaScript jest rzucany", + "loc.browser.javascript.event.exceptionthrown.remove": "Rezygnacja z subskrypcji do zdarzenia wyjątek JavaScript jest rzucany", + "loc.browser.javascript.event.consoleapicalled.add": "Subskrybowanie do zdarzenia wywołania API konsoli JavaScript", + "loc.browser.javascript.event.consoleapicalled.remove": "Rezygnacja z subskrypcji do zdarzenia wywołania API konsoli JavaScript", + "loc.browser.javascript.event.dommutated.add": "Subskrybowanie do zdarzenia mutacji DOM", + "loc.browser.javascript.event.dommutated.remove": "Rezygnacja z subskrypcji do zdarzenia mutacji DOM", + "loc.browser.javascript.initializationscript.add": "Dodawanie inicjującego JavaScript o przyjaznej nazwie '{0}'", + "loc.browser.javascript.initializationscript.remove": "Usuwanie inicjującego JavaScriptu według przyjaznej nazwy '{0}'", + "loc.browser.javascript.initializationscripts.clear": "Usuwanie wszystkich inicjujących skryptów JavaScript", + "loc.browser.javascript.scriptcallbackbinding.add": "Dodanie powiązania wywołania zwrotnego JavaScript o nazwie '{0}'", + "loc.browser.javascript.scriptcallbackbinding.remove": "Usuwanie powiązania wywołania zwrotnego JavaScript o nazwie '{0}'", + "loc.browser.javascript.scriptcallbackbindings.clear": "Usuwanie wszystkich powiązań wywołań zwrotnych JavaScript", + "loc.browser.javascript.dommutation.monitoring.enable": "Włączanie monitorowania mutacji DOM", + "loc.browser.javascript.dommutation.monitoring.disable": "Wyłączanie monitorowania mutacji DOM", + "loc.browser.javascript.snippet.pin": "Przypinanie fragmentu kodu JavaScript", + "loc.browser.javascript.snippet.unpin": "Odpinanie fragmentu kodu JavaScript", + "loc.browser.javascript.event.monitoring.start": "Uruchamianie monitorowania zdarzeń JavaScript", + "loc.browser.javascript.event.monitoring.stop": "Zatrzymywanie monitorowania zdarzeń JavaScript", + "loc.browser.javascript.clearall": "Usuwanie wszystkich powiązań wywołań zwrotnych JavaScript i skrypty inicjujące", + "loc.browser.javascript.reset": "Usunięcie wszystkich powiązań wywołań zwrotnych JavaScript i skrypty inicjujące oraz zatrzymanie nasłuchiwania zdarzeń", + "loc.shadowroot.expand": "Rozwidnienie drzewa ukrytych elementów", + "loc.shadowroot.expand.js": "Rozwidnienie drzewa ukrytych elementów przez JavaScript" +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json index 77441c1c..0dc5e1c4 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json @@ -1,6 +1,6 @@ { "loc.browser.arguments": "Получили стартовые аргументы браузера из settings файла: {0}", - "loc.browser.excludedArguments": "Исключение аргументов браузера из settings файла: {0}", + "loc.browser.excludedArguments": "Получили исключённые аргументы браузера из settings файла: {0}", "loc.browser.back": "Возврат на предыдущую страницу", "loc.browser.forward": "Перейти на следующую страницу", "loc.browser.capabilities": "Получили capabilities браузера из settings файла: {0}", @@ -22,7 +22,7 @@ "loc.button": "Кнопка", "loc.checkbox": "Чекбокс", "loc.checkable.get.state": "Получение состояния", - "loc.checkable.state": "Cостояние: [{0}]", + "loc.checkable.state": "Состояние: [{0}]", "loc.clicking": "Клик", "loc.clicking.double": "Двойной Клик", "loc.clicking.js": "Клик посредством JavaScript", @@ -40,9 +40,9 @@ "loc.combobox.get.text.js": "Получение списка значений посредством JavaScript", "loc.combobox.texts": "Список текстов опций: [{0}]", "loc.combobox.values": "Список значений: [{0}]", - "loc.el.getattr": "Получение аттрибута '{0}'", - "loc.el.attr.value": "Значение аттрибута '{0}': [{1}]", - "loc.el.attr.set": "Установка значения аттрибута '{0}': [{1}]", + "loc.el.getattr": "Получение атрибута '{0}'", + "loc.el.attr.value": "Значение атрибута '{0}': [{1}]", + "loc.el.attr.set": "Установка значения атрибута '{0}': [{1}]", "loc.el.cssvalue": "Получение значения css '{0}'", "loc.el.execute.pinnedjs": "Исполнение закреплённого JavaScript", "loc.el.execute.pinnedjs.result": "Результат исполнения закреплённого JavaScript: [{0}]", @@ -86,6 +86,12 @@ "loc.browser.devtools.command.execute.result": "Результат DevTools команды: [{0}]", "loc.browser.network.event.requestsent.add": "Подписываемся на событие отправки сетевого запроса", "loc.browser.network.event.requestsent.remove": "Отписываемся от события отправки сетевого запроса", + "loc.browser.network.event.requestsent.log.info": "Отправлен HTTP запрос:\r\nМетод: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nID запроса: \t{2}", + "loc.browser.network.event.requestsent.log.headers": "Заголовки запроса:\r\n{{{0}\r\n}}", + "loc.browser.network.event.requestsent.log.data": "POST данные запроса:\r\n{0}", + "loc.browser.network.event.responsereceived.log.info": "Получен HTTP ответ:\r\nСтатус-код: \t{0}, \r\nURL: \t\t\t{1}, \r\nТип ресурса: \t{2}, \r\nID запроса: \t{3}", + "loc.browser.network.event.responsereceived.log.headers": "Заголовки ответа:\r\n{{{0}\r\n}}", + "loc.browser.network.event.responsereceived.log.body": "Тело ответа:\r\n{0}", "loc.browser.network.event.responsereceived.add": "Подписываемся на событие получения сетевого ответа", "loc.browser.network.event.responsereceived.remove": "Отписываемся от события получения сетевого ответа", "loc.browser.network.handler.authentication.add": "Добавление обработчика базовой аутентификации", diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/uk.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/uk.json new file mode 100644 index 00000000..2af776f7 --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/uk.json @@ -0,0 +1,131 @@ +{ + "loc.browser.arguments": "Отримані аргументи запуску браузера з файлу налаштувань: {0}", + "loc.browser.excludedArguments": "Отримані виключені аргументи браузера з файлу налаштувань: {0}", + "loc.browser.back": "Повертання до попередньої сторінки", + "loc.browser.forward": "Перехід до наступної сторінки", + "loc.browser.capabilities": "Отримані можливості браузера з файлу налаштувань: {0}", + "loc.browser.options": "Отримані параметри профілю браузера з файлу налаштувань: {0}", + "loc.browser.driver.quit": "Закриття браузера", + "loc.browser.getUrl": "Отримання адреси поточної сторінки", + "loc.browser.url.value": "Адреса поточної сторінки: [{0}]", + "loc.browser.grid": "Встановлення драйвера для браузера з Selenium Grid hub", + "loc.browser.grid.fail": "Не вдалося встановити драйвер браузера з Selenium Grid hub", + "loc.browser.maximize": "Розгортання вікно браузера на весь екран", + "loc.browser.navigate": "Перехід до '{0}'", + "loc.browser.page.wait": "Очікування завантаження сторінки", + "loc.browser.page.timeout": "Вичерпано час очікування завантаження сторінки", + "loc.browser.ready": "Браузер '{0}' готовий ...", + "loc.browser.refresh": "Оновлення сторінки", + "loc.browser.alert.accept": "Підтвердження дію у вікні сповіщення", + "loc.browser.alert.decline": "Відхилення дію у вікні сповіщення", + "loc.browser.alert.fail": "Помилка взаємодії з вікном сповіщень", + "loc.button": "Кнопка", + "loc.checkbox": "Чекбокс", + "loc.checkable.get.state": "Отримання стану", + "loc.checkable.state": "Стан: [{0}]", + "loc.clicking": "Натискання", + "loc.clicking.double": "Двійне натискання", + "loc.clicking.js": "Натискання за допомогою JavaScript", + "loc.clicking.right": "Натискання правою кнопкою миші", + "loc.combobox": "Комбобокс", + "loc.combobox.getting.selected.text": "Отримання вибраного тексту", + "loc.combobox.getting.selected.value": "Отримання вибраного значення", + "loc.combobox.selected.text": "Вибраний текст: [{0}]", + "loc.combobox.selected.value": "Вибране значення: [{0}]", + "loc.combobox.select.by.text": "Вибір значення за текстом '{0}'", + "loc.combobox.select.by.text.js": "Вибір значення за текстом '{0}' за допомогою JavaScript", + "loc.combobox.get.texts": "Отримання масиву текстів опцій", + "loc.combobox.get.texts.js": "Отримання текстового масиву опцій через JavaScript", + "loc.combobox.get.values": "Отримання масиву значень", + "loc.combobox.get.text.js": "Отримання виділеного тексту за допомогою JavaScript", + "loc.combobox.texts": "Тексти опцій: [{0}]", + "loc.combobox.values": "Значення опцій: [{0}]", + "loc.el.getattr": "Отримання атрибута '{0}'", + "loc.el.attr.value": "Значення атрибута '{0}': [{1}]", + "loc.el.attr.set": "Встановлення значення атрибута '{0}': [{1}]", + "loc.el.cssvalue": "Отримання значення css '{0}'", + "loc.el.execute.pinnedjs": "Виконання закріпленого JavaScript", + "loc.el.execute.pinnedjs.result": "Результат виконання закріпленого JavaScript: [{0}]", + "loc.focusing": "Фокусування", + "loc.get.text": "Отримання тексту з елемента", + "loc.text.value": "Текст елемента: [{0}]", + "loc.get.text.js": "Отримання тексту з елемента за допомогою JavaScript", + "loc.hover.js": "Наведення курсору миші на елемент за допомогою JavaScript", + "loc.is.present.js": "Визначення, чи є елемент на екрані за допомогою JavaScript", + "loc.is.present.value": "Чи є елемент на екрані: [{0}]", + "loc.get.xpath.js": "Отримання XPath локатора елемента за допомогою JavaScript", + "loc.xpath.value": "Локатор XPath: [{0}]", + "loc.label": "Мітка", + "loc.link": "Посилання", + "loc.moving": "Переміщення миші до елемента", + "loc.movingFrom": "Переміщення миші від елемента", + "loc.radio": "Радіокнопка", + "loc.scrolling.center.js": "Прокрутка до центру за допомогою JavaScript", + "loc.scrolling.js": "Прокрутка за допомогою JavaScript", + "loc.selecting.value": "Вибір значення - '{0}'", + "loc.send.text": "Встановлення тексту - '{0}'", + "loc.setting.value": "Встановлення значення - '{0}'", + "loc.text.clearing": "Очищення", + "loc.text.submitting": "Надсилання", + "loc.text.field": "Текстове поле", + "loc.text.sending.key": "Надсилання клавіш '{0}'", + "loc.text.typing": "Введення '{0}'", + "loc.browser.switch.to.tab.handle": "Перехід на вкладку за дескриптором '{0}'", + "loc.browser.switch.to.tab.index": "Перехід на вкладку за індексом '{0}'", + "loc.browser.switch.to.new.tab": "Перехід на нову вкладку", + "loc.browser.get.tab.handles": "Отримання дескрипторів вкладок", + "loc.browser.get.tab.handle": "Отримання дескриптора поточної вкладки", + "loc.browser.tab.open.new": "Відкриття нової вкладки", + "loc.browser.tab.close": "Закриття вкладки", + "loc.browser.devtools.session.isactive": "Перевірка, чи активний сеанс DevTools", + "loc.browser.devtools.session.isactive.result": "Чи активний сеанс DevTools: [{0}]", + "loc.browser.devtools.session.close": "Закриття сеансу DevTools", + "loc.browser.devtools.session.get": "Отримання сеансу DevTools з версією протоколу [{0}]", + "loc.browser.devtools.command.execute": "Виконання команди DevTools [{0}]", + "loc.browser.devtools.command.execute.withparams": "Виконання команди DevTools [{0}] з параметрами [{1}]", + "loc.browser.devtools.command.execute.result": "Результат команди DevTools: [{0}]", + "loc.browser.network.event.requestsent.add": "Підписка на подію надісланого запиту мережі", + "loc.browser.network.event.requestsent.remove": "Скасування підписки на подію запиту мережі", + "loc.browser.network.event.requestsent.log.info": "HTTP-запит надіслано:\r\nМетод: \t\t{0}, \r\nURL: \t\t\t{1}, \r\nID запиту: \t{2} ", + "loc.browser.network.event.requestsent.log.headers": "Заголовки запиту:\r\n{{{0}\r\n}}", + "loc.browser.network.event.requestsent.log.data": "POST дані запиту:\r\n{0}", + "loc.browser.network.event.responsereceived.log.info": "Отримана відповідь HTTP:\r\nСтатус-код: \t{0},\r\nURL: \t\t\t{1}, \r\nТип ресурсу: \t{2}, \r\nID запиту: \t{3}", + "loc.browser.network.event.responsereceived.log.headers": "Заголовки відповіді:\r\n{{{0}\r\n}}", + "loc.browser.network.event.responsereceived.log.body": "Тіло відповіді:\r\n{0}", + "loc.browser.network.event.responsereceived.add": "Підписка на подію відповіді мережі", + "loc.browser.network.event.responsereceived.remove": "Скасування підписки на подію відповіді мережі", + "loc.browser.network.handler.authentication.add": "Додавання обробника базової автентифікації", + "loc.browser.network.handler.authentication.clear": "Очищення обробників базової автентифікації", + "loc.browser.network.handler.request.add": "Додання обробника мережевих запитів", + "loc.browser.network.handler.request.clear": "Очищення обробників мережевих запитів", + "loc.browser.network.handler.response.add": "Додання обробника відповіді мережі", + "loc.browser.network.handler.response.clear": "Очищення обробників відповідей мережі", + "loc.browser.network.monitoring.start": "Початок моніторингу мережі", + "loc.browser.network.monitoring.stop": "Зупинення моніторингу мережі", + "loc.browser.javascript.initializationscripts.get": "Отримання сценаріїв ініціалізації", + "loc.browser.javascript.scriptcallbackbindings.get": "Отримання прив'язок зворотного виклику JavaScript", + "loc.browser.javascript.event.callbackexecuted.add": "Підписка на подію іменованої прив'язки зворотного виклику JavaScript", + "loc.browser.javascript.event.callbackexecuted.remove": "Скасування підписку на подію іменованої прив'язки зворотного виклику JavaScript", + "loc.browser.javascript.event.exceptionthrown.add": "Підписка на подію викидування помилки JavaScript", + "loc.browser.javascript.event.exceptionthrown.remove": "Скасування підписки на подію викидування помилки JavaScript", + "loc.browser.javascript.event.consoleapicalled.add": "Підписка на подію виклику API консолі JavaScript", + "loc.browser.javascript.event.consoleapicalled.remove": "Скасувати підписку на подію виклику API консолі JavaScript", + "loc.browser.javascript.event.dommutated.add": "Підписка на подію змін у DOM", + "loc.browser.javascript.event.dommutated.remove": "Скасувати підписку на подію змін у DOM", + "loc.browser.javascript.initializationscript.add": "Додавання JavaScript ініціалізації зі зручною назвою '{0}'", + "loc.browser.javascript.initializationscript.remove": "Видалення JavaScript ініціалізації зі зручною назвою '{0}'", + "loc.browser.javascript.initializationscripts.clear": "Видалення всіх сценаріїв ініціалізації", + "loc.browser.javascript.scriptcallbackbinding.add": "Додавання прив'язки зворотного виклику JavaScript з ім'ям '{0}'", + "loc.browser.javascript.scriptcallbackbinding.remove": "Видалення прив'язки зворотного виклику JavaScript з ім'ям '{0}'", + "loc.browser.javascript.scriptcallbackbindings.clear": "Видалення всіх прив'язок зворотного виклику JavaScript", + "loc.browser.javascript.dommutation.monitoring.enable": "Увімкнення моніторингу змін у DOM", + "loc.browser.javascript.dommutation.monitoring.disable": "Вимкнення моніторингу змін у DOM", + "loc.browser.javascript.snippet.pin": "Закріплення фрагменту JavaScript", + "loc.browser.javascript.snippet.unpin": "Відкріплення фрагменту JavaScript", + "loc.browser.javascript.event.monitoring.start": "Початок моніторингу подій JavaScript", + "loc.browser.javascript.event.monitoring.stop": "Припинення моніторингу подій JavaScript", + "loc.browser.javascript.clearall": "Видалення усіх прив'язок зворотного виклику JavaScript та сценаріїв ініціалізації", + "loc.browser.javascript.reset": "Видалення усіх прив'язок зворотного виклику JavaScript та сценаріїв ініціалізації та скасування підписок на події", + "loc.shadowroot.expand": "Розгорнення дерева прихованих елементів", + "loc.shadowroot.expand.js": "Розгорнення дерева прихованих елементів за допомогою JavaScript" +} diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj index 9b102dcc..469b2d22 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false @@ -30,11 +30,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs index 5a1405aa..0fd30e4d 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs @@ -1,6 +1,5 @@ using Aquality.Selenium.Browsers; using NUnit.Framework; -using OpenQA.Selenium.DevTools.V96.Performance; using System.Collections.Generic; namespace Aquality.Selenium.Tests.Integration diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs index 4c4445d2..59a42a9a 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs @@ -2,11 +2,15 @@ using Aquality.Selenium.Tests.Integration.TestApp.TheInternet.Forms; using NUnit.Framework; using OpenQA.Selenium; +using System.IO; +using System.Linq; namespace Aquality.Selenium.Tests.Integration { internal class NetworkHandlingTests : UITest { + private const string LogPath = "../../../Log/log.log"; + [Test] public void Should_BePossibleTo_SetBasicAuthentication() { @@ -104,5 +108,20 @@ public void Should_BePossibleTo_SubscribeToResponseReceivedEvent_AndUnsubscribeF welcomeForm.Open(); Assert.AreEqual(oldValue, counter, "Should be possible to unsubscribe from Response Received event"); } + + [Test] + [Parallelizable(ParallelScope.None)] + public void Should_BePossibleTo_EnableHttpExchangeLogging_AndDisableIt() + { + var someForm = new DropdownForm(); + someForm.Open(); + var logMessage1 = File.ReadAllLines(LogPath).LastOrDefault(); + Assert.IsFalse(string.IsNullOrEmpty(logMessage1), "Some message should appear in log file and should not be empty"); + Assert.DoesNotThrowAsync(() => AqualityServices.Browser.EnableHttpExchangeLoggingAndStartMonitoring(), "Should be possible to enable HTTP exchange logging"); + AqualityServices.Browser.Driver.Navigate().Refresh(); + var logMessage2 = File.ReadAllLines(LogPath).LastOrDefault(); + Assert.IsFalse(string.IsNullOrEmpty(logMessage2), "Some message should appear in log file and should not be empty"); + Assert.AreNotEqual(logMessage1, logMessage2, "HTTP logging message should be in file, although no Aquality-actions performed"); + } } } diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c96c59e6..8651f7d0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -25,7 +25,13 @@ stages: projectVersion: '$(Build.BuildNumber)' extraProperties: | sonar.coverage.exclusions=**/** - + + - task: UseDotNet@2 + displayName: Use .NET 6.0 + inputs: + packageType: 'sdk' + version: '6.0.x' + - task: DotNetCoreCLI@2 displayName: 'Build solution' env: @@ -48,7 +54,13 @@ stages: variables: profile: 'azure' - steps: + steps: + - task: UseDotNet@2 + displayName: Use .NET 6.0 + inputs: + packageType: 'sdk' + version: '6.0.x' + - task: DotNetCoreCLI@2 displayName: 'Run tests' inputs: @@ -73,6 +85,12 @@ stages: inputs: useConfigFile: true configFilePath: 'GitVersion.yml' + + - task: UseDotNet@2 + displayName: Use .NET 6.0 + inputs: + packageType: 'sdk' + version: '6.0.x' - script: dotnet pack Aquality.Selenium\src\Aquality.Selenium\Aquality.Selenium.csproj -c $(buildConfiguration) -p:Version=$(GitVersion.NuGetVersion) -o $(Build.ArtifactStagingDirectory) displayName: 'Pack to NuGet package'