public void Remove_ElementInCollection_ReturnsTrue()
        {
            // Setup
            var elementToBeRemoved = new TestItem("Item X");

            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);
            var expectedCollections = new[]
            {
                new TestItem("Item A"),
                new TestItem("Item B"),
                new TestItem("Item C"),
                new TestItem("Item D")
            };

            collection.AddRange(expectedCollections.Concat(new[]
            {
                elementToBeRemoved
            }), "path");

            // Call
            bool removeSuccessful = collection.Remove(elementToBeRemoved);

            // Assert
            Assert.IsTrue(removeSuccessful);
            CollectionAssert.AreEqual(expectedCollections, collection);
        }
        public void NotifyObservers_MultipleObserversDetachingOrAttachingOthers_NoUpdatesForAttachedAndDetachedObservers()
        {
            // Setup
            var mocks = new MockRepository();
            var observableCollection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            var observer1 = mocks.Stub <IObserver>();
            var observer2 = mocks.Stub <IObserver>();
            var observer3 = mocks.Stub <IObserver>();
            var observer4 = mocks.Stub <IObserver>();
            var observer5 = mocks.Stub <IObserver>();
            var observer6 = mocks.Stub <IObserver>();

            observableCollection.Attach(observer1);
            observableCollection.Attach(observer2);
            observableCollection.Attach(observer3);
            observableCollection.Attach(observer4);
            observableCollection.Attach(observer6);

            observer1.Expect(o => o.UpdateObserver());
            observer2.Expect(o => o.UpdateObserver()).Do((Action)(() => observableCollection.Detach(observer3)));
            observer3.Expect(o => o.UpdateObserver()).Repeat.Never(); // A detached observer should no longer be updated
            observer4.Expect(o => o.UpdateObserver()).Do((Action)(() => observableCollection.Attach(observer5)));
            observer5.Expect(o => o.UpdateObserver()).Repeat.Never(); // An attached observer should not be updated too
            observer6.Expect(o => o.UpdateObserver());

            mocks.ReplayAll();

            // Call
            observableCollection.NotifyObservers();

            // Assert
            mocks.VerifyAll();
        }
        public void GivenCollectionWithItems_WhenAddRangeWithItemsAlreadyInCollection_ThenThrowsArgumentException()
        {
            // Given
            const string filePath   = "some/file/path";
            var          collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            const string duplicateNameOne   = "Item A";
            const string duplicateNameTwo   = "Item B";
            var          expectedCollection = new[]
            {
                new TestItem(duplicateNameOne),
                new TestItem(duplicateNameTwo),
                new TestItem("Item C"),
                new TestItem("Item D")
            };

            collection.AddRange(expectedCollection, filePath);

            // When
            TestDelegate call = () => collection.AddRange(new[]
            {
                new TestItem(duplicateNameOne),
                new TestItem(duplicateNameTwo)
            }, "other/path");

            // Then
            string message = $"TestItems moeten een unieke Feature hebben. Gevonden dubbele elementen: {duplicateNameOne}, {duplicateNameTwo}.";

            TestHelper.AssertThrowsArgumentExceptionAndTestMessage <ArgumentException>(call, message);
            CollectionAssert.AreEqual(expectedCollection, collection);
            Assert.AreEqual(filePath, collection.SourcePath);
        }
        public void AddRange_AddMultipleDuplicateItems_ThrowsArgumentException()
        {
            // Setup
            const string duplicateNameOne = "Duplicate name it is";
            const string duplicateNameTwo = "Duplicate name again";

            var itemsToAdd = new[]
            {
                new TestItem(duplicateNameOne),
                new TestItem(duplicateNameOne),
                new TestItem(duplicateNameTwo),
                new TestItem(duplicateNameTwo)
            };

            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            // Call
            TestDelegate call = () => collection.AddRange(itemsToAdd, "some/path");

            // Assert
            string message = $"TestItems moeten een unieke Feature hebben. Gevonden dubbele elementen: {duplicateNameOne}, {duplicateNameTwo}.";

            TestHelper.AssertThrowsArgumentExceptionAndTestMessage <ArgumentException>(call, message);
        }
        public void DefaultConstructor_ReturnObservableUniqueItemCollectionWithSourcePath()
        {
            // Call
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            // Assert
            Assert.IsInstanceOf <Observable>(collection);
            Assert.IsNull(collection.SourcePath);
            Assert.AreEqual(0, collection.Count);
            CollectionAssert.IsEmpty(collection);
        }
        public void AddRange_ItemsNull_ThrowArgumentNullException()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            // Call
            TestDelegate call = () => collection.AddRange(null, "path");

            // Assert
            string paramName = Assert.Throws <ArgumentNullException>(call).ParamName;

            Assert.AreEqual("items", paramName);
        }
        public void Indexer_GetItemAtIndexOutOfRange_ThrowsArgumentOutOfRangeException(int invalidIndex)
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            // Call
            TestDelegate call = () =>
            {
                object item = collection[invalidIndex];
            };

            // Assert
            Assert.Throws <ArgumentOutOfRangeException>(call);
        }
        public void AddRange_NotAnActualFilePath_ThrowArgumentNull()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            const string invalidFilePath = @"            ";

            // Call
            TestDelegate call = () => collection.AddRange(Enumerable.Empty <TestItem>(), invalidFilePath);

            // Assert
            string message   = $"'{invalidFilePath}' is not a valid file path.";
            string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage <ArgumentException>(call, message).ParamName;

            Assert.AreEqual("filePath", paramName);
        }
        public void AddRange_AddNewItem_CollectionContainsItem()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);
            var item = new TestItem("Item A");

            // Call
            const string filePath = "some/file/path";

            collection.AddRange(new[]
            {
                item
            }, filePath);

            // Assert
            CollectionAssert.Contains(collection, item);
            Assert.AreEqual(filePath, collection.SourcePath);
        }
        public void NotifyObserver_AttachedObserverDetachedAgain_ObserverNoLongerNotified()
        {
            // Setup
            var mocks    = new MockRepository();
            var observer = mocks.StrictMock <IObserver>();

            mocks.ReplayAll();

            var observableCollection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            observableCollection.Attach(observer);
            observableCollection.Detach(observer);

            // Call
            observableCollection.NotifyObservers();

            // Assert
            mocks.VerifyAll(); // Expect no calls on 'observer'
        }
        public void Count_CollectionFilledWithElements_ReturnsExpectedNumberOfElements()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            collection.AddRange(new[]
            {
                new TestItem("Item A"),
                new TestItem("Item B"),
                new TestItem("Item C"),
                new TestItem("Item D")
            }, "path");

            // Call
            int nrOfElements = collection.Count;

            // Assert
            Assert.AreEqual(4, nrOfElements);
        }
        public void NotifyObservers_WithObserverAttached_ObserverIsNotified()
        {
            // Setup
            var mocks    = new MockRepository();
            var observer = mocks.StrictMock <IObserver>();

            observer.Expect(o => o.UpdateObserver()); // Expect to be called once
            mocks.ReplayAll();

            var observableCollection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            observableCollection.Attach(observer);

            // Call
            observableCollection.NotifyObservers();

            // Assert
            mocks.VerifyAll();
        }
        public void AddRange_ItemsHasNullElement_ThrowArgumentException()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);
            var items = new[]
            {
                new TestItem("Item A"),
                null,
                new TestItem("Item B")
            };

            // Call
            TestDelegate call = () => collection.AddRange(items, "path");

            // Assert
            const string message   = "Collection cannot contain null.";
            string       paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage <ArgumentException>(call, message).ParamName;

            Assert.AreEqual("items", paramName);
        }
        public void Indexer_GetElementAtIndex_ReturnsExpectedElement()
        {
            // Setup
            var elementToRetrieve = new TestItem("Item X");
            var collection        = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            collection.AddRange(new[]
            {
                new TestItem("Item A"),
                new TestItem("Item B"),
                new TestItem("Item C"),
                new TestItem("Item D"),
                elementToRetrieve
            }, "path");

            // Call
            object retrievedElement = collection[4];

            // Assert
            Assert.AreSame(elementToRetrieve, retrievedElement);
        }
        public void Remove_RemoveLastElement_ReturnsTrueAndClearSourcePath()
        {
            // Setup
            var elementToBeRemoved = new TestItem("Item X");
            var collection         = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);

            collection.AddRange(new[]
            {
                elementToBeRemoved
            }, "path");

            // Precondition
            Assert.IsNotNull(collection.SourcePath);

            // Call
            bool removeSuccessful = collection.Remove(elementToBeRemoved);

            // Assert
            Assert.IsTrue(removeSuccessful);
            Assert.IsNull(collection.SourcePath);
        }
        public void AddRange_AddingNewItems_CollectionContainsExpectedElements()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);
            var expectedCollection = new[]
            {
                new TestItem("Item A"),
                new TestItem("Item B"),
                new TestItem("Item C"),
                new TestItem("Item D")
            };

            const string filePath = "some/file/path";

            // Call
            collection.AddRange(expectedCollection, filePath);

            // Assert
            CollectionAssert.AreEqual(expectedCollection, collection);
            Assert.AreEqual(filePath, collection.SourcePath);
        }
        public void Clear_CollectionFullyDefined_ClearsSourcePathAndCollection()
        {
            // Setup
            var collection = new ConcreteObservableUniqueItemCollectionWithSourcePath <TestItem>(
                getUniqueFeature, typeDescriptor, featureDescription);
            var expectedObjectCollection = new[]
            {
                new TestItem("Item A"),
                new TestItem("Item B"),
                new TestItem("Item C"),
                new TestItem("Item D")
            };

            collection.AddRange(expectedObjectCollection, "path");

            // Call
            collection.Clear();

            // Assert
            Assert.IsNull(collection.SourcePath);
            Assert.AreEqual(0, collection.Count);
            CollectionAssert.IsEmpty(collection);
        }