commit pre-purge

This commit is contained in:
2023-01-04 20:26:15 -07:00
parent c28230691e
commit b9824a7327
16 changed files with 229 additions and 75 deletions

View File

@@ -0,0 +1,10 @@
namespace Management.Test;
public class SemesterPlannerTests
{
[Test]
public void TestCanCreatePlannerFromCanvasSemester()
{
// var
}
}

View File

@@ -9,11 +9,18 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" /> <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" /> <PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
<PackageReference Include="coverlet.collector" Version="3.1.2" /> <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="RestSharp" Version="108.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Management\Management.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,22 @@
public class DeserializationTests
{
[Test]
public void TestTerm()
{
var canvasContentResponse = @"{
""enrollment_terms"": [
{
""id"": 1,
""name"": ""one"",
""start_at"": 2022-01-01T00:00:00Z,
""end_at"": 2022-02-01T00:00:00Z,
""created_at"": ""2011-04-26T23:34:35Z"",
""workflow_state"": ""active"",
""grading_period_group_id"": null
},
}";
}
}

View File

@@ -0,0 +1,39 @@
using CanvasModel.Courses;
using CanvasModel.EnrollmentTerms;
using FluentAssertions;
using Moq;
using RestSharp;
using System.Net;
namespace Management.Test;
public class CanvasServiceTests
{
[Test]
public async Task CanReadCanvasSemesters()
{
var expectedTerms = new EnrollmentTermModel[] {
new EnrollmentTermModel(
Id: 1,
Name: "one",
StartAt: new DateTime(2022, 1, 1),
EndAt: new DateTime(2022, 2, 1)
),
};
var data = new RedundantEnrollmentTermsResponse(EnrollmentTerms: expectedTerms);
var response = new RestResponse<RedundantEnrollmentTermsResponse>();
response.Data = data;
var mockRequestor = new Mock<IWebRequestor>();
mockRequestor
.Setup(s => s.GetAsync<RedundantEnrollmentTermsResponse>(It.IsAny<RestRequest>()))
.ReturnsAsync(response);
var service = new CanvasService(mockRequestor.Object);
var canvasTerms = await service.GetTerms();
canvasTerms.Should().BeEquivalentTo(expectedTerms);
}
}

View File

@@ -1,4 +1,4 @@
@page "/fetchdata" @page "/testing"
@using Management.Web.Data @using Management.Web.Data
@inject WeatherForecastService ForecastService @inject WeatherForecastService ForecastService

View File

@@ -20,8 +20,8 @@
</NavLink> </NavLink>
</div> </div>
<div class="nav-item px-3"> <div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata"> <NavLink class="nav-link" href="/testing">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data <span class="oi oi-list-rich" aria-hidden="true"></span> Testing Page
</NavLink> </NavLink>
</div> </div>
</nav> </nav>

View File

@@ -6,4 +6,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="RestSharp" Version="108.0.3" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,8 +1,5 @@
namespace CanvasModel.Courses; namespace CanvasModel.Courses;
public struct CalendarLinkModel public record CalendarLinkModel
{ (
[JsonPropertyName("ics")] [property: JsonPropertyName("ics")] string Ics
public string Ics { get; set; } );
}

View File

@@ -1,17 +1,8 @@
namespace CanvasModel.Courses; namespace CanvasModel.Courses;
public class TermModel public record TermModel
{ (
[property: JsonPropertyName("id")] ulong Id,
[JsonPropertyName("id")] [property: JsonPropertyName("name")] string Name,
public ulong Id { get; set; } [property: JsonPropertyName("start_at")] DateTime? StartAt,
[property: JsonPropertyName("end_at")] DateTime? EndAt
[JsonPropertyName("name")] );
public string Name { get; set; }
[JsonPropertyName("start_at")]
public DateTime? StartAt { get; set; }
[JsonPropertyName("end_at")]
public DateTime? EndAt { get; set; }
}

View File

@@ -1,43 +1,21 @@
using System;
using System.Collections.Generic;
namespace CanvasModel.EnrollmentTerms; namespace CanvasModel.EnrollmentTerms;
public class EnrollmentTermModel
{
[JsonPropertyName("id")]
public ulong Id { get; set; }
[JsonPropertyName("sis_term_id")] public record EnrollmentTermModel
public string SisTermId { get; set; } (
[property: JsonPropertyName("id")] ulong Id,
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("sis_term_id")] string? SisTermId = null,
[property: JsonPropertyName("sis_import_id")] ulong? SisImportId = null,
[property: JsonPropertyName("start_at")] DateTime? StartAt = null,
[property: JsonPropertyName("end_at")] DateTime? EndAt = null,
[property: JsonPropertyName("grading_period_group_id")] ulong? GradingPeriodGroupId = null,
[property: JsonPropertyName("workflow_state")] string? WorkflowState = null,
[property: JsonPropertyName("overrides")]
Dictionary<string, EnrollmentTermDateOverrideModel>? Overrides = null
);
[JsonPropertyName("sis_import_id")] public record EnrollmentTermDateOverrideModel
public ulong? SisImportId { get; set; } (
[property: JsonPropertyName("start_at")] DateTime? StartAt = null,
[JsonPropertyName("name")] [property: JsonPropertyName("end_at")] DateTime? EndAt = null
public string Name { get; set; } );
[JsonPropertyName("start_at")]
public DateTime? StartAt { get; set; }
[JsonPropertyName("end_at")]
public DateTime? EndAt { get; set; }
[JsonPropertyName("grading_period_group_id")]
public ulong? GradingPeriodGroupId { get; set; }
[JsonPropertyName("workflow_state")]
public string WorkflowState { get; set; }
[JsonPropertyName("overrides")]
public Dictionary<string, EnrollmentTermDateOverrideModel> Overrides { get; set; }
}
public struct EnrollmentTermDateOverrideModel
{
[JsonPropertyName("start_at")]
public DateTime? StartAt { get; set; }
[JsonPropertyName("end_at")]
public DateTime? EndAt { get; set; }
}

View File

@@ -1,9 +1,7 @@
using System.Collections.Generic;
namespace CanvasModel.EnrollmentTerms; namespace CanvasModel.EnrollmentTerms;
public struct RedundantEnrollmentTermsResponse public record RedundantEnrollmentTermsResponse
{ (
[JsonPropertyName("enrollment_terms")] [property: JsonPropertyName("enrollment_terms")]
public IEnumerable<EnrollmentTermModel> EnrollmentTerms { get; set; } IEnumerable<EnrollmentTermModel> EnrollmentTerms
} );

View File

@@ -1,4 +1,68 @@
using CanvasModel.Courses;
using CanvasModel.EnrollmentTerms;
using RestSharp;
public class CanvasService public class CanvasService
{ {
private const string BaseUrl = "https://snow.instructure.com/api/v1/";
private readonly IWebRequestor webRequestor;
private RestClient client;
private string courseid { get; }
public CanvasService(IWebRequestor webRequestor)
{
courseid = "774898";
this.webRequestor = webRequestor;
}
public async Task<IEnumerable<EnrollmentTermModel>> GetTerms()
{
var url = $"accounts/10/terms";
var request = new RestRequest(url);
var terms = await PaginatedRequest<EnrollmentTermModel>(request);
return terms;
}
private async Task<IEnumerable<T>> PaginatedRequest<T>(RestRequest request)
{
var requestCount = 1;
request.AddQueryParameter("per_page", "100");
IEnumerable<T> returnData = new T[] { };
RestResponse<T[]> response = await webRequestor.GetAsync<T>(request);
returnData = returnData.Concat(response.Data);
var nextUrl = getNextUrl(response);
while (nextUrl is not null)
{
requestCount += 1;
var nextRequest = new RestRequest(nextUrl);
var nextResponse = await webRequestor.GetAsync<T>(nextRequest);
if (nextResponse.Data is not null)
returnData = returnData.Concat(nextResponse.Data);
nextUrl = getNextUrl(nextResponse);
}
System.Console.WriteLine($"Requesting {typeof(T)} took {requestCount} requests");
return returnData;
}
private static string? getNextUrl<T>(RestResponse<T[]> response) => response.Headers?
.ToList()
.Find(h => h.Name == "Link")?
.Value?
.ToString()?
.Split(",")
.Where(url => url.Contains("rel=\"next\""))
.FirstOrDefault()?
.Split(";")
.FirstOrDefault()?
.TrimEnd('>')
.TrimStart('<')
.Replace(" ", "")
.Replace(BaseUrl, "");
} }

View File

@@ -0,0 +1,7 @@
using RestSharp;
public interface IWebRequestor
{
Task<RestResponse<T[]>> GetManyAsync<T>(RestRequest request);
Task<RestResponse<T>> GetAsync<T>(RestRequest request);
}

View File

@@ -0,0 +1,26 @@
using RestSharp;
public class WebRequestor : IWebRequestor
{
private const string BaseUrl = "https://snow.instructure.com/api/v1/";
private string token;
private RestClient client;
private string courseid { get; }
public WebRequestor(RestClient client)
{
// token = Environment.GetEnvironmentVariable("CANVAS_TOKEN");
// client = new RestClient(BaseUrl);
// client.AddDefaultHeader("Authorization", $"Bearer {token}");
this.client = client;
courseid = "774898";
}
public async Task<RestResponse<T[]>> GetManyAsync<T>(RestRequest request)
{
return await client.ExecuteGetAsync<T[]>(request);
}
public async Task<RestResponse<T>> GetAsync<T>(RestRequest request)
{
return await client.ExecuteGetAsync<T>(request);
}
}

View File

@@ -4,3 +4,5 @@
install specflow template `dotnet new install Specflow.Templates.DotNet` install specflow template `dotnet new install Specflow.Templates.DotNet`
view templates with `dotnet new -l` view templates with `dotnet new -l`
find outdated packages `dotnet list package --outdated`

9
requests/semester.http Normal file
View File

@@ -0,0 +1,9 @@
###
GET https://snow.instructure.com/api/v1/account_calendars
Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
###
GET https://snow.instructure.com/api/v1/accounts/10/terms
Authorization: Bearer {{$dotenv CANVAS_TOKEN}}