Skip to content

Commit ca06cdb

Browse files
authored
Merge pull request #139 from emncnozge/slider-theme-tree-tests
Add Slider marker feature and unit tests for Slider, Tree, and Theme
2 parents 18f3dcd + 2aa23aa commit ca06cdb

File tree

7 files changed

+477
-10
lines changed

7 files changed

+477
-10
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ public partial class Index
152152
- [Pill](#pill)
153153
- [Radio Button](#radio-button)
154154
- [Select](#select)
155+
- [Slider](#slider)
155156
- [Spinner](#spinner)
156157
- [Split Button](#split-button)
157158
- [Tabs](#tabs)
@@ -1173,6 +1174,14 @@ AddItemEvent="SelectItemAdded" Mode="SelectMode.Single" SelectedIndices="2" Id="
11731174
<SelectItem Id="selectItem2" Label="Item 2" Value="2"></SelectItem>
11741175
</Select>
11751176
```
1177+
## Slider
1178+
1179+
```razor
1180+
<Slider Id="slider-demo" Min="0" Max="50" Step="5" Value="0" Marker="[0, 10, 20, 30, 40, 50]">
1181+
<span slot="label-start">0</span>
1182+
<span slot="label-end">50</span>
1183+
</Slider>
1184+
```
11761185

11771186
## Spinner
11781187

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// -----------------------------------------------------------------------
2+
// SPDX-FileCopyrightText: 2025 Siemens AG
3+
//
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This source code is licensed under the MIT license found in the
7+
// LICENSE file in the root directory of this source tree.
8+
// -----------------------------------------------------------------------
9+
10+
using Bunit;
11+
using Microsoft.AspNetCore.Components;
12+
using Microsoft.Extensions.DependencyInjection;
13+
using Microsoft.JSInterop;
14+
using Moq;
15+
using SiemensIXBlazor.Components.Slider;
16+
17+
namespace SiemensIXBlazor.Tests;
18+
19+
public class SliderTests : TestContextBase
20+
{
21+
[Fact]
22+
public void Slider_RenderedWithCorrectAttributes()
23+
{
24+
// Arrange
25+
var id = "slider1";
26+
var error = "error message";
27+
28+
var cut = RenderComponent<Slider>(parameters => parameters
29+
.Add(p => p.Id, id)
30+
.Add(p => p.Value, 42)
31+
.Add<dynamic>(p => p.Error, error)
32+
.Add(p => p.Max, 100)
33+
.Add(p => p.Min, 0)
34+
.Add(p => p.Step, 1)
35+
.Add(p => p.Disabled, true)
36+
.Add(p => p.Trace, true)
37+
.Add(p => p.TraceReference, 5)
38+
);
39+
40+
cut.MarkupMatches(@$"
41+
<ix-slider
42+
id=""{id}""
43+
value=""42""
44+
disabled
45+
error=""{error}""
46+
max=""100""
47+
min=""0""
48+
step=""1""
49+
trace
50+
trace-reference=""5"">
51+
</ix-slider>");
52+
}
53+
54+
[Fact]
55+
public async Task ValueChanged_InvokesValueChangeEvent()
56+
{
57+
// Arrange
58+
double eventValue = 0;
59+
var cut = RenderComponent<Slider>(parameters => parameters
60+
.Add(p => p.Id, "slider2")
61+
.Add(p => p.ValueChangeEvent, EventCallback.Factory.Create<double>(this, v => eventValue = v))
62+
);
63+
64+
// Act
65+
await cut.Instance.ValueChanged(75.5);
66+
67+
// Assert
68+
Assert.Equal(75.5, eventValue);
69+
}
70+
71+
[Fact]
72+
public void OnAfterRenderAsync_FirstRender_AttachesListenerAndSetsMarker()
73+
{
74+
// Arrange
75+
var jsRuntimeMock = new Mock<IJSRuntime>();
76+
var jsObjectReferenceMock = new Mock<IJSObjectReference>();
77+
78+
jsRuntimeMock
79+
.Setup(js => js.InvokeAsync<IJSObjectReference>(
80+
"import",
81+
It.IsAny<object[]>()
82+
))
83+
.ReturnsAsync(jsObjectReferenceMock.Object);
84+
85+
jsObjectReferenceMock
86+
.Setup(js => js.InvokeAsync<string>(
87+
"listenEvent",
88+
It.IsAny<object[]>()
89+
))
90+
.ReturnsAsync("fakeEventId");
91+
92+
jsObjectReferenceMock
93+
.Setup(js => js.InvokeAsync<object>(
94+
"setMarker",
95+
It.IsAny<object[]>()
96+
))
97+
.ReturnsAsync(new object());
98+
99+
Services.AddSingleton(jsRuntimeMock.Object);
100+
101+
var markerArray = new double[] { 0, 25, 50 };
102+
103+
// Act
104+
var cut = RenderComponent<Slider>(parameters => parameters
105+
.Add(p => p.Id, "slider-js")
106+
.Add(p => p.Marker, markerArray)
107+
);
108+
109+
// Assert
110+
jsObjectReferenceMock.Verify(js => js.InvokeAsync<string>(
111+
"listenEvent",
112+
It.Is<object[]>(args =>
113+
args.Length >= 4 &&
114+
args[1] != null &&
115+
args[1].ToString() == "slider-js" &&
116+
args[2] != null &&
117+
args[2].ToString() == "valueChange" &&
118+
args[3] != null &&
119+
args[3].ToString() == "ValueChanged"
120+
)
121+
), Times.Once());
122+
123+
jsObjectReferenceMock.Verify(js => js.InvokeAsync<object>(
124+
"setMarker",
125+
It.Is<object[]>(args =>
126+
args.Length == 2 &&
127+
args[0] != null &&
128+
args[0].ToString() == "slider-js" &&
129+
args[1] != null &&
130+
args[1].GetType() == typeof(double[]) &&
131+
((double[])args[1]).SequenceEqual(markerArray)
132+
)
133+
), Times.Once());
134+
}
135+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// -----------------------------------------------------------------------
2+
// SPDX-FileCopyrightText: 2025 Siemens AG
3+
//
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This source code is licensed under the MIT license found in the
7+
// LICENSE file in the root directory of this source tree.
8+
// -----------------------------------------------------------------------
9+
10+
using Microsoft.Extensions.DependencyInjection;
11+
using Microsoft.JSInterop;
12+
using Moq;
13+
using SiemensIXBlazor.Components;
14+
15+
namespace SiemensIXBlazor.Tests;
16+
17+
public class ThemeTests : TestContextBase
18+
{
19+
[Fact]
20+
public async Task SetTheme_InvokesJsRuntimeWithCorrectParameters()
21+
{
22+
// Arrange
23+
var jsRuntimeMock = new Mock<IJSRuntime>();
24+
Services.AddSingleton<IJSRuntime>(jsRuntimeMock.Object);
25+
var themeName = "dark";
26+
27+
// Act
28+
var cut = RenderComponent<Theme>();
29+
await cut.Instance.SetTheme(themeName);
30+
31+
// Assert
32+
jsRuntimeMock.Verify(js => js.InvokeAsync<object>(
33+
"siemensIXInterop.setTheme",
34+
It.Is<object[]>(args =>
35+
args.Length == 1 &&
36+
args[0] is string &&
37+
(string)args[0] == themeName
38+
)
39+
), Times.Once());
40+
41+
jsRuntimeMock.VerifyNoOtherCalls();
42+
}
43+
44+
[Fact]
45+
public async Task ToggleTheme_InvokesJsRuntimeWithCorrectParameters()
46+
{
47+
// Arrange
48+
var jsRuntimeMock = new Mock<IJSRuntime>();
49+
Services.AddSingleton<IJSRuntime>(jsRuntimeMock.Object);
50+
51+
// Act
52+
var cut = RenderComponent<Theme>();
53+
await cut.Instance.ToggleTheme();
54+
55+
// Assert
56+
jsRuntimeMock.Verify(js => js.InvokeAsync<object>(
57+
"siemensIXInterop.toggleTheme",
58+
It.Is<object[]>(args => args.Length == 0)
59+
), Times.Once());
60+
61+
jsRuntimeMock.VerifyNoOtherCalls();
62+
}
63+
64+
[Fact]
65+
public async Task ToggleSystemTheme_InvokesJsRuntimeWithCorrectParameters()
66+
{
67+
// Arrange
68+
var jsRuntimeMock = new Mock<IJSRuntime>();
69+
Services.AddSingleton<IJSRuntime>(jsRuntimeMock.Object);
70+
var useSystemTheme = true;
71+
72+
// Act
73+
var cut = RenderComponent<Theme>();
74+
await cut.Instance.ToggleSystemTheme(useSystemTheme);
75+
76+
// Assert
77+
jsRuntimeMock.Verify(js => js.InvokeAsync<object>(
78+
"siemensIXInterop.toggleSystemTheme",
79+
It.Is<object[]>(args =>
80+
args.Length == 1 &&
81+
args[0] is bool &&
82+
(bool)args[0] == useSystemTheme
83+
)
84+
), Times.Once());
85+
86+
jsRuntimeMock.VerifyNoOtherCalls();
87+
}
88+
}

0 commit comments

Comments
 (0)