// Copyright (c) Microsoft. All rights reserved. using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.AI; namespace Microsoft.Agents.AI.UnitTests.AgentSkills; /// /// Unit tests for . /// public sealed class AgentInlineSkillTests { [Fact] public void Constructor_WithNameAndDescription_SetsFrontmatter() { // Arrange & Act var skill = new AgentInlineSkill("my-skill", "A valid skill.", "Instructions."); // Assert Assert.Equal("my-skill", skill.Frontmatter.Name); Assert.Equal("A valid skill.", skill.Frontmatter.Description); Assert.Null(skill.Frontmatter.License); Assert.Null(skill.Frontmatter.Compatibility); Assert.Null(skill.Frontmatter.AllowedTools); Assert.Null(skill.Frontmatter.Metadata); } [Fact] public void Constructor_WithAllProps_SetsFrontmatter() { // Arrange var metadata = new AdditionalPropertiesDictionary { ["key"] = "value" }; // Act var skill = new AgentInlineSkill( "my-skill", "A valid skill.", "Instructions.", license: "MIT", compatibility: "gpt-4", allowedTools: "tool-a tool-b", metadata: metadata); // Assert Assert.Equal("my-skill", skill.Frontmatter.Name); Assert.Equal("A valid skill.", skill.Frontmatter.Description); Assert.Equal("MIT", skill.Frontmatter.License); Assert.Equal("gpt-4", skill.Frontmatter.Compatibility); Assert.Equal("tool-a tool-b", skill.Frontmatter.AllowedTools); Assert.NotNull(skill.Frontmatter.Metadata); Assert.Equal("value", skill.Frontmatter.Metadata["key"]); } [Fact] public void Constructor_WithFrontmatter_UsesFrontmatterDirectly() { // Arrange var frontmatter = new AgentSkillFrontmatter("my-skill", "A valid skill.") { License = "Apache-2.0", Compatibility = "gpt-4", AllowedTools = "tool-a", Metadata = new AdditionalPropertiesDictionary { ["env"] = "prod" }, }; // Act var skill = new AgentInlineSkill(frontmatter, "Instructions."); // Assert Assert.Same(frontmatter, skill.Frontmatter); Assert.Equal("Apache-2.0", skill.Frontmatter.License); Assert.Equal("gpt-4", skill.Frontmatter.Compatibility); Assert.Equal("tool-a", skill.Frontmatter.AllowedTools); Assert.Equal("prod", skill.Frontmatter.Metadata!["env"]); } [Fact] public void Constructor_WithFrontmatter_NullFrontmatter_Throws() { // Act & Assert Assert.Throws(() => new AgentInlineSkill(null!, "Instructions.")); } [Fact] public void Constructor_WithFrontmatter_NullInstructions_Throws() { // Arrange var frontmatter = new AgentSkillFrontmatter("my-skill", "A valid skill."); // Act & Assert Assert.Throws(() => new AgentInlineSkill(frontmatter, null!)); } [Fact] public void Constructor_WithAllProps_NullInstructions_Throws() { // Act & Assert Assert.Throws(() => new AgentInlineSkill("my-skill", "A valid skill.", null!)); } [Fact] public async Task Content_ContainsNameDescriptionAndInstructionsAsync() { // Arrange var skill = new AgentInlineSkill("my-skill", "A valid skill.", "Do the thing."); // Act var content = await skill.GetContentAsync(); // Assert Assert.Contains("my-skill", content); Assert.Contains("A valid skill.", content); Assert.Contains("\nDo the thing.\n", content); } [Fact] public async Task Content_EscapesXmlCharactersAsync() { // Arrange var skill = new AgentInlineSkill("my-skill", "xz\"w & it's more", "1 & 2 < 3"); // Act var content = await skill.GetContentAsync(); // Assert Assert.Contains("my-skill", content); Assert.Contains("x<y>z"w & it's more", content); Assert.Contains("1 & 2 < 3", content); // instructions are escaped } [Fact] public async Task Content_IsCachedAcrossAccessesAsync() { // Arrange var skill = new AgentInlineSkill("my-skill", "A valid skill.", "Instructions."); // Act var first = await skill.GetContentAsync(); var second = await skill.GetContentAsync(); // Assert Assert.Same(first, second); } [Fact] public async Task Content_IncludesResourcesInBodyAsync() { // Arrange var skill = new AgentInlineSkill("my-skill", "A valid skill.", "Instructions."); skill.AddResource("config", "value1", "A config resource."); // Act var content = await skill.GetContentAsync(); // Assert — resources are rendered in the body so the model can discover them Assert.Contains("", content); Assert.Contains("", content); } [Fact] public async Task Content_IncludesDelegateResourcesInBodyAsync() { // Arrange var skill = new AgentInlineSkill("my-skill", "A valid skill.", "Instructions."); skill.AddResource("dynamic", () => "hello"); // Act var content = await skill.GetContentAsync(); // Assert — resources are rendered in the body Assert.Contains("", content); Assert.Contains("", content); } [Fact] public async Task Content_IncludesScriptsAddedBeforeFirstAccessAsync() { // Arrange var skill = new AgentInlineSkill("my-skill", "A valid skill.", "Instructions."); skill.AddScript("run", () => "result", "Runs something."); // Act var content = await skill.GetContentAsync(); // Assert Assert.Contains("", content); Assert.Contains("