/// <summary> /// Initializes a new instance of the <see cref="BatchCaptureJobInfo"/> class. /// </summary> /// <param name="url"> /// The URL to capture. /// </param> /// <param name="filenameTemplate"> /// The filename template that will be used to capture the screenshot. /// </param> /// <param name="jobInfo"> /// The job information. /// </param> /// <param name="browsers"> /// The browsers. /// </param> public BatchCaptureJobInfo(string url, string filenameTemplate, Job.JobInfo jobInfo, params Browser[] browsers) { Contract.Requires(!string.IsNullOrEmpty(url)); Contract.Requires(!string.IsNullOrEmpty(filenameTemplate)); Contract.Requires(!illegalFileNameCharactersRegex.IsMatch(filenameTemplate), "The filename contains illegal characters."); Contract.Requires(jobInfo != null); Contract.Requires(browsers != null); Contract.Requires(browsers.Length > 1); this.Url = url; this.Filename = filenameTemplate; this.JobInfo = jobInfo; this.Browsers = browsers; }
/// <summary> /// Starts a BrowserStack screenshot job asynchronously. /// </summary> /// <param name="url">The url for which screenshots are required.</param> /// <param name="jobInfo">The job information that will be used to start the job.</param> /// <param name="usingTunnel">set to <c>true</c> if the BrowserStack jobs need to run under a tunnel. The tunnel must have been initiated externally.</param> /// <param name="browsers">The browsers that will be used to start the job.</param> /// <returns> /// The <see cref="Task" />. /// </returns> /// <exception cref="ApplicationException">Thrown when the call to the BrowserStack API results in an http code other than 200 (OK).</exception> public async Task<Job> StartJobAsync(string url, Job.JobInfo jobInfo, bool usingTunnel = false, params Browser[] browsers) { var jobRequest = new ScreenshotJobRequest() { url = url, callback_url = jobInfo.CallbackUrl, orientation = jobInfo.Orientation.HasValue ? jobInfo.Orientation.ToString().ToLower() : null, quality = jobInfo.Quality.HasValue ? jobInfo.Quality.ToString().ToLower() : null, wait_time = jobInfo.WaitTime, mac_res = jobInfo.OsxResolution.HasValue ? jobInfo.OsxResolution.ToString().ToLower().Replace("r_", string.Empty) : null, win_res = jobInfo.WinResolution.HasValue ? jobInfo.WinResolution.ToString().ToLower().Replace("r_", string.Empty) : null, tunnel = usingTunnel, browsers = browsers.Select(x => new BrowserInfo() { browser = x.BrowserName, browser_version = x.BrowserVersion, device = x.Device, os = x.OS, os_version = x.OSVersion, }).ToArray() }; using (var httpClient = this.httpClientFactory.Invoke()) { var request = new HttpRequestMessage(HttpMethod.Post, screenshotsRestAPIBaseUrl) { Content = new StringContent(JsonConvert.SerializeObject(jobRequest), Encoding.Default, "application/json") }; if (this.AuthenticateForStartJob) { request.Headers.Authorization = this.GetAuthenticationHeader(); } var response = await httpClient.SendAsync(request); var responseString = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { throw new ApplicationException( string.Format("Error while starting the job.\nResponse status is {0} ({1}).\nResponse is: {2}", response.ReasonPhrase, response.StatusCode, responseString)); } var screenshotJob = await JsonConvert.DeserializeObjectAsync<ScreenshotJob>(responseString); return MapToJob(screenshotJob); } }
/// <summary> /// Initializes a new instance of the <see cref="JobEventArgs"/> class. /// </summary> /// <param name="job"> /// The job. /// </param> public JobEventArgs(Job job) { this.Job = job; this.State = job.State; }
/// <summary> /// Initializes a new instance of the <see cref="JobFailureEventArgs" /> class. /// </summary> /// <param name="jobUrl">The job URL.</param> /// <param name="jobInfo">The job information.</param> /// <param name="browsers">The browsers.</param> /// <param name="exception">The exception that caused the failure.</param> public JobFailureEventArgs(string jobUrl, Job.JobInfo jobInfo, IEnumerable<Browser> browsers, Exception exception) { this.Exception = exception; this.Browsers = browsers; this.JobInfo = jobInfo; this.JobUrl = jobUrl; }
/// <summary> /// The save screenshot async. /// </summary> /// <param name="screenshot">The screenshot.</param> /// <param name="jobId">The job identifier.</param> /// <param name="jobInfo">The job info.</param> /// <param name="rootPath">The root path.</param> /// <returns> /// The <see cref="Task" />. /// </returns> private async Task SaveScreenshotAsync(Screenshot screenshot, string jobId, Job.JobInfo jobInfo, string rootPath) { // Create the folder for the screenshot var directory = this.CreateScreenshotDirectory(jobInfo, screenshot.Browser, rootPath); var filename = this.jobsToJobsToRun[jobId.ToLower()].Filename; try { if (screenshot.State == Screenshot.States.Done) { var tasksToWaitFor = new List<Task>(); tasksToWaitFor.Add(this.screenshotsApi.SaveScreenshotToFileAsync(screenshot, directory.FullName, filename, false)); if (this.captureThumbnails) { tasksToWaitFor.Add(this.screenshotsApi.SaveThumbnailToFileAsync(screenshot, directory.FullName, filename + "_thumbnail", false)); } await Task.WhenAll(tasksToWaitFor.ToArray()); } } catch (Exception ex) { this.OnScreenshotFailed(new ScreenshotFailedEventArgs(screenshot, ex, filename)); } this.ScreenhotsCompleted.Add(screenshot); this.OnScreenshotCompleted(new ScreenshotEventArgs(screenshot)); }
/// <summary> /// The create screenshot directory. /// </summary> /// <param name="jobInfo">The job info.</param> /// <param name="browser">The browser.</param> /// <param name="rootPath">The root path.</param> /// <returns> /// The <see cref="DirectoryInfo" />. /// </returns> private DirectoryInfo CreateScreenshotDirectory(Job.JobInfo jobInfo, Browser browser, string rootPath) { const string deviceFolderStructureTemplate = @"{0}\{1}\{2}\{3}"; const string browserFolderStructureTemplate = @"{0}\{1}\{2}\{3}\{4}"; string screenshotFolderName; if (string.IsNullOrEmpty(browser.Device)) { screenshotFolderName = string.Format( browserFolderStructureTemplate, browser.OS, browser.OSVersion, browser.BrowserName, browser.BrowserVersion, (browser.OS.ToLower().Contains("os x") ? jobInfo.OsxResolution.ToString() : jobInfo.WinResolution.ToString()).Replace("R_", string.Empty)); } else { screenshotFolderName = string.Format(deviceFolderStructureTemplate, browser.OS, browser.OSVersion, browser.Device, jobInfo.Orientation); } return Directory.CreateDirectory(Path.Combine(rootPath, screenshotFolderName)); }