Skip to content

Commit f2ed551

Browse files
authored
Merge pull request #1 from tarrball/atarr/main/search-tests
Cleaning up data contracts around models and search options to better match the API
2 parents 99082fa + 7a62492 commit f2ed551

30 files changed

Lines changed: 1493 additions & 1368 deletions
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
using GuardianClient.Options.Search;
2+
using Shouldly;
3+
4+
namespace GuardianClient.Tests;
5+
6+
[TestClass]
7+
public class GetItemAsyncTests : TestBase
8+
{
9+
[TestMethod]
10+
public async Task GetItemAsync_WithValidId_ReturnsItem()
11+
{
12+
// First get a valid item ID from search
13+
var searchResult = await ApiClient.SearchAsync(new GuardianApiContentSearchOptions
14+
{
15+
Query = "technology",
16+
PageOptions = new GuardianApiContentPageOptions { PageSize = 1 }
17+
});
18+
searchResult.ShouldNotBeNull("Search should return results");
19+
searchResult.Results.Count.ShouldBe(1, "Should return exactly one result");
20+
21+
var contentItem = searchResult.Results.First();
22+
var itemId = contentItem.Id;
23+
24+
// Now get the specific item
25+
var singleItemResult = await ApiClient.GetItemAsync(itemId,
26+
new GuardianApiContentAdditionalInformationOptions { ShowFields = [GuardianApiContentShowFieldsOption.Body] });
27+
28+
singleItemResult.ShouldNotBeNull("GetItem result should not be null");
29+
singleItemResult.Status.ShouldBe("ok", "API response status should be 'ok'");
30+
singleItemResult.Content.ShouldNotBeNull("Content should not be null");
31+
singleItemResult.Content.Id.ShouldBe(itemId, "Returned content ID should match requested ID");
32+
singleItemResult.Content.WebTitle.ShouldNotBeNullOrEmpty("Content should have a title");
33+
singleItemResult.Content.Fields.ShouldNotBeNull("Fields should be populated when ShowFields is specified");
34+
35+
Console.WriteLine($"Retrieved item: {singleItemResult.Content.WebTitle}");
36+
Console.WriteLine($"Item ID: {singleItemResult.Content.Id}");
37+
Console.WriteLine($"Published: {singleItemResult.Content.WebPublicationDate}");
38+
39+
if (!string.IsNullOrEmpty(singleItemResult.Content.Fields.Body))
40+
{
41+
Console.WriteLine($"Body length: {singleItemResult.Content.Fields.Body.Length} characters");
42+
Console.WriteLine(
43+
$"Body preview: {singleItemResult.Content.Fields.Body[..Math.Min(200, singleItemResult.Content.Fields.Body.Length)]}...");
44+
}
45+
}
46+
47+
[TestMethod]
48+
public async Task GetItemAsync_WithInvalidId_ThrowsException()
49+
{
50+
var invalidId = "invalid/article/id/that/does/not/exist";
51+
52+
var exception = await Should.ThrowAsync<HttpRequestException>(async () =>
53+
{
54+
await ApiClient.GetItemAsync(invalidId);
55+
});
56+
57+
Console.WriteLine($"Expected exception for invalid ID: {exception.Message}");
58+
}
59+
60+
[TestMethod]
61+
public async Task GetItemAsync_WithNullId_ThrowsArgumentException()
62+
{
63+
var exception = await Should.ThrowAsync<ArgumentException>(async () =>
64+
{
65+
await ApiClient.GetItemAsync(null!);
66+
});
67+
68+
Console.WriteLine($"Expected exception for null ID: {exception.Message}");
69+
}
70+
71+
[TestMethod]
72+
public async Task GetItemAsync_WithEmptyId_ThrowsArgumentException()
73+
{
74+
var exception = await Should.ThrowAsync<ArgumentException>(async () =>
75+
{
76+
await ApiClient.GetItemAsync("");
77+
});
78+
79+
Console.WriteLine($"Expected exception for empty ID: {exception.Message}");
80+
}
81+
82+
[TestMethod]
83+
public async Task GetItemAsync_WithShowFields_ReturnsEnhancedContent()
84+
{
85+
// Get a valid item ID
86+
var searchResult = await ApiClient.SearchAsync(new GuardianApiContentSearchOptions
87+
{
88+
Query = "politics",
89+
PageOptions = new GuardianApiContentPageOptions { PageSize = 1 }
90+
});
91+
92+
var itemId = searchResult.Results.First().Id;
93+
94+
// Request with multiple fields
95+
var result = await ApiClient.GetItemAsync(itemId,
96+
new GuardianApiContentAdditionalInformationOptions
97+
{
98+
ShowFields =
99+
[
100+
GuardianApiContentShowFieldsOption.Headline,
101+
GuardianApiContentShowFieldsOption.Body,
102+
GuardianApiContentShowFieldsOption.Byline,
103+
GuardianApiContentShowFieldsOption.Thumbnail
104+
]
105+
});
106+
107+
result.ShouldNotBeNull();
108+
result.Content.Fields.ShouldNotBeNull("Fields should be populated");
109+
result.Content.Fields.Headline.ShouldNotBeNullOrEmpty("Headline should be populated");
110+
111+
Console.WriteLine($"Enhanced content for: {result.Content.WebTitle}");
112+
Console.WriteLine($"Headline: {result.Content.Fields.Headline}");
113+
Console.WriteLine($"Has body: {!string.IsNullOrEmpty(result.Content.Fields.Body)}");
114+
Console.WriteLine($"Has byline: {!string.IsNullOrEmpty(result.Content.Fields.Byline)}");
115+
}
116+
117+
[TestMethod]
118+
public async Task GetItemAsync_WithShowTags_ReturnsContentWithTags()
119+
{
120+
// Get a valid item ID
121+
var searchResult = await ApiClient.SearchAsync(new GuardianApiContentSearchOptions
122+
{
123+
Query = "sport",
124+
PageOptions = new GuardianApiContentPageOptions { PageSize = 1 }
125+
});
126+
127+
var itemId = searchResult.Results.First().Id;
128+
129+
// Request with tags
130+
var result = await ApiClient.GetItemAsync(itemId,
131+
new GuardianApiContentAdditionalInformationOptions
132+
{
133+
ShowTags = [GuardianApiContentShowTagsOption.Keyword, GuardianApiContentShowTagsOption.Tone, GuardianApiContentShowTagsOption.Type]
134+
});
135+
136+
result.ShouldNotBeNull();
137+
result.Content.Tags.ShouldNotBeNull("Tags should be populated");
138+
result.Content.Tags.Count.ShouldBeGreaterThan(0, "Should have at least one tag");
139+
140+
Console.WriteLine($"Content '{result.Content.WebTitle}' has {result.Content.Tags.Count} tags:");
141+
foreach (var tag in result.Content.Tags.Take(5)) // Show first 5 tags
142+
{
143+
Console.WriteLine($" - {tag.WebTitle} ({tag.Type})");
144+
}
145+
}
146+
147+
[TestMethod]
148+
public async Task GetItemAsync_WithShowElements_ReturnsContentWithElements()
149+
{
150+
// Get a valid item ID
151+
var searchResult = await ApiClient.SearchAsync(new GuardianApiContentSearchOptions
152+
{
153+
Query = "music",
154+
PageOptions = new GuardianApiContentPageOptions { PageSize = 1 }
155+
});
156+
157+
var itemId = searchResult.Results.First().Id;
158+
159+
// Request with elements
160+
var result = await ApiClient.GetItemAsync(itemId,
161+
new GuardianApiContentAdditionalInformationOptions
162+
{
163+
ShowElements = [GuardianApiContentShowElementsOption.Image, GuardianApiContentShowElementsOption.Video]
164+
});
165+
166+
result.ShouldNotBeNull();
167+
// Elements might be null if the article has no media, so we don't assert their presence
168+
169+
Console.WriteLine($"Content '{result.Content.WebTitle}' elements:");
170+
if (result.Content.Elements != null)
171+
{
172+
Console.WriteLine($" Has {result.Content.Elements.Count} media elements");
173+
}
174+
else
175+
{
176+
Console.WriteLine(" No media elements found");
177+
}
178+
}
179+
180+
[TestMethod]
181+
public async Task GetItemAsync_WithShowBlocks_ReturnsContentWithBlocks()
182+
{
183+
// Get a valid item ID
184+
var searchResult = await ApiClient.SearchAsync(new GuardianApiContentSearchOptions
185+
{
186+
Query = "news",
187+
PageOptions = new GuardianApiContentPageOptions { PageSize = 1 }
188+
});
189+
190+
var itemId = searchResult.Results.First().Id;
191+
192+
// Request with blocks using string array (as it's still string-based)
193+
var result = await ApiClient.GetItemAsync(itemId,
194+
new GuardianApiContentAdditionalInformationOptions
195+
{
196+
ShowBlocks = ["main", "body"]
197+
});
198+
199+
result.ShouldNotBeNull();
200+
// Blocks might be null depending on content type
201+
202+
Console.WriteLine($"Content '{result.Content.WebTitle}' blocks:");
203+
if (result.Content.Blocks != null)
204+
{
205+
Console.WriteLine($" Requested main and body blocks");
206+
}
207+
else
208+
{
209+
Console.WriteLine(" No blocks found");
210+
}
211+
}
212+
213+
[TestMethod]
214+
public async Task GetItemAsync_WithAllOptions_ReturnsFullyEnhancedContent()
215+
{
216+
// Get a valid item ID
217+
var searchResult = await ApiClient.SearchAsync(new GuardianApiContentSearchOptions
218+
{
219+
Query = "culture",
220+
PageOptions = new GuardianApiContentPageOptions { PageSize = 1 }
221+
});
222+
223+
var itemId = searchResult.Results.First().Id;
224+
225+
// Request with all enhancement options
226+
var result = await ApiClient.GetItemAsync(itemId,
227+
new GuardianApiContentAdditionalInformationOptions
228+
{
229+
ShowFields = [GuardianApiContentShowFieldsOption.All],
230+
ShowTags = [GuardianApiContentShowTagsOption.All],
231+
ShowElements = [GuardianApiContentShowElementsOption.All],
232+
ShowBlocks = ["all"]
233+
});
234+
235+
result.ShouldNotBeNull();
236+
result.Content.Fields.ShouldNotBeNull("All fields should be populated");
237+
result.Content.Tags.ShouldNotBeNull("All tags should be populated");
238+
239+
Console.WriteLine($"Fully enhanced content: {result.Content.WebTitle}");
240+
Console.WriteLine($" Fields populated: Yes");
241+
Console.WriteLine($" Tags count: {result.Content.Tags.Count}");
242+
Console.WriteLine($" Elements: {(result.Content.Elements?.Count ?? 0)}");
243+
Console.WriteLine($" Has blocks: {result.Content.Blocks != null}");
244+
}
245+
}

0 commit comments

Comments
 (0)