diff --git a/dotnet/src/webdriver/EncodedFile.cs b/dotnet/src/webdriver/EncodedFile.cs index c8f9e1626a3f9..45ab15a74f64a 100644 --- a/dotnet/src/webdriver/EncodedFile.cs +++ b/dotnet/src/webdriver/EncodedFile.cs @@ -19,6 +19,8 @@ using System; +#nullable enable + namespace OpenQA.Selenium { /// @@ -26,34 +28,32 @@ namespace OpenQA.Selenium /// public abstract class EncodedFile { - private string base64Encoded = string.Empty; - private byte[] byteArray; - /// /// Initializes a new instance of the class. /// /// The file as a Base64-encoded string. + /// If is . + /// + /// The length of , ignoring white-space characters, is not zero or a multiple of 4. + /// -or- + /// The format of is invalid. contains a non-base-64 character, + /// more than two padding characters, or a non-white space-character among the padding characters. + /// protected EncodedFile(string base64EncodedFile) { - this.base64Encoded = base64EncodedFile; - this.byteArray = Convert.FromBase64String(this.base64Encoded); + this.AsBase64EncodedString = base64EncodedFile ?? throw new ArgumentNullException(nameof(base64EncodedFile)); + this.AsByteArray = Convert.FromBase64String(base64EncodedFile); } /// /// Gets the value of the encoded file as a Base64-encoded string. /// - public string AsBase64EncodedString - { - get { return this.base64Encoded; } - } + public string AsBase64EncodedString { get; } /// /// Gets the value of the encoded file as an array of bytes. /// - public byte[] AsByteArray - { - get { return this.byteArray; } - } + public byte[] AsByteArray { get; } /// /// Saves the file, overwriting it if it already exists. @@ -65,9 +65,6 @@ public byte[] AsByteArray /// Returns a String that represents the current Object. /// /// A String that represents the current Object. - public override string ToString() - { - return this.base64Encoded; - } + public override string ToString() => this.AsBase64EncodedString; } } diff --git a/dotnet/src/webdriver/ISupportsPrint.cs b/dotnet/src/webdriver/ISupportsPrint.cs index 6c79abf1a08e5..84c712c15aca6 100644 --- a/dotnet/src/webdriver/ISupportsPrint.cs +++ b/dotnet/src/webdriver/ISupportsPrint.cs @@ -17,6 +17,10 @@ // under the License. // +using System; + +#nullable enable + namespace OpenQA.Selenium { /// @@ -29,6 +33,7 @@ public interface ISupportsPrint /// /// A object describing the options of the printed document. /// The object containing the PDF-formatted print representation of the page. + /// If is . PrintDocument Print(PrintOptions options); } } diff --git a/dotnet/src/webdriver/PrintDocument.cs b/dotnet/src/webdriver/PrintDocument.cs index 7244a9c42dde7..61e558a756b0a 100644 --- a/dotnet/src/webdriver/PrintDocument.cs +++ b/dotnet/src/webdriver/PrintDocument.cs @@ -20,6 +20,8 @@ using System; using System.IO; +#nullable enable + namespace OpenQA.Selenium { /// @@ -31,6 +33,13 @@ public class PrintDocument : EncodedFile /// Initializes a new instance of the class. /// /// The printed document as a Base64-encoded string. + /// If is . + /// + /// The length of , ignoring white-space characters, is not zero or a multiple of 4. + /// -or- + /// The format of is invalid. contains a non-base-64 character, + /// more than two padding characters, or a non-white space-character among the padding characters. + /// public PrintDocument(string base64EncodedDocument) : base(base64EncodedDocument) { } @@ -39,6 +48,14 @@ public PrintDocument(string base64EncodedDocument) : base(base64EncodedDocument) /// Saves this as a PDF formatted file, overwriting the file if it already exists. /// /// The full path and file name to save the printed document to. + /// + /// If is or whitespace. + /// -or- + /// refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in an NTFS environment. + /// + /// refers to a non-file device, such as "con:", "com1:", "lpt1:", etc. in a non-NTFS environment. + /// The specified path is invalid, such as being on an unmapped drive. + /// The specified path, file name, or both exceed the system-defined maximum length. public override void SaveAsFile(string fileName) { if (string.IsNullOrEmpty(fileName)) diff --git a/dotnet/src/webdriver/PrintOptions.cs b/dotnet/src/webdriver/PrintOptions.cs index f1d9660565618..b1f3efd30692e 100644 --- a/dotnet/src/webdriver/PrintOptions.cs +++ b/dotnet/src/webdriver/PrintOptions.cs @@ -21,6 +21,8 @@ using System.Collections.Generic; using System.Globalization; +#nullable enable + namespace OpenQA.Selenium { /// @@ -49,96 +51,80 @@ public class PrintOptions private const double DefaultPageWidth = 27.94; private const double CentimetersPerInch = 2.54; - private PrintOrientation orientation = PrintOrientation.Portrait; private double scale = 1.0; - private bool background = false; - private bool shrinkToFit = true; private PageSize pageSize = new PageSize(); private Margins margins = new Margins(); - private HashSet pageRanges = new HashSet(); + private readonly HashSet pageRanges = new HashSet(); /// /// Gets or sets the orientation of the pages in the printed document. /// - public PrintOrientation Orientation - { - get { return orientation; } - set { orientation = value; } - } + public PrintOrientation Orientation { get; set; } = PrintOrientation.Portrait; /// /// Gets or sets the amount which the printed content is zoomed. Valid values are 0.1 to 2.0. /// + /// If the value is not set between 0.1 and 2.0. public double ScaleFactor { - get { return scale; } + get => this.scale; set { if (value < 0.1 || value > 2.0) { - throw new ArgumentException("Scale factor must be between 0.1 and 2.0."); + throw new ArgumentOutOfRangeException(nameof(value), "Scale factor must be between 0.1 and 2.0."); } - scale = value; + this.scale = value; } } /// /// Gets or sets a value indicating whether to print background images in the printed document. /// - public bool OutputBackgroundImages - { - get { return background; } - set { background = value; } - } + public bool OutputBackgroundImages { get; set; } /// /// Gets or sets a value indicating whether to shrink the content to fit the printed page size. /// - public bool ShrinkToFit - { - get { return shrinkToFit; } - set { shrinkToFit = value; } - } + public bool ShrinkToFit { get; set; } = true; /// /// Gets or sets the dimensions for each page in the printed document. /// + /// If the value is set to . public PageSize PageDimensions { - get { return pageSize; } - set - { - pageSize = value ?? throw new ArgumentNullException(nameof(value)); - } + get => this.pageSize; + set => this.pageSize = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the margins for each page in the doucment. /// + /// If the value is set to . public Margins PageMargins { - get { return margins; } - set - { - margins = value ?? throw new ArgumentNullException(nameof(value)); - } + get => this.margins; + set => this.margins = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Adds a page to the list of pages to be included in the document. /// /// The page number to be included in the document. + /// If is negative. + /// If the requested page has already been added. public void AddPageToPrint(int pageNumber) { if (pageNumber < 0) { - throw new ArgumentException("Page number must be greater than or equal to zero"); + throw new ArgumentOutOfRangeException(nameof(pageNumber), "Page number must be greater than or equal to zero"); } if (this.pageRanges.Contains(pageNumber)) { - throw new ArgumentException("Cannot add the same page number twice"); + throw new ArgumentException("Cannot add the same page number twice", nameof(pageNumber)); } this.pageRanges.Add(pageNumber); @@ -148,28 +134,42 @@ public void AddPageToPrint(int pageNumber) /// Adds a range of pages to be included in the document. /// /// A string of the form "x-y" representing the page numbers to include. + /// + /// If is or . + /// -or- + /// If the requested is already included. + /// -or- + /// If the requested has multiple '-' separators. + /// -or- + /// If a bound value is neither empty nor a number. + /// + /// + /// If has a negative lower bound. + /// -or- + /// If has an upper bound less than the lower bound. + /// public void AddPageRangeToPrint(string pageRange) { if (string.IsNullOrEmpty(pageRange)) { - throw new ArgumentException("Page range cannot be null or the empty string"); + throw new ArgumentException("Page range cannot be null or the empty string", nameof(pageRange)); } if (this.pageRanges.Contains(pageRange)) { - throw new ArgumentException("Cannot add the same page range twice"); + throw new ArgumentException("Cannot add the same page range twice", nameof(pageRange)); } string[] pageRangeParts = pageRange.Trim().Split('-'); if (pageRangeParts.Length > 2) { - throw new ArgumentException("Page range cannot have multiple separators"); + throw new ArgumentException("Page range cannot have multiple separators", nameof(pageRange)); } int startPage = ParsePageRangePart(pageRangeParts[0], 1); if (startPage < 1) { - throw new ArgumentException("Start of a page range must be greater than or equal to 1"); + throw new ArgumentOutOfRangeException(nameof(pageRange), "Start of a page range must be greater than or equal to 1"); } if (pageRangeParts.Length == 2) @@ -177,20 +177,20 @@ public void AddPageRangeToPrint(string pageRange) int endPage = ParsePageRangePart(pageRangeParts[1], int.MaxValue); if (endPage < startPage) { - throw new ArgumentException("End of a page range must be greater than or equal to the start of the page range"); + throw new ArgumentOutOfRangeException(nameof(pageRange), "End of a page range must be greater than or equal to the start of the page range"); } } this.pageRanges.Add(pageRange); } - internal Dictionary ToDictionary() + internal Dictionary ToDictionary() { - Dictionary toReturn = new Dictionary(); + Dictionary toReturn = new Dictionary(); - if (this.orientation != PrintOrientation.Portrait) + if (this.Orientation != PrintOrientation.Portrait) { - toReturn["orientation"] = this.orientation.ToString().ToLowerInvariant(); + toReturn["orientation"] = this.Orientation.ToString().ToLowerInvariant(); } if (this.scale != 1.0) @@ -198,19 +198,19 @@ internal Dictionary ToDictionary() toReturn["scale"] = this.scale; } - if (this.background) + if (this.OutputBackgroundImages) { - toReturn["background"] = this.background; + toReturn["background"] = this.OutputBackgroundImages; } - if (!this.shrinkToFit) + if (!this.ShrinkToFit) { - toReturn["shrinkToFit"] = this.shrinkToFit; + toReturn["shrinkToFit"] = this.ShrinkToFit; } if (this.pageSize.Height != DefaultPageHeight || this.pageSize.Width != DefaultPageWidth) { - Dictionary pageSizeDictionary = new Dictionary(); + Dictionary pageSizeDictionary = new Dictionary(); pageSizeDictionary["width"] = this.pageSize.Width; pageSizeDictionary["height"] = this.pageSize.Height; toReturn["page"] = pageSizeDictionary; @@ -218,7 +218,7 @@ internal Dictionary ToDictionary() if (this.margins.Top != DefaultMarginSize || this.margins.Bottom != DefaultMarginSize || this.margins.Left != DefaultMarginSize || this.margins.Right != DefaultMarginSize) { - Dictionary marginsDictionary = new Dictionary(); + Dictionary marginsDictionary = new Dictionary(); marginsDictionary["top"] = this.margins.Top; marginsDictionary["bottom"] = this.margins.Bottom; marginsDictionary["left"] = this.margins.Left; @@ -228,7 +228,7 @@ internal Dictionary ToDictionary() if (this.pageRanges.Count > 0) { - toReturn["pageRanges"] = new List(this.pageRanges); + toReturn["pageRanges"] = new List(this.pageRanges); } return toReturn; @@ -237,16 +237,18 @@ internal Dictionary ToDictionary() private static int ParsePageRangePart(string pageRangePart, int defaultValue) { pageRangePart = pageRangePart.Trim(); - int pageRangePartValue = defaultValue; - if (!string.IsNullOrEmpty(pageRangePart)) + + if (string.IsNullOrEmpty(pageRangePart)) { - if (!int.TryParse(pageRangePart, NumberStyles.Integer, CultureInfo.InvariantCulture, out pageRangePartValue)) - { - throw new ArgumentException("Parts of a page range must be an empty string or an integer"); - } + return defaultValue; + } + + if (int.TryParse(pageRangePart, NumberStyles.Integer, CultureInfo.InvariantCulture, out int pageRangePartValue)) + { + return pageRangePartValue; } - return pageRangePartValue; + throw new ArgumentException("Parts of a page range must be an empty string or an integer"); } /// @@ -260,53 +262,57 @@ public class PageSize /// /// Gets or sets the height of each page in centimeters. /// + /// If the value is set to a negative value. public double Height { - get { return height; } + get => this.height; set { if (value < 0) { - throw new ArgumentException("Height must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(value), "Height must be greater than or equal to zero."); } - height = value; + this.height = value; } } /// /// Gets or sets the width of each page in centimeters. /// + /// If the value is set to a negative value. public double Width { - get { return width; } + get => this.width; set { if (value < 0) { - throw new ArgumentException("Width must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(value), "Width must be greater than or equal to zero."); } - width = value; + this.width = value; } } /// /// Gets or sets the height of each page in inches. /// + /// If the value is set to a negative value. public double HeightInInches { - get { return Height / CentimetersPerInch; } - set { Height = value * CentimetersPerInch; } + get => this.Height / CentimetersPerInch; + set => this.Height = value * CentimetersPerInch; } /// /// Gets or sets the width of each page in inches. /// + /// If the value is set to a negative value. public double WidthInInches { - get { return Width / CentimetersPerInch; } - set { Width = value * CentimetersPerInch; } + get => this.Width / CentimetersPerInch; + set => this.Width = value * CentimetersPerInch; } } @@ -323,68 +329,72 @@ public class Margins /// /// Gets or sets the top margin of the print options. /// + /// If the value is set to a negative value. public double Top { - get { return top; } + get => this.top; set { if (value < 0) { - throw new ArgumentException("Top margin must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(value), "Top margin must be greater than or equal to zero."); } - top = value; + this.top = value; } } /// /// Gets or sets the bottom margin of the print options. /// + /// If the value is set to a negative value. public double Bottom { - get { return bottom; } + get => this.bottom; set { if (value < 0) { - throw new ArgumentException("Bottom margin must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(value), "Bottom margin must be greater than or equal to zero."); } - bottom = value; + this.bottom = value; } } /// /// Gets or sets the left margin of the print options. /// + /// If the value is set to a negative value. public double Left { - get { return left; } + get => this.left; set { if (value < 0) { - throw new ArgumentException("Left margin must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(value), "Left margin must be greater than or equal to zero."); } - left = value; + this.left = value; } } /// /// Gets or sets the right margin of the print options. /// + /// If the value is set to a negative value. public double Right { - get { return right; } + get => this.right; set { if (value < 0) { - throw new ArgumentException("Right margin must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(value), "Right margin must be greater than or equal to zero."); } - right = value; + this.right = value; } } } diff --git a/dotnet/src/webdriver/Screenshot.cs b/dotnet/src/webdriver/Screenshot.cs index 67b59aab6ac01..7b5f869fb6728 100644 --- a/dotnet/src/webdriver/Screenshot.cs +++ b/dotnet/src/webdriver/Screenshot.cs @@ -20,6 +20,8 @@ using System; using System.IO; +#nullable enable + namespace OpenQA.Selenium { /// @@ -32,6 +34,13 @@ public class Screenshot : EncodedFile /// Initializes a new instance of the class. /// /// The image of the page as a Base64-encoded string. + /// If is . + /// + /// The length of , ignoring white-space characters, is not zero or a multiple of 4. + /// -or- + /// The format of is invalid. contains a non-base-64 character, + /// more than two padding characters, or a non-white space-character among the padding characters. + /// public Screenshot(string base64EncodedScreenshot) : base(base64EncodedScreenshot) { } diff --git a/dotnet/src/webdriver/WebDriver.cs b/dotnet/src/webdriver/WebDriver.cs index 6bd964136c928..235b2e648058e 100644 --- a/dotnet/src/webdriver/WebDriver.cs +++ b/dotnet/src/webdriver/WebDriver.cs @@ -380,8 +380,14 @@ public Screenshot GetScreenshot() /// /// A object describing the options of the printed document. /// The object containing the PDF-formatted print representation of the page. + /// If is . public PrintDocument Print(PrintOptions printOptions) { + if (printOptions is null) + { + throw new ArgumentNullException(nameof(printOptions)); + } + Response commandResponse = this.Execute(DriverCommand.Print, printOptions.ToDictionary()); string base64 = commandResponse.Value.ToString(); return new PrintDocument(base64); diff --git a/dotnet/test/common/PrintTest.cs b/dotnet/test/common/PrintTest.cs index f48f63f4815fc..324fc6e399c48 100644 --- a/dotnet/test/common/PrintTest.cs +++ b/dotnet/test/common/PrintTest.cs @@ -89,5 +89,38 @@ public void MarginsCannotBeNull() { Assert.That(() => new PrintOptions { PageMargins = null }, Throws.InstanceOf()); } + + [Test] + public void PageNumberCannotHaveInvalidValues() + { + Assert.That(() => new PrintOptions().AddPageToPrint(-1), Throws.TypeOf()); + Assert.That(() => new PrintOptions().AddPageRangeToPrint(null), Throws.TypeOf()); + Assert.That(() => new PrintOptions().AddPageRangeToPrint(""), Throws.TypeOf()); + Assert.That(() => new PrintOptions().AddPageRangeToPrint("1-2-3"), Throws.TypeOf()); + Assert.That(() => + { + var options = new PrintOptions(); + options.AddPageToPrint(1); + options.AddPageToPrint(1); + }, Throws.TypeOf()); + } + + [Test] + public void PageSizeCannotHaveNegativeValues() + { + Assert.That(() => new PrintOptions.PageSize { Height = -1 }, Throws.TypeOf()); + Assert.That(() => new PrintOptions.PageSize { HeightInInches = -1 }, Throws.TypeOf()); + Assert.That(() => new PrintOptions.PageSize { Width = -1 }, Throws.TypeOf()); + Assert.That(() => new PrintOptions.PageSize { WidthInInches = -1 }, Throws.TypeOf()); + } + + [Test] + public void MarginsCannotHaveNegativeValues() + { + Assert.That(() => new PrintOptions.Margins { Top = -1 }, Throws.TypeOf()); + Assert.That(() => new PrintOptions.Margins { Bottom = -1 }, Throws.TypeOf()); + Assert.That(() => new PrintOptions.Margins { Left = -1 }, Throws.TypeOf()); + Assert.That(() => new PrintOptions.Margins { Right = -1 }, Throws.TypeOf()); + } } }