1 module unittesting.articlegenerator; 2 3 import std.datetime; 4 import std.random; 5 import std.range; 6 7 import vibe.data.json; 8 9 import devto.api; 10 11 @safe: 12 13 string articleTemplate = `{ 14 "published_at":null, 15 "canonical_url":"https://dev.to/username/articleslug", 16 "comments_count":0, 17 "page_views_count":0, 18 "id":111111, 19 "published_timestamp":"2020-01-16T01:22:00Z", 20 "positive_reactions_count":0, 21 "published":false, 22 "body_markdown":"Text used in the article.", 23 "title":"Title of the Article", 24 "url":"https://dev.to/username/articleslug", 25 "user":{ 26 "username":"username", 27 "profile_image":"https://res.cloudinary.com/practicaldev/SomeImage.png", 28 "github_username":"GitHubUserName", 29 "profile_image_90":"https://res.cloudinary.com/practicaldev/SomeImage.png", 30 "website_url":"https://www.example.com", 31 "twitter_username":null, 32 "name":"User Name" 33 }, 34 "cover_image":null, 35 "slug":"articleslug", 36 "description":"", 37 "path":"/username/articleslug", 38 "tag_list":[ 39 "testing" 40 ], 41 "type_of":"article" 42 }`; 43 44 /** 45 * Provides an initial article template for testing. 46 * 47 * It is expected to be combined with std.range.generate and seqence. 48 * 49 * `generate!fakeArticleMe.seqence().take(3);` 50 */ 51 auto fakeArticleMe() { 52 // Deep copy Json object 53 return articleTemplate.parseJsonString; 54 } 55 56 /** 57 * Given a range of `fakeArticleMe()` apply a decending id and publish date 58 * to replicate the behavior of the API. 59 * 60 * Note: This does not provide any unpublished articles which are provided 61 * first in the API. 62 */ 63 auto seqence(R)(R articles, const SysTime newestDate = Clock.currTime) 64 if(is(ElementType!R == Json)) { 65 struct DateSequencing { 66 DateTime date; 67 uint id = 10_000; 68 R inner; 69 70 auto empty () { 71 if(inner.empty) return true; 72 if(id < 2) return true; 73 return false; 74 } 75 76 auto front() { 77 auto ans = inner.front; 78 ans["id"] = Json(id); 79 // DateTime has no timezone, we pretend it is UTC after cast 80 ans["published_timestamp"] = Json(date.toISOExtString ~ "Z"); 81 return ans; 82 } 83 84 auto popFront() { 85 inner.popFront(); 86 id--; 87 date -= dur!"days"(uniform(1,12)); 88 } 89 } 90 91 DateSequencing ds; 92 ds.date = cast(DateTime) newestDate; 93 ds.inner = articles; 94 return ds; 95 } unittest { 96 import std.algorithm : equal, map, isSorted; 97 auto seq = generate!fakeArticleMe.seqence(Clock.currTime).take(3); 98 assert(seq.map!(x => x["id"].get!uint).equal([10_000, 9_999, 9_998])); 99 assert(seq.map!(x => x["published_timestamp"].get!string).array.isSorted!"a > b"); 100 }