From 00a6619cbeb43e64394a4b3ffbbed4194244689e Mon Sep 17 00:00:00 2001
From: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
Date: Tue, 27 Jan 2026 16:35:48 +0000
Subject: [PATCH] feat(api)!: Add model permission checks and deprecate
`canPublish` (#434)
* Add permission checks and deprecate canPublish
* Fix tests
* How's this
* make tests more reliable
* lets test this first
* test
* This should speed up unit tests
* skip slow tests
* I HATE flaky tests
---
Speckle.Sdk.slnx | 1 +
.../GraphQL/Models/ModelPermissionChecks.cs | 8 ++++
.../GraphQL/Models/ProjectPermissionChecks.cs | 2 +
.../GraphQL/Resources/ActiveUserResource.cs | 5 --
.../Api/GraphQL/Resources/ModelResource.cs | 47 +++++++++++++++++++
src/Speckle.Sdk/Host/TypeLoader.cs | 17 ++++++-
.../SerializationTests.cs | 2 +-
...s.CancelNonExistentIngestion.verified.json | 8 ----
...eIngestionNonExistentProject.verified.json | 8 ----
...UpdateNonExistentNonExistent.verified.json | 8 ----
.../ModelIngestionResourceExceptionalTests.cs | 15 +++---
.../Resources/ModelIngestionResourceTests.cs | 6 +--
.../GraphQL/Resources/ModelResourceTests.cs | 20 +++++++-
.../GraphQL/Resources/ProjectResourceTests.cs | 24 +++++++++-
.../Resources/SubscriptionResourceTests.cs | 4 +-
.../Speckle.Sdk.Tests.Integration/Fixtures.cs | 5 ++
.../MemoryTransportTests.cs | 7 +--
.../SendReceiveTests.cs | 7 +--
.../Api/Operations/ClosureTests.cs | 4 +-
.../Api/Operations/OperationsReceiveTests.cs | 4 +-
.../Api/Operations/SendObjectReferences.cs | 4 +-
.../Api/Operations/SendReceiveLocal.cs | 4 +-
.../Api/Operations/SerializationTests.cs | 4 +-
tests/Speckle.Sdk.Tests.Unit/Assembly.cs | 2 +-
tests/Speckle.Sdk.Tests.Unit/Collections.cs | 7 +++
.../Credentials/AccountManagerTests.cs | 1 +
.../AccountServerMigrationTests.cs | 1 +
.../Credentials/Accounts.cs | 1 +
.../Models/BaseTests.cs | 4 +-
.../Models/DynamicBaseTests.cs | 4 +-
.../Models/Extensions/BaseExtensionsTests.cs | 4 +-
.../Models/Extensions/DisplayValueTests.cs | 4 +-
.../GraphTraversal/GraphTraversalTests.cs | 4 +-
.../Speckle.Sdk.Tests.Unit/Models/Hashing.cs | 5 +-
.../Models/SpeckleType.cs | 4 +-
.../Serialisation/ChunkingTests.cs | 4 +-
.../Serialisation/JsonIgnoreAttributeTests.cs | 4 +-
.../ObjectModelDeprecationTests.cs | 4 +-
.../SerializerBreakingChanges.cs | 4 +-
.../SerializerNonBreakingChanges.cs | 4 +-
.../Serialisation/SimpleRoundTripTests.cs | 3 ++
41 files changed, 182 insertions(+), 96 deletions(-)
create mode 100644 src/Speckle.Sdk/Api/GraphQL/Models/ModelPermissionChecks.cs
delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CancelNonExistentIngestion.verified.json
delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CreateIngestionNonExistentProject.verified.json
delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.UpdateNonExistentNonExistent.verified.json
create mode 100644 tests/Speckle.Sdk.Tests.Unit/Collections.cs
diff --git a/Speckle.Sdk.slnx b/Speckle.Sdk.slnx
index 8b77f1f3..3f7ded3f 100644
--- a/Speckle.Sdk.slnx
+++ b/Speckle.Sdk.slnx
@@ -10,6 +10,7 @@
+
diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/ModelPermissionChecks.cs b/src/Speckle.Sdk/Api/GraphQL/Models/ModelPermissionChecks.cs
new file mode 100644
index 00000000..c1539050
--- /dev/null
+++ b/src/Speckle.Sdk/Api/GraphQL/Models/ModelPermissionChecks.cs
@@ -0,0 +1,8 @@
+namespace Speckle.Sdk.Api.GraphQL.Models;
+
+public sealed class ModelPermissionChecks
+{
+ public PermissionCheckResult canUpdate { get; init; }
+ public PermissionCheckResult canDelete { get; init; }
+ public PermissionCheckResult canCreateVersion { get; init; }
+}
diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/ProjectPermissionChecks.cs b/src/Speckle.Sdk/Api/GraphQL/Models/ProjectPermissionChecks.cs
index 90ba8e52..dd4e318f 100644
--- a/src/Speckle.Sdk/Api/GraphQL/Models/ProjectPermissionChecks.cs
+++ b/src/Speckle.Sdk/Api/GraphQL/Models/ProjectPermissionChecks.cs
@@ -5,5 +5,7 @@ public sealed class ProjectPermissionChecks
public PermissionCheckResult canCreateModel { get; init; }
public PermissionCheckResult canDelete { get; init; }
public PermissionCheckResult canLoad { get; init; }
+
+ [Obsolete("Use ModelPermissionChecks.CanCreateVersion instead", true)]
public PermissionCheckResult canPublish { get; init; }
}
diff --git a/src/Speckle.Sdk/Api/GraphQL/Resources/ActiveUserResource.cs b/src/Speckle.Sdk/Api/GraphQL/Resources/ActiveUserResource.cs
index 17615a02..cb545181 100644
--- a/src/Speckle.Sdk/Api/GraphQL/Resources/ActiveUserResource.cs
+++ b/src/Speckle.Sdk/Api/GraphQL/Resources/ActiveUserResource.cs
@@ -397,11 +397,6 @@ public sealed class ActiveUserResource
authorized
message
}
- canPublish {
- code
- authorized
- message
- }
}
}
}
diff --git a/src/Speckle.Sdk/Api/GraphQL/Resources/ModelResource.cs b/src/Speckle.Sdk/Api/GraphQL/Resources/ModelResource.cs
index 87607ee8..6e0af0b9 100644
--- a/src/Speckle.Sdk/Api/GraphQL/Resources/ModelResource.cs
+++ b/src/Speckle.Sdk/Api/GraphQL/Resources/ModelResource.cs
@@ -312,4 +312,51 @@ public sealed class ModelResource
return res.data.data;
}
+
+ ///
+ ///
+ ///
+ ///
+ public async Task GetPermissions(
+ string projectId,
+ string modelId,
+ CancellationToken cancellationToken = default
+ )
+ {
+ //language=graphql
+ const string QUERY = """
+ query ModelPermissions($projectId: String!, $modelId: String!) {
+ data:project(id: $projectId) {
+ data:model(id: $modelId) {
+ data:permissions {
+ canUpdate {
+ authorized
+ code
+ message
+ }
+ canDelete {
+ authorized
+ code
+ message
+ }
+ canCreateVersion {
+ authorized
+ code
+ message
+ }
+ }
+ }
+ }
+ }
+ """;
+ GraphQLRequest request = new() { Query = QUERY, Variables = new { projectId, modelId } };
+
+ var response = await _client
+ .ExecuteGraphQLRequest>>>(
+ request,
+ cancellationToken
+ )
+ .ConfigureAwait(false);
+ return response.data.data.data;
+ }
}
diff --git a/src/Speckle.Sdk/Host/TypeLoader.cs b/src/Speckle.Sdk/Host/TypeLoader.cs
index ad9a452b..18f17661 100644
--- a/src/Speckle.Sdk/Host/TypeLoader.cs
+++ b/src/Speckle.Sdk/Host/TypeLoader.cs
@@ -140,7 +140,22 @@ internal static class TypeLoader
return typeof(Base);
}
- //Don't use unless you're testing
+ ///
+ /// For testing purposes only
+ ///
+ internal static void ReInitialize(params Assembly[] assemblies)
+ {
+ lock (s_availableTypes)
+ {
+ Reset();
+ Load(assemblies);
+ s_initialized = true;
+ }
+ }
+
+ ///
+ /// For testing purposes only
+ ///
public static void Reset()
{
s_availableTypes = new();
diff --git a/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs b/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs
index e7f5f0e7..a6725a9f 100644
--- a/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs
+++ b/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs
@@ -184,7 +184,7 @@ public class SerializationTests
idToBase.Count.Should().Be(count);
}
- [Theory]
+ [Theory(Skip = "Takes too long")]
[InlineData(1)]
[InlineData(4)]
public async Task Roundtrip_Test_New(int concurrency)
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CancelNonExistentIngestion.verified.json b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CancelNonExistentIngestion.verified.json
deleted file mode 100644
index e743803c..00000000
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CancelNonExistentIngestion.verified.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "Type": "AggregateException",
- "InnerException": {
- "Data": {},
- "Message": "NOT_FOUND_ERROR: Model ingestion not found",
- "Type": "SpeckleGraphQLException"
- }
-}
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CreateIngestionNonExistentProject.verified.json b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CreateIngestionNonExistentProject.verified.json
deleted file mode 100644
index 04a2199a..00000000
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.CreateIngestionNonExistentProject.verified.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "Type": "AggregateException",
- "InnerException": {
- "Data": {},
- "Message": "STREAM_NOT_FOUND: Project not found",
- "Type": "SpeckleGraphQLStreamNotFoundException"
- }
-}
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.UpdateNonExistentNonExistent.verified.json b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.UpdateNonExistentNonExistent.verified.json
deleted file mode 100644
index e743803c..00000000
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.UpdateNonExistentNonExistent.verified.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "Type": "AggregateException",
- "InnerException": {
- "Data": {},
- "Message": "NOT_FOUND_ERROR: Model ingestion not found",
- "Type": "SpeckleGraphQLException"
- }
-}
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.cs
index 0bae1526..722fcfab 100644
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceExceptionalTests.cs
@@ -1,10 +1,7 @@
-using System.Reflection;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Api.GraphQL.Resources;
-using Speckle.Sdk.Host;
-using Speckle.Sdk.Models;
namespace Speckle.Sdk.Tests.Integration.API.GraphQL.Resources;
@@ -20,9 +17,6 @@ public sealed class ModelIngestionResourceExceptionalTests : IAsyncLifetime
public async Task InitializeAsync()
{
- TypeLoader.Reset();
- TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly());
-
_testUser = await Fixtures.SeedUserWithClient();
_project = await _testUser.Project.Create(new("Test project", "", null));
_model = await _testUser.Model.Create(new("Test Model 1", "", _project.id));
@@ -42,7 +36,8 @@ public sealed class ModelIngestionResourceExceptionalTests : IAsyncLifetime
{
_ = await Sut.Create(createInput);
});
- await Verify(ex);
+ Assert.Single(ex.InnerExceptions);
+ Assert.All(ex.InnerExceptions, item => Assert.IsType(item));
}
[Fact]
@@ -54,7 +49,8 @@ public sealed class ModelIngestionResourceExceptionalTests : IAsyncLifetime
{
_ = await Sut.UpdateProgress(updateInput);
});
- await Verify(ex);
+ Assert.Single(ex.InnerExceptions);
+ Assert.All(ex.InnerExceptions, item => Assert.IsType(item));
}
[Fact]
@@ -69,6 +65,7 @@ public sealed class ModelIngestionResourceExceptionalTests : IAsyncLifetime
{
_ = await Sut.FailWithCancel(input);
});
- await Verify(ex);
+ Assert.Single(ex.InnerExceptions);
+ Assert.All(ex.InnerExceptions, item => Assert.IsType(item));
}
}
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceTests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceTests.cs
index 829deb5a..88ff78d2 100644
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelIngestionResourceTests.cs
@@ -1,11 +1,9 @@
-using System.Reflection;
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Enums;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Api.GraphQL.Resources;
-using Speckle.Sdk.Host;
using Speckle.Sdk.Models;
using Speckle.Sdk.Transports;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
@@ -25,8 +23,6 @@ public sealed class ModelIngestionResourceTests : IAsyncLifetime
public async Task InitializeAsync()
{
- TypeLoader.Reset();
- TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly());
var serviceProvider = TestServiceSetup.GetServiceProvider();
_operations = serviceProvider.GetRequiredService();
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelResourceTests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelResourceTests.cs
index 0b7b9481..b38436a3 100644
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelResourceTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ModelResourceTests.cs
@@ -1,5 +1,6 @@
using FluentAssertions;
using Speckle.Sdk.Api;
+using Speckle.Sdk.Api.GraphQL.Enums;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Api.GraphQL.Resources;
@@ -17,7 +18,7 @@ public class ModelResourceTests : IAsyncLifetime
{
// Runs instead of [SetUp] in NUnit
_testUser = await Fixtures.SeedUserWithClient();
- _project = await _testUser.Project.Create(new("Test project", "", null));
+ _project = await _testUser.Project.Create(new("Test project", "", ProjectVisibility.Public));
_model = await _testUser.Model.Create(new("Test Model", "", _project.id));
}
@@ -123,4 +124,21 @@ public class ModelResourceTests : IAsyncLifetime
var delEx = await FluentActions.Invoking(() => Sut.Delete(input)).Should().ThrowAsync();
getEx.WithInnerExceptionExactly();
}
+
+ [Fact]
+ public async Task TestUserHasModelPermissions()
+ {
+ var ownerResult = await Sut.GetPermissions(_project.id, _model.id);
+ ownerResult.canUpdate.authorized.Should().Be(true);
+ ownerResult.canCreateVersion.authorized.Should().Be(true);
+ ownerResult.canDelete.authorized.Should().Be(true);
+
+ // Test with another user
+ var guest = await Fixtures.SeedUserWithClient();
+
+ var guestResult = await guest.Model.GetPermissions(_project.id, _model.id);
+ guestResult.canUpdate.authorized.Should().Be(false);
+ guestResult.canCreateVersion.authorized.Should().Be(false);
+ guestResult.canDelete.authorized.Should().Be(false);
+ }
}
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ProjectResourceTests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ProjectResourceTests.cs
index 0947d096..167fb4e9 100644
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ProjectResourceTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/ProjectResourceTests.cs
@@ -103,8 +103,30 @@ public class ProjectResourceTests
[Fact]
public async Task TestUserHasProjectPermissions()
{
- var res = await Sut.GetPermissions(_testProject.id);
+ var privateProject = await _testUser.Project.Create(
+ new ProjectCreateInput("asdfasdf", "desc", ProjectVisibility.Private)
+ );
+
+ var resp = await Sut.GetPermissions(privateProject.id);
+ resp.canCreateModel.authorized.Should().Be(true);
+ resp.canDelete.authorized.Should().Be(true);
+ resp.canLoad.authorized.Should().Be(true);
+
+ var publicProject = await _testUser.Project.Create(
+ new ProjectCreateInput("asdfasdf", "desc", ProjectVisibility.Public)
+ );
+
+ var res = await Sut.GetPermissions(publicProject.id);
res.canCreateModel.authorized.Should().Be(true);
res.canDelete.authorized.Should().Be(true);
+ res.canLoad.authorized.Should().Be(true);
+
+ // Test with another user
+ var guest = await Fixtures.SeedUserWithClient();
+
+ var guestResult = await guest.Project.GetPermissions(publicProject.id);
+ guestResult.canCreateModel.authorized.Should().Be(false);
+ guestResult.canDelete.authorized.Should().Be(false);
+ guestResult.canLoad.authorized.Should().Be(false);
}
}
diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/SubscriptionResourceTests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/SubscriptionResourceTests.cs
index 63e4f780..e680e8b8 100644
--- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/SubscriptionResourceTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Resources/SubscriptionResourceTests.cs
@@ -13,9 +13,9 @@ public class SubscriptionResourceTests : IAsyncLifetime
#if DEBUG
private const int WAIT_PERIOD = 4000; // WSL is slow AF, so for local runs, we're being extra generous
#else
- private const int WAIT_PERIOD = 400; // For CI runs, a much smaller wait time is acceptable
+ private const int WAIT_PERIOD = 500; // For CI runs, a much smaller wait time is acceptable
#endif
- private const int TIMEOUT = WAIT_PERIOD + WAIT_PERIOD + 400;
+ private const int TIMEOUT = WAIT_PERIOD + WAIT_PERIOD + 500;
private IClient _testUser;
private Project _testProject;
private Model _testModel;
diff --git a/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs b/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs
index 3fcfd670..95da56e5 100644
--- a/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs
@@ -17,6 +17,11 @@ using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
[assembly: AssemblyTrait("Category", "Integration")]
+#if DEBUG
+[assembly: CollectionBehavior(MaxParallelThreads = 8)]
+
+#endif
+
namespace Speckle.Sdk.Tests.Integration;
public static class Fixtures
diff --git a/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs b/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs
index f1c7cc8b..d8e01c20 100644
--- a/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs
@@ -1,8 +1,6 @@
-using System.Reflection;
-using FluentAssertions;
+using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Sdk.Api;
-using Speckle.Sdk.Host;
using Speckle.Sdk.Models;
using Speckle.Sdk.Transports;
@@ -16,8 +14,7 @@ public class MemoryTransportTests : IDisposable
public MemoryTransportTests()
{
CleanData();
- TypeLoader.Reset();
- TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly());
+
var serviceProvider = TestServiceSetup.GetServiceProvider();
_operations = serviceProvider.GetRequiredService();
}
diff --git a/tests/Speckle.Sdk.Tests.Integration/SendReceiveTests.cs b/tests/Speckle.Sdk.Tests.Integration/SendReceiveTests.cs
index 78227b1a..56cbd17f 100644
--- a/tests/Speckle.Sdk.Tests.Integration/SendReceiveTests.cs
+++ b/tests/Speckle.Sdk.Tests.Integration/SendReceiveTests.cs
@@ -1,11 +1,8 @@
-using System.Reflection;
-using System.Text;
+using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Enums;
using Speckle.Sdk.Api.GraphQL.Models;
-using Speckle.Sdk.Host;
-using Speckle.Sdk.Models;
namespace Speckle.Sdk.Tests.Integration;
@@ -19,8 +16,6 @@ public sealed class SendReceiveTests : IAsyncLifetime
public async Task InitializeAsync()
{
- TypeLoader.Reset();
- TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly());
var serviceProvider = TestServiceSetup.GetServiceProvider();
_operations = serviceProvider.GetRequiredService();
ClearCache();
diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs
index 1397a9ec..08f9b964 100644
--- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs
+++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs
@@ -10,14 +10,14 @@ using Speckle.Sdk.Transports;
namespace Speckle.Sdk.Tests.Unit.Api.Operations;
+[Collection(nameof(RequiresTypeLoaderCollection))]
public class Closures
{
private readonly IOperations _operations;
public Closures()
{
- TypeLoader.Reset();
- TypeLoader.Initialize(typeof(Base).Assembly, typeof(TableLegFixture).Assembly);
+ TypeLoader.ReInitialize(typeof(Base).Assembly, typeof(TableLegFixture).Assembly);
var serviceProvider = TestServiceSetup.GetServiceProvider();
_operations = serviceProvider.GetRequiredService();
}
diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs
index 8ca3a9a9..fb734b45 100644
--- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs
+++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs
@@ -7,6 +7,7 @@ using Speckle.Sdk.Transports;
namespace Speckle.Sdk.Tests.Unit.Api.Operations;
+[Collection(nameof(RequiresTypeLoaderCollection))]
public sealed partial class OperationsReceiveTests : IDisposable
{
private static readonly Base[] s_testObjects;
@@ -44,8 +45,7 @@ public sealed partial class OperationsReceiveTests : IDisposable
private static void Reset()
{
- TypeLoader.Reset();
- TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly());
+ TypeLoader.ReInitialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly());
}
public static IEnumerable