Skip to content

Commit 1327294

Browse files
committed
Merge branch 'main' into feature/add-delete-items-support
2 parents 5cf0efb + f751c98 commit 1327294

File tree

7 files changed

+97
-29
lines changed

7 files changed

+97
-29
lines changed

Optimizely.Graph.Source.Sdk/Optimizely.Graph.Source.Sdk.Sample/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@
192192
}
193193
};
194194

195-
await client.SaveContentAsync(generateId: (x) => $"{x.Name}_{x.Address.City}", exampleDataInstance1, exampleDataInstance2, exampleDataInstance3);
195+
await client.SaveContentAsync(generateId: (x) => $"{x.Name}_{x.Address.City}", "en", exampleDataInstance1, exampleDataInstance2, exampleDataInstance3);
196196
#endregion
197197

198198
#region ExampleTypes

Optimizely.Graph.Source.Sdk/Optimizely.Graph.Source.Sdk.Tests/RepositoryTests/GraphSourceRepositoryTests.cs

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,62 @@ public async Task SaveContentAsync_SerializesData_AndCallsGraphClient()
203203
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/content/v2/data?id={source}") { Content = content };
204204

205205
mockRestClient.Setup(c => c.SendAsync(It.IsAny<HttpRequestMessage>())).ReturnsAsync(response);
206-
mockRestClient.Setup(c => c.HandleResponse(response));
206+
mockRestClient.Setup(c => c.HandleResponse<ContentV2ApiResponse>(response));
207207

208208
// Act
209-
await repository.SaveContentAsync(generateId: (x) => x.ToString(), exampleData);
209+
await repository.SaveContentAsync(generateId: (x) => x.ToString(), "en", exampleData);
210210

211211
// Assert
212212
mockRestClient.Verify(c => c.SendAsync(It.Is<HttpRequestMessage>(x => Compare(request, x))), Times.Once);
213-
mockRestClient.Verify(c => c.HandleResponse(response), Times.Once);
213+
mockRestClient.Verify(c => c.HandleResponse<ContentV2ApiResponse>(response), Times.Once);
214+
mockRestClient.VerifyAll();
215+
}
216+
217+
[TestMethod]
218+
public async Task SaveContentAsync_SerializesData_ReturnsJournalId()
219+
{
220+
// Arrange
221+
repository.ConfigureContentType<ExampleClassObject>()
222+
.Field(x => x.FirstName, IndexingType.Searchable)
223+
.Field(x => x.LastName, IndexingType.Searchable)
224+
.Field(x => x.Age, IndexingType.Queryable)
225+
.Field(x => x.SubType, IndexingType.PropertyType);
226+
227+
repository.ConfigurePropertyType<ExampleClassObject.SubType1>()
228+
.Field(x => x.One, IndexingType.Searchable)
229+
.Field(x => x.Two, IndexingType.Queryable);
230+
231+
var exampleData = new ExampleClassObject
232+
{
233+
FirstName = "First",
234+
LastName = "Last",
235+
Age = 99,
236+
SubType = new ExampleClassObject.SubType1
237+
{
238+
One = "one",
239+
Two = 13
240+
}
241+
};
242+
243+
var expectedJsonString = BuildExpectedContentJsonString(x => x.ToString(), exampleData);
244+
245+
var content = new StringContent(expectedJsonString, Encoding.UTF8, "application/json");
246+
247+
var response = new HttpResponseMessage(HttpStatusCode.OK);
248+
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/content/v2/data?id={source}") { Content = content };
249+
250+
var expectedApiResponse = new ContentV2ApiResponse { JournalId = "stream/id" };
251+
252+
mockRestClient.Setup(c => c.SendAsync(It.IsAny<HttpRequestMessage>())).ReturnsAsync(response);
253+
mockRestClient.Setup(c => c.HandleResponse<ContentV2ApiResponse>(response)).ReturnsAsync(expectedApiResponse);
254+
255+
// Act
256+
var actualJournalId = await repository.SaveContentAsync(generateId: (x) => x.ToString(), exampleData);
257+
258+
// Assert
259+
Assert.AreEqual(expectedApiResponse.JournalId, actualJournalId);
260+
mockRestClient.Verify(c => c.SendAsync(It.Is<HttpRequestMessage>(x => Compare(request, x))), Times.Once);
261+
mockRestClient.Verify(c => c.HandleResponse<ContentV2ApiResponse>(response), Times.Once);
214262
mockRestClient.VerifyAll();
215263
}
216264

@@ -284,11 +332,11 @@ public async Task SaveContentAsync_WithMultipleTypes_ShouldGenerateJsonForConten
284332
{""index"":{""_id"":""Location-London"",""language_routing"":""en""}}
285333
{""Status$$String"":""Published"",""__typename"":""Location"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Location""],""Language"":{""Name$$String"":""en""},""Longitude$$Float"":0.1275,""Latitude$$Float"":51.5072,""Name$$String___searchable"":""London""}
286334
{""index"":{""_id"":""Event-Future of Project Management"",""language_routing"":""en""}}
287-
{""Status$$String"":""Published"",""__typename"":""Event"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Event""],""Language"":{""Name$$String"":""en""},""LocationName$$String"":""Stockholm"",""Time$$DateTime"":""2024-10-21T22:00:00Z"",""Name$$String___searchable"":""Future of Project Management"",""AdditionalInfo"":{""Example1$$String___skip"":""test1"",""Example2$$Int"":1}}
335+
{""Status$$String"":""Published"",""__typename"":""Event"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Event""],""Language"":{""Name$$String"":""en""},""LocationName$$String"":""Stockholm"",""Time$$DateTime"":""2024-10-22T04:00:00Z"",""Name$$String___searchable"":""Future of Project Management"",""AdditionalInfo"":{""Example1$$String___skip"":""test1"",""Example2$$Int"":1}}
288336
{""index"":{""_id"":""Event-Week of Hope: Football Camp for Homeless Children in Hanoi!"",""language_routing"":""en""}}
289-
{""Status$$String"":""Published"",""__typename"":""Event"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Event""],""Language"":{""Name$$String"":""en""},""LocationName$$String"":""Hanoi"",""Time$$DateTime"":""2024-10-26T22:00:00Z"",""Name$$String___searchable"":""Week of Hope: Football Camp for Homeless Children in Hanoi!"",""AdditionalInfo"":{""Example1$$String___skip"":""test2"",""Example2$$Int"":2}}
337+
{""Status$$String"":""Published"",""__typename"":""Event"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Event""],""Language"":{""Name$$String"":""en""},""LocationName$$String"":""Hanoi"",""Time$$DateTime"":""2024-10-27T04:00:00Z"",""Name$$String___searchable"":""Week of Hope: Football Camp for Homeless Children in Hanoi!"",""AdditionalInfo"":{""Example1$$String___skip"":""test2"",""Example2$$Int"":2}}
290338
{""index"":{""_id"":""Event-Optimizing Project Management: Strategies for Success"",""language_routing"":""en""}}
291-
{""Status$$String"":""Published"",""__typename"":""Event"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Event""],""Language"":{""Name$$String"":""en""},""LocationName$$String"":""London"",""Time$$DateTime"":""2024-11-02T23:00:00Z"",""Name$$String___searchable"":""Optimizing Project Management: Strategies for Success"",""AdditionalInfo"":{""Example1$$String___skip"":""test3"",""Example2$$Int"":3}}
339+
{""Status$$String"":""Published"",""__typename"":""Event"",""_rbac"":""r:Everyone:Read"",""ContentType$$String"":[""Event""],""Language"":{""Name$$String"":""en""},""LocationName$$String"":""London"",""Time$$DateTime"":""2024-11-03T04:00:00Z"",""Name$$String___searchable"":""Optimizing Project Management: Strategies for Success"",""AdditionalInfo"":{""Example1$$String___skip"":""test3"",""Example2$$Int"":3}}
292340
";
293341

294342
Func<object, string> generateId = (x) =>
@@ -313,16 +361,16 @@ public async Task SaveContentAsync_WithMultipleTypes_ShouldGenerateJsonForConten
313361
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/content/v2/data?id={source}") { Content = content };
314362

315363
mockRestClient.Setup(c => c.SendAsync(It.IsAny<HttpRequestMessage>())).ReturnsAsync(response);
316-
mockRestClient.Setup(c => c.HandleResponse(response));
364+
mockRestClient.Setup(c => c.HandleResponse<ContentV2ApiResponse>(response));
317365

318366
// Act
319-
await repository.SaveContentAsync<object>(generateId, locationStockholm, locationLondon, event1, event2, event3);
367+
await repository.SaveContentAsync<object>(generateId, "en", locationStockholm, locationLondon, event1, event2, event3);
320368

321369
// Assert
322370
Assert.AreEqual(expectedJsonString, jsonString);
323371

324372
mockRestClient.Verify(c => c.SendAsync(It.Is<HttpRequestMessage>(x => Compare(request, x))), Times.Once);
325-
mockRestClient.Verify(c => c.HandleResponse(response), Times.Once);
373+
mockRestClient.Verify(c => c.HandleResponse<ContentV2ApiResponse>(response), Times.Once);
326374
mockRestClient.VerifyAll();
327375
}
328376

@@ -353,7 +401,7 @@ public async Task CreateContent_ShouldContainTwoNewLines()
353401
};
354402

355403
// Act
356-
var createdContent = repository.CreateContent(generateId: (x) => x.ToString(), exampleData);
404+
var createdContent = repository.CreateContent(generateId: (x) => x.ToString(), "en", exampleData);
357405
var result = createdContent.ReadAsStringAsync().Result;
358406

359407
// Assert
@@ -387,7 +435,7 @@ public async Task CreateContent_ShouldProduceMinifiedContent()
387435
};
388436

389437
// Act
390-
var createdContent = repository.CreateContent(generateId: (x) => x.ToString(), exampleData);
438+
var createdContent = repository.CreateContent(generateId: (x) => x.ToString(), "en", exampleData);
391439
var result = createdContent.ReadAsStringAsync().Result;
392440

393441
// Assert

Optimizely.Graph.Source.Sdk/Optimizely.Graph.Source.Sdk/GraphSourceClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ public async Task<string> SaveTypesAsync()
8989
/// <param name="generateId">Id associated with content.</param>
9090
/// <param name="data">Dynamic data being saved to Content Graph.</param>
9191
/// <returns></returns>
92-
public async Task<string> SaveContentAsync<T>(Func<T, string> generateId, params T[] data)
92+
public async Task<string> SaveContentAsync<T>(Func<T, string> generateId, string language, params T[] data)
9393
where T : class, new()
9494
{
95-
return await repository.SaveContentAsync(generateId, data);
95+
return await repository.SaveContentAsync(generateId, language, data);
9696
}
9797

9898
/// <summary>

Optimizely.Graph.Source.Sdk/Optimizely.Graph.Source.Sdk/Repositories/GraphSourceRepository.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,23 +81,19 @@ public async Task<string> SaveTypesAsync()
8181
}
8282

8383
/// <inheritdoc/>
84-
public async Task<string> SaveContentAsync<T>(Func<T, string> generateId, params T[] data)
84+
public async Task<string> SaveContentAsync<T>(Func<T, string> generateId, string language, params T[] data)
8585
where T : class, new()
8686
{
87-
var content = CreateContent(generateId, data);
87+
var content = CreateContent(generateId, language, data);
8888

89-
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, $"{DataUrl}?id={source}"))
90-
{
91-
requestMessage.Content = content;
92-
using (var responseMessage = await client.SendAsync(requestMessage))
93-
{
94-
await client.HandleResponse(responseMessage);
95-
}
96-
}
97-
return string.Empty;
89+
using var requestMessage = new HttpRequestMessage(HttpMethod.Post, $"{DataUrl}?id={source}");
90+
requestMessage.Content = content;
91+
using var responseMessage = await client.SendAsync(requestMessage);
92+
var response = await client.HandleResponse<ContentV2ApiResponse>(responseMessage);
93+
return response?.JournalId ?? string.Empty;
9894
}
9995

100-
public StringContent CreateContent<T>(Func<T, string> generateId, params T[] data)
96+
public StringContent CreateContent<T>(Func<T, string> generateId, string language, params T[] data)
10197
{
10298
var serializeOptions = new JsonSerializerOptions
10399
{
@@ -112,7 +108,6 @@ public StringContent CreateContent<T>(Func<T, string> generateId, params T[] dat
112108
foreach (var item in data)
113109
{
114110
var id = generateId(item);
115-
var language = "en";
116111

117112
itemJson += $"{{\"index\":{{\"_id\":\"{id}\",\"language_routing\":\"{language}\"}}}}";
118113
itemJson += Environment.NewLine;

Optimizely.Graph.Source.Sdk/Optimizely.Graph.Source.Sdk/Repositories/IGraphSourceRepository.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public interface IGraphSourceRepository
4040
/// <param name="generateId">Id associated with content.</param>
4141
/// <param name="data">Dynamic data being saved to Content Graph.</param>
4242
/// <returns></returns>
43-
Task<string> SaveContentAsync<T>(Func<T, string> generateId, params T[] data) where T : class, new();
43+
Task<string> SaveContentAsync<T>(Func<T, string> generateId, string language, params T[] data) where T : class, new();
4444

4545
/// <summary>
4646
/// Removes content previously stored by source.
@@ -54,4 +54,4 @@ public interface IGraphSourceRepository
5454
/// <returns></returns>
5555
Task<string> DeleteContentItemsAsync(string language, params string[] ids);
5656
}
57-
}
57+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ContentV2ApiResponse
2+
{
3+
public string JournalId { get; set; }
4+
}

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ You can find more information https://docs.developers.optimizely.com/platform-op
1616

1717
You can use the client by calling `Create()` and providing your base url, Content Graph source, application key and secret, then calling one of the provided functions for synchronizing Content Types and Content Data.
1818

19+
#### Sync Content Types
1920
```csharp
2021
// Initialize the GraphSourceClient by calling the Create method
2122
var client = GraphSourceClient.Create(new Uri("https://cg.optimizely.com"), "", "", "");
@@ -57,6 +58,26 @@ client.ConfigurePropertyType<ExampleClassObject.SubType1>()
5758
var result = await graphSourceClient.SaveTypesAsync();
5859
```
5960

61+
#### Sync Content
62+
```csharp
63+
// Instantiate custom C# object and assign values
64+
var exampleData = new ExampleClassObject
65+
{
66+
FirstName = "First",
67+
LastName = "Last",
68+
Age = 30,
69+
SubType = new SubType1
70+
{
71+
One = "One",
72+
Two = 2,
73+
}
74+
};
75+
76+
// Use the client to sync content
77+
// Parameters are generated id, language, and data object
78+
await client.SaveContentAsync(generateId: (x) => $"{x.FirstName}_{x.LastName}", "en", exampleData);
79+
```
80+
6081
## Run Examples
6182
In visual studio, set your startup project to the Optimizely.Graph.Source.Sdk.Sample project.
6283

0 commit comments

Comments
 (0)