Skip to content

Commit 646eb92

Browse files
committed
Merge branch 'bugfix/PermittedContentTypes-tests' into develop
To better reflect real-world conditions, the `StubTopicRepository` was set to treat all topics as "saved"—i.e., by assigning them an `Id`. Most of the topics already had an `Id` set, but not the `ContentTypeDescriptors`. This exposed two bugs. The first bug was simply an issue with the unit test; the `TopicMappingService` cached view models based on their `Topic.Id`, and so `IsNew` topics aren't cached; when these were migrated to "saved" topics, a circular reference in the test case was exposed which failed to adequately test associations of associations (#82). The second bug fix was due to an underlying problem in the `TopicRepository.Save()`. This test confirmed that the `PermittedContentTypes` were refreshed after a `ContentTypeDescriptor` with updated relationships was saved. The problem is that it evaluated if the relationships were dirty _after_ the topic had been saved—and marked as clean. As such, the relationships should _never_ be dirty. This issue was obscured by the `IsNew` content types because a relationship cannot be marked clean if it still references `IsNew` topics, since in a real-world scenario, only relationships to saved topics can be persisted. This is easily fixed by evaluating the `Topic.Relationships.IsDirty()` state prior to marking the collection as saved. This resolved #81.
2 parents 7fc9436 + f6a479b commit 646eb92

3 files changed

Lines changed: 24 additions & 20 deletions

File tree

OnTopic.TestDoubles/StubTopicRepository.cs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -234,21 +234,21 @@ private Topic CreateFakeData() {
234234
/*------------------------------------------------------------------------------------------------------------------------
235235
| Establish root
236236
\-----------------------------------------------------------------------------------------------------------------------*/
237-
var rootTopic = new Topic("Root", "Container", null, 900);
238237
var currentAttributeId = 800;
238+
var rootTopic = new Topic("Root", "Container", null, currentAttributeId++);
239239

240240
/*------------------------------------------------------------------------------------------------------------------------
241241
| Establish configuration
242242
\-----------------------------------------------------------------------------------------------------------------------*/
243-
var configuration = new Topic("Configuration", "Container", rootTopic);
244-
var contentTypes = new ContentTypeDescriptor("ContentTypes", "ContentTypeDescriptor", configuration);
243+
var configuration = new Topic("Configuration", "Container", rootTopic, currentAttributeId++);
244+
var contentTypes = new ContentTypeDescriptor("ContentTypes", "ContentTypeDescriptor", configuration, currentAttributeId++);
245245

246246
addAttribute(contentTypes, "Key", "TextAttributeDescriptor", false, true);
247247
addAttribute(contentTypes, "ContentType", "TextAttributeDescriptor", false, true);
248248
addAttribute(contentTypes, "Title", "TextAttributeDescriptor", true, true);
249249
addAttribute(contentTypes, "BaseTopic", "TopicReferenceAttributeDescriptor", false);
250250

251-
var contentTypeDescriptor = new ContentTypeDescriptor("ContentTypeDescriptor", "ContentTypeDescriptor", contentTypes);
251+
var contentTypeDescriptor = new ContentTypeDescriptor("ContentTypeDescriptor", "ContentTypeDescriptor", contentTypes, currentAttributeId++);
252252

253253
addAttribute(contentTypeDescriptor, "ContentTypes", "RelationshipAttributeDescriptor");
254254
addAttribute(contentTypeDescriptor, "Attributes", "NestedTopicListAttributeDescriptor");
@@ -258,7 +258,7 @@ private Topic CreateFakeData() {
258258
TopicFactory.Create("LookupListItem", "ContentTypeDescriptor", contentTypes);
259259
TopicFactory.Create("List", "ContentTypeDescriptor", contentTypes);
260260

261-
var attributeDescriptor = new ContentTypeDescriptor("AttributeDescriptor", "ContentTypeDescriptor", contentTypes);
261+
var attributeDescriptor = new ContentTypeDescriptor("AttributeDescriptor", "ContentTypeDescriptor", contentTypes, currentAttributeId++);
262262

263263
addAttribute(attributeDescriptor, "DefaultValue", "TextAttributeDescriptor", false, true);
264264
addAttribute(attributeDescriptor, "IsRequired", "TextAttributeDescriptor", false, true);
@@ -270,22 +270,23 @@ private Topic CreateFakeData() {
270270
TopicFactory.Create("TextAttributeDescriptor", "ContentTypeDescriptor", attributeDescriptor);
271271
TopicFactory.Create("TopicReferenceAttributeDescriptor", "ContentTypeDescriptor", attributeDescriptor);
272272

273-
var pageContentType = new ContentTypeDescriptor("Page", "ContentTypeDescriptor", contentTypes);
273+
var pageContentType = new ContentTypeDescriptor("Page", "ContentTypeDescriptor", contentTypes, currentAttributeId++);
274274

275275
addAttribute(pageContentType, "MetaTitle");
276276
addAttribute(pageContentType, "MetaDescription");
277277
addAttribute(pageContentType, "IsHidden", "TextAttributeDescriptor", false);
278278
addAttribute(pageContentType, "TopicReference", "TopicReferenceAttributeDescriptor", false);
279279

280-
pageContentType.Relationships.SetValue("ContentTypes", pageContentType);
281-
pageContentType.Relationships.SetValue("ContentTypes", contentTypeDescriptor);
282-
283-
var contactContentType = new ContentTypeDescriptor("Contact", "ContentTypeDescriptor", contentTypes);
280+
var contactContentType = new ContentTypeDescriptor("Contact", "ContentTypeDescriptor", contentTypes, currentAttributeId++);
284281

285282
addAttribute(contactContentType, "Name", isExtended: false);
286283
addAttribute(contactContentType, "AlternateEmail", isExtended: false);
287284
addAttribute(contactContentType, "BillingContactEmail", isExtended: false);
288285

286+
pageContentType.Relationships.SetValue("ContentTypes", pageContentType);
287+
pageContentType.Relationships.SetValue("ContentTypes", contactContentType);
288+
contactContentType.Relationships.SetValue("ContentTypes", pageContentType);
289+
289290
/*------------------------------------------------------------------------------------------------------------------------
290291
| Local addAttribute() helper function
291292
\-----------------------------------------------------------------------------------------------------------------------*/
@@ -310,9 +311,9 @@ AttributeDescriptor addAttribute(
310311
/*------------------------------------------------------------------------------------------------------------------------
311312
| Establish metadata
312313
\-----------------------------------------------------------------------------------------------------------------------*/
313-
var metadata = new Topic("Metadata", "Container", configuration);
314-
var categories = new Topic("Categories", "Lookup", metadata);
315-
var lookup = new Topic("LookupList", "List", categories);
314+
var metadata = new Topic("Metadata", "Container", configuration, currentAttributeId++);
315+
var categories = new Topic("Categories", "Lookup", metadata, currentAttributeId++);
316+
var lookup = new Topic("LookupList", "List", categories, currentAttributeId++);
316317

317318
for (var i=1; i<=5; i++) {
318319
_ = new Topic("Category" + i, "LookupListItem", lookup);
@@ -325,10 +326,10 @@ AttributeDescriptor addAttribute(
325326

326327
CreateFakeData(web, 2, 3);
327328

328-
var pageGroup = new Topic("Web_3", "PageGroup", web);
329-
_ = new Topic("Web_3_0", "Page", pageGroup);
330-
var childPage = new Topic("Web_3_1", "Page", pageGroup);
331-
var leafPage = new Topic("Web_3_1_0", "Page", childPage);
329+
var pageGroup = new Topic("Web_3", "PageGroup", web, currentAttributeId++);
330+
_ = new Topic("Web_3_0", "Page", pageGroup, currentAttributeId++);
331+
var childPage = new Topic("Web_3_1", "Page", pageGroup, currentAttributeId++);
332+
var leafPage = new Topic("Web_3_1_0", "Page", childPage, currentAttributeId++);
332333

333334
leafPage.Attributes.SetValue("NavigationRoot", "Configuration");
334335

OnTopic.Tests/TopicMappingServiceTest.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,14 +680,16 @@ public async Task Map_AlternateRelationship_ReturnsCorrectRelationship() {
680680
[Fact]
681681
public async Task Map_CustomCollection_ReturnsCollection() {
682682

683-
var topic = _topicRepository.Load("Root:Configuration:ContentTypes:Page");
683+
var topic = (ContentTypeDescriptor)_topicRepository.Load("Root:Configuration:ContentTypes:Page");
684684
var target = await _mappingService.MapAsync<ContentTypeDescriptorTopicViewModel>(topic).ConfigureAwait(false);
685685

686686
Assert.Equal<int?>(8, target?.AttributeDescriptors.Count);
687687
Assert.Equal<int?>(2, target?.PermittedContentTypes.Count);
688688

689689
//Ensure custom collections are not recursively followed without instruction
690-
Assert.Empty(target?.PermittedContentTypes.FirstOrDefault()?.PermittedContentTypes);
690+
Assert.NotEqual<Topic?>(topic, topic?.PermittedContentTypes.LastOrDefault());
691+
Assert.NotEmpty(topic?.PermittedContentTypes.LastOrDefault()?.PermittedContentTypes);
692+
Assert.Empty(target?.PermittedContentTypes.LastOrDefault()?.PermittedContentTypes);
691693

692694
}
693695

OnTopic/Repositories/TopicRepository.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ private void Save([NotNull]Topic topic, bool isRecursive, TopicCollection unreso
327327
| Establish variables
328328
\-----------------------------------------------------------------------------------------------------------------------*/
329329
var isNew = topic.IsNew;
330+
var areRelationshipsDirty = topic.Relationships.IsDirty();
330331

331332
/*------------------------------------------------------------------------------------------------------------------------
332333
| Validate content type
@@ -405,7 +406,7 @@ _contentTypeDescriptors is not null &&
405406
/*------------------------------------------------------------------------------------------------------------------------
406407
| If content type, and relationships have been updated, refresh permitted content types
407408
\-----------------------------------------------------------------------------------------------------------------------*/
408-
if (asContentType is not null && asContentType.Relationships.IsDirty()) {
409+
if (asContentType is not null && areRelationshipsDirty) {
409410
asContentType.ResetPermittedContentTypes();
410411
}
411412

0 commit comments

Comments
 (0)