From b9f3982d42bb5324d35b4b34769352e6130fefaf Mon Sep 17 00:00:00 2001 From: Steven Atkinson Date: Tue, 5 Feb 2019 17:07:08 +0000 Subject: [PATCH] Added the LoremPixel faker (#114) * Added the documentation. * Implemented the LoremPixel faker. * Added the LoremPixelFaker to the main faker classes. --- README.md | 1 + doc/lorem_pixel.md | 17 +++ src/FakerDotNet/Faker.cs | 1 + src/FakerDotNet/FakerContainer.cs | 3 + src/FakerDotNet/Fakers/LoremPixelFaker.cs | 104 ++++++++++++++ .../FakerDotNet.Tests/FakerContainerTests.cs | 6 + tests/FakerDotNet.Tests/FakerTests.cs | 6 + .../Fakers/LoremPixelFakerTests.cs | 128 ++++++++++++++++++ 8 files changed, 266 insertions(+) create mode 100644 doc/lorem_pixel.md create mode 100644 src/FakerDotNet/Fakers/LoremPixelFaker.cs create mode 100644 tests/FakerDotNet.Tests/Fakers/LoremPixelFakerTests.cs diff --git a/README.md b/README.md index 4ebb1f9..43b5340 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ A .NET port of the Ruby [faker](https://github.com/stympy/faker) gem - [Faker.LordOfTheRings](doc/lord_of_the_rings.md) - [Faker.Lorem](doc/lorem.md) - [Faker.LoremFlickr](doc/lorem_flickr.md) + - [Faker.LoremPixel](doc/lorem_pixel.md) - [Faker.Matz](doc/matz.md) - [Faker.Music](doc/music.md) - [Faker.Name](doc/name.md) diff --git a/doc/lorem_pixel.md b/doc/lorem_pixel.md new file mode 100644 index 0000000..044e805 --- /dev/null +++ b/doc/lorem_pixel.md @@ -0,0 +1,17 @@ +# Faker.LoremPixel + +```cs +Faker.LoremPixel.Image() //=> "https://lorempixel.Com/300/300" + +Faker.LoremPixel.Image("50x60") //=> "https://lorempixel.Com/50/60" + +Faker.LoremPixel.Image("50x60", true) //=> "https://lorempixel.Com/g/50/60" + +Faker.LoremPixel.Image("50x60", false, "sports") //=> "https://lorempixel.Com/50/60/sports" + +Faker.LoremPixel.Image("50x60", false, "sports", 3) //=> "https://lorempixel.Com/50/60/sports/3" + +Faker.LoremPixel.Image("50x60", false, "sports", 3, "Dummy-text") //=> "https://lorempixel.Com/50/60/sports/3/Dummy-text" + +Faker.LoremPixel.Image("50x60", false, "sports", null, "Dummy-text") //=> "https://lorempixel.Com/50/60/sports/Dummy-text" +``` diff --git a/src/FakerDotNet/Faker.cs b/src/FakerDotNet/Faker.cs index 366764e..85697ac 100644 --- a/src/FakerDotNet/Faker.cs +++ b/src/FakerDotNet/Faker.cs @@ -35,6 +35,7 @@ public static class Faker public static ILordOfTheRingsFaker LordOfTheRings { get; } = Container.LordOfTheRings; public static ILoremFaker Lorem { get; } = Container.Lorem; public static ILoremFlickrFaker LoremFlickr { get; } = Container.LoremFlickr; + public static ILoremPixelFaker LoremPixel { get; } = Container.LoremPixel; public static IMatzFaker Matz { get; } = Container.Matz; public static IMusicFaker Music { get; } = Container.Music; public static INameFaker Name { get; } = Container.Name; diff --git a/src/FakerDotNet/FakerContainer.cs b/src/FakerDotNet/FakerContainer.cs index 31298f2..8884c37 100644 --- a/src/FakerDotNet/FakerContainer.cs +++ b/src/FakerDotNet/FakerContainer.cs @@ -33,6 +33,7 @@ internal interface IFakerContainer ILordOfTheRingsFaker LordOfTheRings { get; } ILoremFaker Lorem { get; } ILoremFlickrFaker LoremFlickr { get; } + ILoremPixelFaker LoremPixel { get; } IMatzFaker Matz { get; } IMusicFaker Music { get; } INameFaker Name { get; } @@ -89,6 +90,7 @@ public FakerContainer() LordOfTheRings = new LordOfTheRingsFaker(this); Lorem = new LoremFaker(this); LoremFlickr = new LoremFlickrFaker(this); + LoremPixel = new LoremPixelFaker(this); Matz = new MatzFaker(this); Music = new MusicFaker(this); Name = new NameFaker(this); @@ -141,6 +143,7 @@ public FakerContainer() public ILordOfTheRingsFaker LordOfTheRings { get; } public ILoremFaker Lorem { get; } public ILoremFlickrFaker LoremFlickr { get; } + public ILoremPixelFaker LoremPixel { get; } public IMatzFaker Matz { get; } public IMusicFaker Music { get; } public INameFaker Name { get; } diff --git a/src/FakerDotNet/Fakers/LoremPixelFaker.cs b/src/FakerDotNet/Fakers/LoremPixelFaker.cs new file mode 100644 index 0000000..da20886 --- /dev/null +++ b/src/FakerDotNet/Fakers/LoremPixelFaker.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace FakerDotNet.Fakers +{ + public interface ILoremPixelFaker + { + string Image( + string size = "300x300", + bool isGray = false, + string category = null, + int? number = null, + string text = null); + } + + internal class LoremPixelFaker : ILoremPixelFaker + { + internal static readonly IEnumerable SupportedCategories = new[] + { + "abstract", + "animals", + "business", + "cats", + "city", + "food", + "nightlife", + "fashion", + "people", + "nature", + "sports", + "technics", + "transport" + }; + + private readonly IFakerContainer _fakerContainer; + + public LoremPixelFaker(IFakerContainer fakerContainer) + { + _fakerContainer = fakerContainer; + } + + public string Image( + string size = "300x300", + bool isGray = false, + string category = null, + int? number = null, + string text = null) + { + if (!IsValidSize(size)) + throw new ArgumentException("Size should be specified in format 300x300", nameof(size)); + + if (!IsSupportedCategory(category)) + throw new ArgumentException($"Supported categories are {string.Join(", ", SupportedCategories)}", + nameof(category)); + + if (!IsValidNumber(number)) + throw new ArgumentException("Number must be between 1 and 10", nameof(number)); + + if (!IsValidCategoryNumber(category, number)) + throw new ArgumentException("Category required when number is passed", nameof(number)); + + if (!IsValidCategoryText(category, text)) + throw new ArgumentException("Category and number must be passed when text is passed", nameof(text)); + + return string.Join("/", new[] + { + "https://lorempixel.com", + isGray ? "g" : "", + string.Join("/", size.Split('x')), + category, + Convert.ToString(number), + text + }.Where(x => !string.IsNullOrEmpty(x))); + } + + private static bool IsValidSize(string size) + { + return Regex.IsMatch(size, "^[0-9]+x[0-9]+$"); + } + + private static bool IsSupportedCategory(string category) + { + return string.IsNullOrEmpty(category) || SupportedCategories.Contains(category); + } + + private static bool IsValidNumber(int? number) + { + var n = number.GetValueOrDefault(1); + return n >= 1 && n <= 10; + } + + private static bool IsValidCategoryNumber(string category, int? number) + { + return !number.HasValue || !string.IsNullOrEmpty(category); + } + + private static bool IsValidCategoryText(string category, string text) + { + return string.IsNullOrEmpty(text) || !string.IsNullOrEmpty(category); + } + } +} diff --git a/tests/FakerDotNet.Tests/FakerContainerTests.cs b/tests/FakerDotNet.Tests/FakerContainerTests.cs index 247fc58..89d5c14 100644 --- a/tests/FakerDotNet.Tests/FakerContainerTests.cs +++ b/tests/FakerDotNet.Tests/FakerContainerTests.cs @@ -189,6 +189,12 @@ public void LoremFlickr_returns_ILoremFlickrFaker() Assert.IsInstanceOf(_fakerContainer.LoremFlickr); } + [Test] + public void LoremPixel_returns_ILoremPixelFaker() + { + Assert.IsInstanceOf(_fakerContainer.LoremPixel); + } + [Test] public void Matz_returns_IMatzFaker() { diff --git a/tests/FakerDotNet.Tests/FakerTests.cs b/tests/FakerDotNet.Tests/FakerTests.cs index 8d0368c..5d0c1c1 100644 --- a/tests/FakerDotNet.Tests/FakerTests.cs +++ b/tests/FakerDotNet.Tests/FakerTests.cs @@ -181,6 +181,12 @@ public void LoremFlickr_returns_ILoremFlickrFaker() Assert.IsInstanceOf(Faker.LoremFlickr); } + [Test] + public void LoremPixel_returns_ILoremPixelFaker() + { + Assert.IsInstanceOf(Faker.LoremPixel); + } + [Test] public void Matz_returns_IMatzFaker() { diff --git a/tests/FakerDotNet.Tests/Fakers/LoremPixelFakerTests.cs b/tests/FakerDotNet.Tests/Fakers/LoremPixelFakerTests.cs new file mode 100644 index 0000000..87f9333 --- /dev/null +++ b/tests/FakerDotNet.Tests/Fakers/LoremPixelFakerTests.cs @@ -0,0 +1,128 @@ +using System; +using FakeItEasy; +using FakerDotNet.Fakers; +using NUnit.Framework; + +namespace FakerDotNet.Tests.Fakers +{ + [TestFixture] + [Parallelizable] + public class LoremPixelFakerTests + { + [SetUp] + public void SetUp() + { + _fakerContainer = A.Fake(); + _lorempixelFaker = new LoremPixelFaker(_fakerContainer); + } + + private IFakerContainer _fakerContainer; + private ILoremPixelFaker _lorempixelFaker; + + [Test] + public void Image_returns_an_image_url() + { + Assert.AreEqual( + "https://lorempixel.com/300/300", + _lorempixelFaker.Image()); + } + + [Test] + public void Image_returns_an_image_url_with_the_specified_size() + { + Assert.AreEqual( + "https://lorempixel.com/50/60", + _lorempixelFaker.Image("50x60")); + } + + [Test] + public void Image_throws_ArgumentException_when_size_is_not_in_a_valid_format() + { + var ex = Assert.Throws(() => + _lorempixelFaker.Image("ABCxDEF")); + + Assert.That(ex.Message.StartsWith("Size should be specified in format 300x300")); + } + + [Test] + public void Image_returns_a_gray_image_url_when_is_gray_is_specified() + { + Assert.AreEqual( + "https://lorempixel.com/g/50/60", + _lorempixelFaker.Image("50x60", true)); + } + + [Test] + public void Image_returns_an_image_url_with_the_specified_category() + { + Assert.AreEqual( + "https://lorempixel.com/g/50/60/sports", + _lorempixelFaker.Image("50x60", true, "sports")); + } + + [Test] + public void Image_throws_ArgumentException_when_format_is_not_supported() + { + var supportedCategories = string.Join(", ", LoremPixelFaker.SupportedCategories); + + var ex = Assert.Throws(() => + _lorempixelFaker.Image("50x50", false, "bad")); + + Assert.That(ex.Message.StartsWith($"Supported categories are {supportedCategories}")); + } + + [Test] + public void Image_returns_an_image_url_with_the_specified_number() + { + Assert.AreEqual( + "https://lorempixel.com/g/50/60/sports/3", + _lorempixelFaker.Image("50x60", true, "sports", 3)); + } + + [Test] + [TestCase(-1)] + [TestCase(0)] + [TestCase(11)] + public void Image_throws_ArgumentException_when_number_is_not_in_valid_range(int number) + { + var ex = Assert.Throws(() => + _lorempixelFaker.Image("50x50", false, "sports", number)); + + Assert.That(ex.Message.StartsWith("Number must be between 1 and 10")); + } + + [Test] + public void Image_throws_ArgumentException_when_number_is_not_supplied_with_category() + { + var ex = Assert.Throws(() => + _lorempixelFaker.Image("50x50", false, null, 3)); + + Assert.That(ex.Message.StartsWith("Category required when number is passed")); + } + + [Test] + public void Image_returns_an_image_url_with_the_specified_text() + { + Assert.AreEqual( + "https://lorempixel.com/g/50/60/sports/3/Dummy-text", + _lorempixelFaker.Image("50x60", true, "sports", 3, "Dummy-text")); + } + + [Test] + public void Image_returns_an_image_url_with_the_specified_category_and_text() + { + Assert.AreEqual( + "https://lorempixel.com/g/50/60/sports/Dummy-text", + _lorempixelFaker.Image("50x60", true, "sports", null, "Dummy-text")); + } + + [Test] + public void Image_throw_ArgumentException_when_category_and_number_is_not_supplied_with_text() + { + var ex = Assert.Throws(() => + _lorempixelFaker.Image("50x50", false, null, null, "Dummy-text")); + + Assert.That(ex.Message.StartsWith("Category and number must be passed when text is passed")); + } + } +}