Skip to content

Commit c4b3d24

Browse files
committed
Repository reorganization and addition of new example.
This change refactors common code into a WebDriverProxyUtilities project, allowing new examples to be created that use the same driver factory to launch browsers. Concurrent with this change, a new example for capturing JavaScript errors on a page has been added into the solution.
1 parent 169f6ee commit c4b3d24

18 files changed

+446
-46
lines changed

HttpStatusCodeExample.sln

-20
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<?xml version="1.0" encoding="utf-8" ?>
1+
<?xml version="1.0"?>
22
<configuration>
33
<startup>
4-
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
55
</startup>
6-
</configuration>
6+
</configuration>

ExtensionMethods.cs HttpStatusCodeExample/ExtensionMethods.cs

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
namespace HttpStatusCodeExample
1010
{
11+
/// <summary>
12+
/// A class of extension methods for a WebDriver instance.
13+
/// </summary>
1114
static class ExtensionMethods
1215
{
1316
private static TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10);

HttpStatusCodeExample.csproj HttpStatusCodeExample/HttpStatusCodeExample.csproj

+8-14
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<AppDesignerFolder>Properties</AppDesignerFolder>
1010
<RootNamespace>HttpStatusCodeExample</RootNamespace>
1111
<AssemblyName>HttpStatusCodeExample</AssemblyName>
12-
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
12+
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
1313
<FileAlignment>512</FileAlignment>
14+
<TargetFrameworkProfile />
1415
</PropertyGroup>
1516
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1617
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -33,7 +34,7 @@
3334
</PropertyGroup>
3435
<ItemGroup>
3536
<Reference Include="FiddlerCore4">
36-
<HintPath>lib\FiddlerCore4.dll</HintPath>
37+
<HintPath>..\lib\FiddlerCore4.dll</HintPath>
3738
</Reference>
3839
<Reference Include="System" />
3940
<Reference Include="System.Core" />
@@ -43,12 +44,10 @@
4344
<Reference Include="System.Data" />
4445
<Reference Include="System.Xml" />
4546
<Reference Include="WebDriver">
46-
<HintPath>lib\WebDriver.dll</HintPath>
47+
<HintPath>..\lib\WebDriver.dll</HintPath>
4748
</Reference>
4849
</ItemGroup>
4950
<ItemGroup>
50-
<Compile Include="BrowserKind.cs" />
51-
<Compile Include="WebDriverFactory.cs" />
5251
<Compile Include="Program.cs" />
5352
<Compile Include="Properties\AssemblyInfo.cs" />
5453
<Compile Include="ExtensionMethods.cs" />
@@ -57,15 +56,10 @@
5756
<None Include="App.config" />
5857
</ItemGroup>
5958
<ItemGroup>
60-
<Content Include="chromedriver.exe">
61-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
62-
</Content>
63-
<Content Include="IEDriverServer.exe">
64-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
65-
</Content>
66-
<Content Include="phantomjs.exe">
67-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
68-
</Content>
59+
<ProjectReference Include="..\WebDriverProxyUtilities\WebDriverProxyUtilities.csproj">
60+
<Project>{8fa94c46-361e-4ace-8542-d81863205154}</Project>
61+
<Name>WebDriverProxyUtilities</Name>
62+
</ProjectReference>
6963
</ItemGroup>
7064
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
7165
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

Program.cs HttpStatusCodeExample/Program.cs

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Text;
5-
using System.Threading.Tasks;
65
using Fiddler;
76
using OpenQA.Selenium;
8-
using OpenQA.Selenium.Chrome;
9-
using OpenQA.Selenium.Firefox;
10-
using OpenQA.Selenium.IE;
7+
using WebDriverProxyUtilities;
118

129
namespace HttpStatusCodeExample
1310
{
@@ -36,14 +33,14 @@ static void Main(string[] args)
3633
driver.Quit();
3734

3835
StopFiddlerProxy();
36+
Console.WriteLine("Complete! Press <Enter> to exit.");
3937
Console.ReadLine();
4038
}
4139

4240
private static void StopFiddlerProxy()
4341
{
4442
Console.WriteLine("Shutting down Fiddler proxy");
4543
FiddlerApplication.Shutdown();
46-
Console.WriteLine("Complete! Press <Enter> to exit.");
4744
}
4845

4946
private static int StartFiddlerProxy(int desiredPort)
File renamed without changes.
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Text.RegularExpressions;
7+
using System.Threading.Tasks;
8+
using Fiddler;
9+
using OpenQA.Selenium;
10+
11+
namespace JavaScriptErrorsExample
12+
{
13+
/// <summary>
14+
/// A class of extension methods for a WebDriver instance.
15+
/// </summary>
16+
static class ExtensionMethods
17+
{
18+
private static TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10);
19+
20+
/// <summary>
21+
/// Navigates to a specified URL, injecting code to capture JavaScript errors on the page.
22+
/// </summary>
23+
/// <param name="driver">The driver used to navigate to the URL.</param>
24+
/// <param name="targetUrl">The URL to navigate to.</param>
25+
public static void NavigateTo(this IWebDriver driver, string targetUrl)
26+
{
27+
string errorScript = "window.__webdriver_javascript_errors = []; window.onerror = function(errorMsg, url, line) { window.__webdriver_javascript_errors.push(errorMsg + ' (found at ' + url + ', line ' + line + ')'); };";
28+
SessionStateHandler beforeRequestHandler = delegate(Session targetSession)
29+
{
30+
// Tell Fiddler to buffer the response so that we can modify
31+
// it before it gets back to the browser.
32+
targetSession.bBufferResponse = true;
33+
};
34+
35+
SessionStateHandler beforeResponseHandler = delegate(Session targetSession)
36+
{
37+
if (targetSession.fullUrl == targetUrl &&
38+
targetSession.oResponse.headers.ExistsAndContains("Content-Type", "html"))
39+
{
40+
targetSession.utilDecodeResponse();
41+
string responseBody = targetSession.GetResponseBodyAsString();
42+
string headTag = Regex.Match(responseBody,
43+
"<head.*>",
44+
RegexOptions.IgnoreCase).ToString();
45+
string addition = headTag + "<script>" + errorScript + "</script>";
46+
targetSession.utilReplaceOnceInResponse(headTag, addition, false);
47+
}
48+
};
49+
50+
FiddlerApplication.BeforeRequest += beforeRequestHandler;
51+
FiddlerApplication.BeforeResponse += beforeResponseHandler;
52+
driver.Url = targetUrl;
53+
FiddlerApplication.BeforeResponse -= beforeResponseHandler;
54+
FiddlerApplication.BeforeRequest -= beforeRequestHandler;
55+
}
56+
57+
/// <summary>
58+
/// Gets the JavaScript errors on the current page.
59+
/// </summary>
60+
/// <param name="driver">The driver used to retrieve the errors.</param>
61+
/// <returns>A list of all JavaScript errors captured on the page.</returns>
62+
public static IList<string> GetJavaScriptErrors(this IWebDriver driver)
63+
{
64+
return GetJavaScriptErrors(driver, TimeSpan.FromSeconds(5));
65+
}
66+
67+
/// <summary>
68+
/// Gets the JavaScript errors on the current page.
69+
/// </summary>
70+
/// <param name="driver">The driver used to retrieve the errors.</param>
71+
/// <param name="timeout">A <see cref="TimeSpan"/> structure for the time out of the retrieval.</param>
72+
/// <returns>A list of all JavaScript errors captured on the page.</returns>
73+
public static IList<string> GetJavaScriptErrors(this IWebDriver driver, TimeSpan timeout)
74+
{
75+
string errorRetrievalScript = "var errorList = window.__webdriver_javascript_errors; window.__webdriver_javascript_errors = []; return errorList;";
76+
DateTime endTime = DateTime.Now.Add(timeout);
77+
List<string> errorList = new List<string>();
78+
IJavaScriptExecutor executor = driver as IJavaScriptExecutor;
79+
ReadOnlyCollection<object> returnedList = executor.ExecuteScript(errorRetrievalScript) as ReadOnlyCollection<object>;
80+
while (returnedList == null && DateTime.Now < endTime)
81+
{
82+
System.Threading.Thread.Sleep(250);
83+
returnedList = executor.ExecuteScript(errorRetrievalScript) as ReadOnlyCollection<object>;
84+
}
85+
86+
if (returnedList == null)
87+
{
88+
return null;
89+
}
90+
else
91+
{
92+
foreach (object returnedError in returnedList)
93+
{
94+
errorList.Add(returnedError.ToString());
95+
}
96+
}
97+
98+
return errorList;
99+
}
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{BE8329F5-EAA0-49A5-A919-4EF4E3F3F7BB}</ProjectGuid>
8+
<OutputType>Exe</OutputType>
9+
<AppDesignerFolder>Properties</AppDesignerFolder>
10+
<RootNamespace>JavaScriptErrorsExample</RootNamespace>
11+
<AssemblyName>JavaScriptErrorsExample</AssemblyName>
12+
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
13+
<FileAlignment>512</FileAlignment>
14+
</PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16+
<PlatformTarget>AnyCPU</PlatformTarget>
17+
<DebugSymbols>true</DebugSymbols>
18+
<DebugType>full</DebugType>
19+
<Optimize>false</Optimize>
20+
<OutputPath>bin\Debug\</OutputPath>
21+
<DefineConstants>DEBUG;TRACE</DefineConstants>
22+
<ErrorReport>prompt</ErrorReport>
23+
<WarningLevel>4</WarningLevel>
24+
</PropertyGroup>
25+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26+
<PlatformTarget>AnyCPU</PlatformTarget>
27+
<DebugType>pdbonly</DebugType>
28+
<Optimize>true</Optimize>
29+
<OutputPath>bin\Release\</OutputPath>
30+
<DefineConstants>TRACE</DefineConstants>
31+
<ErrorReport>prompt</ErrorReport>
32+
<WarningLevel>4</WarningLevel>
33+
</PropertyGroup>
34+
<ItemGroup>
35+
<Reference Include="FiddlerCore4">
36+
<HintPath>..\lib\FiddlerCore4.dll</HintPath>
37+
</Reference>
38+
<Reference Include="System" />
39+
<Reference Include="System.Core" />
40+
<Reference Include="System.Xml.Linq" />
41+
<Reference Include="System.Data.DataSetExtensions" />
42+
<Reference Include="Microsoft.CSharp" />
43+
<Reference Include="System.Data" />
44+
<Reference Include="System.Xml" />
45+
<Reference Include="WebDriver">
46+
<HintPath>..\lib\WebDriver.dll</HintPath>
47+
</Reference>
48+
</ItemGroup>
49+
<ItemGroup>
50+
<Compile Include="ExtensionMethods.cs" />
51+
<Compile Include="Program.cs" />
52+
<Compile Include="Properties\AssemblyInfo.cs" />
53+
</ItemGroup>
54+
<ItemGroup>
55+
<ProjectReference Include="..\WebDriverProxyUtilities\WebDriverProxyUtilities.csproj">
56+
<Project>{8fa94c46-361e-4ace-8542-d81863205154}</Project>
57+
<Name>WebDriverProxyUtilities</Name>
58+
</ProjectReference>
59+
</ItemGroup>
60+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
61+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
62+
Other similar extension points exist, see Microsoft.Common.targets.
63+
<Target Name="BeforeBuild">
64+
</Target>
65+
<Target Name="AfterBuild">
66+
</Target>
67+
-->
68+
</Project>

JavaScriptErrorsExample/Program.cs

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using Fiddler;
6+
using OpenQA.Selenium;
7+
using WebDriverProxyUtilities;
8+
9+
namespace JavaScriptErrorsExample
10+
{
11+
class Program
12+
{
13+
static void Main(string[] args)
14+
{
15+
// Note that we're using a port of 0, which tells Fiddler to
16+
// select a random available port to listen on.
17+
int proxyPort = StartFiddlerProxy(0);
18+
19+
// We are only proxying HTTP traffic, but could just as easily
20+
// proxy HTTPS or FTP traffic.
21+
OpenQA.Selenium.Proxy proxy = new OpenQA.Selenium.Proxy();
22+
proxy.HttpProxy = string.Format("127.0.0.1:{0}", proxyPort);
23+
24+
// See the code of the individual methods for the details of how
25+
// to create the driver instance with the proxy settings properly set.
26+
IWebDriver driver = WebDriverFactory.CreateWebDriverWithProxy(BrowserKind.IE, proxy);
27+
//IWebDriver driver = WebDriverFactory.CreateWebDriverWithProxy(BrowserKind.Firefox, proxy);
28+
//IWebDriver driver = WebDriverFactory.CreateWebDriverWithProxy(BrowserKind.Chrome, proxy);
29+
//IWebDriver driver = WebDriverFactory.CreateWebDriverWithProxy(BrowserKind.PhantomJS, proxy);
30+
31+
TestJavaScriptErrors(driver);
32+
33+
driver.Quit();
34+
35+
StopFiddlerProxy();
36+
Console.WriteLine("Complete! Press <Enter> to exit.");
37+
Console.ReadLine();
38+
}
39+
40+
private static void StopFiddlerProxy()
41+
{
42+
Console.WriteLine("Shutting down Fiddler proxy");
43+
FiddlerApplication.Shutdown();
44+
}
45+
46+
private static int StartFiddlerProxy(int desiredPort)
47+
{
48+
// We explicitly do *NOT* want to register this running Fiddler
49+
// instance as the system proxy. This lets us keep isolation.
50+
Console.WriteLine("Starting Fiddler proxy");
51+
FiddlerCoreStartupFlags flags = FiddlerCoreStartupFlags.Default & ~FiddlerCoreStartupFlags.RegisterAsSystemProxy;
52+
FiddlerApplication.Startup(desiredPort, flags);
53+
int proxyPort = FiddlerApplication.oProxy.ListenPort;
54+
Console.WriteLine("Fiddler proxy listening on port {0}", proxyPort);
55+
return proxyPort;
56+
}
57+
58+
private static void TestJavaScriptErrors(IWebDriver driver)
59+
{
60+
string url = "http://localhost.:2310/common/jserror.html";
61+
Console.WriteLine("Navigating to {0}", url);
62+
driver.NavigateTo(url);
63+
IList<string> javaScriptErrors = driver.GetJavaScriptErrors();
64+
if (javaScriptErrors == null)
65+
{
66+
Console.WriteLine("Could not access JavaScript errors collection. This is a catastrophic failure.");
67+
}
68+
else
69+
{
70+
if (javaScriptErrors.Count > 0)
71+
{
72+
Console.WriteLine("Found the following JavaScript errors on the page:");
73+
foreach (string javaScriptError in javaScriptErrors)
74+
{
75+
Console.WriteLine(javaScriptError);
76+
}
77+
}
78+
else
79+
{
80+
Console.WriteLine("No JavaScript errors found on the page.");
81+
}
82+
}
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)