microsoft/TypeAgent

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/review-tests-to-test-live

Branches

Tags

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

Clone

HTTPS

Download ZIP

dotnet/autoShell.Tests/EndToEndTests.cs

269lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Newtonsoft.Json.Linq;
5
6namespace autoShell.Tests;
7
8/// <summary>
9/// End-to-end tests that launch autoShell.exe as a child process and communicate
10/// via the stdin/stdout JSON protocol. Tests the full pipeline including process
11/// startup, JSON parsing, command dispatch, and response serialization.
12/// </summary>
13[Trait("Category", "E2E")]
14public sealed class EndToEndTests : IDisposable
15{
16 private readonly AutoShellProcess _process;
17
18 public EndToEndTests()
19 {
20 _process = AutoShellProcess.StartInteractive();
21 }
22
23 public void Dispose()
24 {
25 _process.Dispose();
26 }
27
28 // --- Query commands (assert JSON stdout) ---
29
30 /// <summary>
31 /// Verifies that ListAppNames returns a valid JSON array of app names via stdout.
32 /// </summary>
33 [Fact]
34 public async Task ListAppNames_ReturnsJsonArray()
35 {
36 _process.SendCommand("""{"ListAppNames":""}""");
37
38 string? response = await _process.ReadLineAsync();
39
40 Assert.NotNull(response);
41 var array = JArray.Parse(response);
42 Assert.NotEmpty(array);
43 }
44
45 /// <summary>
46 /// Verifies that ListThemes returns a valid JSON array of theme file paths via stdout.
47 /// </summary>
48 [Fact]
49 public async Task ListThemes_ReturnsJsonArray()
50 {
51 _process.SendCommand("""{"ListThemes":""}""");
52
53 // Theme scanning involves disk I/O; allow extra time
54 string? response = await _process.ReadLineAsync(10000);
55
56 Assert.NotNull(response);
57 var array = JArray.Parse(response);
58 Assert.NotEmpty(array);
59 }
60
61 /// <summary>
62 /// Verifies that multiple sequential query commands each return a separate response.
63 /// </summary>
64 [Fact]
65 public async Task MultipleQueries_EachReturnsResponse()
66 {
67 _process.SendCommand("""{"ListAppNames":""}""");
68 string? response1 = await _process.ReadLineAsync();
69
70 _process.SendCommand("""{"ListThemes":""}""");
71 string? response2 = await _process.ReadLineAsync();
72
73 Assert.NotNull(response1);
74 Assert.NotNull(response2);
75 JArray.Parse(response1);
76 JArray.Parse(response2);
77 }
78
79 /// <summary>
80 /// Verifies that ListResolutions returns a valid JSON string via stdout.
81 /// </summary>
82 [Fact]
83 public async Task ListResolutions_ReturnsResponse()
84 {
85 _process.SendCommand("""{"ListResolutions":""}""");
86
87 string? response = await _process.ReadLineAsync(10000);
88
89 Assert.NotNull(response);
90 Assert.NotEmpty(response);
91 }
92
93 /// <summary>
94 /// Verifies that ListWifiNetworks returns a response via stdout.
95 /// </summary>
96 [Fact]
97 public async Task ListWifiNetworks_ReturnsResponse()
98 {
99 _process.SendCommand("""{"ListWifiNetworks":""}""");
100
101 string? response = await _process.ReadLineAsync(10000);
102
103 Assert.NotNull(response);
104 Assert.NotEmpty(response);
105 }
106
107 /// <summary>
108 /// Verifies that SetScreenResolution with an invalid value produces a response without crashing.
109 /// Uses an intentionally invalid resolution to avoid changing the actual display.
110 /// </summary>
111 [Fact]
112 public async Task SetScreenResolution_InvalidValue_ReturnsResponse()
113 {
114 _process.SendCommand("""{"SetScreenResolution":"99999x99999"}""");
115
116 // May produce an error message or status — just verify the process survives
117 // and we can still send commands
118 await _process.ReadLineAsync(5000);
119
120 _process.SendCommand("""{"ListAppNames":""}""");
121 string? response = await _process.ReadLineAsync();
122
123 Assert.False(_process.HasExited);
124 Assert.NotNull(response);
125 }
126
127 // --- Protocol edge cases ---
128
129 /// <summary>
130 /// Verifies that multiple commands in a single JSON object each produce stdout output.
131 /// </summary>
132 [Fact]
133 public async Task MultiCommandObject_ProducesMultipleResponses()
134 {
135 _process.SendCommand("""{"ListAppNames":"", "ListThemes":""}""");
136
137 string? response1 = await _process.ReadLineAsync();
138 string? response2 = await _process.ReadLineAsync();
139
140 Assert.NotNull(response1);
141 Assert.NotNull(response2);
142 // One should be app names, the other themes — both valid JSON arrays
143 JArray.Parse(response1);
144 JArray.Parse(response2);
145 }
146
147 /// <summary>
148 /// Verifies that quit stops processing mid-batch. Commands after quit should not execute.
149 /// </summary>
150 [Fact]
151 public async Task Quit_StopsMidBatch()
152 {
153 // ListAppNames produces output, quit should stop before ListThemes runs
154 _process.SendCommand("""{"ListAppNames":"", "quit":"", "ListThemes":""}""");
155
156 string? response1 = await _process.ReadLineAsync();
157 Assert.NotNull(response1);
158 JArray.Parse(response1);
159
160 // Process should have exited — no second response
161 _process.WaitForExit(10000);
162 Assert.True(_process.HasExited);
163 }
164
165 /// <summary>
166 /// Verifies that sending {"quit":""} causes the process to exit cleanly.
167 /// </summary>
168 [Fact]
169 public void Quit_ProcessExits()
170 {
171 _process.SendQuit();
172
173 Assert.True(_process.HasExited);
174 }
175
176 /// <summary>
177 /// Verifies that malformed JSON does not crash the process.
178 /// Sends invalid JSON followed by a valid query to confirm the process is still alive.
179 /// </summary>
180 [Fact]
181 public async Task MalformedJson_ProcessSurvives()
182 {
183 _process.SendCommand("this is not json");
184
185 // Process should still be alive — send a valid command to verify
186 _process.SendCommand("""{"ListAppNames":""}""");
187 string? response = await _process.ReadLineAsync();
188
189 Assert.False(_process.HasExited);
190 Assert.NotNull(response);
191 }
192
193 /// <summary>
194 /// Verifies that an empty line does not crash the process.
195 /// The error message goes to stdout (known protocol limitation), so we
196 /// consume it before verifying the process is still responsive.
197 /// </summary>
198 [Fact]
199 public async Task EmptyLine_ProcessSurvives()
200 {
201 _process.SendCommand("");
202 // Consume the error message that goes to stdout
203 await _process.ReadLineAsync();
204
205 _process.SendCommand("""{"ListAppNames":""}""");
206 string? response = await _process.ReadLineAsync();
207
208 Assert.False(_process.HasExited);
209 Assert.NotNull(response);
210 }
211
212 /// <summary>
213 /// Verifies that an unknown command does not crash the process.
214 /// </summary>
215 [Fact]
216 public async Task UnknownCommand_ProcessSurvives()
217 {
218 _process.SendCommand("""{"NonExistentCommand":"value"}""");
219
220 _process.SendCommand("""{"ListAppNames":""}""");
221 string? response = await _process.ReadLineAsync();
222
223 Assert.False(_process.HasExited);
224 Assert.NotNull(response);
225 }
226
227 /// <summary>
228 /// Verifies that closing stdin (EOF) causes the process to exit cleanly.
229 /// </summary>
230 [Fact]
231 public void StdinClosed_ProcessExits()
232 {
233 _process.CloseStdin();
234 _process.WaitForExit(5000);
235
236 Assert.True(_process.HasExited);
237 }
238
239 // --- Command-line mode ---
240
241 /// <summary>
242 /// Verifies that passing a single JSON command as a command-line argument
243 /// executes it and exits (non-interactive mode).
244 /// </summary>
245 [Fact]
246 public void CommandLineMode_SingleObject_ExecutesAndExits()
247 {
248 var (output, exitCode) = AutoShellProcess.RunWithArgs(
249 """{"ListAppNames":""}""");
250
251 Assert.Equal(0, exitCode);
252 Assert.NotEmpty(output);
253 JArray.Parse(output.Trim());
254 }
255
256 /// <summary>
257 /// Verifies that passing a JSON array of commands as command-line arguments
258 /// executes all of them and exits.
259 /// </summary>
260 [Fact]
261 public void CommandLineMode_JsonArray_ExecutesAllAndExits()
262 {
263 var (output, exitCode) = AutoShellProcess.RunWithArgs(
264 """[{"ListAppNames":""},{"ListThemes":""}]""");
265
266 Assert.Equal(0, exitCode);
267 Assert.NotEmpty(output);
268 }
269}
270