Repository: ant-design-blazor/ant-design-blazor (csharp)

Issue:
JS interop Exception when Tabs ".ant-tabs-nav-list" "margin" is set to auto
### Describe the bug

When Tabs `.ant-tabs-nav-list` margin set to `auto` by custom style, margin computed style will become `auto` and `parseFloat` return NaN, causing crash in JS interop when called from `AntDesign.Tabs.ResetSizes()`.
https://github.com/ant-design-blazor/ant-design-blazor/blob/cdb3b7499264faa78a1e013a49054253f0dba856/components/core/JsInterop/modules/dom/infoHelper.ts#L35-L41


### Steps to reproduce

Modified from https://antblazor.com/en-US/components/modal#components-modal-demo-basic
```razor
<Button OnClick="@ShowModal">Show modal with tabs</Button>

<Modal @bind-Visible="@_visible">
    <Tabs>
        <TabPane Key="Tab" Tab="Tab">
            <p>Sample tab</p>
        </TabPane>
    </Tabs>
</Modal>

<style>
    .ant-tabs-nav-list {
        margin: auto; // will cause crash
    }
</style>

@code {

    private bool _visible;

    private void ShowModal()
    {
        _visible = true;
    }

}
```

### Exceptions

![Image](https://github.com/user-attachments/assets/9e87dcf9-9f62-4c14-972a-b5da793d60ec)

<details><summary>Exception details from the page web console</summary>

```
Microsoft.AspNetCore.Components.Web.ErrorBoundary[0]
      Microsoft.JSInterop.JSException: An exception occurred executing JS interop: DeserializeUnableToConvertValue, System.Decimal Path: $.ant-blazor-cbb8972b-4123-4621-8a63-85f2707485be-nav-list.marginTop | LineNumber: 0 | BytePositionInLine: 315.. See InnerException for more details.
       ---> System.Text.Json.JsonException: DeserializeUnableToConvertValue, System.Decimal Path: $.ant-blazor-cbb8972b-4123-4621-8a63-85f2707485be-nav-list.marginTop | LineNumber: 0 | BytePositionInLine: 315.
       ---> System.InvalidOperationException: InvalidCast, Null, number
         at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1[[System.Decimal, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadJsonAndSetMember(Object , ReadStack& , Utf8JsonReader& )
         at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& , Dictionary`2& , JsonSerializerOptions , ReadStack& )
         Exception_EndOfInnerExceptionStack
         at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& , Dictionary`2& , JsonSerializerOptions , ReadStack& )
         at System.Text.Json.JsonSerializer.ReadAsObject(Utf8JsonReader& , JsonTypeInfo )
         at Microsoft.JSInterop.JSRuntime.EndInvokeJS(Int64 , Boolean , Utf8JsonReader& )
         Exception_EndOfInnerExceptionStack
         at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
         at AntDesign.AntComponentBase.<JsInvokeAsync>d__15`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
         at AntDesign.Tabs.ResetSizes()
         at AntDesign.Tabs.OnAfterRenderAsync(Boolean firstRender)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState )
Microsoft.JSInterop.JSException: An exception occurred executing JS interop: DeserializeUnableToConvertValue, System.Decimal Path: $.ant-blazor-cbb8972b-4123-4621-8a63-85f2707485be-nav-list.marginTop | LineNumber: 0 | BytePositionInLine: 315.. See InnerException for more details.
 ---> System.Text.Json.JsonException: DeserializeUnableToConvertValue, System.Decimal Path: $.ant-blazor-cbb8972b-4123-4621-8a63-85f2707485be-nav-list.marginTop | LineNumber: 0 | BytePositionInLine: 315.
 ---> System.InvalidOperationException: InvalidCast, Null, number
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1[[System.Decimal, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadJsonAndSetMember(Object , ReadStack& , Utf8JsonReader& )
   at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& , Dictionary`2& , JsonSerializerOptions , ReadStack& )
   Exception_EndOfInnerExceptionStack
   at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& , Dictionary`2& , JsonSerializerOptions , ReadStack& )
   at System.Text.Json.JsonSerializer.ReadAsObject(Utf8JsonReader& , JsonTypeInfo )
   at Microsoft.JSInterop.JSRuntime.EndInvokeJS(Int64 , Boolean , Utf8JsonReader& )
   Exception_EndOfInnerExceptionStack
   at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at AntDesign.AntComponentBase.<JsInvokeAsync>d__15`1[[System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[AntDesign.JsInterop.HtmlElement, AntDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at AntDesign.Tabs.ResetSizes()
   at AntDesign.Tabs.OnAfterRenderAsync(Boolean firstRender)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState )
```
</details>

Pull request description:
- Added manipulationHelper class with parseNumericValue method to safely parse CSS numeric values, handling cases like 'auto', 'inherit', and 'initial'.
- Updated tableHelper and infoHelper to utilize manipulationHelper for margin and padding calculations, improving robustness against invalid CSS values.
- Enhanced tests for manipulationHelper to cover various edge cases and ensure correct behavior for auto, inherit, and initial values.

<!--
First of all, thank you for your contribution! 😄

New feature please send pull request to feature branch, and rest to master branch.
Pull request will be merged after one of collaborators approve.
Please makes sure that these form are filled before submitting your pull request, thank you!

[[中文版模板 / Chinese template](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]

-->

### 🤔 This is a ...

- [ ] New feature
- [x] Bug fix
- [ ] Site / documentation update
- [ ] Demo update
- [ ] Component style update
- [ ] Bundle size optimization
- [ ] Performance optimization
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Test Case
- [ ] Branch merge
- [ ] Other (about what?)

### 🔗 Related issue link

fixed #4609

<!--
1. Describe the source of requirement, like related issue link.
-->

### 💡 Background and solution

<!--
1. Describe the problem and the scenario.
2. GIF or snapshot should be provided if includes UI/interactive modification.
3. How to fix the problem, and list final API implementation and usage sample if that is an new feature.
-->

### 📝 Changelog

<!--
Describe changes from userside, and list all potential break changes or other risks.
--->

| Language   | Changelog |
| ---------- | --------- |
| 🇺🇸 English |           |
| 🇨🇳 Chinese |           |

### ☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] Changelog is provided or not needed

Patch:
diff --git a/components/core/JsInterop/modules/components/tableHelper.ts b/components/core/JsInterop/modules/components/tableHelper.ts
index a964dba186..37fec73e36 100644
--- a/components/core/JsInterop/modules/components/tableHelper.ts
+++ b/components/core/JsInterop/modules/components/tableHelper.ts
@@ -1,4 +1,7 @@
-﻿export class tableHelper {
+﻿import { manipulationHelper } from '../dom/manipulationHelper'
+
+export class tableHelper {
+
   static isHidden(element) {
     if (element) {
       const computedStyle = getComputedStyle(element);
@@ -40,24 +43,23 @@
     if (parentElement) {
       const parentComputedStyle = getComputedStyle(parentElement);
       if (parentComputedStyle.rowGap && parentComputedStyle.rowGap.endsWith('px')) {
-        rowGap = parseFloat(parentComputedStyle.rowGap);        
+        rowGap = manipulationHelper.parseNumericValue(parentComputedStyle.rowGap);        
       }
       if (parentComputedStyle.borderStyle != 'none' && parentComputedStyle.borderBottom) {        
-        parentBorderBottom = parseFloat(parentComputedStyle.borderBottom);        
+        parentBorderBottom = manipulationHelper.parseNumericValue(parentComputedStyle.borderBottom);        
       }
       if (parentComputedStyle.paddingBottom) {
-        parentPaddingBottom = parseFloat(parentComputedStyle.paddingBottom);
+        parentPaddingBottom = manipulationHelper.parseNumericValue(parentComputedStyle.paddingBottom);
       }
     }
     let previousElement = element;
     let previousComputedStyle = getComputedStyle(element);
 
-
     while (currentElement) {
       const currentComputedStyle = getComputedStyle(currentElement);
       const hasSameZIndex = previousComputedStyle.getPropertyValue('z-index') == currentComputedStyle.getPropertyValue('z-index');
       if (!tableHelper.isIgnore(currentElement, currentComputedStyle, left, right) && hasSameZIndex) {
-        totalHeight += currentElement.offsetHeight + Math.max(parseFloat(currentComputedStyle.marginTop), parseFloat(previousComputedStyle.marginBottom)) + rowGap;
+        totalHeight += currentElement.offsetHeight + Math.max(manipulationHelper.parseNumericValue(currentElement, 'marginTop'), manipulationHelper.parseNumericValue(previousElement, 'marginBottom')) + rowGap;
 
         previousElement = currentElement;
         previousComputedStyle = currentComputedStyle;
@@ -66,7 +68,7 @@
    
     }
     if (!tableHelper.isIgnore(previousElement, previousComputedStyle, left, right)) {
-      marginBottom = Math.max(parseFloat(previousComputedStyle.marginBottom), marginBottom);
+      marginBottom = Math.max(manipulationHelper.parseNumericValue(previousElement, 'marginBottom'), marginBottom);
       if (parentBorderBottom > 0.1 || parentPaddingBottom>0.1) {
         totalHeight += marginBottom;
         marginBottom = 0;
diff --git a/components/core/JsInterop/modules/dom/infoHelper.ts b/components/core/JsInterop/modules/dom/infoHelper.ts
index 9507b08f9d..dddcb68043 100644
--- a/components/core/JsInterop/modules/dom/infoHelper.ts
+++ b/components/core/JsInterop/modules/dom/infoHelper.ts
@@ -1,6 +1,8 @@
 ﻿import { domTypes } from './exports'
+import { manipulationHelper } from './manipulationHelper'
 
 export class infoHelper {
+
   static getWindow() {
     return {
       innerWidth: window.innerWidth,
@@ -33,11 +35,10 @@ export class infoHelper {
     let elementMarginLeft = 0;
     let elementMarginRight = 0;
     if (domElement instanceof HTMLElement) {
-      const style = window.getComputedStyle(domElement);
-      elementMarginTop = parseFloat(style.marginTop);
-      elementMarginBottom = parseFloat(style.marginBottom);
-      elementMarginLeft = parseFloat(style.marginLeft);
-      elementMarginRight = parseFloat(style.marginRight);
+      elementMarginTop = manipulationHelper.parseNumericValue(domElement, 'marginTop');
+      elementMarginBottom = manipulationHelper.parseNumericValue(domElement, 'marginBottom');
+      elementMarginLeft = manipulationHelper.parseNumericValue(domElement, 'marginLeft');
+      elementMarginRight = manipulationHelper.parseNumericValue(domElement, 'marginRight');
     }
 
     const result: domTypes.domInfo = {
diff --git a/components/core/JsInterop/modules/dom/manipulationHelper.ts b/components/core/JsInterop/modules/dom/manipulationHelper.ts
index 86fa125233..7f4b0e20e9 100644
--- a/components/core/JsInterop/modules/dom/manipulationHelper.ts
+++ b/components/core/JsInterop/modules/dom/manipulationHelper.ts
@@ -7,6 +7,164 @@ let cachedScrollBarSize: number | undefined = undefined;
 const scrollIds = new Map<HTMLElement, number>();
 
 export class manipulationHelper {
+  /**
+   * Safely parse CSS numeric values, returning 0 for "auto" or invalid values
+   * @param element The HTML element to get CSS property from
+   * @param property The CSS property name (e.g., 'marginTop', 'marginLeft')
+   * @returns Parsed number or 0 if invalid
+   */
+  static parseNumericValue(element: HTMLElement, property: string): number;
+  /**
+   * Safely parse CSS numeric values, returning 0 for "auto" or invalid values
+   * @param value CSS value to parse
+   * @returns Parsed number or 0 if invalid
+   */
+  static parseNumericValue(value: string): number;
+  static parseNumericValue(elementOrValue: HTMLElement | string, property?: string): number {
+    // If first parameter is HTMLElement, get the style value and calculate
+    if (elementOrValue instanceof HTMLElement && property) {
+      const element = elementOrValue;
+      const style = window.getComputedStyle(element);
+      const value = style[property];
+
+      // Check if the element's inline style has the property set to inherit
+      // This is needed because in some test environments, getComputedStyle
+      // returns empty string for inherit values
+      const cssProperty = property.replace(/([A-Z])/g, '-$1').toLowerCase();
+      const inlineValue = element.style[property] || element.style.getPropertyValue(cssProperty);
+      if (inlineValue === 'inherit') {
+        return this.calculateInheritValue(element, property);
+      }
+
+      if (!value) {
+        return 0;
+      }
+
+      // Handle special CSS values
+      if (value === 'auto') {
+        return this.calculateAutoValue(element, property);
+      } else if (value === 'inherit') {
+        return this.calculateInheritValue(element, property);
+      } else if (value === 'initial' || value === 'unset') {
+        return 0;
+      }
+
+      const parsed = parseFloat(value);
+      return isNaN(parsed) ? 0 : parsed;
+    }
+
+    // Legacy support: if first parameter is string, parse it directly
+    if (typeof elementOrValue === 'string') {
+      const value = elementOrValue;
+      if (!value || value === 'auto' || value === 'inherit' || value === 'initial' || value === 'unset') {
+        return 0;
+      }
+
+      const parsed = parseFloat(value);
+      return isNaN(parsed) ? 0 : parsed;
+    }
+
+    return 0;
+  }
+
+  /**
+   * Calculate the actual pixel value for CSS properties set to "auto"
+   * @param element The HTML element
+   * @param property The CSS property name (e.g., 'marginTop', 'marginLeft')
+   * @returns The calculated pixel value or 0 if cannot be determined
+   */
+  private static calculateAutoValue(element: HTMLElement, property: string): number {
+    try {
+      const rect = element.getBoundingClientRect();
+      const parent = element.parentElement;
+
+      if (!parent) return 0;
+
+      const parentRect = parent.getBoundingClientRect();
+
+      switch (property) {
+        case 'marginTop': {
+          // Calculate actual top margin
+          return Math.max(0, rect.top - parentRect.top - element.offsetTop);
+        }
+
+        case 'marginBottom': {
+          // Calculate actual bottom margin
+          const parentBottom = parentRect.bottom;
+          const elementBottom = rect.bottom;
+          return Math.max(0, parentBottom - elementBottom - (parent.offsetHeight - element.offsetTop - element.offsetHeight));
+        }
+
+        case 'marginLeft': {
+          // For auto left margin, calculate actual left margin
+          const parentLeft = parentRect.left;
+          const elementLeft = rect.left;
+          return Math.max(0, elementLeft - parentLeft - element.offsetLeft);
+        }
+
+        case 'marginRight': {
+          // For auto right margin, calculate actual right margin
+          const parentRight = parentRect.right;
+          const elementRight = rect.right;
+          return Math.max(0, parentRight - elementRight - (parent.offsetWidth - element.offsetLeft - element.offsetWidth));
+        }
+
+        default:
+          return 0;
+      }
+    } catch (error) {
+      // If calculation fails, return 0 as fallback
+      return 0;
+    }
+  }
+
+  /**
+   * Calculate the actual pixel value for CSS properties set to "inherit"
+   * @param element The HTML element
+   * @param property The CSS property name
+   * @returns The inherited value from parent element or 0 if cannot be determined
+   */
+  private static calculateInheritValue(element: HTMLElement, property: string): number {
+    try {
+      const parent = element.parentElement;
+      if (!parent) return 0;
+
+      // First try to get the parent's computed style value
+      const parentStyle = window.getComputedStyle(parent);
+      const parentValue = parentStyle[property];
+
+      // If parent has a valid numeric value, parse it directly
+      if (parentValue && parentValue !== 'inherit' && parentValue !== 'auto' && parentValue !== 'initial' && parentValue !== 'unset' && parentValue.trim() !== '') {
+        const parsed = parseFloat(parentValue);
+        if (!isNaN(parsed)) {
+          return parsed;
+        }
+      }
+
+      // If getComputedStyle doesn't work (empty string in test environments),
+      // try to get the value from the parent's inline style
+      if (parent instanceof HTMLElement && parent.style) {
+        const inlineValue = parent.style[property];
+        if (inlineValue && inlineValue !== 'inherit' && inlineValue !== 'auto' && inlineValue !== 'initial' && inlineValue !== 'unset') {
+          const parsed = parseFloat(inlineValue);
+          if (!isNaN(parsed)) {
+            return parsed;
+          }
+        }
+      }
+
+      // If parent value is also inherit/auto/etc, recursively parse it
+      if (parentValue === 'inherit' || parentValue === 'auto' || parentValue === 'initial' || parentValue === 'unset') {
+        return this.parseNumericValue(parent, property);
+      }
+
+      // If we still can't get the parent value, return 0 as fallback
+      return 0;
+    } catch (error) {
+      return 0;
+    }
+  }
+
   static addElementToBody(element) {
     document.body.appendChild(element);
   }
@@ -312,10 +470,10 @@ export class manipulationHelper {
       cachedScrollBarSize = widthContained - widthScroll;
     }
 
-    if (manipulationHelper.hasScrollbar()){
+    if (manipulationHelper.hasScrollbar()) {
       document.documentElement.style.setProperty('--ant-scrollbar-width', `${cachedScrollBarSize}px`);
     }
-  
+
     return cachedScrollBarSize;
   };
 }


Test patch:
diff --git a/tests/AntDesign.Tests.Js/tests/domInit.ts b/tests/AntDesign.Tests.Js/tests/domInit.ts
index fbca2a48a2..e17615309d 100644
--- a/tests/AntDesign.Tests.Js/tests/domInit.ts
+++ b/tests/AntDesign.Tests.Js/tests/domInit.ts
@@ -16,6 +16,8 @@ const { window } = new JSDOM('<!doctype html><html><body></body></html>');
 global.document = window.document;
 global.window = global.document.defaultView;
 global.Node = window.Node;
+global.HTMLElement = window.HTMLElement;
+global.getComputedStyle = window.getComputedStyle;
 
 export class Guid {
   static newGuid() {
diff --git a/tests/AntDesign.Tests.Js/tests/modules/dom/infoHelper.test.ts b/tests/AntDesign.Tests.Js/tests/modules/dom/infoHelper.test.ts
index b8993f6f86..7c5e9c0cc3 100644
--- a/tests/AntDesign.Tests.Js/tests/modules/dom/infoHelper.test.ts
+++ b/tests/AntDesign.Tests.Js/tests/modules/dom/infoHelper.test.ts
@@ -21,4 +21,76 @@ describe('domInfoHelper', () => {
     expect(pos).to.haveOwnProperty("x");
     expect(pos).to.haveOwnProperty("y");
   });
+
+  it('getInfo should handle elements with auto margins without crashing', () => {
+    //arrange
+    const testedElement = domInit.addElementToBody('<div id="autoMarginTest" style="margin: auto; width: 100px;">Test element</div>');
+    
+    //act
+    let info = infoHelper.getInfo(testedElement);
+    
+    //assert
+    expect(info).to.haveOwnProperty("marginTop");
+    expect(info).to.haveOwnProperty("marginBottom");
+    expect(info).to.haveOwnProperty("marginLeft");
+    expect(info).to.haveOwnProperty("marginRight");
+    
+    // All margin values should be numbers (not NaN) when margin is auto
+    // Now they might be actual calculated values instead of just 0
+    expect(typeof info.marginTop).to.equal('number');
+    expect(typeof info.marginBottom).to.equal('number');
+    expect(typeof info.marginLeft).to.equal('number');
+    expect(typeof info.marginRight).to.equal('number');
+    
+    expect(Number.isNaN(info.marginTop)).to.be.false;
+    expect(Number.isNaN(info.marginBottom)).to.be.false;
+    expect(Number.isNaN(info.marginLeft)).to.be.false;
+    expect(Number.isNaN(info.marginRight)).to.be.false;
+    
+    // Values should be >= 0 (could be 0 or actual calculated margins)
+    expect(info.marginTop).to.be.at.least(0);
+    expect(info.marginBottom).to.be.at.least(0);
+    expect(info.marginLeft).to.be.at.least(0);
+    expect(info.marginRight).to.be.at.least(0);
+  });
+
+  it('getInfo should handle elements with inherit margins without crashing', () => {
+    //arrange
+    const testedElement = domInit.addElementToBody('<div id="inheritMarginTest" style="margin: inherit;">Test element</div>');
+    
+    //act
+    let info = infoHelper.getInfo(testedElement);
+    
+    //assert
+    // Values should be numbers (not NaN) and >= 0
+    expect(typeof info.marginTop).to.equal('number');
+    expect(typeof info.marginBottom).to.equal('number');
+    expect(typeof info.marginLeft).to.equal('number');
+    expect(typeof info.marginRight).to.equal('number');
+    
+    expect(Number.isNaN(info.marginTop)).to.be.false;
+    expect(Number.isNaN(info.marginBottom)).to.be.false;
+    expect(Number.isNaN(info.marginLeft)).to.be.false;
+    expect(Number.isNaN(info.marginRight)).to.be.false;
+    
+    expect(info.marginTop).to.be.at.least(0);
+    expect(info.marginBottom).to.be.at.least(0);
+    expect(info.marginLeft).to.be.at.least(0);
+    expect(info.marginRight).to.be.at.least(0);
+  });
+
+  it('getInfo should handle elements with initial margins correctly', () => {
+    //arrange
+    const testedElement = domInit.addElementToBody('<div id="initialMarginTest" style="margin: initial;">Test element</div>');
+    
+    //act
+    let info = infoHelper.getInfo(testedElement);
+    
+    //assert
+    // Initial margin values should be 0
+    expect(info.marginTop).to.equal(0);
+    expect(info.marginBottom).to.equal(0);
+    expect(info.marginLeft).to.equal(0);
+    expect(info.marginRight).to.equal(0);
+  });
 });
diff --git a/tests/AntDesign.Tests.Js/tests/modules/dom/manipulationHelper.test.ts b/tests/AntDesign.Tests.Js/tests/modules/dom/manipulationHelper.test.ts
index 405f1cd4d9..a2f94d6115 100644
--- a/tests/AntDesign.Tests.Js/tests/modules/dom/manipulationHelper.test.ts
+++ b/tests/AntDesign.Tests.Js/tests/modules/dom/manipulationHelper.test.ts
@@ -66,4 +66,199 @@ describe("domManipulationHelper", () => {
     expect(document.body.getAttribute("class")).to.equal(attributes.class);
   });
 
+  describe("parseNumericValue", () => {
+    it("should return 0 for 'auto' value", () => {
+      const result = manipulationHelper.parseNumericValue("auto");
+      expect(result).to.equal(0);
+    });
+
+    it("should return 0 for 'inherit' value", () => {
+      const result = manipulationHelper.parseNumericValue("inherit");
+      expect(result).to.equal(0);
+    });
+
+    it("should return 0 for 'initial' value", () => {
+      const result = manipulationHelper.parseNumericValue("initial");
+      expect(result).to.equal(0);
+    });
+
+    it("should return 0 for empty string", () => {
+      const result = manipulationHelper.parseNumericValue("");
+      expect(result).to.equal(0);
+    });
+
+    it("should return 0 for null/undefined", () => {
+      const result1 = manipulationHelper.parseNumericValue(null as any);
+      const result2 = manipulationHelper.parseNumericValue(undefined as any);
+      expect(result1).to.equal(0);
+      expect(result2).to.equal(0);
+    });
+
+    it("should parse valid numeric values correctly", () => {
+      expect(manipulationHelper.parseNumericValue("10px")).to.equal(10);
+      expect(manipulationHelper.parseNumericValue("15.5")).to.equal(15.5);
+      expect(manipulationHelper.parseNumericValue("0")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("-5")).to.equal(-5);
+      expect(manipulationHelper.parseNumericValue("100%")).to.equal(100);
+    });
+
+    it("should return 0 for invalid numeric values", () => {
+      expect(manipulationHelper.parseNumericValue("invalid")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("abc")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("px")).to.equal(0);
+    });
+
+    it("should handle edge cases that would cause NaN", () => {
+      // These are the cases that would previously cause crashes
+      expect(manipulationHelper.parseNumericValue("auto")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("inherit")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("initial")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("unset")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("revert")).to.equal(0);
+    });
+
+    it("should calculate actual values for auto margins when element is provided", () => {
+      // Create a test element with auto margins
+      const container = document.createElement("div");
+      container.style.width = "200px";
+      container.style.height = "100px";
+      container.style.position = "relative";
+      document.body.appendChild(container);
+
+      const element = document.createElement("div");
+      element.style.width = "100px";
+      element.style.height = "50px";
+      element.style.margin = "auto";
+      element.style.position = "absolute";
+      element.style.top = "0";
+      element.style.left = "0";
+      container.appendChild(element);
+
+      // Test with element and property - new API
+      const marginValue = manipulationHelper.parseNumericValue(element, "marginLeft");
+      
+      // Should return a number (actual calculated margin) instead of 0
+      expect(typeof marginValue).to.equal("number");
+      expect(Number.isNaN(marginValue)).to.be.false;
+      
+      // Clean up
+      document.body.removeChild(container);
+    });
+
+    it("should fallback to 0 when auto calculation fails", () => {
+      const element = document.createElement("div");
+      // Don't add to DOM, so calculation should fail gracefully
+      element.style.margin = "auto";
+      
+      const marginValue = manipulationHelper.parseNumericValue(element, "marginLeft");
+      expect(marginValue).to.equal(0);
+    });
+
+    it("should support legacy string-based API", () => {
+      // Test legacy API still works
+      expect(manipulationHelper.parseNumericValue("10px")).to.equal(10);
+      expect(manipulationHelper.parseNumericValue("auto")).to.equal(0);
+      expect(manipulationHelper.parseNumericValue("inherit")).to.equal(0);
+    });
+
+    it("should calculate inherit values from parent element", () => {
+      // Create parent with specific margin
+      const parent = document.createElement("div");
+      parent.style.marginLeft = "20px";
+      document.body.appendChild(parent);
+
+      // Create child with inherit margin
+      const child = document.createElement("div");
+      child.style.setProperty('margin-left', 'inherit');
+      parent.appendChild(child);
+
+      // Test that the method handles inherit without crashing and returns a number
+      const marginValue = manipulationHelper.parseNumericValue(child, "marginLeft");
+      expect(typeof marginValue).to.equal("number");
+      expect(Number.isNaN(marginValue)).to.be.false;
+      
+      // In test environment (JSDOM), inherit might not work as expected
+      // In real browser, it should return 20, but in test environment it might return 0
+      // The important thing is that it doesn't crash and returns a valid number
+      expect(marginValue).to.be.at.least(0);
+
+      // Clean up
+      document.body.removeChild(parent);
+    });
+
+    it("should handle nested inherit values", () => {
+      // Create grandparent with specific margin
+      const grandparent = document.createElement("div");
+      grandparent.style.marginTop = "30px";
+      document.body.appendChild(grandparent);
+
+      // Create parent with inherit margin
+      const parent = document.createElement("div");
+      parent.style.marginTop = "inherit";
+      grandparent.appendChild(parent);
+
+      // Create child with inherit margin
+      const child = document.createElement("div");
+      child.style.marginTop = "inherit";
+      parent.appendChild(child);
+
+      // Test that nested inherit doesn't crash
+      const marginValue = manipulationHelper.parseNumericValue(child, "marginTop");
+      expect(typeof marginValue).to.equal("number");
+      expect(Number.isNaN(marginValue)).to.be.false;
+      expect(marginValue).to.be.at.least(0);
+
+      // Clean up
+      document.body.removeChild(grandparent);
+    });
+
+    it("should directly test inherit calculation with known parent value", () => {
+      // Create parent with specific margin
+      const parent = document.createElement("div");
+      parent.style.marginLeft = "25px";
+      document.body.appendChild(parent);
+
+      // Create child
+      const child = document.createElement("div");
+      parent.appendChild(child);
+
+      // Test calculateInheritValue method directly by accessing it through the class
+      // We'll simulate the inherit scenario by directly calling the method
+      const inheritValue = (manipulationHelper as any).calculateInheritValue(child, "marginLeft");
+      expect(typeof inheritValue).to.equal("number");
+      expect(Number.isNaN(inheritValue)).to.be.false;
+      // Should get the parent's 25px value
+      expect(inheritValue).to.equal(25);
+
+      // Clean up
+      document.body.removeChild(parent);
+    });
+
+    it("should handle initial values correctly", () => {
+      const element = document.createElement("div");
+      element.style.marginTop = "initial";
+      document.body.appendChild(element);
+
+      // Initial value for margin should be 0
+      const marginValue = manipulationHelper.parseNumericValue(element, "marginTop");
+      expect(marginValue).to.equal(0);
+
+      // Clean up
+      document.body.removeChild(element);
+    });
+
+    it("should handle unset values correctly", () => {
+      const element = document.createElement("div");
+      element.style.marginBottom = "unset";
+      document.body.appendChild(element);
+
+      // Unset value for margin should be 0 (since margin is not inherited)
+      const marginValue = manipulationHelper.parseNumericValue(element, "marginBottom");
+      expect(marginValue).to.equal(0);
+
+      // Clean up
+      document.body.removeChild(element);
+    });
+  });
+
 });