Best Atata code snippet using Atata.EventBus.Subscribe
AtataContext.cs
Source:AtataContext.cs
1using System;2using System.Collections.Generic;3using System.Collections.ObjectModel;4using System.Diagnostics;5using System.Globalization;6using System.Linq;7using System.Text;8using System.Threading;9using OpenQA.Selenium;1011namespace Atata12{13 /// <summary>14 /// Represents the Atata context, the entry point for the test set-up.15 /// </summary>16 public sealed class AtataContext : IDisposable17 {18 private static readonly object s_buildStartSyncLock = new object();1920 private static readonly AsyncLocal<AtataContext> s_currentAsyncLocalContext = new AsyncLocal<AtataContext>();2122 private static AtataContextModeOfCurrent s_modeOfCurrent = AtataContextModeOfCurrent.AsyncLocal;2324 [ThreadStatic]25 private static AtataContext s_currentThreadStaticContext;2627 private static AtataContext s_currentStaticContext;2829 private string _testName;3031 private string _testSuiteName;3233 private IWebDriver _driver;3435 private bool _disposed;3637 /// <summary>38 /// Gets the base retry timeout, which is <c>5</c> seconds.39 /// </summary>40 public static readonly TimeSpan DefaultRetryTimeout = TimeSpan.FromSeconds(5);4142 /// <summary>43 /// Gets the default retry interval, which is <c>500</c> milliseconds.44 /// </summary>45 public static readonly TimeSpan DefaultRetryInterval = TimeSpan.FromSeconds(0.5);4647 internal AtataContext()48 {49 Go = new AtataNavigator(this);50 }5152 /// <summary>53 /// Gets or sets the current context.54 /// </summary>55 public static AtataContext Current56 {57 get58 {59 return ModeOfCurrent == AtataContextModeOfCurrent.ThreadStatic60 ? s_currentThreadStaticContext61 : ModeOfCurrent == AtataContextModeOfCurrent.AsyncLocal62 ? s_currentAsyncLocalContext.Value63 : s_currentStaticContext;64 }6566 set67 {68 if (ModeOfCurrent == AtataContextModeOfCurrent.ThreadStatic)69 s_currentThreadStaticContext = value;70 else if (ModeOfCurrent == AtataContextModeOfCurrent.AsyncLocal)71 s_currentAsyncLocalContext.Value = value;72 else73 s_currentStaticContext = value;74 }75 }7677 /// <summary>78 /// Gets or sets the mode of <see cref="Current"/> property.79 /// The default value is <see cref="AtataContextModeOfCurrent.AsyncLocal"/>.80 /// </summary>81 public static AtataContextModeOfCurrent ModeOfCurrent82 {83 get => s_modeOfCurrent;84 set85 {86 s_modeOfCurrent = value;8788 RetrySettings.ThreadBoundary = value == AtataContextModeOfCurrent.ThreadStatic89 ? RetrySettingsThreadBoundary.ThreadStatic90 : value == AtataContextModeOfCurrent.AsyncLocal91 ? RetrySettingsThreadBoundary.AsyncLocal92 : RetrySettingsThreadBoundary.Static;93 }94 }9596 /// <summary>97 /// Gets the global configuration.98 /// </summary>99 public static AtataContextBuilder GlobalConfiguration { get; } = new AtataContextBuilder(new AtataBuildingContext());100101 /// <summary>102 /// Gets the build start local date and time.103 /// Contains the same value for all the tests being executed within one build.104 /// </summary>105 public static DateTime? BuildStart { get; private set; }106107 /// <summary>108 /// Gets the build start UTC date and time.109 /// Contains the same value for all the tests being executed within one build.110 /// </summary>111 public static DateTime? BuildStartUtc { get; private set; }112113 // TODO: Review BuildStartInTimeZone property.114 internal DateTime BuildStartInTimeZone { get; private set; }115116 internal IDriverFactory DriverFactory { get; set; }117118 /// <summary>119 /// Gets the driver.120 /// </summary>121 public IWebDriver Driver122 {123 get124 {125 switch (DriverInitializationStage)126 {127 case AtataContextDriverInitializationStage.Build:128 return _driver;129 case AtataContextDriverInitializationStage.OnDemand:130 if (_driver is null)131 InitDriver();132 return _driver;133 default:134 return null;135 }136 }137 }138139 /// <summary>140 /// Gets a value indicating whether this instance has <see cref="Driver"/> instance.141 /// </summary>142 public bool HasDriver => _driver != null;143 /// <summary>144 /// Gets the driver alias.145 /// </summary>146 public string DriverAlias { get; internal set; }147148 /// <summary>149 /// Gets the driver initialization stage.150 /// </summary>151 public AtataContextDriverInitializationStage DriverInitializationStage { get; internal set; }152 /// <summary>153 /// Gets the instance of the log manager.154 /// </summary>155 public ILogManager Log { get; internal set; }156157 /// <summary>158 /// Gets the name of the test.159 /// </summary>160 public string TestName161 {162 get => _testName;163 internal set164 {165 _testName = value;166 TestNameSanitized = value.SanitizeForFileName();167 }168 }169170 /// <summary>171 /// Gets the name of the test sanitized for file path/name.172 /// </summary>173 public string TestNameSanitized { get; private set; }174175 /// <summary>176 /// Gets the name of the test suite (fixture/class).177 /// </summary>178 public string TestSuiteName179 {180 get => _testSuiteName;181 internal set182 {183 _testSuiteName = value;184 TestSuiteNameSanitized = value.SanitizeForFileName();185 }186 }187188 /// <summary>189 /// Gets the name of the test suite sanitized for file path/name.190 /// </summary>191 public string TestSuiteNameSanitized { get; private set; }192193 /// <summary>194 /// Gets the test suite (fixture/class) type.195 /// </summary>196 public Type TestSuiteType { get; internal set; }197198 /// <summary>199 /// Gets the local date/time of the start.200 /// </summary>201 public DateTime StartedAt { get; private set; }202203 /// <summary>204 /// Gets the UTC date/time of the start.205 /// </summary>206 public DateTime StartedAtUtc { get; private set; }207208 /// <summary>209 /// Gets the time zone.210 /// The default value is <see cref="TimeZoneInfo.Local"/>.211 /// </summary>212 public TimeZoneInfo TimeZone { get; internal set; }213214 /// <summary>215 /// Gets or sets the base URL.216 /// </summary>217 public string BaseUrl { get; set; }218219 /// <summary>220 /// Gets the base retry timeout.221 /// The default value is <c>5</c> seconds.222 /// </summary>223 public TimeSpan BaseRetryTimeout { get; internal set; }224225 /// <summary>226 /// Gets the base retry interval.227 /// The default value is <c>500</c> milliseconds.228 /// </summary>229 public TimeSpan BaseRetryInterval { get; internal set; }230231 /// <summary>232 /// Gets the element find timeout.233 /// The default value is <c>5</c> seconds.234 /// </summary>235 public TimeSpan ElementFindTimeout { get; internal set; }236237 /// <summary>238 /// Gets the element find retry interval.239 /// The default value is <c>500</c> milliseconds.240 /// </summary>241 public TimeSpan ElementFindRetryInterval { get; internal set; }242243 /// <summary>244 /// Gets the waiting timeout.245 /// The default value is <c>5</c> seconds.246 /// </summary>247 public TimeSpan WaitingTimeout { get; internal set; }248249 /// <summary>250 /// Gets the waiting retry interval.251 /// The default value is <c>500</c> milliseconds.252 /// </summary>253 public TimeSpan WaitingRetryInterval { get; internal set; }254255 /// <summary>256 /// Gets the verification timeout.257 /// The default value is <c>5</c> seconds.258 /// </summary>259 public TimeSpan VerificationTimeout { get; internal set; }260261 /// <summary>262 /// Gets the verification retry interval.263 /// The default value is <c>500</c> milliseconds.264 /// </summary>265 public TimeSpan VerificationRetryInterval { get; internal set; }266267 /// <summary>268 /// Gets the default control visibility.269 /// The default value is <see cref="Visibility.Any"/>.270 /// </summary>271 public Visibility DefaultControlVisibility { get; internal set; }272273 /// <summary>274 /// Gets the culture.275 /// The default value is <see cref="CultureInfo.CurrentCulture"/>.276 /// </summary>277 public CultureInfo Culture { get; internal set; }278279 /// <summary>280 /// Gets the type of the assertion exception.281 /// The default value is a type of <see cref="AssertionException"/>.282 /// </summary>283 public Type AssertionExceptionType { get; internal set; }284285 /// <summary>286 /// Gets the type of the aggregate assertion exception.287 /// The default value is a type of <see cref="AggregateAssertionException"/>.288 /// The exception type should have public constructor with <c>IEnumerable<AssertionResult></c> argument.289 /// </summary>290 public Type AggregateAssertionExceptionType { get; internal set; }291292 /// <summary>293 /// Gets the aggregate assertion strategy.294 /// The default value is an instance of <see cref="AtataAggregateAssertionStrategy"/>.295 /// </summary>296 public IAggregateAssertionStrategy AggregateAssertionStrategy { get; internal set; }297298 /// <summary>299 /// Gets the aggregate assertion depth level.300 /// </summary>301 public int AggregateAssertionLevel { get; internal set; }302303 /// <summary>304 /// Gets the strategy for warning assertion reporting.305 /// The default value is an instance of <see cref="AtataWarningReportStrategy"/>.306 /// </summary>307 public IWarningReportStrategy WarningReportStrategy { get; internal set; }308309 /// <summary>310 /// Gets the list of all assertion results.311 /// </summary>312 public List<AssertionResult> AssertionResults { get; } = new List<AssertionResult>();313314 /// <summary>315 /// Gets the list of pending assertion results with <see cref="AssertionStatus.Failed"/> or <see cref="AssertionStatus.Warning"/> status.316 /// </summary>317 public List<AssertionResult> PendingFailureAssertionResults { get; } = new List<AssertionResult>();318319 /// <summary>320 /// Gets the context of the attributes.321 /// </summary>322 public AtataAttributesContext Attributes { get; internal set; }323324 /// <summary>325 /// Gets the <see cref="DirectorySubject"/> of Artifacts directory.326 /// Artifacts directory can contain any files produced during test execution, logs, screenshots, downloads, etc.327 /// The default Artifacts directory path is <c>"{basedir}/artifacts/{build-start:yyyyMMddTHHmmss}{test-suite-name-sanitized:/*}{test-name-sanitized:/*}"</c>.328 /// </summary>329 public DirectorySubject Artifacts { get; internal set; }330331 /// <summary>332 /// Gets the <see cref="AtataNavigator"/> instance,333 /// which provides the navigation functionality between pages and windows.334 /// </summary>335 public AtataNavigator Go { get; }336337 /// <summary>338 /// Gets the current page object.339 /// </summary>340 public UIComponent PageObject { get; internal set; }341342 internal List<UIComponent> TemporarilyPreservedPageObjectList { get; private set; } = new List<UIComponent>();343344 internal bool IsNavigated { get; set; }345346 internal Stopwatch ExecutionStopwatch { get; } = Stopwatch.StartNew();347348 internal Stopwatch PureExecutionStopwatch { get; } = new Stopwatch();349350 public ReadOnlyCollection<UIComponent> TemporarilyPreservedPageObjects351 {352 get { return TemporarilyPreservedPageObjectList.ToReadOnly(); }353 }354355 /// <summary>356 /// Gets the UI component access chain scope cache.357 /// </summary>358 public UIComponentAccessChainScopeCache UIComponentAccessChainScopeCache { get; } = new UIComponentAccessChainScopeCache();359360 /// <summary>361 /// Gets the object creator.362 /// </summary>363 public IObjectCreator ObjectCreator { get; internal set; }364365 /// <summary>366 /// Gets the object converter.367 /// </summary>368 public IObjectConverter ObjectConverter { get; internal set; }369370 /// <summary>371 /// Gets the object mapper.372 /// </summary>373 public IObjectMapper ObjectMapper { get; internal set; }374375 /// <summary>376 /// Gets the event bus, which can used to subscribe to and publish events.377 /// </summary>378 public IEventBus EventBus { get; internal set; }379380 /// <summary>381 /// Gets the variables dictionary.382 /// <para>383 /// The list of predefined variables:384 /// <list type="bullet">385 /// <item><c>build-start</c></item>386 /// <item><c>build-start-utc</c></item>387 /// <item><c>basedir</c></item>388 /// <item><c>artifacts</c></item>389 /// <item><c>test-name-sanitized</c></item>390 /// <item><c>test-name</c></item>391 /// <item><c>test-suite-name-sanitized</c></item>392 /// <item><c>test-suite-name</c></item>393 /// <item><c>test-start</c></item>394 /// <item><c>test-start-utc</c></item>395 /// <item><c>driver-alias</c></item>396 /// </list>397 /// </para>398 /// <para>399 /// Custom variables can be added as well.400 /// </para>401 /// </summary>402 public IDictionary<string, object> Variables { get; } = new Dictionary<string, object>();403404 /// <summary>405 /// Creates <see cref="AtataContextBuilder"/> instance for <see cref="AtataContext"/> configuration.406 /// Sets the value to <see cref="AtataContextBuilder.BuildingContext"/> copied from <see cref="GlobalConfiguration"/>.407 /// </summary>408 /// <returns>The created <see cref="AtataContextBuilder"/> instance.</returns>409 public static AtataContextBuilder Configure()410 {411 AtataBuildingContext buildingContext = GlobalConfiguration.BuildingContext.Clone();412 return new AtataContextBuilder(buildingContext);413 }414415 internal void InitDateTimeProperties()416 {417 StartedAtUtc = DateTime.UtcNow;418 StartedAt = TimeZoneInfo.ConvertTimeFromUtc(StartedAtUtc, TimeZone);419420 if (BuildStartUtc is null)421 {422 lock (s_buildStartSyncLock)423 {424 if (BuildStartUtc is null)425 {426 BuildStartUtc = StartedAtUtc;427 BuildStart = BuildStartUtc.Value.ToLocalTime();428 }429 }430 }431432 BuildStartInTimeZone = TimeZoneInfo.ConvertTimeFromUtc(BuildStartUtc.Value, TimeZone);433 }434435 internal void InitMainVariables()436 {437 var variables = Variables;438439 variables["build-start"] = BuildStartInTimeZone;440 variables["build-start-utc"] = BuildStartUtc;441442 variables["basedir"] = AppDomain.CurrentDomain.BaseDirectory;443444 variables["test-name-sanitized"] = TestNameSanitized;445 variables["test-name"] = TestName;446 variables["test-suite-name-sanitized"] = TestSuiteNameSanitized;447 variables["test-suite-name"] = TestSuiteName;448 variables["test-start"] = StartedAt;449 variables["test-start-utc"] = StartedAtUtc;450451 variables["driver-alias"] = DriverAlias;452 }453454 internal void InitCustomVariables(IDictionary<string, object> customVariables)455 {456 var variables = Variables;457458 foreach (var variable in customVariables)459 variables[variable.Key] = variable.Value;460 }461462 internal void InitArtifactsVariable() =>463 Variables["artifacts"] = Artifacts.FullName.Value;464465 internal void LogTestStart()466 {467 StringBuilder logMessageBuilder = new StringBuilder(468 $"Starting {GetTestUnitKindName()}");469470 string[] testFullNameParts = GetTestFullNameParts().ToArray();471472 if (testFullNameParts.Length > 0)473 {474 logMessageBuilder.Append(": ")475 .Append(string.Join(".", testFullNameParts));476 }477478 Log.Info(logMessageBuilder.ToString());479 }480481 private IEnumerable<string> GetTestFullNameParts()482 {483 if (TestSuiteType != null)484 yield return TestSuiteType.Namespace;485486 if (TestSuiteName != null)487 yield return TestSuiteName;488489 if (TestName != null)490 yield return TestName;491 }492493 private string GetTestUnitKindName()494 {495 return TestName != null496 ? "test"497 : TestSuiteType != null498 ? "test suite"499 : "test unit";500 }501502 /// <summary>503 /// Executes aggregate assertion using <see cref="AggregateAssertionStrategy" />.504 /// </summary>505 /// <param name="action">The action to execute in scope of aggregate assertion.</param>506 /// <param name="assertionScopeName">507 /// Name of the scope being asserted (page object, control, etc.).508 /// Is used to identify the assertion section in log.509 /// Can be null.510 /// </param>511 public void AggregateAssert(Action action, string assertionScopeName = null)512 {513 action.CheckNotNull(nameof(action));514515 AggregateAssertionStrategy.Assert(() =>516 {517 AggregateAssertionLevel++;518519 try520 {521 Log.ExecuteSection(522 new AggregateAssertionLogSection(assertionScopeName),523 action);524 }525 finally526 {527 AggregateAssertionLevel--;528 }529 });530 }531532 /// <summary>533 /// Cleans up the test context.534 /// </summary>535 /// <param name="quitDriver">if set to <see langword="true"/> quits WebDriver.</param>536 public void CleanUp(bool quitDriver = true)537 {538 if (_disposed)539 return;540541 PureExecutionStopwatch.Stop();542543 Log.ExecuteSection(544 new LogSection("Clean up AtataContext", LogLevel.Trace),545 () =>546 {547 EventBus.Publish(new AtataContextCleanUpEvent(this));548549 CleanUpTemporarilyPreservedPageObjectList();550551 if (PageObject != null)552 UIComponentResolver.CleanUpPageObject(PageObject);553554 UIComponentAccessChainScopeCache.Release();555556 if (quitDriver)557 _driver?.Dispose();558 });559560 ExecutionStopwatch.Stop();561562 string testUnitKindName = GetTestUnitKindName();563 Log.InfoWithExecutionTimeInBrackets($"Finished {testUnitKindName}", ExecutionStopwatch.Elapsed);564 Log.InfoWithExecutionTime($"Pure {testUnitKindName} execution time:", PureExecutionStopwatch.Elapsed);565566 Log = null;567568 if (Current == this)569 Current = null;570571 _disposed = true;572573 AssertionResults.Clear();574575 if (PendingFailureAssertionResults.Any())576 {577 var copyOfPendingFailureAssertionResults = PendingFailureAssertionResults.ToArray();578 PendingFailureAssertionResults.Clear();579580 throw VerificationUtils.CreateAggregateAssertionException(copyOfPendingFailureAssertionResults);581 }582 }583584 internal void InitDriver()585 {586 if (DriverFactory is null)587 throw new InvalidOperationException(588 $"Failed to create an instance of {typeof(IWebDriver).FullName} as driver factory is not specified.");589590 _driver = DriverFactory.Create()591 ?? throw new InvalidOperationException(592 $"Failed to create an instance of {typeof(IWebDriver).FullName} as driver factory returned null as a driver.");593594 _driver.Manage().Timeouts().SetRetryTimeout(ElementFindTimeout, ElementFindRetryInterval);595596 EventBus.Publish(new DriverInitEvent(_driver));597 }598599 /// <summary>600 /// Restarts the driver.601 /// </summary>602 public void RestartDriver()603 {604 Log.ExecuteSection(605 new LogSection("Restart driver"),606 () =>607 {608 CleanUpTemporarilyPreservedPageObjectList();609610 if (PageObject != null)611 {612 UIComponentResolver.CleanUpPageObject(PageObject);613 PageObject = null;614 }615616 _driver.Dispose();617618 InitDriver();619 });620 }621622 internal void CleanUpTemporarilyPreservedPageObjectList()623 {624 UIComponentResolver.CleanUpPageObjects(TemporarilyPreservedPageObjects);625 TemporarilyPreservedPageObjectList.Clear();626 }627628 /// <summary>629 /// Fills the template string with variables of this <see cref="AtataContext"/> instance.630 /// The <paramref name="template"/> can contain variables wrapped with curly braces, e.g. <c>"{varName}"</c>.631 /// Variables support standard .NET formatting (<c>"{numberVar:D5}"</c> or <c>"{dateTimeVar:yyyy-MM-dd}"</c>)632 /// and extended formatting for strings633 /// (for example, <c>"{stringVar:/*}"</c> appends <c>"/"</c> to the beginning of the string, if variable is not null).634 /// <para>635 /// The list of predefined variables:636 /// <list type="bullet">637 /// <item><c>{build-start}</c></item>638 /// <item><c>{build-start-utc}</c></item>639 /// <item><c>{basedir}</c></item>640 /// <item><c>{artifacts}</c></item>641 /// <item><c>{test-name-sanitized}</c></item>642 /// <item><c>{test-name}</c></item>643 /// <item><c>{test-suite-name-sanitized}</c></item>644 /// <item><c>{test-suite-name}</c></item>645 /// <item><c>{test-start}</c></item>646 /// <item><c>{test-start-utc}</c></item>647 /// <item><c>{driver-alias}</c></item>648 /// </list>649 /// </para>650 /// </summary>651 /// <param name="template">The template string.</param>652 /// <returns>The filled string.</returns>653 public string FillTemplateString(string template) =>654 FillTemplateString(template, null);655656 /// <inheritdoc cref="FillTemplateString(string)"/>657 /// <param name="template">The template string.</param>658 /// <param name="additionalVariables">The additional variables.</param>659 public string FillTemplateString(string template, IDictionary<string, object> additionalVariables)660 {661 template.CheckNotNull(nameof(template));662663 if (!template.Contains('{'))664 return template;665666 var variables = Variables;667668 if (additionalVariables != null)669 {670 variables = new Dictionary<string, object>(variables);671672 foreach (var variable in additionalVariables)673 variables[variable.Key] = variable.Value;674 }675676 return TemplateStringTransformer.Transform(template, variables);677 }678679 /// <summary>680 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.681 /// </summary>682 public void Dispose()683 {684 CleanUp();685 }686 }687}
...
EventBusTests.cs
Source:EventBusTests.cs
...31 public void WhenThereIsSubscription()32 {33 var actionMock = new Mock<Action<TestEvent>>();34 var eventData = new TestEvent();35 Sut.Object.Subscribe(actionMock.Object);36 Sut.Act(x => x.Publish(eventData));37 actionMock.Verify(x => x(eventData), Times.Once);38 }39 [Test]40 public void WhenThereIsSubscription_CanHandle_False()41 {42 var conditionalEventHandlerMock = new Mock<IConditionalEventHandler<TestEvent>>(MockBehavior.Strict);43 var eventData = new TestEvent();44 Sut.Object.Subscribe(conditionalEventHandlerMock.Object);45 conditionalEventHandlerMock.Setup(x => x.CanHandle(eventData, Context)).Returns(false);46 Sut.Act(x => x.Publish(eventData));47 }48 [Test]49 public void WhenThereIsSubscription_CanHandle_True()50 {51 var conditionalEventHandlerMock = new Mock<IConditionalEventHandler<TestEvent>>(MockBehavior.Strict);52 var eventData = new TestEvent();53 Sut.Object.Subscribe(conditionalEventHandlerMock.Object);54 conditionalEventHandlerMock.Setup(x => x.CanHandle(eventData, Context)).Returns(true);55 conditionalEventHandlerMock.Setup(x => x.Handle(eventData, Context));56 Sut.Act(x => x.Publish(eventData));57 }58 [Test]59 public void WhenThereAreMultipleSubscriptions()60 {61 var actionMock1 = new Mock<Action<TestEvent>>(MockBehavior.Strict);62 var actionMock2 = new Mock<Action<TestEvent, AtataContext>>(MockBehavior.Strict);63 var eventHandlerMock1 = new Mock<IConditionalEventHandler<TestEvent>>(MockBehavior.Strict);64 var eventHandlerMock2 = new Mock<IEventHandler<TestEvent>>(MockBehavior.Strict);65 var eventData = new TestEvent();66 Sut.Object.Subscribe(actionMock1.Object);67 Sut.Object.Subscribe(actionMock2.Object);68 Sut.Object.Subscribe(eventHandlerMock1.Object);69 Sut.Object.Subscribe(eventHandlerMock2.Object);70 MockSequence sequence = new MockSequence();71 actionMock1.InSequence(sequence).Setup(x => x(eventData));72 actionMock2.InSequence(sequence).Setup(x => x(eventData, Context));73 eventHandlerMock1.InSequence(sequence).Setup(x => x.CanHandle(eventData, Context)).Returns(true);74 eventHandlerMock1.InSequence(sequence).Setup(x => x.Handle(eventData, Context));75 eventHandlerMock2.InSequence(sequence).Setup(x => x.Handle(eventData, Context));76 Sut.Act(x => x.Publish(eventData));77 }78 [Test]79 public void AfterUnsubscribe()80 {81 var actionMock1 = new Mock<Action<TestEvent>>();82 var actionMock2 = new Mock<Action<TestEvent, AtataContext>>();83 var eventData = new TestEvent();84 var subscription1 = Sut.Object.Subscribe(actionMock1.Object);85 Sut.Object.Subscribe(actionMock2.Object);86 Sut.Object.Unsubscribe(subscription1);87 Sut.Act(x => x.Publish(eventData));88 actionMock1.Verify(x => x(eventData), Times.Never);89 actionMock2.Verify(x => x(eventData, Context), Times.Once);90 }91 [Test]92 public void AfterUnsubscribeHandler()93 {94 var actionMock = new Mock<Action<TestEvent>>();95 var eventHandlerMock = new Mock<IEventHandler<TestEvent>>();96 var eventData = new TestEvent();97 Sut.Object.Subscribe(actionMock.Object);98 Sut.Object.Subscribe(eventHandlerMock.Object);99 Sut.Object.UnsubscribeHandler(eventHandlerMock.Object);100 Sut.Act(x => x.Publish(eventData));101 actionMock.Verify(x => x(eventData), Times.Once);102 eventHandlerMock.Verify(x => x.Handle(eventData, Context), Times.Never);103 }104 [Test]105 public void AfterUnsubscribeAll()106 {107 var actionMock1 = new Mock<Action<TestEvent>>();108 var actionMock2 = new Mock<Action<TestEvent, AtataContext>>();109 var eventData = new TestEvent();110 Sut.Object.Subscribe(actionMock1.Object);111 Sut.Object.Subscribe(actionMock2.Object);112 Sut.Object.UnsubscribeAll<TestEvent>();113 Sut.Act(x => x.Publish(eventData));114 actionMock1.Verify(x => x(eventData), Times.Never);115 actionMock2.Verify(x => x(eventData, Context), Times.Never);116 }117 }118 [TestFixture]119 public class Subscribe : EventBusTests120 {121 [Test]122 public void Action_Null() =>123 Sut.Invoking(x => x.Subscribe<TestEvent>(null as Action))124 .Should.Throw<ArgumentNullException>();125 [Test]126 public void Action()127 {128 var actionMock = new Mock<Action<TestEvent>>();129 Sut.ResultOf(x => x.Subscribe(actionMock.Object))130 .Should.Not.BeNull();131 }132 }133 [TestFixture]134 public class Unsubscribe : EventBusTests135 {136 [Test]137 public void Null() =>138 Sut.Invoking(x => x.Unsubscribe(null))139 .Should.Throw<ArgumentNullException>();140 [Test]141 public void Valid()142 {143 var actionMock = new Mock<Action<TestEvent>>();144 var subscription = Sut.Object.Subscribe(actionMock.Object);145 Sut.Invoking(x => x.Unsubscribe(subscription))146 .Should.Not.Throw();147 }148 [Test]149 public void Twice()150 {151 var actionMock = new Mock<Action<TestEvent>>();152 var subscription = Sut.Object.Subscribe(actionMock.Object);153 Sut.Act(x => x.Unsubscribe(subscription));154 Sut.Invoking(x => x.Unsubscribe(subscription))155 .Should.Not.Throw();156 }157 }158 [TestFixture]159 public class UnsubscribeHandler : EventBusTests160 {161 [Test]162 public void Null() =>163 Sut.Invoking(x => x.UnsubscribeHandler(null))164 .Should.Throw<ArgumentNullException>();165 [Test]166 public void Valid()167 {168 var actionMock = new Mock<IEventHandler<TestEvent>>();169 Sut.Object.Subscribe(actionMock.Object);170 Sut.Invoking(x => x.UnsubscribeHandler(actionMock.Object))171 .Should.Not.Throw();172 }173 [Test]174 public void Twice()175 {176 var actionMock = new Mock<IEventHandler<TestEvent>>();177 Sut.Object.Subscribe(actionMock.Object);178 Sut.Act(x => x.UnsubscribeHandler(actionMock.Object));179 Sut.Invoking(x => x.UnsubscribeHandler(actionMock.Object))180 .Should.Not.Throw();181 }182 }183 public class TestEvent184 {185 }186 }187}...
EventBus.cs
Source:EventBus.cs
...23 {24 _context = context.CheckNotNull(nameof(context));25 if (eventSubscriptions != null)26 foreach (var subscription in eventSubscriptions)27 Subscribe(subscription.EventType, subscription.EventHandler);28 }29 /// <inheritdoc/>30 public void Publish<TEvent>(TEvent eventData)31 {32 eventData.CheckNotNull(nameof(eventData));33 if (_subscriptionMap.TryGetValue(typeof(TEvent), out var eventHandlerSubscriptions))34 {35 object[] eventHandlersArray;36 lock (eventHandlerSubscriptions)37 {38 eventHandlersArray = eventHandlerSubscriptions.Select(x => x.EventHandler).ToArray();39 }40 foreach (IEventHandler<TEvent> handler in eventHandlersArray)41 {42 if (!(handler is IConditionalEventHandler<TEvent> conditionalEventHandler)43 || conditionalEventHandler.CanHandle(eventData, _context))44 {45 handler.Handle(eventData, _context);46 }47 }48 }49 }50 /// <inheritdoc/>51 public object Subscribe<TEvent>(Action eventHandler)52 {53 eventHandler.CheckNotNull(nameof(eventHandler));54 return Subscribe(new ActionEventHandler<TEvent>(eventHandler));55 }56 /// <inheritdoc/>57 public object Subscribe<TEvent>(Action<TEvent> eventHandler)58 {59 eventHandler.CheckNotNull(nameof(eventHandler));60 return Subscribe(new ActionEventHandler<TEvent>(eventHandler));61 }62 /// <inheritdoc/>63 public object Subscribe<TEvent>(Action<TEvent, AtataContext> eventHandler)64 {65 eventHandler.CheckNotNull(nameof(eventHandler));66 return Subscribe(new ActionEventHandler<TEvent>(eventHandler));67 }68 /// <inheritdoc/>69 public object Subscribe<TEvent, TEventHandler>()70 where TEventHandler : class, IEventHandler<TEvent>, new()71 =>72 Subscribe(new TEventHandler());73 /// <inheritdoc/>74 public object Subscribe<TEvent>(IEventHandler<TEvent> eventHandler) =>75 Subscribe(typeof(TEvent), eventHandler);76 private static List<EventHandlerSubscription> CreateEventHandlerSubscriptionList(Type eventType) =>77 new List<EventHandlerSubscription>();78 private object Subscribe(Type eventType, object eventHandler)79 {80 eventHandler.CheckNotNull(nameof(eventHandler));81 object subscription = new object();82 var eventHandlerSubscriptions = _subscriptionMap.GetOrAdd(eventType, CreateEventHandlerSubscriptionList);83 lock (eventHandlerSubscriptions)84 {85 eventHandlerSubscriptions.Add(new EventHandlerSubscription(subscription, eventHandler));86 }87 return subscription;88 }89 /// <inheritdoc/>90 public void Unsubscribe(object subscription)91 {92 subscription.CheckNotNull(nameof(subscription));...
Subscribe
Using AI Code Generation
1using Atata;2using NUnit.Framework;3{4 {5 public void Test1()6 {7 Build();8 AtataContext.Current.AutoSetUp();
Subscribe
Using AI Code Generation
1using Atata;2using NUnit.Framework;3using OpenQA.Selenium;4using OpenQA.Selenium.Chrome;5using System;6using System.Collections.Generic;7using System.Linq;8using System.Text;9using System.Threading.Tasks;10{11 {12 public void TestMethod1()13 {
Subscribe
Using AI Code Generation
1Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));2Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));3Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));4Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));5Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));6Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));7Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));8Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));9Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));10Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));11Atata.EventBus.Subscribe<LogEntryAdded>(e => Console.WriteLine($"Log entry added: {e.LogEntry.Message}"));
Subscribe
Using AI Code Generation
1Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);2private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)3{4}5Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);6private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)7{8}9Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);10private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)11{12}13Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);14private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)15{16}17Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);18private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)19{20}21Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);22private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)23{24}25Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);26private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)27{28}29Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);30private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)31{32}33Atata.EventBus.Subscribe<OnPageObjectInitialized>(OnPageObjectInitializedHandler);34private void OnPageObjectInitializedHandler(OnPageObjectInitialized e)35{
Subscribe
Using AI Code Generation
1{2 {3 public void Test1()4 {5 Atata.EventBus.Subscribe<CustomEvent>(e => Console.WriteLine(e.Message));6 Atata.EventBus.Subscribe<CustomEvent>(e => Console.WriteLine("Second subscriber: {0}", e.Message));7 Atata.EventBus.Send(new CustomEvent("Hello World!"));8 Atata.EventBus.Unsubscribe<CustomEvent>(e => Console.WriteLine(e.Message));9 Atata.EventBus.Unsubscribe<CustomEvent>(e => Console.WriteLine("Second subscriber: {0}", e.Message));10 }11 }12}13{14 {15 public void Test1()16 {17 Atata.EventBus.Subscribe<CustomEvent>(e => Console.WriteLine(e.Message));18 Atata.EventBus.Subscribe<CustomEvent>(e => Console.WriteLine("Second subscriber: {0}", e.Message));19 Atata.EventBus.Send(new CustomEvent("Hello World!"));20 Atata.EventBus.Unsubscribe<CustomEvent>(e => Console.WriteLine(e.Message));21 Atata.EventBus.Unsubscribe<CustomEvent>(e => Console.WriteLine("Second subscriber: {0}", e.Message));22 }23 }24}25{26 {27 public void Test1()28 {29 Atata.EventBus.Subscribe<CustomEvent>(e => Console.WriteLine(e.Message));30 Atata.EventBus.Subscribe<CustomEvent>(e => Console.WriteLine("Second subscriber: {0}", e.Message));31 Atata.EventBus.Send(new CustomEvent("Hello World!"));32 Atata.EventBus.Unsubscribe<CustomEvent>(e => Console.WriteLine(e.Message));33 Atata.EventBus.Unsubscribe<CustomEvent>(e => Console.WriteLine("Second subscriber: {0}", e.Message));34 }35 }36}37{
Subscribe
Using AI Code Generation
1Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 2{3 Console.WriteLine("AfterNavigateToPageEvent is fired");4});5Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 6{7 Console.WriteLine("AfterNavigateToPageEvent is fired");8});9Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 10{11 Console.WriteLine("AfterNavigateToPageEvent is fired");12});13Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 14{15 Console.WriteLine("AfterNavigateToPageEvent is fired");16});17Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 18{19 Console.WriteLine("AfterNavigateToPageEvent is fired");20});21Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 22{23 Console.WriteLine("AfterNavigateToPageEvent is fired");24});25Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 26{27 Console.WriteLine("AfterNavigateToPageEvent is fired");28});29Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 30{31 Console.WriteLine("AfterNavigateToPageEvent is fired");32});33Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 34{35 Console.WriteLine("AfterNavigateToPageEvent is fired");36});37Atata.EventBus.Subscribe<AfterNavigateToPageEvent>(x => 38{39 Console.WriteLine("AfterNavigateToPageEvent is fired");40});
Subscribe
Using AI Code Generation
1[ Test , TestCaseSource ( typeof ( TestData ), nameof ( TestData . GetTestCases ))]2 public void Test ( string name )3{4 AtataContext . Configure ()5 . UseChrome ()6 . UseCulture ( "en-US" )7 . UseNUnitTestName ( name )8 . UseAllNUnitFeatures ()9 . AddNUnitTestContextLogging ()10 . UseTestName ( name )11 . LogNUnitError ( "Test {testFullName} failed." )12 . LogNUnitInfo ( "Test {testFullName} started." )13 . LogNUnitWarning ( "Test {testFullName} has a warning." )14 . UseAssertionExceptionType < NUnit.Framework.AssertionException >()15 . UseDriver ( new ChromeDriver ())16 . UseEventBus < Atata.EventBus >()17 . Build ();18 AtataContext . Current . Log . Info ( "Test started" );19 AtataContext . Current . GoTo < GooglePage >()20 .SearchFor ( "Atata" );21 AtataContext . Current . Log . Info ( "Test finished" );22 AtataContext . Current . CleanUp ();23}24[ Test , TestCaseSource ( typeof ( TestData ), nameof ( TestData . GetTestCases ))]25 public void Test ( string name )26{27 AtataContext . Configure ()28 . UseChrome ()29 . UseCulture ( "en-US" )30 . UseNUnitTestName ( name )31 . UseAllNUnitFeatures ()32 . AddNUnitTestContextLogging ()33 . UseTestName ( name )34 . LogNUnitError ( "Test {testFullName} failed." )35 . LogNUnitInfo ( "Test {testFullName} started." )36 . LogNUnitWarning ( "Test {testFullName} has a warning." )37 . UseAssertionExceptionType < NUnit.Framework.AssertionException >()38 . UseDriver ( new ChromeDriver ())39 . UseEventBus < Atata.EventBus >()40 . Build ();41 AtataContext . Current . Log . Info ( "Test started" );42 AtataContext . Current . GoTo < GooglePage >()
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!