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
35 changes: 35 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Azure Bicep

on:
workflow_dispatch

env:
targetEnv: dev

jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
steps:
# Checkout code
- uses: actions/checkout@main

# Log into Azure
- uses: azure/[email protected]
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true

# Deploy ARM template
- name: Run ARM deploy
uses: azure/arm-deploy@v1
with:
subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
resourceGroupName: ${{ secrets.AZURE_RG }}
template: ./src/InfrastructureAsCode/main.bicep
parameters: environment=${{ env.targetEnv }}
31 changes: 31 additions & 0 deletions .github/workflows/dotnet-deploy-1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: .NET CI

on:
push:
branches: [ main ]
paths:
- src/Application/**
pull_request:
branches: [ main ]
paths:
- src/Application/**
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'

- name: Restore dependencies
run: dotnet restore ./src/Application/src/RazorPagesTestSample/RazorPagesTestSample.csproj
- name: Build
run: dotnet build --no-restore ./src/Application/src/RazorPagesTestSample/RazorPagesTestSample.csproj
- name: Test
run: dotnet test --no-build --verbosity normal ./src/Application/tests/RazorPagesTestSample.Tests/RazorPagesTestSample.Tests.csproj
22 changes: 22 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Save All Files",
"command": "${command:workbench.action.files.saveAll}",
"type": "shell",
"problemMatcher": []
},
{
"label": "Build Project",
"dependsOn": "Save All Files",
"command": "dotnet build",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": "$msCompile"
}
]
}
2 changes: 1 addition & 1 deletion docs/03_improve_deploy_app/0301.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ We have a work machine configured, so now it is time to ensure that everything w

## Description

Developers at Munson's Pickles and Preserves like the Team Messaging System in general, but they consistently bring up issues with one aspect of the application: it limits messages to 200 characters or fewer. Developers have made a case that the app should support messages of up to 250 characters in length instead.
Developers at Munson's Pickles and Preserves like the Team Messaging System in general, but they consistently bring up issues with one aspect of the application: it limits messages to 250 characters or fewer. Developers have made a case that the app should support messages of up to 250 characters in length instead.

In this task, you will modify the application to support 250 characters instead of 200. You will also follow a feature branching strategy and use a pull request to bring your change into the `main` branch. If you wish to complete this task using a Test-Driven Design approach, please read the **Advanced Challenges (optional)** section below before making any changes.

Expand Down
4 changes: 2 additions & 2 deletions src/Application/src/RazorPagesTestSample/Data/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public class Message

[Required]
[DataType(DataType.Text)]
[StringLength(200, ErrorMessage = "There's a 200 character limit on messages. Please shorten your message.")]
[StringLength(250, ErrorMessage = "There's a 250 character limit on messages. Please shorten your message.")]
public string Text { get; set; }
}
#endregion
}
}
24 changes: 24 additions & 0 deletions src/Application/src/RazorPagesTestSample/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Use the official .NET 8 SDK image as a build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

# Copy the project file and restore dependencies
COPY *.csproj .
RUN dotnet restore

# Copy the rest of the application code
COPY . .

# Build the application
RUN dotnet publish -c Release -o out

# Use the official .NET 8 runtime image as a runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/out .

# Set the environment variable for ASP.NET Core HTTP ports
ENV ASPNETCORE_HTTP_PORTS=80

# Set the entry point for the application
ENTRYPOINT ["dotnet", "RazorPagesTestSample.dll"]
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
<h3 class="text-danger">An error occurred while processing your request.</h3>

@if (Model.ShowRequestId)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<!-- https://github.com/NuGet/Home/issues/4412 -->


<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="xunit" Version="2.7.0" />
Expand All @@ -22,12 +18,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>


<ItemGroup>
<Reference Include="RazorPagesTestSample">
<HintPath>..\..\src\RazorPagesTestSample\bin\Debug\net8.0\RazorPagesTestSample.dll</HintPath>
</Reference>
<ProjectReference Include="..\..\src\RazorPagesTestSample\RazorPagesTestSample.csproj" />
</ItemGroup>

</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.EntityFrameworkCore;
using Xunit;
using RazorPagesTestSample.Data;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesTestSample.Tests.UnitTests
{
Expand All @@ -25,7 +26,7 @@ public async Task GetMessagesAsync_MessagesAreReturned()
// Assert
var actualMessages = Assert.IsAssignableFrom<List<Message>>(result);
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}
Expand Down Expand Up @@ -77,7 +78,7 @@ public async Task DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound()
await db.AddRangeAsync(seedMessages);
await db.SaveChangesAsync();
var recId = 1;
var expectedMessages =
var expectedMessages =
seedMessages.Where(message => message.Id != recId).ToList();
#endregion

Expand All @@ -90,7 +91,7 @@ public async Task DeleteMessageAsync_MessageIsDeleted_WhenMessageIsFound()
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
#endregion
}
Expand Down Expand Up @@ -121,10 +122,42 @@ public async Task DeleteMessageAsync_NoMessageIsDeleted_WhenMessageIsNotFound()
// Assert
var actualMessages = await db.Messages.AsNoTracking().ToListAsync();
Assert.Equal(
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
expectedMessages.OrderBy(m => m.Id).Select(m => m.Text),
actualMessages.OrderBy(m => m.Id).Select(m => m.Text));
}
}



//Generate a unit test theory to generate messages of various lengths including 250 and try to validate the message object.
[Theory]
[InlineData(150, true)]
[InlineData(199, true)]
[InlineData(200, true)]
[InlineData(201, true)]
[InlineData(249, true)]
[InlineData(250, true)]
[InlineData(251, false)]
[InlineData(300, false)]
public async Task AddMessageAsync_TestMessageLength(int messageLength, bool expectedValidMessage)
{
using (var db = new AppDbContext(Utilities.TestDbContextOptions()))
{
// Arrange
var recId = 10;
var expectedMessage = new Message() { Id = recId, Text = new string('X', messageLength) };

// Act
var isValidMessage = Validator.TryValidateObject(expectedMessage, new ValidationContext(expectedMessage), null, validateAllProperties: true);

// Simulate an asynchronous operation
await Task.Delay(1);

// Assert
Assert.Equal(expectedValidMessage, isValidMessage);
}
}

#endregion
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System.ComponentModel.DataAnnotations;
using RazorPagesTestSample.Data;
using Xunit;
using System.Collections.Generic;

namespace RazorPagesTestSample.Tests.UnitTests
{
public class MessageTests
{
[Fact]
public void MessageText_ShouldNotExceed250Characters()
{
// Arrange
var message = new Message
{
Text = new string('a', 251) // 251 characters
};
var validationContext = new ValidationContext(message);
var validationResults = new List<ValidationResult>();

// Act
var isValid = Validator.TryValidateObject(message, validationContext, validationResults, true);

// Assert
Assert.False(isValid);
Assert.Contains(validationResults, v => v.ErrorMessage.Contains("250 character limit"));
}

[Fact]
public void MessageText_ShouldBeValid_WhenWithin250Characters()
{
// Arrange
var message = new Message
{
Text = new string('a', 250) // 250 characters
};
var validationContext = new ValidationContext(message);
var validationResults = new List<ValidationResult>();

// Act
var isValid = Validator.TryValidateObject(message, validationContext, validationResults, true);

// Assert
Assert.True(isValid);
}

//test the insertion of a message of length 150
[Fact]
public void MessageText_ShouldBeValid_WhenWithin150Characters()
{
// Arrange
var message = new Message
{
Text = new string('a', 150) // 150 characters
};
var validationContext = new ValidationContext(message);
var validationResults = new List<ValidationResult>();

// Act
var isValid = Validator.TryValidateObject(message, validationContext, validationResults, true);

// Assert
Assert.True(isValid);
}

//test a message of length 249
[Fact]
public void MessageText_ShouldBeValid_WhenWithin249Characters()
{
// Arrange
var message = new Message
{
Text = new string('a', 249) // 249 characters
};
var validationContext = new ValidationContext(message);
var validationResults = new List<ValidationResult>();

// Act
var isValid = Validator.TryValidateObject(message, validationContext, validationResults, true);

// Assert
Assert.True(isValid);
}
}
}
Loading
Loading