mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
commit pre-purge
This commit is contained in:
10
Management.Test/Features/SemesterPlannerTests.cs
Normal file
10
Management.Test/Features/SemesterPlannerTests.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Management.Test;
|
||||||
|
|
||||||
|
public class SemesterPlannerTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCanCreatePlannerFromCanvasSemester()
|
||||||
|
{
|
||||||
|
// var
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
22
Management.Test/Models/TermTests.cs
Normal file
22
Management.Test/Models/TermTests.cs
Normal 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
|
||||||
|
},
|
||||||
|
}";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Management.Test/Services/CanvasServiceTests.cs
Normal file
39
Management.Test/Services/CanvasServiceTests.cs
Normal 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@page "/fetchdata"
|
@page "/testing"
|
||||||
@using Management.Web.Data
|
@using Management.Web.Data
|
||||||
@inject WeatherForecastService ForecastService
|
@inject WeatherForecastService ForecastService
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -6,4 +6,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="RestSharp" Version="108.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -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; }
|
);
|
||||||
}
|
|
||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
);
|
||||||
|
|||||||
@@ -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, "");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
7
Management/Services/IWebRequestor.cs
Normal file
7
Management/Services/IWebRequestor.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using RestSharp;
|
||||||
|
|
||||||
|
public interface IWebRequestor
|
||||||
|
{
|
||||||
|
Task<RestResponse<T[]>> GetManyAsync<T>(RestRequest request);
|
||||||
|
Task<RestResponse<T>> GetAsync<T>(RestRequest request);
|
||||||
|
}
|
||||||
26
Management/Services/WebRequestor.cs
Normal file
26
Management/Services/WebRequestor.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,4 +3,6 @@
|
|||||||
|
|
||||||
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
9
requests/semester.http
Normal 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}}
|
||||||
|
|
||||||
Reference in New Issue
Block a user