Skip to content

Commit f4cb61c

Browse files
committed
use built-in sample verification service
1 parent 36f566c commit f4cb61c

6 files changed

Lines changed: 290 additions & 472 deletions

File tree

tools/azsdk-cli/Azure.Sdk.Tools.Cli.Tests/Services/Languages/TypeScriptTypecheckerTests.cs

Lines changed: 68 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -50,104 +50,16 @@ public void Constructor_WithNullLogger_ThrowsArgumentNullException()
5050
new TypeScriptTypechecker(mockDockerService.Object, null!));
5151
}
5252

53-
[Test]
54-
public void ParseImportedPackages_WithBasicImports_ReturnsExpectedPackages()
55-
{
56-
var code = @"
57-
import { Client } from '@azure/storage-blob';
58-
import * as fs from 'fs';
59-
import './relative-file';
60-
import { DefaultAzureCredential } from '@azure/identity';
61-
const path = require('path');
62-
";
63-
64-
var excludedPackages = new HashSet<string>();
65-
var packages = TypeScriptTypechecker.ParseImportedPackages(code, excludedPackages);
66-
67-
Assert.That(packages, Contains.Item("@azure/storage-blob"));
68-
Assert.That(packages, Contains.Item("@azure/identity"));
69-
Assert.That(packages, Contains.Item("fs"));
70-
Assert.That(packages, Contains.Item("path"));
71-
Assert.That(packages, Contains.Item("typescript"));
72-
Assert.That(packages, Contains.Item("@types/node"));
73-
74-
// Should not contain relative imports
75-
Assert.That(packages, Does.Not.Contain("./relative-file"));
76-
}
77-
78-
[Test]
79-
public void ParseImportedPackages_WithScopedPackages_ExtractsCorrectPackageRoot()
80-
{
81-
var code = @"
82-
import { Client } from '@azure/storage-blob/types';
83-
import { helper } from '@azure/core-auth/helpers/utils';
84-
import { normalPkg } from 'normal-package/sub/path';
85-
";
86-
87-
var excludedPackages = new HashSet<string>();
88-
var packages = TypeScriptTypechecker.ParseImportedPackages(code, excludedPackages);
89-
90-
Assert.That(packages, Contains.Item("@azure/storage-blob"));
91-
Assert.That(packages, Contains.Item("@azure/core-auth"));
92-
Assert.That(packages, Contains.Item("normal-package"));
93-
}
94-
95-
[Test]
96-
public void ParseImportedPackages_WithExcludedPackages_FiltersCorrectly()
97-
{
98-
var code = @"
99-
import { Client } from '@azure/storage-blob';
100-
import { DefaultAzureCredential } from '@azure/identity';
101-
";
102-
103-
var excludedPackages = new HashSet<string> { "@azure/identity" };
104-
var packages = TypeScriptTypechecker.ParseImportedPackages(code, excludedPackages);
105-
106-
Assert.That(packages, Contains.Item("@azure/storage-blob"));
107-
Assert.That(packages, Does.Not.Contain("@azure/identity"));
108-
}
109-
110-
[Test]
111-
public void ParseImportedPackages_WithDynamicImports_ExtractsPackages()
112-
{
113-
var code = @"
114-
const module = await import('@azure/storage-blob');
115-
const fs = await import('fs/promises');
116-
";
117-
118-
var excludedPackages = new HashSet<string>();
119-
var packages = TypeScriptTypechecker.ParseImportedPackages(code, excludedPackages);
120-
121-
Assert.That(packages, Contains.Item("@azure/storage-blob"));
122-
Assert.That(packages, Contains.Item("fs"));
123-
}
124-
125-
[Test]
126-
public void ParseImportedPackages_WithBarePackageNames_ExtractsCorrectly()
127-
{
128-
var code = @"
129-
import fs from 'fs';
130-
import path from 'path';
131-
import crypto from 'crypto';
132-
import { Client } from '@azure/storage-blob';
133-
";
134-
135-
var excludedPackages = new HashSet<string>();
136-
var packages = TypeScriptTypechecker.ParseImportedPackages(code, excludedPackages);
137-
138-
// Verify bare package names (Node.js built-ins) are extracted correctly
139-
Assert.That(packages, Contains.Item("fs"));
140-
Assert.That(packages, Contains.Item("path"));
141-
Assert.That(packages, Contains.Item("crypto"));
142-
Assert.That(packages, Contains.Item("@azure/storage-blob"));
143-
}
144-
14553
[Test]
14654
public async Task TypecheckAsync_WithValidCode_ReturnsSuccess()
14755
{
14856
// Arrange
14957
var code = "const message: string = 'Hello, World!';";
150-
var parameters = new TypeCheckRequest(code, null, null);
58+
var parameters = new TypeCheckRequest(
59+
code,
60+
"sample.ts",
61+
"/path/to/azure-sdk-for-js/sdk/keyvault/keyvault-keys",
62+
"/path/to/azure-sdk-for-js");
15163

15264
SetupSuccessfulDockerInteractions();
15365

@@ -164,7 +76,11 @@ public async Task TypecheckAsync_WithFailedTypeCheck_ReturnsFailure()
16476
{
16577
// Arrange
16678
var code = "const message: string = 123; // Type error";
167-
var parameters = new TypeCheckRequest(code, null, null);
79+
var parameters = new TypeCheckRequest(
80+
code,
81+
"sample.ts",
82+
"/path/to/azure-sdk-for-js/sdk/keyvault/keyvault-keys",
83+
"/path/to/azure-sdk-for-js");
16884

16985
SetupFailedTypecheckInteraction();
17086

@@ -173,43 +89,7 @@ public async Task TypecheckAsync_WithFailedTypeCheck_ReturnsFailure()
17389

17490
// Assert
17591
Assert.That(result.Succeeded, Is.False);
176-
Assert.That(result.Output, Contains.Substring("tsc output:"));
177-
}
178-
179-
[Test]
180-
public async Task TypecheckAsync_WithClientDist_InstallsClientPackage()
181-
{
182-
// Arrange
183-
var code = "const message: string = 'Hello, World!';";
184-
var clientDist = "/path/to/client.tgz";
185-
var parameters = new TypeCheckRequest(code, clientDist, null);
186-
187-
SetupSuccessfulDockerInteractions();
188-
SetupClientDistInstallation(clientDist);
189-
190-
// Create a mock temporary file to simulate the client dist file existing
191-
var tempFile = Path.GetTempFileName();
192-
try
193-
{
194-
await File.WriteAllTextAsync(tempFile, "mock client dist content");
195-
196-
// Update the test to use the actual temp file path
197-
var parametersWithRealFile = new TypeCheckRequest(code, tempFile, null);
198-
199-
// Act
200-
var result = await typechecker.TypecheckAsync(parametersWithRealFile, CancellationToken.None);
201-
202-
// Assert
203-
Assert.That(result.Succeeded, Is.True);
204-
VerifyClientDistInstallation(tempFile);
205-
}
206-
finally
207-
{
208-
if (File.Exists(tempFile))
209-
{
210-
File.Delete(tempFile);
211-
}
212-
}
92+
Assert.That(result.Output, Contains.Substring("Type error"));
21393
}
21494

21595
private void SetupSuccessfulDockerInteractions()
@@ -218,7 +98,12 @@ private void SetupSuccessfulDockerInteractions()
21898
var createResult = new ProcessResult { ExitCode = 0 };
21999
createResult.AppendStdout("container-id");
220100
mockDockerService.Setup(x => x.CreateContainerAsync(
221-
"node:alpine", It.IsAny<string>(), null, null, It.IsAny<CancellationToken>()))
101+
"node:20",
102+
It.IsAny<string>(),
103+
It.IsAny<Dictionary<string, string>>(), // environmentVars
104+
null, // workingDirectory
105+
It.IsAny<Dictionary<string, string>>(), // volumeMounts
106+
It.IsAny<CancellationToken>()))
222107
.ReturnsAsync(createResult);
223108

224109
mockDockerService.Setup(x => x.StartContainerAsync(
@@ -229,6 +114,18 @@ private void SetupSuccessfulDockerInteractions()
229114
It.IsAny<string>(), It.IsAny<CancellationToken>()))
230115
.ReturnsAsync(false); // Force container creation
231116

117+
// pnpm install globally
118+
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
119+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "install", "-g", "pnpm" })),
120+
It.IsAny<string>(), It.IsAny<CancellationToken>()))
121+
.ReturnsAsync(new ProcessResult { ExitCode = 0 });
122+
123+
// turbo install globally
124+
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
125+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "install", "-g", "turbo" })),
126+
It.IsAny<string>(), It.IsAny<CancellationToken>()))
127+
.ReturnsAsync(new ProcessResult { ExitCode = 0 });
128+
232129
// File operations
233130
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
234131
It.IsAny<string>(), It.Is<string[]>(args => args.Contains("mkdir")),
@@ -239,93 +136,83 @@ private void SetupSuccessfulDockerInteractions()
239136
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
240137
.ReturnsAsync(new ProcessResult { ExitCode = 0 });
241138

242-
// npm install
243-
var npmInstallResult = new ProcessResult { ExitCode = 0 };
244-
npmInstallResult.AppendStdout("npm install completed");
139+
// pnpm install in monorepo
140+
var pnpmInstallResult = new ProcessResult { ExitCode = 0 };
141+
pnpmInstallResult.AppendStdout("pnpm install completed");
245142
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
246-
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "install" })),
143+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "pnpm", "install" })),
247144
It.IsAny<string>(), It.IsAny<CancellationToken>()))
248-
.ReturnsAsync(npmInstallResult);
145+
.ReturnsAsync(pnpmInstallResult);
249146

250-
// TypeScript compilation
251-
var tscResult = new ProcessResult { ExitCode = 0 };
252-
tscResult.AppendStdout("Compilation successful");
147+
// turbo run build for package
148+
var turboBuildResult = new ProcessResult { ExitCode = 0 };
149+
turboBuildResult.AppendStdout("turbo build completed");
253150
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
254-
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "run", "typecheck" })),
151+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "turbo", "run", "build" })),
255152
It.IsAny<string>(), It.IsAny<CancellationToken>()))
256-
.ReturnsAsync(tscResult);
153+
.ReturnsAsync(turboBuildResult);
257154

258-
// Cleanup
155+
// build:samples
156+
var buildResult = new ProcessResult { ExitCode = 0 };
157+
buildResult.AppendStdout("Compilation successful");
259158
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
260-
It.IsAny<string>(), It.Is<string[]>(args => args.Contains("rm")),
159+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "pnpm", "run", "build:samples" })),
261160
It.IsAny<string>(), It.IsAny<CancellationToken>()))
262-
.ReturnsAsync(new ProcessResult { ExitCode = 0 });
161+
.ReturnsAsync(buildResult);
263162
}
264163

265164
private void SetupFailedTypecheckInteraction()
266165
{
267166
SetupSuccessfulDockerInteractions();
268167

269-
// Override TypeScript compilation to fail
270-
var failedTscResult = new ProcessResult { ExitCode = 1 };
271-
failedTscResult.AppendStderr("Type error: string is not assignable to number");
272-
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
273-
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "run", "typecheck" })),
274-
It.IsAny<string>(), It.IsAny<CancellationToken>()))
275-
.ReturnsAsync(failedTscResult);
276-
}
277-
278-
private void SetupClientDistInstallation(string clientDist)
279-
{
280-
// Client dist installation
281-
var installResult = new ProcessResult { ExitCode = 0 };
282-
installResult.AppendStdout("Client package installed");
168+
// Override build:samples to fail
169+
var failedBuildResult = new ProcessResult { ExitCode = 1 };
170+
failedBuildResult.AppendStderr("Type error: string is not assignable to number");
283171
mockDockerService.Setup(x => x.RunCommandInContainerAsync(
284-
It.IsAny<string>(), It.Is<string[]>(args =>
285-
args.Length >= 4 && args[0] == "npm" && args[1] == "install" && args[2] == "--no-save"),
172+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "pnpm", "run", "build:samples" })),
286173
It.IsAny<string>(), It.IsAny<CancellationToken>()))
287-
.ReturnsAsync(installResult);
174+
.ReturnsAsync(failedBuildResult);
288175
}
289176

290177
private void VerifyDockerInteractionSequence()
291178
{
292-
// Verify container creation
179+
// Verify container creation with volume mounts and environment vars
293180
mockDockerService.Verify(x => x.CreateContainerAsync(
294-
"node:alpine", It.IsAny<string>(), null, null, It.IsAny<CancellationToken>()),
181+
"node:20",
182+
It.IsAny<string>(),
183+
It.IsAny<Dictionary<string, string>>(), // environmentVars
184+
null, // workingDirectory
185+
It.IsAny<Dictionary<string, string>>(), // volumeMounts
186+
It.IsAny<CancellationToken>()),
295187
Times.Once);
296188

297-
// Verify npm install
189+
// Verify pnpm install globally
298190
mockDockerService.Verify(x => x.RunCommandInContainerAsync(
299-
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "install" })),
191+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "install", "-g", "pnpm" })),
300192
It.IsAny<string>(), It.IsAny<CancellationToken>()),
301193
Times.Once);
302194

303-
// Verify TypeScript compilation
195+
// Verify turbo install globally
304196
mockDockerService.Verify(x => x.RunCommandInContainerAsync(
305-
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "run", "typecheck" })),
197+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "npm", "install", "-g", "turbo" })),
306198
It.IsAny<string>(), It.IsAny<CancellationToken>()),
307199
Times.Once);
308200

309-
// Verify cleanup
201+
// Verify pnpm install in monorepo
310202
mockDockerService.Verify(x => x.RunCommandInContainerAsync(
311-
It.IsAny<string>(), It.Is<string[]>(args => args.Contains("rm")),
203+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "pnpm", "install" })),
312204
It.IsAny<string>(), It.IsAny<CancellationToken>()),
313205
Times.Once);
314-
}
315206

316-
private void VerifyClientDistInstallation(string clientDist)
317-
{
318-
var fileName = Path.GetFileName(clientDist);
319-
320-
// Verify client dist copy
321-
mockDockerService.Verify(x => x.CopyToContainerAsync(
322-
It.IsAny<string>(), clientDist, It.IsAny<string>(), It.IsAny<CancellationToken>()),
207+
// Verify turbo run build
208+
mockDockerService.Verify(x => x.RunCommandInContainerAsync(
209+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "turbo", "run", "build" })),
210+
It.IsAny<string>(), It.IsAny<CancellationToken>()),
323211
Times.Once);
324212

325-
// Verify client dist installation
213+
// Verify build:samples
326214
mockDockerService.Verify(x => x.RunCommandInContainerAsync(
327-
It.IsAny<string>(), It.Is<string[]>(args =>
328-
args.Length >= 4 && args[0] == "npm" && args[1] == "install" && args[2] == "--no-save" && args[3] == fileName),
215+
It.IsAny<string>(), It.Is<string[]>(args => args.SequenceEqual(new[] { "pnpm", "run", "build:samples" })),
329216
It.IsAny<string>(), It.IsAny<CancellationToken>()),
330217
Times.Once);
331218
}

tools/azsdk-cli/Azure.Sdk.Tools.Cli.Tests/Services/SampleVerificationServiceTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public async Task VerifyAndFixSampleAsync_WithDockerNotAvailable_ReturnsFailureR
3636
// Act
3737
var result = await SampleVerification.VerifyAndFixSampleAsync(
3838
sample, "typescript", mockDockerService.Object, mockMicroagentService.Object,
39-
logger, null, null, CancellationToken.None);
39+
logger, "/path/to/package", "/path/to/repo", CancellationToken.None);
4040

4141
// Assert
4242
Assert.That(result.Succeeded, Is.False);
@@ -57,7 +57,7 @@ public async Task VerifyAndFixSampleAsync_WithUnsupportedLanguage_ReturnsFailure
5757
// Act
5858
var result = await SampleVerification.VerifyAndFixSampleAsync(
5959
sample, "unsupported", mockDockerService.Object, mockMicroagentService.Object,
60-
logger, null, null, CancellationToken.None);
60+
logger, "/path/to/package", "/path/to/repo", CancellationToken.None);
6161

6262
// Assert
6363
Assert.That(result.Succeeded, Is.False);

0 commit comments

Comments
 (0)