-
Notifications
You must be signed in to change notification settings - Fork 8
Iteration 1: Hello World works, button hidden for others #863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Joshua-Lester3
merged 18 commits into
IntelliTect:main
from
Joshua-Lester3:jlester/try-net
Feb 14, 2026
Merged
Changes from 5 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
edd4ef9
Implement ListingSourceCode feature with controller, service, and tests
Joshua-Lester3 30402fa
feat: add TryDotNet integration for interactive code execution
Joshua-Lester3 41d9c03
Merge branch 'main' into jlester/try-net
Joshua-Lester3 bd8d5d4
fix: ensure ListingSourceCode files are copied to output directory fo…
Joshua-Lester3 17e3b38
fix: enhance WebApplicationFactory to use TestData for IListingSource…
Joshua-Lester3 122cc0a
fix: update API routes in ListingSourceCodeController and tests for c…
Joshua-Lester3 c746e71
Update EssentialCSharp.Web.Tests/WebApplicationFactory.cs
Joshua-Lester3 6e2d455
refactor: convert ListingSourceCodeResponse to a record class for imp…
Joshua-Lester3 ee8a892
Merge branch 'jlester/try-net' of https://github.com/Joshua-Lester3/E…
Joshua-Lester3 30a3fd5
bug fix: Source code response syntax and instantiation
Joshua-Lester3 e7ebdff
fix: correct service removal in WebApplicationFactory for test data i…
Joshua-Lester3 d1e638e
refactor: update CreateService and GetTestDataPath methods to use Dir…
Joshua-Lester3 4ddcc59
refactor: temporarily (possibly use AutoMoq after I research it) repl…
Joshua-Lester3 76c08f4
refactor: update test project to use Moq.AutoMock for improved mockin…
Joshua-Lester3 2b1afe1
refactor: replace Mock with AutoMocker for IWebHostEnvironment in Web…
Joshua-Lester3 ecf4699
Merge branch 'main' into jlester/try-net
Joshua-Lester3 168c8d5
fix: accidentally removed system.data.common, added back here
Joshua-Lester3 36e9efd
Merge branch 'jlester/try-net' of https://github.com/Joshua-Lester3/E…
Joshua-Lester3 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
EssentialCSharp.Web.Tests/ListingSourceCodeControllerTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| using System.Net; | ||
| using System.Net.Http.Json; | ||
| using EssentialCSharp.Web.Models; | ||
|
|
||
| namespace EssentialCSharp.Web.Tests; | ||
|
|
||
| public class ListingSourceCodeControllerTests | ||
| { | ||
| [Fact] | ||
| public async Task GetListing_WithValidChapterAndListing_Returns200WithContent() | ||
| { | ||
| // Arrange | ||
| using WebApplicationFactory factory = new(); | ||
| HttpClient client = factory.CreateClient(); | ||
|
|
||
| // Act | ||
| using HttpResponseMessage response = await client.GetAsync("/api/ListingSourceCode/1/1"); | ||
|
|
||
| // Assert | ||
| Assert.Equal(HttpStatusCode.OK, response.StatusCode); | ||
|
|
||
| ListingSourceCodeResponse? result = await response.Content.ReadFromJsonAsync<ListingSourceCodeResponse>(); | ||
| Assert.NotNull(result); | ||
| Assert.Equal(1, result.ChapterNumber); | ||
| Assert.Equal(1, result.ListingNumber); | ||
| Assert.NotEmpty(result.FileExtension); | ||
| Assert.NotEmpty(result.Content); | ||
| } | ||
|
|
||
|
|
||
| [Fact] | ||
| public async Task GetListing_WithInvalidChapter_Returns404() | ||
| { | ||
| // Arrange | ||
| using WebApplicationFactory factory = new(); | ||
| HttpClient client = factory.CreateClient(); | ||
|
|
||
| // Act | ||
| using HttpResponseMessage response = await client.GetAsync("/api/ListingSourceCode/999/1"); | ||
|
|
||
| // Assert | ||
| Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListing_WithInvalidListing_Returns404() | ||
| { | ||
| // Arrange | ||
| using WebApplicationFactory factory = new(); | ||
| HttpClient client = factory.CreateClient(); | ||
|
|
||
| // Act | ||
| using HttpResponseMessage response = await client.GetAsync("/api/ListingSourceCode/1/999"); | ||
|
|
||
| // Assert | ||
| Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingsByChapter_WithValidChapter_ReturnsMultipleListings() | ||
| { | ||
| // Arrange | ||
| using WebApplicationFactory factory = new(); | ||
| HttpClient client = factory.CreateClient(); | ||
|
|
||
| // Act | ||
| using HttpResponseMessage response = await client.GetAsync("/api/ListingSourceCode/1"); | ||
|
Joshua-Lester3 marked this conversation as resolved.
Outdated
|
||
|
|
||
| // Assert | ||
| Assert.Equal(HttpStatusCode.OK, response.StatusCode); | ||
|
|
||
| List<ListingSourceCodeResponse>? results = await response.Content.ReadFromJsonAsync<List<ListingSourceCodeResponse>>(); | ||
| Assert.NotNull(results); | ||
| Assert.NotEmpty(results); | ||
|
|
||
| // Verify all results are from chapter 1 | ||
| Assert.All(results, r => Assert.Equal(1, r.ChapterNumber)); | ||
|
|
||
| // Verify results are ordered by listing number | ||
| Assert.Equal(results.OrderBy(r => r.ListingNumber).ToList(), results); | ||
|
|
||
| // Verify each listing has required properties | ||
| Assert.All(results, r => | ||
| { | ||
| Assert.NotEmpty(r.FileExtension); | ||
| Assert.NotEmpty(r.Content); | ||
| }); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingsByChapter_WithInvalidChapter_ReturnsEmptyList() | ||
| { | ||
| // Arrange | ||
| using WebApplicationFactory factory = new(); | ||
| HttpClient client = factory.CreateClient(); | ||
|
|
||
| // Act | ||
| using HttpResponseMessage response = await client.GetAsync("/api/ListingSourceCode/999"); | ||
|
|
||
| // Assert | ||
| Assert.Equal(HttpStatusCode.OK, response.StatusCode); | ||
|
|
||
| List<ListingSourceCodeResponse>? results = await response.Content.ReadFromJsonAsync<List<ListingSourceCodeResponse>>(); | ||
| Assert.NotNull(results); | ||
| Assert.Empty(results); | ||
| } | ||
| } | ||
147 changes: 147 additions & 0 deletions
147
EssentialCSharp.Web.Tests/ListingSourceCodeServiceTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| using EssentialCSharp.Web.Models; | ||
| using EssentialCSharp.Web.Services; | ||
| using Microsoft.AspNetCore.Hosting; | ||
| using Microsoft.Extensions.FileProviders; | ||
| using Microsoft.Extensions.Logging; | ||
| using Moq; | ||
|
|
||
| namespace EssentialCSharp.Web.Tests; | ||
|
|
||
| public class ListingSourceCodeServiceTests | ||
| { | ||
| [Fact] | ||
| public async Task GetListingAsync_WithValidChapterAndListing_ReturnsCorrectListing() | ||
| { | ||
| // Arrange | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act | ||
| ListingSourceCodeResponse? result = await service.GetListingAsync(1, 1); | ||
|
|
||
| // Assert | ||
| Assert.NotNull(result); | ||
| Assert.Equal(1, result.ChapterNumber); | ||
| Assert.Equal(1, result.ListingNumber); | ||
| Assert.Equal("cs", result.FileExtension); | ||
| Assert.NotEmpty(result.Content); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingAsync_WithInvalidChapter_ReturnsNull() | ||
| { | ||
| // Arrange | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act | ||
| ListingSourceCodeResponse? result = await service.GetListingAsync(999, 1); | ||
|
|
||
| // Assert | ||
| Assert.Null(result); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingAsync_WithInvalidListing_ReturnsNull() | ||
| { | ||
| // Arrange | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act | ||
| ListingSourceCodeResponse? result = await service.GetListingAsync(1, 999); | ||
|
|
||
| // Assert | ||
| Assert.Null(result); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingAsync_DifferentFileExtension_AutoDiscoversFileExtension() | ||
| { | ||
| // Arrange | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act - Get an XML file (01.02.xml exists in Chapter 1) | ||
| ListingSourceCodeResponse? result = await service.GetListingAsync(1, 2); | ||
|
|
||
| // Assert | ||
| Assert.NotNull(result); | ||
| Assert.Equal("xml", result.FileExtension); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingsByChapterAsync_WithValidChapter_ReturnsAllListings() | ||
| { | ||
| // Arrange | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act | ||
| IReadOnlyList<ListingSourceCodeResponse> results = await service.GetListingsByChapterAsync(1); | ||
|
|
||
| // Assert | ||
| Assert.NotEmpty(results); | ||
| Assert.All(results, r => Assert.Equal(1, r.ChapterNumber)); | ||
| Assert.All(results, r => Assert.NotEmpty(r.Content)); | ||
| Assert.All(results, r => Assert.NotEmpty(r.FileExtension)); | ||
|
|
||
| // Verify results are ordered | ||
| Assert.Equal(results.OrderBy(r => r.ListingNumber).ToList(), results); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingsByChapterAsync_DirectoryContainsNonListingFiles_ExcludesNonListingFiles() | ||
| { | ||
| // Arrange - Chapter 10 has Employee.cs which doesn't match the pattern | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act | ||
| IReadOnlyList<ListingSourceCodeResponse> results = await service.GetListingsByChapterAsync(10); | ||
|
|
||
| // Assert | ||
| Assert.NotEmpty(results); | ||
|
|
||
| // Ensure all results match the {CC}.{LL}.{ext} pattern | ||
| Assert.All(results, r => | ||
| { | ||
| Assert.Equal(10, r.ChapterNumber); | ||
| Assert.InRange(r.ListingNumber, 1, 99); | ||
| }); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task GetListingsByChapterAsync_WithInvalidChapter_ReturnsEmptyList() | ||
| { | ||
| // Arrange | ||
| ListingSourceCodeService service = CreateService(); | ||
|
|
||
| // Act | ||
| IReadOnlyList<ListingSourceCodeResponse> results = await service.GetListingsByChapterAsync(999); | ||
|
|
||
| // Assert | ||
| Assert.Empty(results); | ||
| } | ||
|
|
||
| private static ListingSourceCodeService CreateService() | ||
| { | ||
| string testDataRoot = GetTestDataPath(); | ||
|
|
||
| var mockWebHostEnvironment = new Mock<IWebHostEnvironment>(); | ||
| mockWebHostEnvironment.Setup(m => m.ContentRootPath).Returns(testDataRoot); | ||
| mockWebHostEnvironment.Setup(m => m.ContentRootFileProvider).Returns(new PhysicalFileProvider(testDataRoot)); | ||
|
|
||
| var mockLogger = new Mock<ILogger<ListingSourceCodeService>>(); | ||
|
|
||
| return new ListingSourceCodeService(mockWebHostEnvironment.Object, mockLogger.Object); | ||
|
Joshua-Lester3 marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| private static string GetTestDataPath() | ||
| { | ||
| // Get the test project directory and navigate to TestData folder | ||
| string currentDirectory = Directory.GetCurrentDirectory(); | ||
| string testDataPath = Path.Combine(currentDirectory, "TestData"); | ||
|
|
||
| if (!Directory.Exists(testDataPath)) | ||
| { | ||
| throw new InvalidOperationException($"TestData directory not found at: {testDataPath}"); | ||
| } | ||
|
|
||
| return testDataPath; | ||
| } | ||
|
Joshua-Lester3 marked this conversation as resolved.
Outdated
|
||
| } | ||
10 changes: 10 additions & 0 deletions
10
EssentialCSharp.Web.Tests/TestData/ListingSourceCode/src/Chapter01/01.01.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // Test listing 01.01 | ||
| using System; | ||
|
|
||
| class Program | ||
| { | ||
| static void Main() | ||
| { | ||
| Console.WriteLine("Hello, World!"); | ||
| } | ||
| } |
7 changes: 7 additions & 0 deletions
7
EssentialCSharp.Web.Tests/TestData/ListingSourceCode/src/Chapter01/01.02.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <!-- Test XML listing 01.02 --> | ||
| <configuration> | ||
| <appSettings> | ||
| <add key="TestKey" value="TestValue" /> | ||
| </appSettings> | ||
| </configuration> |
8 changes: 8 additions & 0 deletions
8
EssentialCSharp.Web.Tests/TestData/ListingSourceCode/src/Chapter01/01.03.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // Test listing 01.03 | ||
| namespace TestNamespace | ||
| { | ||
| public class TestClass | ||
| { | ||
| public int TestProperty { get; set; } | ||
| } | ||
| } |
6 changes: 6 additions & 0 deletions
6
EssentialCSharp.Web.Tests/TestData/ListingSourceCode/src/Chapter10/10.01.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // Test listing 10.01 | ||
| public class Employee | ||
| { | ||
| public string Name { get; set; } | ||
| public int Id { get; set; } | ||
| } |
5 changes: 5 additions & 0 deletions
5
EssentialCSharp.Web.Tests/TestData/ListingSourceCode/src/Chapter10/10.02.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| // Test listing 10.02 | ||
| public class Manager : Employee | ||
| { | ||
| public List<Employee> DirectReports { get; set; } | ||
| } |
6 changes: 6 additions & 0 deletions
6
EssentialCSharp.Web.Tests/TestData/ListingSourceCode/src/Chapter10/Employee.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // This file should NOT be picked up by the listing pattern | ||
| // It doesn't match {CC}.{LL}.{ext} format | ||
| public class EmployeeHelper | ||
| { | ||
| public static void DoSomething() { } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.