microsoft/TypeAgent

Public

mirrored fromhttps://github.com/microsoft/TypeAgentAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
d4944c6517c9a96a3c419f827769f518913f1b75

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

dotnet/autoShell.Tests/AudioActionHandlerTests.cs

224lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text.Json;
5using autoShell.Handlers;
6using autoShell.Services;
7using Moq;
8
9namespace autoShell.Tests;
10
11public class AudioActionHandlerTests
12{
13 private readonly Mock<IAudioService> _audioMock = new();
14 private readonly AudioActionHandler _handler;
15
16 public AudioActionHandlerTests()
17 {
18 _handler = new AudioActionHandler(_audioMock.Object);
19 }
20
21 // --- Volume ---
22
23 /// <summary>
24 /// Verifies that valid integer percentage values are forwarded to <see cref="IAudioService.SetVolume"/>.
25 /// </summary>
26 [Theory]
27 [InlineData(0)]
28 [InlineData(50)]
29 [InlineData(100)]
30 public void Volume_ValidPercent_SetsVolume(int targetVolume)
31 {
32 _audioMock.Setup(a => a.GetVolume()).Returns(75);
33
34 _handler.Handle("Volume", JsonDocument.Parse($$"""{"targetVolume":{{targetVolume}}}""").RootElement);
35
36 _audioMock.Verify(a => a.SetVolume(targetVolume), Times.Once);
37 }
38
39 /// <summary>
40 /// Verifies that setting volume reads and saves the current level before applying the new one.
41 /// </summary>
42 [Fact]
43 public void Volume_SavesCurrentVolumeBeforeSetting()
44 {
45 _audioMock.Setup(a => a.GetVolume()).Returns(42);
46
47 _handler.Handle("Volume", JsonDocument.Parse("""{"targetVolume":80}""").RootElement);
48
49 // GetVolume should have been called to save the current level
50 _audioMock.Verify(a => a.GetVolume(), Times.Once);
51 }
52
53 /// <summary>
54 /// Verifies that a missing targetVolume defaults to zero (mute).
55 /// The schema defines targetVolume as required, so the LLM always sends it.
56 /// When missing, the typed parameter defaults to 0, resulting in mute.
57 /// </summary>
58 [Fact]
59 public void Volume_MissingTargetVolume_SetsVolumeToZero()
60 {
61 _handler.Handle("Volume", JsonDocument.Parse("{}").RootElement);
62
63 _audioMock.Verify(a => a.SetVolume(0), Times.Once);
64 }
65
66 // --- RestoreVolume ---
67
68 /// <summary>
69 /// Verifies that RestoreVolume restores the volume to the level saved before the last change.
70 /// </summary>
71 [Fact]
72 public void RestoreVolume_AfterVolumeChange_RestoresSavedLevel()
73 {
74 _audioMock.Setup(a => a.GetVolume()).Returns(65);
75
76 _handler.Handle("Volume", JsonDocument.Parse("""{"targetVolume":20}""").RootElement);
77 _audioMock.Invocations.Clear();
78
79 _handler.Handle("RestoreVolume", JsonDocument.Parse("{}").RootElement);
80
81 _audioMock.Verify(a => a.SetVolume(65), Times.Once);
82 }
83
84 /// <summary>
85 /// Verifies that RestoreVolume defaults to zero when no prior volume change has been recorded.
86 /// </summary>
87 [Fact]
88 public void RestoreVolume_WithoutPriorChange_RestoresZero()
89 {
90 _handler.Handle("RestoreVolume", JsonDocument.Parse("{}").RootElement);
91
92 _audioMock.Verify(a => a.SetVolume(0), Times.Once);
93 }
94
95 /// <summary>
96 /// Verifies that RestoreVolume uses the actual saved volume, not a hardcoded value,
97 /// by using a different initial volume than the other RestoreVolume test.
98 /// </summary>
99 [Fact]
100 public void RestoreVolume_DifferentInitialVolume_RestoresSavedLevel()
101 {
102 _audioMock.Setup(a => a.GetVolume()).Returns(30);
103
104 _handler.Handle("Volume", JsonDocument.Parse("""{"targetVolume":80}""").RootElement);
105 _audioMock.Invocations.Clear();
106
107 _handler.Handle("RestoreVolume", JsonDocument.Parse("{}").RootElement);
108
109 _audioMock.Verify(a => a.SetVolume(30), Times.Once);
110 }
111
112 // --- Mute ---
113
114 /// <summary>
115 /// Verifies that the on parameter is forwarded to <see cref="IAudioService.SetMute"/>.
116 /// </summary>
117 [Theory]
118 [InlineData(true)]
119 [InlineData(false)]
120 public void Mute_SetsMute(bool on)
121 {
122 _handler.Handle("Mute", JsonDocument.Parse($$"""{"on":{{on.ToString().ToLowerInvariant()}}}""").RootElement);
123
124 _audioMock.Verify(a => a.SetMute(on), Times.Once);
125 }
126
127 /// <summary>
128 /// Verifies that a missing on parameter defaults to muting (false).
129 /// </summary>
130 [Fact]
131 public void Mute_MissingOn_DefaultsToFalse()
132 {
133 _handler.Handle("Mute", JsonDocument.Parse("{}").RootElement);
134
135 _audioMock.Verify(a => a.SetMute(false), Times.Once);
136 }
137
138 // --- AdjustVolume ---
139
140 /// <summary>
141 /// Verifies that AdjustVolume "up" increases volume by the specified amount.
142 /// </summary>
143 [Fact]
144 public void AdjustVolume_Up_IncreasesVolume()
145 {
146 _audioMock.Setup(a => a.GetVolume()).Returns(50);
147
148 var result = _handler.Handle("AdjustVolume", JsonDocument.Parse("""{"direction":"up","amount":15}""").RootElement);
149
150 Assert.True(result.Success);
151 _audioMock.Verify(a => a.SetVolume(65), Times.Once);
152 }
153
154 /// <summary>
155 /// Verifies that AdjustVolume "down" decreases volume by the specified amount.
156 /// </summary>
157 [Fact]
158 public void AdjustVolume_Down_DecreasesVolume()
159 {
160 _audioMock.Setup(a => a.GetVolume()).Returns(50);
161
162 var result = _handler.Handle("AdjustVolume", JsonDocument.Parse("""{"direction":"down","amount":20}""").RootElement);
163
164 Assert.True(result.Success);
165 _audioMock.Verify(a => a.SetVolume(30), Times.Once);
166 }
167
168 /// <summary>
169 /// Verifies that AdjustVolume defaults to 10% when amount is omitted.
170 /// </summary>
171 [Fact]
172 public void AdjustVolume_DefaultAmount_AdjustsBy10()
173 {
174 _audioMock.Setup(a => a.GetVolume()).Returns(40);
175
176 _handler.Handle("AdjustVolume", JsonDocument.Parse("""{"direction":"up"}""").RootElement);
177
178 _audioMock.Verify(a => a.SetVolume(50), Times.Once);
179 }
180
181 /// <summary>
182 /// Verifies that AdjustVolume clamps to 0-100 range.
183 /// </summary>
184 [Theory]
185 [InlineData("up", 95, 30, 100)] // 95 + 30 = 125, clamped to 100
186 [InlineData("down", 10, 25, 0)] // 10 - 25 = -15, clamped to 0
187 public void AdjustVolume_ClampsToRange(string direction, int current, int amount, int expected)
188 {
189 _audioMock.Setup(a => a.GetVolume()).Returns(current);
190
191 _handler.Handle("AdjustVolume", JsonDocument.Parse($$"""{"direction":"{{direction}}","amount":{{amount}}}""").RootElement);
192
193 _audioMock.Verify(a => a.SetVolume(expected), Times.Once);
194 }
195
196 /// <summary>
197 /// Verifies that AdjustVolume saves the current volume before adjusting.
198 /// </summary>
199 [Fact]
200 public void AdjustVolume_SavesCurrentVolume()
201 {
202 _audioMock.Setup(a => a.GetVolume()).Returns(60);
203
204 _handler.Handle("AdjustVolume", JsonDocument.Parse("""{"direction":"up","amount":10}""").RootElement);
205 _audioMock.Invocations.Clear();
206
207 _handler.Handle("RestoreVolume", JsonDocument.Parse("{}").RootElement);
208
209 _audioMock.Verify(a => a.SetVolume(60), Times.Once);
210 }
211
212 // --- Unknown key ---
213
214 /// <summary>
215 /// Verifies that an unknown command key does not invoke any audio service methods.
216 /// </summary>
217 [Fact]
218 public void Handle_UnknownKey_DoesNothing()
219 {
220 _handler.Handle("UnknownAudioCmd", JsonDocument.Parse("{}").RootElement);
221
222 _audioMock.VerifyNoOtherCalls();
223 }
224}