Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ on:
paths:
- 'src/**'
- 'samples/**'
- 'tests/**'
- '.github/workflows/build.yml'
pull_request:
branches: [main]
paths:
- 'src/**'
- 'samples/**'
- 'tests/**'
- '.github/workflows/build.yml'

jobs:
Expand Down Expand Up @@ -39,6 +41,81 @@ jobs:
- name: Build Sample Extension
run: dotnet build samples/SampleExtension/SampleExtension.csproj -c Release

# E2E Tests - Build all test projects
- name: Build E2E.Minimal
run: dotnet build tests/e2e/E2E.Minimal/E2E.Minimal.csproj -c Release

- name: Build E2E.AutoIncludes
run: dotnet build tests/e2e/E2E.AutoIncludes/E2E.AutoIncludes.csproj -c Release

- name: Build E2E.SourceGenerators
run: dotnet build tests/e2e/E2E.SourceGenerators/E2E.SourceGenerators.csproj -c Release

- name: Build E2E.VersionOverride
run: dotnet build tests/e2e/E2E.VersionOverride/E2E.VersionOverride.csproj -c Release

- name: Build E2E.VersionOverride with SetVsixVersion
run: dotnet build tests/e2e/E2E.VersionOverride/E2E.VersionOverride.csproj -c Release -p:SetVsixVersion=2.0.0

- name: Build E2E.CustomPkgDef
run: dotnet build tests/e2e/E2E.CustomPkgDef/E2E.CustomPkgDef.csproj -c Release

- name: Build E2E.ManualPkgDef
run: dotnet build tests/e2e/E2E.ManualPkgDef/E2E.ManualPkgDef.csproj -c Release

- name: Build E2E.ImageAndContentManifest
run: dotnet build tests/e2e/E2E.ImageAndContentManifest/E2E.ImageAndContentManifest.csproj -c Release

- name: Build E2E.Validation (expect warnings)
run: dotnet build tests/e2e/E2E.Validation/E2E.Validation.csproj -c Release

- name: Build E2E.ValidationNoManifest (expect warnings)
run: dotnet build tests/e2e/E2E.ValidationNoManifest/E2E.ValidationNoManifest.csproj -c Release

- name: Build E2E.Templates.AutoDiscovery
run: dotnet build tests/e2e/E2E.Templates.AutoDiscovery/E2E.Templates.AutoDiscovery.csproj -c Release

- name: Build E2E.Templates.PreBuiltZip
run: dotnet build tests/e2e/E2E.Templates.PreBuiltZip/E2E.Templates.PreBuiltZip.csproj -c Release

- name: Build E2E.Templates.ManualWithSubPath
run: dotnet build tests/e2e/E2E.Templates.ManualWithSubPath/E2E.Templates.ManualWithSubPath.csproj -c Release

- name: Build E2E.AllFeatures
run: dotnet build tests/e2e/E2E.AllFeatures/E2E.AllFeatures.csproj -c Release

# VSIX Verification - Check that VSIX files contain expected content
- name: Verify E2E.Minimal VSIX
run: |
$vsix = "tests/e2e/E2E.Minimal/bin/Release/net472/E2E.Minimal.vsix"
if (!(Test-Path $vsix)) { throw "VSIX not found: $vsix" }
Expand-Archive -Path $vsix -DestinationPath "tests/e2e/E2E.Minimal/vsix-contents" -Force
$files = Get-ChildItem -Path "tests/e2e/E2E.Minimal/vsix-contents" -Recurse -File | Select-Object -ExpandProperty Name
if ($files -notcontains "extension.vsixmanifest") { throw "Missing extension.vsixmanifest" }
if ($files -notcontains "E2E.Minimal.dll") { throw "Missing E2E.Minimal.dll" }
Write-Host "E2E.Minimal VSIX verified successfully"

- name: Verify E2E.Templates.AutoDiscovery VSIX
run: |
$vsix = "tests/e2e/E2E.Templates.AutoDiscovery/bin/Release/net472/E2E.Templates.AutoDiscovery.vsix"
if (!(Test-Path $vsix)) { throw "VSIX not found: $vsix" }
Expand-Archive -Path $vsix -DestinationPath "tests/e2e/E2E.Templates.AutoDiscovery/vsix-contents" -Force
$files = Get-ChildItem -Path "tests/e2e/E2E.Templates.AutoDiscovery/vsix-contents" -Recurse | Select-Object -ExpandProperty Name
# VSSDK default behavior includes templates as folders with .vstemplate files
if ($files -notcontains "ConsoleApp.vstemplate") { throw "Missing ProjectTemplates/ConsoleApp/ConsoleApp.vstemplate" }
if ($files -notcontains "NewClass.vstemplate") { throw "Missing ItemTemplates/NewClass/NewClass.vstemplate" }
Write-Host "E2E.Templates.AutoDiscovery VSIX verified successfully"

- name: Verify E2E.AllFeatures VSIX
run: |
$vsix = "tests/e2e/E2E.AllFeatures/bin/Release/net472/E2E.AllFeatures.vsix"
if (!(Test-Path $vsix)) { throw "VSIX not found: $vsix" }
Expand-Archive -Path $vsix -DestinationPath "tests/e2e/E2E.AllFeatures/vsix-contents" -Force
$files = Get-ChildItem -Path "tests/e2e/E2E.AllFeatures/vsix-contents" -Recurse | Select-Object -ExpandProperty Name
if ($files -notcontains "extension.vsixmanifest") { throw "Missing extension.vsixmanifest" }
if ($files -notcontains "E2E.AllFeatures.dll") { throw "Missing E2E.AllFeatures.dll" }
Write-Host "E2E.AllFeatures VSIX verified successfully"

- name: Test Template - Install
run: dotnet new install artifacts/packages/CodingWithCalvin.VsixSdk.Templates.1.0.0.nupkg

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ CLAUDE.local.md
Generated/
VsixInfo.g.cs
*Vsct.g.cs

# Pre-built template zips (generated during build)
tests/e2e/*/PreBuilt/
18 changes: 18 additions & 0 deletions tests/e2e/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project>
<!--
For E2E testing, we add VSIX SDK behavior on top of Microsoft.NET.Sdk.
The E2E test projects use Sdk="Microsoft.NET.Sdk" directly.
-->

<PropertyGroup>
<!-- Path to local SDK files -->
<CodingWithCalvinVsixSdkRoot>$(MSBuildThisFileDirectory)..\..\src\CodingWithCalvin.VsixSdk\</CodingWithCalvinVsixSdkRoot>

<!-- Signal that we're running in local development mode -->
<CodingWithCalvinVsixSdkLocalDev>true</CodingWithCalvinVsixSdkLocalDev>
</PropertyGroup>

<!-- Import VSIX-specific properties (after Microsoft.NET.Sdk.props is imported by the project) -->
<Import Project="$(CodingWithCalvinVsixSdkRoot)Sdk\Sdk.Vsix.props" />

</Project>
15 changes: 15 additions & 0 deletions tests/e2e/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project>
<!--
For E2E testing, import the VSIX-specific targets.
These add VSIX build behavior without importing Microsoft.NET.Sdk again.
-->

<!-- Import VSIX-specific item includes and targets -->
<Import Project="$(CodingWithCalvinVsixSdkRoot)Sdk\Sdk.Vsix.targets" />

<!-- Reference the source generators for local development -->
<ItemGroup Condition="'$(CodingWithCalvinVsixSdkLocalDev)' == 'true'">
<Analyzer Include="$(CodingWithCalvinVsixSdkRoot)..\CodingWithCalvin.VsixSdk.Generators\bin\$(Configuration)\netstandard2.0\CodingWithCalvin.VsixSdk.Generators.dll" />
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions tests/e2e/E2E.AllFeatures/Commands/AllCommands.vsct
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<Extern href="stdidcmd.h"/>
<Extern href="vsshlids.h"/>

<Commands package="guidAllFeaturesPackage">
<Groups>
<Group guid="guidAllFeaturesCommandSet" id="AllFeaturesMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>
</Group>
</Groups>

<Buttons>
<Button guid="guidAllFeaturesCommandSet" id="AllFeaturesCommand" priority="0x0100" type="Button">
<Parent guid="guidAllFeaturesCommandSet" id="AllFeaturesMenuGroup" />
<Strings>
<ButtonText>All Features Command</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>

<Symbols>
<GuidSymbol name="guidAllFeaturesPackage" value="{DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD}" />
<GuidSymbol name="guidAllFeaturesCommandSet" value="{EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE}">
<IDSymbol name="AllFeaturesMenuGroup" value="0x1020" />
<IDSymbol name="AllFeaturesCommand" value="0x0100" />
</GuidSymbol>
</Symbols>

</CommandTable>
5 changes: 5 additions & 0 deletions tests/e2e/E2E.AllFeatures/CustomSettings.pkgdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
; Custom pkgdef settings for AllFeatures test

[$RootKey$\E2E\AllFeatures]
"AllFeaturesEnabled"=dword:00000001
"CustomSetting"="AllFeaturesValue"
45 changes: 45 additions & 0 deletions tests/e2e/E2E.AllFeatures/E2E.AllFeatures.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!--
E2E.AllFeatures - Comprehensive test combining ALL SDK features.

Validates:
- All features work together without conflicts
- VSCT + templates + generators + version all coexist
- Complete VSIX package produced
-->
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Version>1.0.0</Version>
<!-- Exclude template source folders from compilation -->
<DefaultItemExcludes>$(DefaultItemExcludes);PreBuiltSource\**;ManualTemplates\**</DefaultItemExcludes>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.*" />
</ItemGroup>

<!-- Pre-built template zip -->
<ItemGroup>
<VsixTemplateZip Include="PreBuilt\PreBuilt.zip" TemplateType="Project" />
</ItemGroup>

<!-- Manual template with subpath -->
<ItemGroup>
<VsixProjectTemplate Include="ManualTemplates\ManualProject" TargetSubPath="Manual" />
</ItemGroup>

<!-- Custom pkgdef files -->
<ItemGroup>
<PkgDefToMerge Include="CustomSettings.pkgdef" />
</ItemGroup>

<!-- Target to create pre-built zip if needed -->
<Target Name="CreatePreBuiltZip" BeforeTargets="PrepareForBuild">
<MakeDir Directories="PreBuilt" Condition="!Exists('PreBuilt')" />
<ZipDirectory SourceDirectory="PreBuiltSource\PreBuiltProject"
DestinationFile="PreBuilt\PreBuilt.zip"
Overwrite="true"
Condition="Exists('PreBuiltSource\PreBuiltProject') and !Exists('PreBuilt\PreBuilt.zip')" />
</Target>

</Project>
19 changes: 19 additions & 0 deletions tests/e2e/E2E.AllFeatures/E2EAllFeaturesPackage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.VisualStudio.Shell;
using Task = System.Threading.Tasks.Task;

namespace E2E.AllFeatures
{
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[Guid("00000000-0000-0000-0000-00000000000D")]
public sealed class E2EAllFeaturesPackage : AsyncPackage
{
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await base.InitializeAsync(cancellationToken, progress);
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
}
}
}
35 changes: 35 additions & 0 deletions tests/e2e/E2E.AllFeatures/FeatureConsumer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// This file uses generated constants to verify all generators work together.

using System;

namespace E2E.AllFeatures
{
/// <summary>
/// Consumes generated constants to verify all features work together.
/// </summary>
public static class FeatureConsumer
{
// VsixInfo constants
public static string ExtensionId => VsixInfo.Id;
public static string ExtensionDisplayName => VsixInfo.DisplayName;

// VSCT constants
public static Guid PackageGuid => AllCommandsVsct.guidAllFeaturesPackage;
public static int CommandId => AllCommandsVsct.guidAllFeaturesCommandSet.AllFeaturesCommand;

/// <summary>
/// Validates that all generated constants are available.
/// </summary>
public static void ValidateAllFeatures()
{
if (string.IsNullOrEmpty(ExtensionId))
throw new InvalidOperationException("VsixInfo.Id is empty");

if (PackageGuid == Guid.Empty)
throw new InvalidOperationException("Package GUID is empty");

if (CommandId != 0x0100)
throw new InvalidOperationException("Command ID has wrong value");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Item" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>Auto-Discovered Item</Name>
<Description>Auto-discovered item template in AllFeatures</Description>
<ProjectType>CSharp</ProjectType>
<DefaultName>AutoItem.cs</DefaultName>
</TemplateData>
<TemplateContent>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$.cs">Item.cs</ProjectItem>
</TemplateContent>
</VSTemplate>
4 changes: 4 additions & 0 deletions tests/e2e/E2E.AllFeatures/ItemTemplates/AutoItem/Item.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace $rootnamespace$
{
public class $safeitemname$ { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace $safeprojectname$
{
public class Class1 { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>Manual Project (SubPath)</Name>
<Description>Manual project template with TargetSubPath in AllFeatures</Description>
<ProjectType>CSharp</ProjectType>
<DefaultName>ManualProject</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
</TemplateData>
<TemplateContent>
<Project File="Project.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true">Class1.cs</ProjectItem>
</Project>
</TemplateContent>
</VSTemplate>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace $safeprojectname$
{
public class Class1 { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>Pre-Built Project</Name>
<Description>Pre-built zip template in AllFeatures</Description>
<ProjectType>CSharp</ProjectType>
<DefaultName>PreBuiltProject</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
</TemplateData>
<TemplateContent>
<Project File="Project.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true">Class1.cs</ProjectItem>
</Project>
</TemplateContent>
</VSTemplate>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>Auto-Discovered Project</Name>
<Description>Auto-discovered project template in AllFeatures</Description>
<ProjectType>CSharp</ProjectType>
<DefaultName>AutoProject</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
</TemplateData>
<TemplateContent>
<Project File="Project.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true">Class1.cs</ProjectItem>
</Project>
</TemplateContent>
</VSTemplate>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace $safeprojectname$
{
public class Class1 { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
Loading
Loading