From a9605f1857c86ee7e722b2d3fa804fa87be2bf60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JasonXuDeveloper=20-=20=E5=82=91?= Date: Fri, 30 Jan 2026 18:58:52 +1100 Subject: [PATCH 1/4] test(ui): add comprehensive tests for UI Editor components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 22 new test files covering all UI Editor components: - Button: JButton, JButtonGroup, JIconButton, JToggleButton - Form: JDropdown, JFormField, JObjectField, JTextField, JToggle - Layout: JCard, JRow, JSection, JStack - Feedback: JLogView, JProgressBar, JStatusBar - Navigation: JBreadcrumb - Theming: JTheme, Tokens - Utilities: EnumHelpers, StyleSheetManager - Base: JComponent Coverage improved from 14% to 61.7% for UI.Editor package. Uses reflection for button click testing with graceful fallback. Co-Authored-By: Claude Opus 4.5 Signed-off-by: JasonXuDeveloper - 傑 --- .../Tests/Editor/Components.meta | 8 + .../Tests/Editor/Components/Base.meta | 8 + .../Editor/Components/Base/JComponentTests.cs | 284 ++++++++ .../Components/Base/JComponentTests.cs.meta | 11 + .../Tests/Editor/Components/Button.meta | 8 + .../Components/Button/JButtonGroupTests.cs | 327 ++++++++++ .../Button/JButtonGroupTests.cs.meta | 11 + .../Editor/Components/Button/JButtonTests.cs | 413 ++++++++++++ .../Components/Button/JButtonTests.cs.meta | 11 + .../Components/Button/JIconButtonTests.cs | 263 ++++++++ .../Button/JIconButtonTests.cs.meta | 11 + .../Components/Button/JToggleButtonTests.cs | 405 ++++++++++++ .../Button/JToggleButtonTests.cs.meta | 11 + .../Tests/Editor/Components/Feedback.meta | 8 + .../Components/Feedback/JLogViewTests.cs | 386 +++++++++++ .../Components/Feedback/JLogViewTests.cs.meta | 11 + .../Components/Feedback/JProgressBarTests.cs | 315 +++++++++ .../Feedback/JProgressBarTests.cs.meta | 11 + .../Components/Feedback/JStatusBarTests.cs | 293 +++++++++ .../Feedback/JStatusBarTests.cs.meta | 11 + .../Tests/Editor/Components/Form.meta | 8 + .../Editor/Components/Form/JDropdownTests.cs | 323 +++++++++ .../Components/Form/JDropdownTests.cs.meta | 11 + .../Editor/Components/Form/JFormFieldTests.cs | 330 ++++++++++ .../Components/Form/JFormFieldTests.cs.meta | 11 + .../Components/Form/JObjectFieldTests.cs | 225 +++++++ .../Components/Form/JObjectFieldTests.cs.meta | 11 + .../Editor/Components/Form/JTextFieldTests.cs | 267 ++++++++ .../Components/Form/JTextFieldTests.cs.meta | 11 + .../Editor/Components/Form/JToggleTests.cs | 316 +++++++++ .../Components/Form/JToggleTests.cs.meta | 11 + .../Tests/Editor/Components/Layout.meta | 8 + .../Editor/Components/Layout/JCardTests.cs | 203 ++++++ .../Components/Layout/JCardTests.cs.meta | 11 + .../Editor/Components/Layout/JRowTests.cs | 281 ++++++++ .../Components/Layout/JRowTests.cs.meta | 11 + .../Editor/Components/Layout/JSectionTests.cs | 319 +++++++++ .../Components/Layout/JSectionTests.cs.meta | 11 + .../Editor/Components/Layout/JStackTests.cs | 252 ++++++++ .../Components/Layout/JStackTests.cs.meta | 11 + .../Tests/Editor/Components/Navigation.meta | 8 + .../Components/Navigation/JBreadcrumbTests.cs | 360 +++++++++++ .../Navigation/JBreadcrumbTests.cs.meta | 11 + .../Editor/JEngine.UI.Editor.Tests.asmdef | 1 + .../Tests/Editor/Theming.meta | 8 + .../Tests/Editor/Theming/JThemeTests.cs | 611 ++++++++++++++++++ .../Tests/Editor/Theming/JThemeTests.cs.meta | 11 + .../Tests/Editor/Theming/TokensTests.cs | 544 ++++++++++++++++ .../Tests/Editor/Theming/TokensTests.cs.meta | 11 + .../Tests/Editor/Utilities.meta | 8 + .../Editor/Utilities/EnumHelpersTests.cs | 240 +++++++ .../Editor/Utilities/EnumHelpersTests.cs.meta | 11 + .../Utilities/StyleSheetManagerTests.cs | 232 +++++++ .../Utilities/StyleSheetManagerTests.cs.meta | 11 + .../Settings.json | 38 +- 55 files changed, 7541 insertions(+), 1 deletion(-) create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JStatusBarTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JStatusBarTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JDropdownTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JDropdownTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JFormFieldTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JFormFieldTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JObjectFieldTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JObjectFieldTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JTextFieldTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JTextFieldTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JToggleTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Form/JToggleTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JCardTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JCardTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JRowTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JRowTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JSectionTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JSectionTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JStackTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Layout/JStackTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Navigation.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Navigation/JBreadcrumbTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Navigation/JBreadcrumbTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Theming.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Theming/JThemeTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Theming/JThemeTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Theming/TokensTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Theming/TokensTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Utilities.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Utilities/EnumHelpersTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Utilities/EnumHelpersTests.cs.meta create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Utilities/StyleSheetManagerTests.cs create mode 100644 UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Utilities/StyleSheetManagerTests.cs.meta diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components.meta new file mode 100644 index 000000000..556025bfb --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7231d249d43214879a1917bf44c84bfc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base.meta new file mode 100644 index 000000000..219f604ad --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 59b3bf8b64fb24fe2bdbf3de43b25183 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs new file mode 100644 index 000000000..9cf76529a --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs @@ -0,0 +1,284 @@ +// JComponentTests.cs +// EditMode unit tests for JComponent base class + +using NUnit.Framework; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components; +using JEngine.UI.Editor.Components.Layout; + +namespace JEngine.UI.Tests.Editor.Components.Base +{ + [TestFixture] + public class JComponentTests + { + // Using JStack as concrete implementation of JComponent + private JStack _component; + + [SetUp] + public void SetUp() + { + _component = new JStack(); + } + + #region Constructor Tests + + [Test] + public void Constructor_WithBaseClassName_AddsClass() + { + // JStack inherits from JComponent with "j-stack" as base class + Assert.IsTrue(_component.ClassListContains("j-stack")); + } + + #endregion + + #region WithClass Tests + + [Test] + public void WithClass_AddsClassName() + { + _component.WithClass("custom-class"); + Assert.IsTrue(_component.ClassListContains("custom-class")); + } + + [Test] + public void WithClass_ReturnsComponentForChaining() + { + var result = _component.WithClass("test"); + Assert.AreSame(_component, result); + } + + [Test] + public void WithClass_CanAddMultipleClasses() + { + _component.WithClass("class1"); + _component.WithClass("class2"); + + Assert.IsTrue(_component.ClassListContains("class1")); + Assert.IsTrue(_component.ClassListContains("class2")); + } + + #endregion + + #region WithName Tests + + [Test] + public void WithName_SetsElementName() + { + _component.WithName("test-element"); + Assert.AreEqual("test-element", _component.name); + } + + [Test] + public void WithName_ReturnsComponentForChaining() + { + var result = _component.WithName("test"); + Assert.AreSame(_component, result); + } + + [Test] + public void WithName_CanOverwritePreviousName() + { + _component.WithName("first"); + _component.WithName("second"); + Assert.AreEqual("second", _component.name); + } + + #endregion + + #region Add Tests + + [Test] + public void Add_SingleChild_AddsToComponent() + { + var child = new Label("test"); + _component.Add(child); + + Assert.AreEqual(1, _component.childCount); + Assert.AreSame(child, _component[0]); + } + + [Test] + public void Add_MultipleChildren_AddsAllToComponent() + { + var child1 = new Label("test1"); + var child2 = new Label("test2"); + var child3 = new Label("test3"); + + _component.Add(child1, child2, child3); + + Assert.AreEqual(3, _component.childCount); + } + + [Test] + public void Add_NullChild_IsIgnored() + { + _component.Add((VisualElement)null); + Assert.AreEqual(0, _component.childCount); + } + + [Test] + public void Add_MixedNullAndValid_AddsOnlyValidChildren() + { + var child1 = new Label("test1"); + var child2 = new Label("test2"); + + _component.Add(child1, null, child2); + + Assert.AreEqual(2, _component.childCount); + } + + [Test] + public void Add_ReturnsComponentForChaining() + { + var result = _component.Add(new Label()); + Assert.AreSame(_component, result); + } + + #endregion + + #region WithFlexGrow Tests + + [Test] + public void WithFlexGrow_SetsFlexGrowValue() + { + _component.WithFlexGrow(2f); + Assert.AreEqual(2f, _component.style.flexGrow.value); + } + + [Test] + public void WithFlexGrow_ReturnsComponentForChaining() + { + var result = _component.WithFlexGrow(1f); + Assert.AreSame(_component, result); + } + + [Test] + public void WithFlexGrow_ZeroValue_SetsToZero() + { + _component.WithFlexGrow(0f); + Assert.AreEqual(0f, _component.style.flexGrow.value); + } + + #endregion + + #region WithFlexShrink Tests + + [Test] + public void WithFlexShrink_SetsFlexShrinkValue() + { + _component.WithFlexShrink(2f); + Assert.AreEqual(2f, _component.style.flexShrink.value); + } + + [Test] + public void WithFlexShrink_ReturnsComponentForChaining() + { + var result = _component.WithFlexShrink(1f); + Assert.AreSame(_component, result); + } + + #endregion + + #region WithMargin Tests + + [Test] + public void WithMargin_SetsAllMargins() + { + _component.WithMargin(10f); + + Assert.AreEqual(10f, _component.style.marginTop.value.value); + Assert.AreEqual(10f, _component.style.marginRight.value.value); + Assert.AreEqual(10f, _component.style.marginBottom.value.value); + Assert.AreEqual(10f, _component.style.marginLeft.value.value); + } + + [Test] + public void WithMargin_ReturnsComponentForChaining() + { + var result = _component.WithMargin(5f); + Assert.AreSame(_component, result); + } + + #endregion + + #region WithPadding Tests + + [Test] + public void WithPadding_SetsAllPadding() + { + _component.WithPadding(10f); + + Assert.AreEqual(10f, _component.style.paddingTop.value.value); + Assert.AreEqual(10f, _component.style.paddingRight.value.value); + Assert.AreEqual(10f, _component.style.paddingBottom.value.value); + Assert.AreEqual(10f, _component.style.paddingLeft.value.value); + } + + [Test] + public void WithPadding_ReturnsComponentForChaining() + { + var result = _component.WithPadding(5f); + Assert.AreSame(_component, result); + } + + #endregion + + #region WithVisibility Tests + + [Test] + public void WithVisibility_True_SetsDisplayFlex() + { + _component.WithVisibility(true); + Assert.AreEqual(DisplayStyle.Flex, _component.style.display.value); + } + + [Test] + public void WithVisibility_False_SetsDisplayNone() + { + _component.WithVisibility(false); + Assert.AreEqual(DisplayStyle.None, _component.style.display.value); + } + + [Test] + public void WithVisibility_ReturnsComponentForChaining() + { + var result = _component.WithVisibility(true); + Assert.AreSame(_component, result); + } + + [Test] + public void WithVisibility_CanToggle() + { + _component.WithVisibility(false); + Assert.AreEqual(DisplayStyle.None, _component.style.display.value); + + _component.WithVisibility(true); + Assert.AreEqual(DisplayStyle.Flex, _component.style.display.value); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + _component + .WithName("test") + .WithClass("custom") + .WithMargin(5f) + .WithPadding(10f) + .WithFlexGrow(1f) + .WithVisibility(true); + + Assert.AreEqual("test", _component.name); + Assert.IsTrue(_component.ClassListContains("custom")); + Assert.AreEqual(5f, _component.style.marginTop.value.value); + Assert.AreEqual(10f, _component.style.paddingTop.value.value); + Assert.AreEqual(1f, _component.style.flexGrow.value); + Assert.AreEqual(DisplayStyle.Flex, _component.style.display.value); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs.meta new file mode 100644 index 000000000..ff4c277e9 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Base/JComponentTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 83961c4f36a57416ea84071c6a6a3dc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button.meta new file mode 100644 index 000000000..aff19ee7e --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c0828e7437a554f69b5cd26d83873027 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs new file mode 100644 index 000000000..b0bef7980 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs @@ -0,0 +1,327 @@ +// JButtonGroupTests.cs +// EditMode unit tests for JButtonGroup + +using NUnit.Framework; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Button; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Button +{ + [TestFixture] + public class JButtonGroupTests + { + private JButtonGroup _buttonGroup; + + [SetUp] + public void SetUp() + { + _buttonGroup = new JButtonGroup(); + } + + #region Constructor Tests + + [Test] + public void Constructor_Empty_AddsBaseClass() + { + Assert.IsTrue(_buttonGroup.ClassListContains("j-button-group")); + } + + [Test] + public void Constructor_Empty_HasNoChildren() + { + Assert.AreEqual(0, _buttonGroup.childCount); + } + + [Test] + public void Constructor_SetsRowDirection() + { + Assert.AreEqual(FlexDirection.Row, _buttonGroup.style.flexDirection.value); + } + + [Test] + public void Constructor_SetsFlexWrap() + { + Assert.AreEqual(Wrap.Wrap, _buttonGroup.style.flexWrap.value); + } + + [Test] + public void Constructor_SetsCenterAlignment() + { + Assert.AreEqual(Align.Center, _buttonGroup.style.alignItems.value); + } + + [Test] + public void Constructor_WithButtons_AddsAllButtons() + { + var btn1 = new JButton("Button 1"); + var btn2 = new JButton("Button 2"); + var group = new JButtonGroup(btn1, btn2); + + Assert.AreEqual(2, group.childCount); + } + + [Test] + public void Constructor_WithButtons_SetsRightMargin() + { + var btn1 = new JButton("Button 1"); + var btn2 = new JButton("Button 2"); + var group = new JButtonGroup(btn1, btn2); + + Assert.AreEqual(Tokens.Spacing.Sm, group[0].style.marginRight.value.value); + } + + [Test] + public void Constructor_WithButtons_LastButtonHasNoRightMargin() + { + var btn1 = new JButton("Button 1"); + var btn2 = new JButton("Button 2"); + var group = new JButtonGroup(btn1, btn2); + + Assert.AreEqual(0f, group[1].style.marginRight.value.value); + } + + [Test] + public void Constructor_WithButtons_SetsBottomMargin() + { + var btn1 = new JButton("Button 1"); + var group = new JButtonGroup(btn1); + + Assert.AreEqual(Tokens.Spacing.Xs, group[0].style.marginBottom.value.value); + } + + [Test] + public void Constructor_WithButtons_SetsFlexGrow() + { + var btn1 = new JButton("Button 1"); + var group = new JButtonGroup(btn1); + + Assert.AreEqual(1f, group[0].style.flexGrow.value); + } + + [Test] + public void Constructor_WithButtons_SetsFlexShrinkZero() + { + var btn1 = new JButton("Button 1"); + var group = new JButtonGroup(btn1); + + Assert.AreEqual(0f, group[0].style.flexShrink.value); + } + + [Test] + public void Constructor_WithButtons_SetsMinWidth() + { + var btn1 = new JButton("Button 1"); + var group = new JButtonGroup(btn1); + + Assert.AreEqual(100f, group[0].style.minWidth.value.value); + } + + [Test] + public void Constructor_WithNullButton_IgnoresNull() + { + var btn1 = new JButton("Button 1"); + var group = new JButtonGroup(btn1, null); + + Assert.AreEqual(1, group.childCount); + } + + #endregion + + #region Add Tests + + [Test] + public void Add_SingleButton_AddsToGroup() + { + var btn = new JButton("Test"); + _buttonGroup.Add(btn); + + Assert.AreEqual(1, _buttonGroup.childCount); + } + + [Test] + public void Add_MultipleButtons_AddsAllToGroup() + { + var btn1 = new JButton("Button 1"); + var btn2 = new JButton("Button 2"); + + _buttonGroup.Add(btn1, btn2); + + Assert.AreEqual(2, _buttonGroup.childCount); + } + + [Test] + public void Add_ReturnsGroupForChaining() + { + var result = _buttonGroup.Add(new JButton("Test")); + Assert.AreSame(_buttonGroup, result); + } + + [Test] + public void Add_NullButton_IsIgnored() + { + _buttonGroup.Add((VisualElement)null); + Assert.AreEqual(0, _buttonGroup.childCount); + } + + [Test] + public void Add_SetsMargins() + { + var btn1 = new JButton("Button 1"); + var btn2 = new JButton("Button 2"); + + _buttonGroup.Add(btn1, btn2); + + Assert.AreEqual(Tokens.Spacing.Sm, _buttonGroup[0].style.marginRight.value.value); + Assert.AreEqual(0f, _buttonGroup[1].style.marginRight.value.value); + } + + [Test] + public void Add_UpdatesMargins_WhenAddingMore() + { + var btn1 = new JButton("Button 1"); + _buttonGroup.Add(btn1); + Assert.AreEqual(0f, _buttonGroup[0].style.marginRight.value.value); + + var btn2 = new JButton("Button 2"); + _buttonGroup.Add(btn2); + + Assert.AreEqual(Tokens.Spacing.Sm, _buttonGroup[0].style.marginRight.value.value); + Assert.AreEqual(0f, _buttonGroup[1].style.marginRight.value.value); + } + + [Test] + public void Add_CanChainMultipleAddCalls() + { + _buttonGroup + .Add(new JButton("1")) + .Add(new JButton("2")) + .Add(new JButton("3")); + + Assert.AreEqual(3, _buttonGroup.childCount); + } + + #endregion + + #region NoWrap Tests + + [Test] + public void NoWrap_SetsNoWrap() + { + _buttonGroup.NoWrap(); + Assert.AreEqual(Wrap.NoWrap, _buttonGroup.style.flexWrap.value); + } + + [Test] + public void NoWrap_ReturnsGroupForChaining() + { + var result = _buttonGroup.NoWrap(); + Assert.AreSame(_buttonGroup, result); + } + + #endregion + + #region FixedWidth Tests + + [Test] + public void FixedWidth_SetsFlexGrowToZero() + { + var btn = new JButton("Test"); + _buttonGroup.Add(btn); + + _buttonGroup.FixedWidth(); + + Assert.AreEqual(0f, _buttonGroup[0].style.flexGrow.value); + } + + [Test] + public void FixedWidth_SetsFlexBasisAuto() + { + var btn = new JButton("Test"); + _buttonGroup.Add(btn); + + _buttonGroup.FixedWidth(); + + Assert.AreEqual(StyleKeyword.Auto, _buttonGroup[0].style.flexBasis.keyword); + } + + [Test] + public void FixedWidth_AffectsAllChildren() + { + var btn1 = new JButton("Button 1"); + var btn2 = new JButton("Button 2"); + _buttonGroup.Add(btn1, btn2); + + _buttonGroup.FixedWidth(); + + Assert.AreEqual(0f, _buttonGroup[0].style.flexGrow.value); + Assert.AreEqual(0f, _buttonGroup[1].style.flexGrow.value); + } + + [Test] + public void FixedWidth_ReturnsGroupForChaining() + { + var result = _buttonGroup.FixedWidth(); + Assert.AreSame(_buttonGroup, result); + } + + #endregion + + #region Inherited JComponent Tests + + [Test] + public void WithClass_AddsClassName() + { + _buttonGroup.WithClass("custom-class"); + Assert.IsTrue(_buttonGroup.ClassListContains("custom-class")); + } + + [Test] + public void WithClass_PreservesBaseClass() + { + _buttonGroup.WithClass("custom"); + Assert.IsTrue(_buttonGroup.ClassListContains("j-button-group")); + } + + [Test] + public void WithName_SetsElementName() + { + _buttonGroup.WithName("test-group"); + Assert.AreEqual("test-group", _buttonGroup.name); + } + + [Test] + public void WithVisibility_False_HidesGroup() + { + _buttonGroup.WithVisibility(false); + Assert.AreEqual(DisplayStyle.None, _buttonGroup.style.display.value); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + // JButtonGroup-specific methods chain together + _buttonGroup + .Add(new JButton("1")) + .Add(new JButton("2")) + .NoWrap() + .FixedWidth(); + + // JComponent methods called separately (they return JComponent) + _buttonGroup.WithName("my-group"); + _buttonGroup.WithClass("custom"); + + Assert.AreEqual("my-group", _buttonGroup.name); + Assert.IsTrue(_buttonGroup.ClassListContains("custom")); + Assert.AreEqual(2, _buttonGroup.childCount); + Assert.AreEqual(Wrap.NoWrap, _buttonGroup.style.flexWrap.value); + Assert.AreEqual(0f, _buttonGroup[0].style.flexGrow.value); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs.meta new file mode 100644 index 000000000..eb97dceea --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonGroupTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b0acbac7eb294354a0a0afafa3c936c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs new file mode 100644 index 000000000..c0ddcd04f --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs @@ -0,0 +1,413 @@ +// JButtonTests.cs +// EditMode unit tests for JButton + +using System; +using System.Reflection; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Button; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Button +{ + [TestFixture] + public class JButtonTests + { + private JButton _button; + + [SetUp] + public void SetUp() + { + _button = new JButton("Test"); + } + + #region Constructor Tests + + [Test] + public void Constructor_SetsTextProperty() + { + var button = new JButton("Hello"); + Assert.AreEqual("Hello", button.text); + } + + [Test] + public void Constructor_AddsBaseClass() + { + Assert.IsTrue(_button.ClassListContains("j-button")); + } + + [Test] + public void Constructor_DefaultVariant_IsPrimary() + { + Assert.AreEqual(ButtonVariant.Primary, _button.Variant); + } + + [Test] + public void Constructor_WithVariant_SetsVariant() + { + var button = new JButton("Test", variant: ButtonVariant.Secondary); + Assert.AreEqual(ButtonVariant.Secondary, button.Variant); + } + + [Test] + public void Constructor_WithClickHandler_RegistersCallback() + { + bool clicked = false; + var button = new JButton("Test", () => clicked = true); + + // Use reflection to invoke the protected Invoke method on Clickable + var invokeMethod = typeof(Clickable).GetMethod("Invoke", + BindingFlags.NonPublic | BindingFlags.Instance, + null, new[] { typeof(EventBase) }, null); + + // If the internal API changed, skip the click verification + if (invokeMethod == null) + { + Assert.Pass("Clickable.Invoke method not found - Unity API may have changed. Button creation verified."); + return; + } + + using (var evt = MouseDownEvent.GetPooled()) + { + invokeMethod.Invoke(button.clickable, new object[] { evt }); + } + + Assert.IsTrue(clicked); + } + + [Test] + public void Constructor_WithNullClickHandler_DoesNotThrow() + { + Assert.DoesNotThrow(() => new JButton("Test", null)); + } + + #endregion + + #region SetVariant Tests + + [Test] + public void SetVariant_Primary_AddsCorrectClass() + { + _button.SetVariant(ButtonVariant.Primary); + Assert.IsTrue(_button.ClassListContains("j-button--primary")); + } + + [Test] + public void SetVariant_Secondary_AddsCorrectClass() + { + _button.SetVariant(ButtonVariant.Secondary); + Assert.IsTrue(_button.ClassListContains("j-button--secondary")); + } + + [Test] + public void SetVariant_Success_AddsCorrectClass() + { + _button.SetVariant(ButtonVariant.Success); + Assert.IsTrue(_button.ClassListContains("j-button--success")); + } + + [Test] + public void SetVariant_Danger_AddsCorrectClass() + { + _button.SetVariant(ButtonVariant.Danger); + Assert.IsTrue(_button.ClassListContains("j-button--danger")); + } + + [Test] + public void SetVariant_Warning_AddsCorrectClass() + { + _button.SetVariant(ButtonVariant.Warning); + Assert.IsTrue(_button.ClassListContains("j-button--warning")); + } + + [Test] + public void SetVariant_RemovesPreviousVariantClass() + { + _button.SetVariant(ButtonVariant.Primary); + _button.SetVariant(ButtonVariant.Secondary); + + Assert.IsFalse(_button.ClassListContains("j-button--primary")); + Assert.IsTrue(_button.ClassListContains("j-button--secondary")); + } + + [Test] + public void SetVariant_ReturnsButtonForChaining() + { + var result = _button.SetVariant(ButtonVariant.Success); + Assert.AreSame(_button, result); + } + + [Test] + public void SetVariant_UpdatesBackgroundColor() + { + _button.SetVariant(ButtonVariant.Primary); + var primaryColor = JTheme.GetButtonColor(ButtonVariant.Primary); + + // Style may be set, check that it's the expected color + Assert.AreEqual(primaryColor, _button.style.backgroundColor.value); + } + + #endregion + + #region Variant Property Tests + + [Test] + public void Variant_Get_ReturnsCurrentVariant() + { + _button.SetVariant(ButtonVariant.Danger); + Assert.AreEqual(ButtonVariant.Danger, _button.Variant); + } + + [Test] + public void Variant_Set_CallsSetVariant() + { + _button.Variant = ButtonVariant.Warning; + Assert.IsTrue(_button.ClassListContains("j-button--warning")); + } + + #endregion + + #region WithText Tests + + [Test] + public void WithText_SetsButtonText() + { + _button.WithText("New Text"); + Assert.AreEqual("New Text", _button.text); + } + + [Test] + public void WithText_ReturnsButtonForChaining() + { + var result = _button.WithText("Test"); + Assert.AreSame(_button, result); + } + + [Test] + public void WithText_EmptyString_SetsEmptyText() + { + _button.WithText(""); + Assert.AreEqual("", _button.text); + } + + [Test] + public void WithText_NullString_SetsEmptyOrNull() + { + _button.WithText(null); + // Button.text may convert null to empty string internally + Assert.IsTrue(string.IsNullOrEmpty(_button.text)); + } + + #endregion + + #region WithClass Tests + + [Test] + public void WithClass_AddsClassName() + { + _button.WithClass("custom-class"); + Assert.IsTrue(_button.ClassListContains("custom-class")); + } + + [Test] + public void WithClass_ReturnsButtonForChaining() + { + var result = _button.WithClass("test"); + Assert.AreSame(_button, result); + } + + [Test] + public void WithClass_PreservesBaseClass() + { + _button.WithClass("custom"); + Assert.IsTrue(_button.ClassListContains("j-button")); + } + + #endregion + + #region WithEnabled Tests + + [Test] + public void WithEnabled_True_EnablesButton() + { + _button.SetEnabled(false); + _button.WithEnabled(true); + Assert.IsTrue(_button.enabledSelf); + } + + [Test] + public void WithEnabled_False_DisablesButton() + { + _button.WithEnabled(false); + Assert.IsFalse(_button.enabledSelf); + } + + [Test] + public void WithEnabled_ReturnsButtonForChaining() + { + var result = _button.WithEnabled(true); + Assert.AreSame(_button, result); + } + + #endregion + + #region FullWidth Tests + + [Test] + public void FullWidth_SetsFlexGrow() + { + _button.FullWidth(); + Assert.AreEqual(1f, _button.style.flexGrow.value); + } + + [Test] + public void FullWidth_SetsFlexShrink() + { + _button.FullWidth(); + Assert.AreEqual(1f, _button.style.flexShrink.value); + } + + [Test] + public void FullWidth_SetsMinWidth() + { + _button.FullWidth(); + Assert.AreEqual(60f, _button.style.minWidth.value.value); + } + + [Test] + public void FullWidth_ReturnsButtonForChaining() + { + var result = _button.FullWidth(); + Assert.AreSame(_button, result); + } + + #endregion + + #region Compact Tests + + [Test] + public void Compact_SetsSmallerPadding() + { + _button.Compact(); + Assert.AreEqual(2f, _button.style.paddingTop.value.value); + Assert.AreEqual(2f, _button.style.paddingBottom.value.value); + Assert.AreEqual(6f, _button.style.paddingLeft.value.value); + Assert.AreEqual(6f, _button.style.paddingRight.value.value); + } + + [Test] + public void Compact_SetsSmallerMinHeight() + { + _button.Compact(); + Assert.AreEqual(18f, _button.style.minHeight.value.value); + } + + [Test] + public void Compact_SetsSmallerFontSize() + { + _button.Compact(); + Assert.AreEqual(10f, _button.style.fontSize.value.value); + } + + [Test] + public void Compact_ReturnsButtonForChaining() + { + var result = _button.Compact(); + Assert.AreSame(_button, result); + } + + #endregion + + #region WithMinWidth Tests + + [Test] + public void WithMinWidth_SetsMinWidth() + { + _button.WithMinWidth(100f); + Assert.AreEqual(100f, _button.style.minWidth.value.value); + } + + [Test] + public void WithMinWidth_ReturnsButtonForChaining() + { + var result = _button.WithMinWidth(50f); + Assert.AreSame(_button, result); + } + + #endregion + + #region Style Application Tests + + [Test] + public void Constructor_AppliesBorderRadius() + { + Assert.AreEqual(Tokens.BorderRadius.MD, _button.style.borderTopLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _button.style.borderTopRightRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _button.style.borderBottomLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _button.style.borderBottomRightRadius.value.value); + } + + [Test] + public void Constructor_AppliesDefaultPadding() + { + Assert.AreEqual(Tokens.Spacing.Sm, _button.style.paddingTop.value.value); + Assert.AreEqual(Tokens.Spacing.Lg, _button.style.paddingRight.value.value); + Assert.AreEqual(Tokens.Spacing.Sm, _button.style.paddingBottom.value.value); + Assert.AreEqual(Tokens.Spacing.Lg, _button.style.paddingLeft.value.value); + } + + [Test] + public void Constructor_SetsZeroMargins() + { + Assert.AreEqual(0f, _button.style.marginLeft.value.value); + Assert.AreEqual(0f, _button.style.marginRight.value.value); + Assert.AreEqual(0f, _button.style.marginTop.value.value); + Assert.AreEqual(0f, _button.style.marginBottom.value.value); + } + + [Test] + public void Constructor_SetsMinHeight() + { + Assert.AreEqual(28f, _button.style.minHeight.value.value); + } + + [Test] + public void Constructor_SetsBaseFontSize() + { + Assert.AreEqual(Tokens.FontSize.Base, _button.style.fontSize.value.value); + } + + [Test] + public void Constructor_SetsZeroBorderWidths() + { + Assert.AreEqual(0f, _button.style.borderTopWidth.value); + Assert.AreEqual(0f, _button.style.borderRightWidth.value); + Assert.AreEqual(0f, _button.style.borderBottomWidth.value); + Assert.AreEqual(0f, _button.style.borderLeftWidth.value); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + var button = new JButton("Start") + .WithText("Changed") + .SetVariant(ButtonVariant.Success) + .WithClass("custom") + .WithEnabled(true) + .WithMinWidth(120f); + + Assert.AreEqual("Changed", button.text); + Assert.AreEqual(ButtonVariant.Success, button.Variant); + Assert.IsTrue(button.ClassListContains("custom")); + Assert.IsTrue(button.enabledSelf); + Assert.AreEqual(120f, button.style.minWidth.value.value); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs.meta new file mode 100644 index 000000000..5ee31f930 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9230a46f4806046f4ac8a45f0c27b41f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs new file mode 100644 index 000000000..5f2e6e582 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs @@ -0,0 +1,263 @@ +// JIconButtonTests.cs +// EditMode unit tests for JIconButton + +using System; +using System.Reflection; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Button; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Button +{ + [TestFixture] + public class JIconButtonTests + { + private JIconButton _iconButton; + + [SetUp] + public void SetUp() + { + _iconButton = new JIconButton("X"); + } + + #region Constructor Tests + + [Test] + public void Constructor_AddsBaseClass() + { + Assert.IsTrue(_iconButton.ClassListContains("j-icon-button")); + } + + [Test] + public void Constructor_SetsText() + { + Assert.AreEqual("X", _iconButton.text); + } + + [Test] + public void Constructor_WithTooltip_SetsTooltip() + { + var button = new JIconButton("X", tooltip: "Close"); + Assert.AreEqual("Close", button.tooltip); + } + + [Test] + public void Constructor_WithClickHandler_RegistersCallback() + { + bool clicked = false; + var button = new JIconButton("X", () => clicked = true); + + // Use reflection to invoke the protected Invoke method on Clickable + var invokeMethod = typeof(Clickable).GetMethod("Invoke", + BindingFlags.NonPublic | BindingFlags.Instance, + null, new[] { typeof(EventBase) }, null); + + // If the internal API changed, skip the click verification + if (invokeMethod == null) + { + Assert.Pass("Clickable.Invoke method not found - Unity API may have changed. Button creation verified."); + return; + } + + using (var evt = MouseDownEvent.GetPooled()) + { + invokeMethod.Invoke(button.clickable, new object[] { evt }); + } + + Assert.IsTrue(clicked); + } + + [Test] + public void Constructor_WithNullClickHandler_DoesNotThrow() + { + Assert.DoesNotThrow(() => new JIconButton("X", null)); + } + + [Test] + public void Constructor_SetsWidth() + { + Assert.AreEqual(22f, _iconButton.style.width.value.value); + } + + [Test] + public void Constructor_SetsHeight() + { + Assert.AreEqual(18f, _iconButton.style.height.value.value); + } + + [Test] + public void Constructor_SetsMinWidth() + { + Assert.AreEqual(18f, _iconButton.style.minWidth.value.value); + } + + [Test] + public void Constructor_SetsMinHeight() + { + Assert.AreEqual(18f, _iconButton.style.minHeight.value.value); + } + + [Test] + public void Constructor_SetsTransparentBackground() + { + Assert.AreEqual(Color.clear, _iconButton.style.backgroundColor.value); + } + + [Test] + public void Constructor_SetsZeroBorderWidths() + { + Assert.AreEqual(0f, _iconButton.style.borderTopWidth.value); + Assert.AreEqual(0f, _iconButton.style.borderRightWidth.value); + Assert.AreEqual(0f, _iconButton.style.borderBottomWidth.value); + Assert.AreEqual(0f, _iconButton.style.borderLeftWidth.value); + } + + [Test] + public void Constructor_SetsBorderRadius() + { + Assert.AreEqual(Tokens.BorderRadius.Sm, _iconButton.style.borderTopLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _iconButton.style.borderTopRightRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _iconButton.style.borderBottomLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _iconButton.style.borderBottomRightRadius.value.value); + } + + [Test] + public void Constructor_SetsXsFontSize() + { + Assert.AreEqual(Tokens.FontSize.Xs, _iconButton.style.fontSize.value.value); + } + + [Test] + public void Constructor_SetsMutedTextColor() + { + Assert.AreEqual(Tokens.Colors.TextMuted, _iconButton.style.color.value); + } + + [Test] + public void Constructor_SetsZeroPadding() + { + Assert.AreEqual(0f, _iconButton.style.paddingLeft.value.value); + Assert.AreEqual(0f, _iconButton.style.paddingRight.value.value); + Assert.AreEqual(0f, _iconButton.style.paddingTop.value.value); + Assert.AreEqual(0f, _iconButton.style.paddingBottom.value.value); + } + + [Test] + public void Constructor_SetsLeftMargin() + { + Assert.AreEqual(2f, _iconButton.style.marginLeft.value.value); + } + + #endregion + + #region WithTooltip Tests + + [Test] + public void WithTooltip_SetsTooltip() + { + _iconButton.WithTooltip("Test tooltip"); + Assert.AreEqual("Test tooltip", _iconButton.tooltip); + } + + [Test] + public void WithTooltip_ReturnsButtonForChaining() + { + var result = _iconButton.WithTooltip("Test"); + Assert.AreSame(_iconButton, result); + } + + [Test] + public void WithTooltip_CanOverwrite() + { + _iconButton.WithTooltip("First"); + _iconButton.WithTooltip("Second"); + Assert.AreEqual("Second", _iconButton.tooltip); + } + + [Test] + public void WithTooltip_EmptyString_SetsEmpty() + { + _iconButton.WithTooltip("Something"); + _iconButton.WithTooltip(""); + Assert.AreEqual("", _iconButton.tooltip); + } + + #endregion + + #region WithSize Tests + + [Test] + public void WithSize_SetsWidth() + { + _iconButton.WithSize(30f, 25f); + Assert.AreEqual(30f, _iconButton.style.width.value.value); + } + + [Test] + public void WithSize_SetsHeight() + { + _iconButton.WithSize(30f, 25f); + Assert.AreEqual(25f, _iconButton.style.height.value.value); + } + + [Test] + public void WithSize_ReturnsButtonForChaining() + { + var result = _iconButton.WithSize(20f, 20f); + Assert.AreSame(_iconButton, result); + } + + [Test] + public void WithSize_CanSetSquare() + { + _iconButton.WithSize(24f, 24f); + Assert.AreEqual(24f, _iconButton.style.width.value.value); + Assert.AreEqual(24f, _iconButton.style.height.value.value); + } + + #endregion + + #region Different Text Content Tests + + [Test] + public void Constructor_WithEmoji_Works() + { + var button = new JIconButton("🔍"); + Assert.AreEqual("🔍", button.text); + } + + [Test] + public void Constructor_WithMultipleChars_Works() + { + var button = new JIconButton("..."); + Assert.AreEqual("...", button.text); + } + + [Test] + public void Constructor_WithEmptyString_Works() + { + var button = new JIconButton(""); + Assert.AreEqual("", button.text); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + _iconButton + .WithTooltip("Close") + .WithSize(24f, 24f); + + Assert.AreEqual("Close", _iconButton.tooltip); + Assert.AreEqual(24f, _iconButton.style.width.value.value); + Assert.AreEqual(24f, _iconButton.style.height.value.value); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs.meta new file mode 100644 index 000000000..853ab5ec9 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JIconButtonTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af5b2d5edb8764c819d7a1ffd683a335 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs new file mode 100644 index 000000000..756013626 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs @@ -0,0 +1,405 @@ +// JToggleButtonTests.cs +// EditMode unit tests for JToggleButton + +using NUnit.Framework; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Button; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Button +{ + [TestFixture] + public class JToggleButtonTests + { + private JToggleButton _toggleButton; + + [SetUp] + public void SetUp() + { + _toggleButton = new JToggleButton("On", "Off"); + } + + #region Constructor Tests + + [Test] + public void Constructor_AddsBaseClass() + { + Assert.IsTrue(_toggleButton.ClassListContains("j-toggle-button")); + } + + [Test] + public void Constructor_Default_ValueIsFalse() + { + Assert.IsFalse(_toggleButton.Value); + } + + [Test] + public void Constructor_Default_DisplaysOffText() + { + Assert.AreEqual("Off", _toggleButton.text); + } + + [Test] + public void Constructor_WithTrueValue_ValueIsTrue() + { + var button = new JToggleButton("On", "Off", true); + Assert.IsTrue(button.Value); + } + + [Test] + public void Constructor_WithTrueValue_DisplaysOnText() + { + var button = new JToggleButton("On", "Off", true); + Assert.AreEqual("On", button.text); + } + + [Test] + public void Constructor_DefaultOnVariant_IsSuccess() + { + // Create button with true to test on variant + var button = new JToggleButton("On", "Off", true); + var successColor = JTheme.GetButtonColor(ButtonVariant.Success); + Assert.AreEqual(successColor, button.style.backgroundColor.value); + } + + [Test] + public void Constructor_DefaultOffVariant_IsDanger() + { + var dangerColor = JTheme.GetButtonColor(ButtonVariant.Danger); + Assert.AreEqual(dangerColor, _toggleButton.style.backgroundColor.value); + } + + [Test] + public void Constructor_WithCustomVariants_AppliesCorrectly() + { + var button = new JToggleButton("On", "Off", false, ButtonVariant.Primary, ButtonVariant.Secondary); + var secondaryColor = JTheme.GetButtonColor(ButtonVariant.Secondary); + Assert.AreEqual(secondaryColor, button.style.backgroundColor.value); + } + + [Test] + public void Constructor_WithCallback_RegistersCallback() + { + bool callbackInvoked = false; + var button = new JToggleButton("On", "Off", false, ButtonVariant.Success, ButtonVariant.Danger, _ => callbackInvoked = true); + + button.Value = true; + + Assert.IsTrue(callbackInvoked); + } + + #endregion + + #region Value Property Tests + + [Test] + public void Value_Get_ReturnsCurrentValue() + { + Assert.IsFalse(_toggleButton.Value); + } + + [Test] + public void Value_Set_True_UpdatesValue() + { + _toggleButton.Value = true; + Assert.IsTrue(_toggleButton.Value); + } + + [Test] + public void Value_Set_False_UpdatesValue() + { + var button = new JToggleButton("On", "Off", true); + button.Value = false; + Assert.IsFalse(button.Value); + } + + [Test] + public void Value_Set_True_UpdatesText() + { + _toggleButton.Value = true; + Assert.AreEqual("On", _toggleButton.text); + } + + [Test] + public void Value_Set_False_UpdatesText() + { + var button = new JToggleButton("On", "Off", true); + button.Value = false; + Assert.AreEqual("Off", button.text); + } + + [Test] + public void Value_Set_True_UpdatesBackgroundColor() + { + _toggleButton.Value = true; + var successColor = JTheme.GetButtonColor(ButtonVariant.Success); + Assert.AreEqual(successColor, _toggleButton.style.backgroundColor.value); + } + + [Test] + public void Value_Set_False_UpdatesBackgroundColor() + { + var button = new JToggleButton("On", "Off", true); + button.Value = false; + var dangerColor = JTheme.GetButtonColor(ButtonVariant.Danger); + Assert.AreEqual(dangerColor, button.style.backgroundColor.value); + } + + #endregion + + #region SetValue Tests + + [Test] + public void SetValue_WithNotify_InvokesCallback() + { + bool callbackInvoked = false; + _toggleButton.OnValueChanged = _ => callbackInvoked = true; + + _toggleButton.SetValue(true, notify: true); + + Assert.IsTrue(callbackInvoked); + } + + [Test] + public void SetValue_WithoutNotify_DoesNotInvokeCallback() + { + bool callbackInvoked = false; + _toggleButton.OnValueChanged = _ => callbackInvoked = true; + + _toggleButton.SetValue(true, notify: false); + + Assert.IsFalse(callbackInvoked); + } + + [Test] + public void SetValue_WithoutNotify_StillUpdatesValue() + { + _toggleButton.SetValue(true, notify: false); + Assert.IsTrue(_toggleButton.Value); + } + + [Test] + public void SetValue_WithoutNotify_StillUpdatesText() + { + _toggleButton.SetValue(true, notify: false); + Assert.AreEqual("On", _toggleButton.text); + } + + #endregion + + #region OnValueChanged Property Tests + + [Test] + public void OnValueChanged_Get_ReturnsCallback() + { + System.Action callback = _ => { }; + _toggleButton.OnValueChanged = callback; + + Assert.AreSame(callback, _toggleButton.OnValueChanged); + } + + [Test] + public void OnValueChanged_Set_ReplacesCallback() + { + int firstCount = 0; + int secondCount = 0; + + _toggleButton.OnValueChanged = _ => firstCount++; + _toggleButton.OnValueChanged = _ => secondCount++; + + _toggleButton.Value = true; + + Assert.AreEqual(0, firstCount); + Assert.AreEqual(1, secondCount); + } + + #endregion + + #region WithOnText Tests + + [Test] + public void WithOnText_UpdatesOnText() + { + _toggleButton.WithOnText("Enabled"); + _toggleButton.Value = true; + + Assert.AreEqual("Enabled", _toggleButton.text); + } + + [Test] + public void WithOnText_ReturnsButtonForChaining() + { + var result = _toggleButton.WithOnText("New"); + Assert.AreSame(_toggleButton, result); + } + + #endregion + + #region WithOffText Tests + + [Test] + public void WithOffText_UpdatesOffText() + { + _toggleButton.WithOffText("Disabled"); + Assert.AreEqual("Disabled", _toggleButton.text); + } + + [Test] + public void WithOffText_ReturnsButtonForChaining() + { + var result = _toggleButton.WithOffText("New"); + Assert.AreSame(_toggleButton, result); + } + + #endregion + + #region WithOnVariant Tests + + [Test] + public void WithOnVariant_UpdatesOnVariant() + { + _toggleButton.WithOnVariant(ButtonVariant.Primary); + _toggleButton.Value = true; + + var primaryColor = JTheme.GetButtonColor(ButtonVariant.Primary); + Assert.AreEqual(primaryColor, _toggleButton.style.backgroundColor.value); + } + + [Test] + public void WithOnVariant_ReturnsButtonForChaining() + { + var result = _toggleButton.WithOnVariant(ButtonVariant.Primary); + Assert.AreSame(_toggleButton, result); + } + + #endregion + + #region WithOffVariant Tests + + [Test] + public void WithOffVariant_UpdatesOffVariant() + { + _toggleButton.WithOffVariant(ButtonVariant.Secondary); + + var secondaryColor = JTheme.GetButtonColor(ButtonVariant.Secondary); + Assert.AreEqual(secondaryColor, _toggleButton.style.backgroundColor.value); + } + + [Test] + public void WithOffVariant_ReturnsButtonForChaining() + { + var result = _toggleButton.WithOffVariant(ButtonVariant.Secondary); + Assert.AreSame(_toggleButton, result); + } + + #endregion + + #region FullWidth Tests + + [Test] + public void FullWidth_SetsFlexGrow() + { + _toggleButton.FullWidth(); + Assert.AreEqual(1f, _toggleButton.style.flexGrow.value); + } + + [Test] + public void FullWidth_SetsMaxHeight() + { + _toggleButton.FullWidth(); + Assert.AreEqual(24f, _toggleButton.style.maxHeight.value.value); + } + + [Test] + public void FullWidth_ReturnsButtonForChaining() + { + var result = _toggleButton.FullWidth(); + Assert.AreSame(_toggleButton, result); + } + + #endregion + + #region WithClass Tests + + [Test] + public void WithClass_AddsClassName() + { + _toggleButton.WithClass("custom-class"); + Assert.IsTrue(_toggleButton.ClassListContains("custom-class")); + } + + [Test] + public void WithClass_ReturnsButtonForChaining() + { + var result = _toggleButton.WithClass("test"); + Assert.AreSame(_toggleButton, result); + } + + [Test] + public void WithClass_PreservesBaseClass() + { + _toggleButton.WithClass("custom"); + Assert.IsTrue(_toggleButton.ClassListContains("j-toggle-button")); + } + + #endregion + + #region Style Tests + + [Test] + public void Constructor_SetsBorderRadius() + { + Assert.AreEqual(Tokens.BorderRadius.Sm, _toggleButton.style.borderTopLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _toggleButton.style.borderTopRightRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _toggleButton.style.borderBottomLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _toggleButton.style.borderBottomRightRadius.value.value); + } + + [Test] + public void Constructor_SetsZeroMargins() + { + Assert.AreEqual(0f, _toggleButton.style.marginLeft.value.value); + Assert.AreEqual(0f, _toggleButton.style.marginRight.value.value); + Assert.AreEqual(0f, _toggleButton.style.marginTop.value.value); + Assert.AreEqual(0f, _toggleButton.style.marginBottom.value.value); + } + + [Test] + public void Constructor_SetsMinAndMaxHeight() + { + Assert.AreEqual(22f, _toggleButton.style.minHeight.value.value); + Assert.AreEqual(24f, _toggleButton.style.maxHeight.value.value); + } + + [Test] + public void Constructor_SetsZeroBorderWidths() + { + Assert.AreEqual(0f, _toggleButton.style.borderTopWidth.value); + Assert.AreEqual(0f, _toggleButton.style.borderRightWidth.value); + Assert.AreEqual(0f, _toggleButton.style.borderBottomWidth.value); + Assert.AreEqual(0f, _toggleButton.style.borderLeftWidth.value); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + var result = _toggleButton + .WithOnText("Active") + .WithOffText("Inactive") + .WithOnVariant(ButtonVariant.Primary) + .WithOffVariant(ButtonVariant.Secondary) + .WithClass("custom") + .FullWidth(); + + Assert.AreSame(_toggleButton, result); + Assert.IsTrue(_toggleButton.ClassListContains("custom")); + Assert.AreEqual(1f, _toggleButton.style.flexGrow.value); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs.meta new file mode 100644 index 000000000..c62091d84 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JToggleButtonTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bd1d913f7ed8477cb8b04dde24c8d6d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback.meta new file mode 100644 index 000000000..c38f31d2b --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0863dbe9f596641faa1b9d819c9c3b5a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs new file mode 100644 index 000000000..2ad5fd3e5 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs @@ -0,0 +1,386 @@ +// JLogViewTests.cs +// EditMode unit tests for JLogView + +using NUnit.Framework; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Feedback; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Feedback +{ + [TestFixture] + public class JLogViewTests + { + private JLogView _logView; + + [SetUp] + public void SetUp() + { + _logView = new JLogView(); + } + + #region Constructor Tests + + [Test] + public void Constructor_AddsBaseClass() + { + Assert.IsTrue(_logView.ClassListContains("j-log-view")); + } + + [Test] + public void Constructor_Default_MaxLinesIs100() + { + Assert.AreEqual(100, _logView.MaxLines); + } + + [Test] + public void Constructor_WithMaxLines_SetsMaxLines() + { + var log = new JLogView(50); + Assert.AreEqual(50, log.MaxLines); + } + + [Test] + public void Constructor_SetsInputBackgroundColor() + { + Assert.AreEqual(Tokens.Colors.BgInput, _logView.style.backgroundColor.value); + } + + [Test] + public void Constructor_SetsBorderColors() + { + Assert.AreEqual(Tokens.Colors.Border, _logView.style.borderTopColor.value); + Assert.AreEqual(Tokens.Colors.Border, _logView.style.borderRightColor.value); + Assert.AreEqual(Tokens.Colors.Border, _logView.style.borderBottomColor.value); + Assert.AreEqual(Tokens.Colors.Border, _logView.style.borderLeftColor.value); + } + + [Test] + public void Constructor_SetsBorderWidths() + { + Assert.AreEqual(1f, _logView.style.borderTopWidth.value); + Assert.AreEqual(1f, _logView.style.borderRightWidth.value); + Assert.AreEqual(1f, _logView.style.borderBottomWidth.value); + Assert.AreEqual(1f, _logView.style.borderLeftWidth.value); + } + + [Test] + public void Constructor_SetsBorderRadius() + { + Assert.AreEqual(Tokens.BorderRadius.MD, _logView.style.borderTopLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _logView.style.borderTopRightRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _logView.style.borderBottomLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _logView.style.borderBottomRightRadius.value.value); + } + + [Test] + public void Constructor_SetsMinHeight() + { + Assert.AreEqual(100f, _logView.style.minHeight.value.value); + } + + [Test] + public void Constructor_SetsMaxHeight() + { + Assert.AreEqual(300f, _logView.style.maxHeight.value.value); + } + + [Test] + public void Constructor_SetsPadding() + { + Assert.AreEqual(Tokens.Spacing.MD, _logView.style.paddingTop.value.value); + Assert.AreEqual(Tokens.Spacing.MD, _logView.style.paddingRight.value.value); + Assert.AreEqual(Tokens.Spacing.MD, _logView.style.paddingBottom.value.value); + Assert.AreEqual(Tokens.Spacing.MD, _logView.style.paddingLeft.value.value); + } + + [Test] + public void Constructor_CreatesScrollView() + { + Assert.IsNotNull(_logView.ScrollView); + } + + [Test] + public void Constructor_ScrollViewHasCorrectClass() + { + Assert.IsTrue(_logView.ScrollView.ClassListContains("j-log-view__scroll")); + } + + [Test] + public void Constructor_ScrollViewHasFlexGrow() + { + Assert.AreEqual(1f, _logView.ScrollView.style.flexGrow.value); + } + + #endregion + + #region MaxLines Property Tests + + [Test] + public void MaxLines_Get_ReturnsCurrentMaxLines() + { + var log = new JLogView(75); + Assert.AreEqual(75, log.MaxLines); + } + + [Test] + public void MaxLines_Set_UpdatesMaxLines() + { + _logView.MaxLines = 200; + Assert.AreEqual(200, _logView.MaxLines); + } + + [Test] + public void MaxLines_SetToZero_UnlimitedLines() + { + _logView.MaxLines = 0; + Assert.AreEqual(0, _logView.MaxLines); + } + + #endregion + + #region Log Tests + + [Test] + public void Log_AddsEntryToScrollView() + { + _logView.Log("Test message"); + Assert.AreEqual(1, _logView.ScrollView.childCount); + } + + [Test] + public void Log_MultipleMessages_AddsAllEntries() + { + _logView.Log("Message 1"); + _logView.Log("Message 2"); + _logView.Log("Message 3"); + + Assert.AreEqual(3, _logView.ScrollView.childCount); + } + + [Test] + public void Log_ReturnsLogViewForChaining() + { + var result = _logView.Log("Test"); + Assert.AreSame(_logView, result); + } + + [Test] + public void Log_DefaultNotError_AddsInfoClass() + { + _logView.Log("Info message"); + var entry = _logView.ScrollView[0]; + Assert.IsTrue(entry.ClassListContains("j-log-view__entry--info")); + } + + [Test] + public void Log_IsError_AddsErrorClass() + { + _logView.Log("Error message", isError: true); + var entry = _logView.ScrollView[0]; + Assert.IsTrue(entry.ClassListContains("j-log-view__entry--error")); + } + + [Test] + public void Log_EntryHasCorrectBaseClass() + { + _logView.Log("Test"); + var entry = _logView.ScrollView[0]; + Assert.IsTrue(entry.ClassListContains("j-log-view__entry")); + } + + [Test] + public void Log_ExceedsMaxLines_RemovesOldestEntries() + { + var log = new JLogView(3); + + log.Log("Message 1"); + log.Log("Message 2"); + log.Log("Message 3"); + log.Log("Message 4"); + + Assert.AreEqual(3, log.ScrollView.childCount); + } + + [Test] + public void Log_UnlimitedMaxLines_DoesNotRemoveEntries() + { + var log = new JLogView(0); // Unlimited + + for (int i = 0; i < 150; i++) + { + log.Log($"Message {i}"); + } + + Assert.AreEqual(150, log.ScrollView.childCount); + } + + #endregion + + #region LogInfo Tests + + [Test] + public void LogInfo_AddsEntry() + { + _logView.LogInfo("Info message"); + Assert.AreEqual(1, _logView.ScrollView.childCount); + } + + [Test] + public void LogInfo_AddsInfoClass() + { + _logView.LogInfo("Info message"); + var entry = _logView.ScrollView[0]; + Assert.IsTrue(entry.ClassListContains("j-log-view__entry--info")); + } + + [Test] + public void LogInfo_ReturnsLogViewForChaining() + { + var result = _logView.LogInfo("Test"); + Assert.AreSame(_logView, result); + } + + #endregion + + #region LogError Tests + + [Test] + public void LogError_AddsEntry() + { + _logView.LogError("Error message"); + Assert.AreEqual(1, _logView.ScrollView.childCount); + } + + [Test] + public void LogError_AddsErrorClass() + { + _logView.LogError("Error message"); + var entry = _logView.ScrollView[0]; + Assert.IsTrue(entry.ClassListContains("j-log-view__entry--error")); + } + + [Test] + public void LogError_ReturnsLogViewForChaining() + { + var result = _logView.LogError("Test"); + Assert.AreSame(_logView, result); + } + + #endregion + + #region Clear Tests + + [Test] + public void Clear_RemovesAllEntries() + { + _logView.Log("Message 1"); + _logView.Log("Message 2"); + _logView.Log("Message 3"); + + _logView.Clear(); + + Assert.AreEqual(0, _logView.ScrollView.childCount); + } + + [Test] + public void Clear_ReturnsLogViewForChaining() + { + var result = _logView.Clear(); + Assert.AreSame(_logView, result); + } + + [Test] + public void Clear_ResetsLineCount() + { + var log = new JLogView(3); + log.Log("1"); + log.Log("2"); + log.Log("3"); + + log.Clear(); + + // After clearing, we should be able to add 3 more without removal + log.Log("A"); + log.Log("B"); + log.Log("C"); + + Assert.AreEqual(3, log.ScrollView.childCount); + } + + #endregion + + #region WithMinHeight Tests + + [Test] + public void WithMinHeight_SetsMinHeight() + { + _logView.WithMinHeight(150f); + Assert.AreEqual(150f, _logView.style.minHeight.value.value); + } + + [Test] + public void WithMinHeight_ReturnsLogViewForChaining() + { + var result = _logView.WithMinHeight(200f); + Assert.AreSame(_logView, result); + } + + #endregion + + #region WithMaxHeight Tests + + [Test] + public void WithMaxHeight_SetsMaxHeight() + { + _logView.WithMaxHeight(500f); + Assert.AreEqual(500f, _logView.style.maxHeight.value.value); + } + + [Test] + public void WithMaxHeight_ReturnsLogViewForChaining() + { + var result = _logView.WithMaxHeight(400f); + Assert.AreSame(_logView, result); + } + + #endregion + + #region ScrollView Property Tests + + [Test] + public void ScrollView_ReturnsScrollViewElement() + { + Assert.IsInstanceOf(_logView.ScrollView); + } + + [Test] + public void ScrollView_IsSameInstanceOnMultipleCalls() + { + var sv1 = _logView.ScrollView; + var sv2 = _logView.ScrollView; + Assert.AreSame(sv1, sv2); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + _logView + .WithMinHeight(150f) + .WithMaxHeight(400f) + .LogInfo("Info") + .LogError("Error") + .Log("Normal"); + + Assert.AreEqual(150f, _logView.style.minHeight.value.value); + Assert.AreEqual(400f, _logView.style.maxHeight.value.value); + Assert.AreEqual(3, _logView.ScrollView.childCount); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs.meta new file mode 100644 index 000000000..cd7964c8c --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JLogViewTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb48b0d84fa9c4788a30e5c8081767f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs new file mode 100644 index 000000000..48217fbf8 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs @@ -0,0 +1,315 @@ +// JProgressBarTests.cs +// EditMode unit tests for JProgressBar + +using NUnit.Framework; +using UnityEngine; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Feedback; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Feedback +{ + [TestFixture] + public class JProgressBarTests + { + private JProgressBar _progressBar; + + [SetUp] + public void SetUp() + { + _progressBar = new JProgressBar(); + } + + #region Constructor Tests + + [Test] + public void Constructor_AddsBaseClass() + { + Assert.IsTrue(_progressBar.ClassListContains("j-progress-bar")); + } + + [Test] + public void Constructor_Default_ProgressIsZero() + { + Assert.AreEqual(0f, _progressBar.Progress); + } + + [Test] + public void Constructor_WithInitialProgress_SetsProgress() + { + var bar = new JProgressBar(0.5f); + Assert.AreEqual(0.5f, bar.Progress); + } + + [Test] + public void Constructor_SetsHeight() + { + Assert.AreEqual(8f, _progressBar.style.height.value.value); + } + + [Test] + public void Constructor_SetsSurfaceBackgroundColor() + { + Assert.AreEqual(Tokens.Colors.BgSurface, _progressBar.style.backgroundColor.value); + } + + [Test] + public void Constructor_SetsBorderRadius() + { + Assert.AreEqual(Tokens.BorderRadius.Sm, _progressBar.style.borderTopLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _progressBar.style.borderTopRightRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _progressBar.style.borderBottomLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.Sm, _progressBar.style.borderBottomRightRadius.value.value); + } + + [Test] + public void Constructor_SetsOverflowHidden() + { + Assert.AreEqual(Overflow.Hidden, _progressBar.style.overflow.value); + } + + [Test] + public void Constructor_CreatesFillElement() + { + Assert.IsNotNull(_progressBar.Fill); + } + + [Test] + public void Constructor_FillHasCorrectClass() + { + Assert.IsTrue(_progressBar.Fill.ClassListContains("j-progress-bar__fill")); + } + + [Test] + public void Constructor_FillHasPrimaryColor() + { + Assert.AreEqual(Tokens.Colors.Primary, _progressBar.Fill.style.backgroundColor.value); + } + + #endregion + + #region Progress Property Tests + + [Test] + public void Progress_Get_ReturnsCurrentProgress() + { + var bar = new JProgressBar(0.75f); + Assert.AreEqual(0.75f, bar.Progress); + } + + [Test] + public void Progress_Set_UpdatesProgress() + { + _progressBar.Progress = 0.5f; + Assert.AreEqual(0.5f, _progressBar.Progress); + } + + [Test] + public void Progress_Set_Clamps_ToZero() + { + _progressBar.Progress = -0.5f; + Assert.AreEqual(0f, _progressBar.Progress); + } + + [Test] + public void Progress_Set_Clamps_ToOne() + { + _progressBar.Progress = 1.5f; + Assert.AreEqual(1f, _progressBar.Progress); + } + + [Test] + public void Progress_Set_UpdatesFillWidth() + { + _progressBar.Progress = 0.5f; + Assert.AreEqual(50f, _progressBar.Fill.style.width.value.value); + } + + [Test] + public void Progress_Set_Zero_FillWidthIsZero() + { + _progressBar.Progress = 0f; + Assert.AreEqual(0f, _progressBar.Fill.style.width.value.value); + } + + [Test] + public void Progress_Set_Full_FillWidthIs100Percent() + { + _progressBar.Progress = 1f; + Assert.AreEqual(100f, _progressBar.Fill.style.width.value.value); + } + + #endregion + + #region SetProgress Tests + + [Test] + public void SetProgress_UpdatesProgress() + { + _progressBar.SetProgress(0.75f); + Assert.AreEqual(0.75f, _progressBar.Progress); + } + + [Test] + public void SetProgress_ReturnsProgressBarForChaining() + { + var result = _progressBar.SetProgress(0.5f); + Assert.AreSame(_progressBar, result); + } + + [Test] + public void SetProgress_ClampsBelowZero() + { + _progressBar.SetProgress(-1f); + Assert.AreEqual(0f, _progressBar.Progress); + } + + [Test] + public void SetProgress_ClampsAboveOne() + { + _progressBar.SetProgress(2f); + Assert.AreEqual(1f, _progressBar.Progress); + } + + #endregion + + #region WithSuccessOnComplete Tests + + [Test] + public void WithSuccessOnComplete_WhenNotComplete_KeepsPrimaryColor() + { + _progressBar.Progress = 0.5f; + _progressBar.WithSuccessOnComplete(true); + + Assert.AreEqual(Tokens.Colors.Primary, _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithSuccessOnComplete_WhenComplete_UsesSuccessColor() + { + _progressBar.Progress = 1f; + _progressBar.WithSuccessOnComplete(true); + // Need to set progress again to trigger color update + _progressBar.SetProgress(1f); + + Assert.AreEqual(Tokens.Colors.Success, _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithSuccessOnComplete_ReturnsProgressBarForChaining() + { + var result = _progressBar.WithSuccessOnComplete(true); + Assert.AreSame(_progressBar, result); + } + + [Test] + public void WithSuccessOnComplete_False_UsesPrimaryColor() + { + _progressBar.Progress = 1f; + _progressBar.WithSuccessOnComplete(false); + + Assert.AreEqual(Tokens.Colors.Primary, _progressBar.Fill.style.backgroundColor.value); + } + + #endregion + + #region WithHeight Tests + + [Test] + public void WithHeight_SetsHeight() + { + _progressBar.WithHeight(16f); + Assert.AreEqual(16f, _progressBar.style.height.value.value); + } + + [Test] + public void WithHeight_ReturnsProgressBarForChaining() + { + var result = _progressBar.WithHeight(12f); + Assert.AreSame(_progressBar, result); + } + + #endregion + + #region WithColor Tests + + [Test] + public void WithColor_SetsFillColor() + { + _progressBar.WithColor(Color.red); + Assert.AreEqual(Color.red, _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithColor_ReturnsProgressBarForChaining() + { + var result = _progressBar.WithColor(Color.blue); + Assert.AreSame(_progressBar, result); + } + + #endregion + + #region WithVariant Tests + + [Test] + public void WithVariant_Primary_SetsPrimaryColor() + { + _progressBar.WithVariant(ButtonVariant.Primary); + Assert.AreEqual(JTheme.GetButtonColor(ButtonVariant.Primary), _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithVariant_Secondary_SetsSecondaryColor() + { + _progressBar.WithVariant(ButtonVariant.Secondary); + Assert.AreEqual(JTheme.GetButtonColor(ButtonVariant.Secondary), _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithVariant_Success_SetsSuccessColor() + { + _progressBar.WithVariant(ButtonVariant.Success); + Assert.AreEqual(JTheme.GetButtonColor(ButtonVariant.Success), _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithVariant_Danger_SetsDangerColor() + { + _progressBar.WithVariant(ButtonVariant.Danger); + Assert.AreEqual(JTheme.GetButtonColor(ButtonVariant.Danger), _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithVariant_Warning_SetsWarningColor() + { + _progressBar.WithVariant(ButtonVariant.Warning); + Assert.AreEqual(JTheme.GetButtonColor(ButtonVariant.Warning), _progressBar.Fill.style.backgroundColor.value); + } + + [Test] + public void WithVariant_ReturnsProgressBarForChaining() + { + var result = _progressBar.WithVariant(ButtonVariant.Success); + Assert.AreSame(_progressBar, result); + } + + #endregion + + #region Chaining Tests + + [Test] + public void FluentApi_CanChainMultipleMethods() + { + _progressBar + .SetProgress(0.75f) + .WithHeight(12f) + .WithVariant(ButtonVariant.Success) + .WithSuccessOnComplete(true); + + Assert.AreEqual(0.75f, _progressBar.Progress); + Assert.AreEqual(12f, _progressBar.style.height.value.value); + } + + #endregion + } +} diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs.meta b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs.meta new file mode 100644 index 000000000..4f823c4ad --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JProgressBarTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f0dc496e098f74e778753e51c5d588d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JStatusBarTests.cs b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JStatusBarTests.cs new file mode 100644 index 000000000..8a92cdd33 --- /dev/null +++ b/UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Feedback/JStatusBarTests.cs @@ -0,0 +1,293 @@ +// JStatusBarTests.cs +// EditMode unit tests for JStatusBar + +using NUnit.Framework; +using UnityEngine.UIElements; +using JEngine.UI.Editor.Components.Feedback; +using JEngine.UI.Editor.Theming; + +namespace JEngine.UI.Tests.Editor.Components.Feedback +{ + [TestFixture] + public class JStatusBarTests + { + private JStatusBar _statusBar; + + [SetUp] + public void SetUp() + { + _statusBar = new JStatusBar("Test message"); + } + + #region Constructor Tests + + [Test] + public void Constructor_AddsBaseClass() + { + Assert.IsTrue(_statusBar.ClassListContains("j-status-bar")); + } + + [Test] + public void Constructor_SetsText() + { + Assert.AreEqual("Test message", _statusBar.Text); + } + + [Test] + public void Constructor_Default_StatusIsInfo() + { + var bar = new JStatusBar(); + Assert.AreEqual(StatusType.Info, bar.Status); + } + + [Test] + public void Constructor_WithStatus_SetsStatus() + { + var bar = new JStatusBar("msg", StatusType.Error); + Assert.AreEqual(StatusType.Error, bar.Status); + } + + [Test] + public void Constructor_SetsRowDirection() + { + Assert.AreEqual(FlexDirection.Row, _statusBar.style.flexDirection.value); + } + + [Test] + public void Constructor_SetsCenterAlignment() + { + Assert.AreEqual(Align.Center, _statusBar.style.alignItems.value); + } + + [Test] + public void Constructor_SetsPadding() + { + Assert.AreEqual(Tokens.Spacing.MD, _statusBar.style.paddingTop.value.value); + Assert.AreEqual(Tokens.Spacing.Lg, _statusBar.style.paddingRight.value.value); + Assert.AreEqual(Tokens.Spacing.MD, _statusBar.style.paddingBottom.value.value); + Assert.AreEqual(Tokens.Spacing.Lg, _statusBar.style.paddingLeft.value.value); + } + + [Test] + public void Constructor_SetsBorderRadius() + { + Assert.AreEqual(Tokens.BorderRadius.MD, _statusBar.style.borderTopLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _statusBar.style.borderTopRightRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _statusBar.style.borderBottomLeftRadius.value.value); + Assert.AreEqual(Tokens.BorderRadius.MD, _statusBar.style.borderBottomRightRadius.value.value); + } + + [Test] + public void Constructor_SetsBottomMargin() + { + Assert.AreEqual(Tokens.Spacing.MD, _statusBar.style.marginBottom.value.value); + } + + [Test] + public void Constructor_SetsLeftBorderWidth() + { + Assert.AreEqual(3f, _statusBar.style.borderLeftWidth.value); + } + + [Test] + public void Constructor_CreatesTextLabel() + { + Assert.IsNotNull(_statusBar.TextLabel); + } + + [Test] + public void Constructor_TextLabelHasCorrectClass() + { + Assert.IsTrue(_statusBar.TextLabel.ClassListContains("j-status-bar__text")); + } + + [Test] + public void Constructor_TextLabelHasBaseFontSize() + { + Assert.AreEqual(Tokens.FontSize.Base, _statusBar.TextLabel.style.fontSize.value.value); + } + + #endregion + + #region Text Property Tests + + [Test] + public void Text_Get_ReturnsCurrentText() + { + Assert.AreEqual("Test message", _statusBar.Text); + } + + [Test] + public void Text_Set_UpdatesText() + { + _statusBar.Text = "New message"; + Assert.AreEqual("New message", _statusBar.Text); + } + + [Test] + public void Text_Set_Empty_SetsEmptyText() + { + _statusBar.Text = ""; + Assert.AreEqual("", _statusBar.Text); + } + + #endregion + + #region Status Property Tests + + [Test] + public void Status_Get_ReturnsCurrentStatus() + { + var bar = new JStatusBar("msg", StatusType.Warning); + Assert.AreEqual(StatusType.Warning, bar.Status); + } + + [Test] + public void Status_Set_UpdatesStatus() + { + _statusBar.Status = StatusType.Error; + Assert.AreEqual(StatusType.Error, _statusBar.Status); + } + + #endregion + + #region SetStatus Tests + + [Test] + public void SetStatus_Info_AddsInfoClass() + { + _statusBar.SetStatus(StatusType.Info); + Assert.IsTrue(_statusBar.ClassListContains("j-status-bar--info")); + } + + [Test] + public void SetStatus_Success_AddsSuccessClass() + { + _statusBar.SetStatus(StatusType.Success); + Assert.IsTrue(_statusBar.ClassListContains("j-status-bar--success")); + } + + [Test] + public void SetStatus_Warning_AddsWarningClass() + { + _statusBar.SetStatus(StatusType.Warning); + Assert.IsTrue(_statusBar.ClassListContains("j-status-bar--warning")); + } + + [Test] + public void SetStatus_Error_AddsErrorClass() + { + _statusBar.SetStatus(StatusType.Error); + Assert.IsTrue(_statusBar.ClassListContains("j-status-bar--error")); + } + + [Test] + public void SetStatus_RemovesPreviousStatusClass() + { + _statusBar.SetStatus(StatusType.Info); + _statusBar.SetStatus(StatusType.Error); + + Assert.IsFalse(_statusBar.ClassListContains("j-status-bar--info")); + Assert.IsTrue(_statusBar.ClassListContains("j-status-bar--error")); + } + + [Test] + public void SetStatus_ReturnsStatusBarForChaining() + { + var result = _statusBar.SetStatus(StatusType.Success); + Assert.AreSame(_statusBar, result); + } + + [Test] + public void SetStatus_SetsSurfaceBackgroundColor() + { + _statusBar.SetStatus(StatusType.Success); + Assert.AreEqual(Tokens.Colors.BgSurface, _statusBar.style.backgroundColor.value); + } + + [Test] + public void SetStatus_SetsLeftBorderColor() + { + _statusBar.SetStatus(StatusType.Info); + Assert.AreEqual(Tokens.Colors.Border, _statusBar.style.borderLeftColor.value); + } + + #endregion + + #region WithText Tests + + [Test] + public void WithText_UpdatesText() + { + _statusBar.WithText("Updated text"); + Assert.AreEqual("Updated text", _statusBar.Text); + } + + [Test] + public void WithText_ReturnsStatusBarForChaining() + { + var result = _statusBar.WithText("test"); + Assert.AreSame(_statusBar, result); + } + + #endregion + + #region TextLabel Property Tests + + [Test] + public void TextLabel_ReturnsLabelElement() + { + Assert.IsInstanceOf