1+ using Applitools ;
2+ using Applitools . Selenium ;
3+ using Applitools . VisualGrid ;
4+ using NUnit . Framework ;
5+ using OpenQA . Selenium ;
6+ using OpenQA . Selenium . Chrome ;
7+ using System . Drawing ;
8+ using System . Runtime ;
9+ using ScreenOrientation = Applitools . VisualGrid . ScreenOrientation ;
10+
11+ namespace Applitools . Example . Tests ;
12+
13+ /// <summary>
14+ /// Tests for the ACME Bank demo app.
15+ /// </summary>
16+ public class AcmeBankTest
17+ {
18+ // Test control inputs to read once and share for all tests
19+ private static string ? ApplitoolsApiKey ;
20+ private static bool Headless ;
21+
22+ // Applitools objects to share for all tests
23+ private static BatchInfo Batch ;
24+ private static Configuration Config ;
25+ private static VisualGridRunner Runner ;
26+
27+ // Test-specific objects
28+ private WebDriver Driver ;
29+ private Eyes Eyes ;
30+
31+ /// <summary>
32+ /// Sets up the configuration for running visual tests in the Ultrafast Grid.
33+ /// The configuration is shared by all tests in a test suite, so it belongs in a `OneTimeSetUp` method.
34+ /// If you have more than one test class, then you should abstract this configuration to avoid duplication.
35+ /// <summary>
36+ [ OneTimeSetUp ]
37+ public static void SetUpConfigAndRunner ( )
38+ {
39+ // Read the Applitools API key from an environment variable.
40+ ApplitoolsApiKey = Environment . GetEnvironmentVariable ( "APPLITOOLS_API_KEY" ) ;
41+
42+ // Read the headless mode setting from an environment variable.
43+ // Use headless mode for Continuous Integration (CI) execution.
44+ // Use headed mode for local development.
45+ Headless = Environment . GetEnvironmentVariable ( "HEADLESS" ) ? . ToLower ( ) == "true" ;
46+
47+ // Create the runner for the Ultrafast Grid.
48+ // Concurrency refers to the number of visual checkpoints Applitools will perform in parallel.
49+ // Warning: If you have a free account, then concurrency will be limited to 1.
50+ Runner = new VisualGridRunner ( new RunnerOptions ( ) . TestConcurrency ( 5 ) ) ;
51+
52+ // Create a new batch for tests.
53+ // A batch is the collection of visual checkpoints for a test suite.
54+ // Batches are displayed in the dashboard, so use meaningful names.
55+ Batch = new BatchInfo ( "Example: Selenium C# NUnit with the Ultrafast Grid" ) ;
56+
57+ // Create a configuration for Applitools Eyes.
58+ Config = new Configuration ( ) ;
59+
60+ // Set the Applitools API key so test results are uploaded to your account.
61+ // If you don't explicitly set the API key with this call,
62+ // then the SDK will automatically read the `APPLITOOLS_API_KEY` environment variable to fetch it.
63+ Config . SetApiKey ( ApplitoolsApiKey ) ;
64+
65+ // Set the batch for the config.
66+ Config . SetBatch ( Batch ) ;
67+
68+ // Add 3 desktop browsers with different viewports for cross-browser testing in the Ultrafast Grid.
69+ // Other browsers are also available, like Edge and IE.
70+ Config . AddBrowser ( 800 , 600 , BrowserType . CHROME ) ;
71+ Config . AddBrowser ( 1600 , 1200 , BrowserType . FIREFOX ) ;
72+ Config . AddBrowser ( 1024 , 768 , BrowserType . SAFARI ) ;
73+
74+ // Add 2 mobile emulation devices with different orientations for cross-browser testing in the Ultrafast Grid.
75+ // Other mobile devices are available, including iOS.
76+ Config . AddDeviceEmulation ( DeviceName . Pixel_2 , ScreenOrientation . Portrait ) ;
77+ Config . AddDeviceEmulation ( DeviceName . Nexus_10 , ScreenOrientation . Landscape ) ;
78+ }
79+
80+ /// <summary>
81+ /// Sets up each test with its own ChromeDriver and Applitools Eyes objects.
82+ /// <summary>
83+ [ SetUp ]
84+ public void OpenBrowserAndEyes ( )
85+ {
86+ // Open the browser with the ChromeDriver instance.
87+ // Even though this test will run visual checkpoints on different browsers in the Ultrafast Grid,
88+ // it still needs to run the test one time locally to capture snapshots.
89+ ChromeOptions options = new ChromeOptions ( ) ;
90+ if ( Headless ) options . AddArgument ( "headless" ) ;
91+ Driver = new ChromeDriver ( options ) ;
92+
93+ // Set an implicit wait of 10 seconds.
94+ // For larger projects, use explicit waits for better control.
95+ // https://www.selenium.dev/documentation/webdriver/waits/
96+ // The following call works for Selenium 4:
97+ Driver . Manage ( ) . Timeouts ( ) . ImplicitWait = TimeSpan . FromSeconds ( 10 ) ;
98+
99+ // Create the Applitools Eyes object connected to the VisualGridRunner and set its configuration.
100+ Eyes = new Eyes ( Runner ) ;
101+ Eyes . SetConfiguration ( Config ) ;
102+ Eyes . SaveNewTests = true ;
103+
104+ // Open Eyes to start visual testing.
105+ // It is a recommended practice to set all four inputs:
106+ string testName = NUnit . Framework . TestContext . CurrentContext . Test . Name ;
107+ Eyes . Open (
108+ Driver , // WebDriver object to "watch"
109+ "ACME Bank Web App" , // The name of the app under test
110+ testName , // The name of the test case
111+ new Size ( 1024 , 768 ) ) ; // The viewport size for the local browser
112+ }
113+
114+ /// <summary>
115+ /// This test covers login for the Applitools demo site, which is a dummy banking app.
116+ /// The interactions use typical Selenium WebDriver calls,
117+ /// but the verifications use one-line snapshot calls with Applitools Eyes.
118+ /// If the page ever changes, then Applitools will detect the changes and highlight them in the dashboard.
119+ /// Traditional assertions that scrape the page for text values are not needed here.
120+ /// <summary>
121+ [ Test ]
122+ public void LogIntoBankAccount ( )
123+ {
124+ // Load the login page.
125+ Driver . Navigate ( ) . GoToUrl ( "https://demo.applitools.com" ) ;
126+
127+ // Verify the full login page loaded correctly.
128+ Eyes . Check ( Target . Window ( ) . Fully ( ) . WithName ( "Login page" ) ) ;
129+
130+ // Perform login.
131+ Driver . FindElement ( By . Id ( "username" ) ) . SendKeys ( "applibot" ) ;
132+ Driver . FindElement ( By . Id ( "password" ) ) . SendKeys ( "I<3VisualTests" ) ;
133+ Driver . FindElement ( By . Id ( "log-in" ) ) . Click ( ) ;
134+
135+ // Verify the full main page loaded correctly.
136+ // This snapshot uses LAYOUT match level to avoid differences in closing time text.
137+ Eyes . Check ( Target . Window ( ) . Fully ( ) . WithName ( "Main page" ) . Layout ( ) ) ;
138+ }
139+
140+ /// <summary>
141+ /// Concludes the test by quitting the browser and closing Eyes.
142+ /// <summary>
143+ [ TearDown ]
144+ public void CleanUpTest ( ) {
145+
146+ // Quit the WebDriver instance.
147+ Driver . Quit ( ) ;
148+
149+ // Close Eyes to tell the server it should display the results.
150+ Eyes . CloseAsync ( ) ;
151+
152+ // Warning: `Eyes.CloseAsync()` will NOT wait for visual checkpoints to complete.
153+ // You will need to check the Applitools dashboard for visual results per checkpoint.
154+ // Note that "unresolved" and "failed" visual checkpoints will not cause the NUnit test to fail.
155+
156+ // If you want the NUnit test to wait synchronously for all checkpoints to complete, then use `eyes.close()`.
157+ // If any checkpoints are unresolved or failed, then `eyes.close()` will make the NUnit test fail.
158+ }
159+
160+ /// <summary>
161+ /// Prints the final summary report for the test suite.
162+ /// <summary>
163+ [ OneTimeTearDown ]
164+ public static void PrintResults ( ) {
165+
166+ // Close the batch and report visual differences to the console.
167+ // Note that it forces NUnit to wait synchronously for all visual checkpoints to complete.
168+ TestResultsSummary allTestResults = Runner . GetAllTestResults ( ) ;
169+ Console . WriteLine ( allTestResults ) ;
170+ }
171+ }
0 commit comments