diff --git a/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs index 49c81ffd..da5e0f27 100644 --- a/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs +++ b/src/TestCentric/testcentric.gui/Dialogs/CategoryFilterDialog.cs @@ -64,6 +64,18 @@ internal void Init(IEnumerable allCategories, IEnumerable select checkedListBoxCategory.ResumeLayout(); } + internal void UpdateCheckedItems(IEnumerable selectedCategories) + { + checkedListBoxCategory.SuspendLayout(); + for (int i = 0; i < checkedListBoxCategory.Items.Count; i++) + { + string category = checkedListBoxCategory.Items[i].ToString(); + bool isChecked = selectedCategories.Contains(category); + checkedListBoxCategory.SetItemChecked(i, isChecked); + } + checkedListBoxCategory.ResumeLayout(); + } + private void OnApplyAndCloseButtonClicked(object sender, EventArgs e) { ApplyButtonClicked?.Invoke(SelectedCategories); diff --git a/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs b/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs index 49aaf385..250812d3 100644 --- a/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs +++ b/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripCategoryFilterButton.cs @@ -44,6 +44,10 @@ public IEnumerable SelectedItems { _selectedItems = value; UpdateFont(); + + // If dialog is currently displayed => updated checked items + if (_dialog != null) + _dialog.UpdateCheckedItems(_selectedItems); } } @@ -79,7 +83,8 @@ protected void OnButtonClicked(object sender, EventArgs e) _dialog.ApplyButtonClicked += (selectedItems) => { - SelectedItems = selectedItems; + _selectedItems = selectedItems; + UpdateFont(); SelectionChanged?.Invoke(); }; @@ -103,7 +108,7 @@ private void SetDialogSizeAndPosition() { // Restore previous position and size of dialog _dialog.Size = _dialogSize; - _dialogLocation = _dialog.Location; + _dialog.Location = _dialogLocation; } else { diff --git a/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripTextBoxElement.cs b/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripTextBoxElement.cs index 787c2d27..40cd18ee 100644 --- a/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripTextBoxElement.cs +++ b/src/TestCentric/testcentric.gui/Elements/ToolStripElements/ToolStripTextBoxElement.cs @@ -25,7 +25,7 @@ public ToolStripTextBoxElement(ToolStripTextBox textBox, string placeHolderText) { TextBox = textBox; PlaceHolderText = placeHolderText; - TextBox.TextChanged += OnTextChanged; + TextBox.KeyUp += OnKeyUp; TextBox.LostFocus += OnTextBoxLostFocus; TextBox.GotFocus += OnTextBoxGotFocus; @@ -63,7 +63,11 @@ private void OnTextBoxLostFocus(object sender, EventArgs e) } } - private void OnTextChanged(object sender, EventArgs e) + /// + /// Use KeyUp event instead of TextChanged event + /// If the Text property is set from client programmatically, a TextChanged event would be triggered => that's not intended + /// + private void OnKeyUp(object sender, KeyEventArgs e) { if (IsPlaceHolderTextShown) return; diff --git a/src/TestCentric/testcentric.gui/Images/ResetFilter.png b/src/TestCentric/testcentric.gui/Images/ResetFilter.png new file mode 100644 index 00000000..8b3bf614 Binary files /dev/null and b/src/TestCentric/testcentric.gui/Images/ResetFilter.png differ diff --git a/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs b/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs index 044b34c7..76610d84 100644 --- a/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs +++ b/src/TestCentric/testcentric.gui/Presenters/TreeViewPresenter.cs @@ -72,6 +72,7 @@ private void WireUpEvents() _model.Events.TestReloaded += (ea) => { EnsureNonRunnableFilesAreVisible(ea.Test); + ResetTestFilterUIElements(); Strategy.OnTestLoaded(ea.Test, null); _view.CheckBoxes = _view.ShowCheckBoxes.Checked; // TODO: View should handle this @@ -81,6 +82,7 @@ private void WireUpEvents() { Strategy.OnTestUnloaded(); _view.CategoryFilter.Close(); + ResetTestFilterUIElements(); }; _model.Events.TestsUnloading += ea => @@ -272,6 +274,8 @@ private void WireUpEvents() _model.TestCentricTestFilter.CategoryFilter = _view.CategoryFilter.SelectedItems; }; + _view.ResetFilterCommand.Execute += () => ResetTestFilter(); + // Node selected in tree //_treeView.SelectedNodesChanged += (nodes) => //{ @@ -302,6 +306,18 @@ private void WireUpEvents() //}; } + private void ResetTestFilter() + { + _model.TestCentricTestFilter.ResetAll(); + ResetTestFilterUIElements(); + } + + private void ResetTestFilterUIElements() + { + _view.TextFilter.Text = ""; + _view.OutcomeFilter.SelectedItems = _model.TestCentricTestFilter.OutcomeFilter; + _view.CategoryFilter.SelectedItems = _model.TestCentricTestFilter.CategoryFilter; + } private void UpdateTreeViewSortMode() { var sortMode = _view.SortCommand.SelectedItem; diff --git a/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs b/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs index 6fe29fbf..e80988da 100644 --- a/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs +++ b/src/TestCentric/testcentric.gui/Views/ITestTreeView.cs @@ -61,6 +61,8 @@ public interface ITestTreeView : IView ICategoryFilterSelection CategoryFilter { get; } + ICommand ResetFilterCommand { get; } + void SetTestFilterVisibility(bool visible); void EnableTestFilter(bool enable); diff --git a/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs b/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs index 86f824e8..c9a0894b 100644 --- a/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs +++ b/src/TestCentric/testcentric.gui/Views/TestTreeView.Designer.cs @@ -43,6 +43,7 @@ private void InitializeComponent() this.filterTextBox = new StretchToolStripTextBox(); this.filterSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.filterByCategory = new System.Windows.Forms.ToolStripDropDownButton(); + this.filterResetButton = new System.Windows.Forms.ToolStripButton(); this.testTreeContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.runMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -134,6 +135,14 @@ private void InitializeComponent() this.filterByCategory.Text = "Filter by category"; this.filterByCategory.ToolTipText = "Filter tests by category"; // + // filterResetButton + // + this.filterResetButton.Name = "filterResetButton"; + this.filterResetButton.Image = ((System.Drawing.Image)(resources.GetObject("ResetFilter.Image"))); + this.filterResetButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.filterResetButton.Size = new System.Drawing.Size(70, 29); + this.filterResetButton.ToolTipText = "Reset all filters"; + // // filterToolStrip // this.filterToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -144,6 +153,7 @@ private void InitializeComponent() this.filterOutcomeNotRunButton, this.filterSeparator1, this.filterByCategory, + this.filterResetButton, }); this.filterToolStrip.Location = new System.Drawing.Point(0, 0); this.filterToolStrip.Name = "filterToolStrip"; @@ -345,6 +355,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripButton filterOutcomeNotRunButton; private System.Windows.Forms.ToolStripSeparator filterSeparator1; private System.Windows.Forms.ToolStripDropDownButton filterByCategory; + private System.Windows.Forms.ToolStripButton filterResetButton; private System.Windows.Forms.ToolStrip filterTextToolStrip; private System.Windows.Forms.ToolStripTextBox filterTextBox; private System.Windows.Forms.ToolStripMenuItem runMenuItem; diff --git a/src/TestCentric/testcentric.gui/Views/TestTreeView.cs b/src/TestCentric/testcentric.gui/Views/TestTreeView.cs index b3748d3c..4811472a 100644 --- a/src/TestCentric/testcentric.gui/Views/TestTreeView.cs +++ b/src/TestCentric/testcentric.gui/Views/TestTreeView.cs @@ -54,6 +54,7 @@ public TestTreeView() OutcomeFilter = new MultiCheckedToolStripButtonGroup(new[] { filterOutcomePassedButton, filterOutcomeFailedButton, filterOutcomeWarningButton, filterOutcomeNotRunButton }); TextFilter = new ToolStripTextBoxElement(filterTextBox, "Filter..."); CategoryFilter = new ToolStripCategoryFilterButton(filterByCategory); + ResetFilterCommand = new ToolStripButtonElement(filterResetButton); TreeView = treeView; // NOTE: We use MouseDown here rather than MouseUp because @@ -135,6 +136,7 @@ public bool CheckBoxes public IMultiSelection OutcomeFilter { get; private set; } public ICategoryFilterSelection CategoryFilter { get; private set; } + public ICommand ResetFilterCommand { get; private set; } public IChanged TextFilter { get; private set; } diff --git a/src/TestCentric/testcentric.gui/Views/TestTreeView.resx b/src/TestCentric/testcentric.gui/Views/TestTreeView.resx index 615f9f90..97b350a9 100644 --- a/src/TestCentric/testcentric.gui/Views/TestTreeView.resx +++ b/src/TestCentric/testcentric.gui/Views/TestTreeView.resx @@ -117,6 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Images\ResetFilter.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + 186, 16 diff --git a/src/TestCentric/tests/Presenters/TestTree/TreeViewPresenterTests.cs b/src/TestCentric/tests/Presenters/TestTree/TreeViewPresenterTests.cs index 3f5b971b..a85995b6 100644 --- a/src/TestCentric/tests/Presenters/TestTree/TreeViewPresenterTests.cs +++ b/src/TestCentric/tests/Presenters/TestTree/TreeViewPresenterTests.cs @@ -314,6 +314,34 @@ public void SortChanged_ToDuration_ShowDuration_IsSet() _view.ShowTestDuration.Received().Checked = true; } + [Test] + public void ResetFilterCommand_TestCentricTestFilter_AreReset() + { + // 1. Arrange + _view.SortCommand.SelectedItem.Returns(TreeViewNodeComparer.Duration); + + // 2. Act + _view.ResetFilterCommand.Execute += Raise.Event(); + + // 3. Assert + _model.TestCentricTestFilter.Received().ResetAll(); + } + + [Test] + public void ResetFilterCommand_Filter_UIElements_AreReset() + { + // 1. Arrange + _view.SortCommand.SelectedItem.Returns(TreeViewNodeComparer.Duration); + + // 2. Act + _view.ResetFilterCommand.Execute += Raise.Event(); + + // 3. Assert + _view.TextFilter.Received().Text = ""; + _view.OutcomeFilter.ReceivedWithAnyArgs().SelectedItems = null; + _view.CategoryFilter.ReceivedWithAnyArgs().SelectedItems = null; + } + // TODO: Version 1 Test - Make it work if needed. //[Test] //public void WhenContextNodeIsNotNull_RunCommandExecutesThatTest() diff --git a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreReloaded.cs b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreReloaded.cs index 5e4a2feb..2a616535 100644 --- a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreReloaded.cs +++ b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreReloaded.cs @@ -13,18 +13,30 @@ namespace TestCentric.Gui.Presenters.TestTree public class WhenTestsAreReloaded : TreeViewPresenterTestBase { [SetUp] - public void SimulateTestReload() + public void Setup() { ClearAllReceivedCalls(); _model.HasTests.Returns(true); _model.IsTestRunning.Returns(false); + } + [Test] + public void TestFilters_IsReset() + { + // Arrange + var project = new TestCentricProject(_model, "dummy.dll"); TestNode testNode = new TestNode(""); _model.LoadedTests.Returns(testNode); - _model.TestCentricProject.Returns(new TestCentricProject(_model, "dummy.dll")); + _model.TestCentricProject.Returns(project); + // Act FireTestReloadedEvent(testNode); + + // Assert + _view.TextFilter.Received().Text = ""; + _view.OutcomeFilter.ReceivedWithAnyArgs().SelectedItems = null; + _view.CategoryFilter.ReceivedWithAnyArgs().SelectedItems = null; } #if NYI // Add after implementation of project or package saving diff --git a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs index aeedd62b..609b24ca 100644 --- a/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs +++ b/src/TestCentric/tests/Presenters/TestTree/WhenTestsAreUnloaded.cs @@ -33,6 +33,18 @@ public void TestUnloaded_CategoryFilter_IsClosed() _view.CategoryFilter.Received().Close(); } + [Test] + public void TestUnloaded_TestFilters_AreReset() + { + // Act: unload tests + FireTestUnloadedEvent(); + + // Assert + _view.TextFilter.Received().Text = ""; + _view.OutcomeFilter.ReceivedWithAnyArgs().SelectedItems = null; + _view.CategoryFilter.ReceivedWithAnyArgs().SelectedItems = null; + } + #if NYI // Add after implementation of project or package saving [TestCase("NewProjectCommand", true)] [TestCase("OpenProjectCommand", true)] diff --git a/src/TestModel/model/Filter/ITestCentricTestFilter.cs b/src/TestModel/model/Filter/ITestCentricTestFilter.cs index 370b19b9..8ed8933b 100644 --- a/src/TestModel/model/Filter/ITestCentricTestFilter.cs +++ b/src/TestModel/model/Filter/ITestCentricTestFilter.cs @@ -40,7 +40,7 @@ public interface ITestCentricTestFilter /// /// Clear all actives filters and reset them to default /// - void ClearAllFilters(); + void ResetAll(bool suppressFilterChangedEvent = false); /// /// Init filter after a project is loaded diff --git a/src/TestModel/model/Filter/TestCentricTestFilter.cs b/src/TestModel/model/Filter/TestCentricTestFilter.cs index 648344d9..76cb51f7 100644 --- a/src/TestModel/model/Filter/TestCentricTestFilter.cs +++ b/src/TestModel/model/Filter/TestCentricTestFilter.cs @@ -57,15 +57,18 @@ public IEnumerable AllCategories public bool IsActive => _filters.Any(x => x.IsActive); - public void ClearAllFilters() + public void ResetAll(bool suppressFilterChangedEvent = false) { foreach (ITestFilter filter in _filters) { filter.Reset(); } - FilterNodes(TestModel.LoadedTests); - FireFilterChangedEvent(); + if (!suppressFilterChangedEvent) + { + FilterNodes(TestModel.LoadedTests); + FireFilterChangedEvent(); + } } public void Init() diff --git a/src/TestModel/model/TestModel.cs b/src/TestModel/model/TestModel.cs index 5c024bf5..67533e39 100644 --- a/src/TestModel/model/TestModel.cs +++ b/src/TestModel/model/TestModel.cs @@ -410,6 +410,8 @@ public void UnloadTests() UnloadTestsIgnoringErrors(); Runner.Dispose(); + + TestCentricTestFilter.ResetAll(true); LoadedTests = null; AvailableCategories = null; ClearResults(); @@ -448,6 +450,7 @@ public void ReloadTests() // Discover tests LoadedTests = new TestNode(Runner.Explore(Engine.TestFilter.Empty)); AvailableCategories = GetAvailableCategories(); + TestCentricTestFilter.ResetAll(true); ClearResults(); #endif diff --git a/src/TestModel/tests/Filter/TestCentricTestFilterTests.cs b/src/TestModel/tests/Filter/TestCentricTestFilterTests.cs index fbdd526c..096787e6 100644 --- a/src/TestModel/tests/Filter/TestCentricTestFilterTests.cs +++ b/src/TestModel/tests/Filter/TestCentricTestFilterTests.cs @@ -108,7 +108,7 @@ public void AllCategories_CategoriesDefinedInModel_ReturnsModelAndDefaultCategor } [Test] - public void ClearFilter_AllFiltersAreReset() + public void ResetFilter_AllFiltersAreReset() { // Arrange var testNode = new TestNode($""); @@ -122,7 +122,7 @@ public void ClearFilter_AllFiltersAreReset() testFilter.OutcomeFilter = new List() { "Passed" }; // Act - testFilter.ClearAllFilters(); + testFilter.ResetAll(); // Assert var allCategories = testFilter.AllCategories; @@ -136,6 +136,28 @@ public void ClearFilter_AllFiltersAreReset() Assert.That(testFilter.TextFilter, Is.Empty); } + [Test] + public void ResetFilter_InvokeFilterChangedEvent() + { + // Arrange + var testNode = new TestNode($""); + _model.LoadedTests.Returns(testNode); + _model.AvailableCategories.Returns(new List() { "Feature_1" }); + + bool isInvoked = false; + TestCentricTestFilter testFilter = new TestCentricTestFilter(_model, () => isInvoked = true); + testFilter.Init(); + testFilter.TextFilter = "TestA"; + testFilter.CategoryFilter = new List() { "Feature_1" }; + testFilter.OutcomeFilter = new List() { "Passed" }; + + // Act + testFilter.ResetAll(); + + // Assert + Assert.That(isInvoked, Is.True); + } + private static object[] FilterByOutcomeTestCases = { new object[] { new List() { "Passed" }, new List() { "3-1000", "3-1001", "3-1010", "3-1011", "3-1012", "3-1020", "3-1022" } },