Compare commits

..

29 Commits

Author SHA1 Message Date
Jedd Morgan efc38d8f5c Added Workspace project visibility (#307)
.NET Build and Publish / build (push) Has been cancelled
2025-05-14 21:37:39 +03:00
Adam Hathcock 8d3985f93b Merge pull request #305 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev to Main
2025-05-14 10:19:51 +01:00
Jedd Morgan 915a18dc98 Merge pull request #303 from specklesystems/jrm/main-dev
Main -> Dev
2025-05-13 11:38:56 +01:00
Jedd Morgan 5fcb3223d6 Merge branch 'dev' into jrm/main-dev 2025-05-13 11:28:13 +01:00
Adam Hathcock 21851c06d2 Use WhenAll instead of WhenAny and avoid manual task exception processing (#300)
* No reason to process exceptions manually

* formatting

* use a pool for gathering child task results

* Use a smaller whenany with a cancellation

* formatting
2025-05-13 10:00:53 +01:00
Adam Hathcock 3a9a633d30 Add empty DataObject tests (#301)
* Add empty DataObject tests

* format
2025-05-09 14:51:03 +00:00
Jedd Morgan 7f092d529c feat(api): Add ActiveUserResource.GetProjectsWithPermissions (#299)
.NET Build and Publish / build (push) Has been cancelled
* Fixed Mistakes (#296)

* Added extra permission checks (#297)

* Add extra query for project with permissions

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-05-08 15:11:53 +00:00
Jedd Morgan a4f0e0e4aa Added extra permission checks (#297)
.NET Build and Publish / build (push) Has been cancelled
2025-05-08 09:25:08 +00:00
Jedd Morgan 227729a0df Fixed Mistakes (#296)
.NET Build and Publish / build (push) Has been cancelled
2025-05-07 17:01:56 +00:00
Jedd Morgan 178085f3f8 dev -> main (#295)
.NET Build and Publish / build (push) Has been cancelled
* Sanitize test references

* add registration tests to SDK and ignore classes that can't be made

* add additional test

* chore(dev) Update to csharpier 1.0 (#284)

* Update to csharpier 1.0

* Fix check and nowarn

* format

* Update dependencies (#285)

* Added extra test for GetMembers (#290)

* Added extra test for GetMembers

* fixed tests

* verify

* Format

* Run the module init on unit tests and make it json

* update deps

* gitignore support was disabled in csharpier 1.0.1

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>

* Add workspaces queries (#291)

* Add workspaces queries

* Format

* extra tweaks

* init speckle verify

* Add workspace creation state

* Add workspace creation test

* test exceptional cases

* GetActiveWorkspace tests

* fixed test

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-05-06 18:02:59 +03:00
Adam Hathcock 9794195e9c Merge pull request #293 from specklesystems/main-dev
.NET Build and Publish / build (push) Has been cancelled
Main to dev (NO SQUASH)
2025-05-06 14:00:54 +01:00
Adam Hathcock a61c442930 Merge branch 'dev' into main-dev 2025-05-06 13:50:16 +01:00
Jedd Morgan 68a407905d Add workspaces queries (#291)
* Add workspaces queries

* Format

* extra tweaks

* init speckle verify

* Add workspace creation state

* Add workspace creation test

* test exceptional cases

* GetActiveWorkspace tests

* fixed test
2025-05-01 21:23:30 +03:00
Adam Hathcock 0f2abaf532 Merge remote-tracking branch 'origin/dev' into main-dev 2025-04-30 16:24:06 +01:00
Adam Hathcock 07634b6f6a Merge remote-tracking branch 'origin/dev' into main-dev 2025-04-30 16:22:39 +01:00
Jedd Morgan e938725d35 Added extra test for GetMembers (#290)
* Added extra test for GetMembers

* fixed tests

* verify

* Format

* Run the module init on unit tests and make it json

* update deps

* gitignore support was disabled in csharpier 1.0.1

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-04-30 16:13:41 +01:00
Adam Hathcock d3369e3ce5 Merge pull request #289 from specklesystems/main-dev
Main to dev (don't squash)
2025-04-30 16:00:46 +01:00
KatKatKateryna d75a61d775 Add text class (#271)
.NET Build and Publish / build (push) Has been cancelled
* draft class

* corrections

* edits

* max width

* remove import

* typo

* naming

* move directories

* delete from old location

* comment

* formatting

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-04-30 10:56:29 +02:00
Adam Hathcock 2ae4003afb Merge branch 'main' into main-dev 2025-04-28 10:52:58 +01:00
Adam Hathcock 88188aace6 Merge pull request #287 from specklesystems/main-dev
Main to dev (NO SQUASH)
2025-04-24 12:12:06 +01:00
Adam Hathcock ad44a7cdbc Merge branch 'dev' into main-dev 2025-04-24 12:01:32 +01:00
Adam Hathcock 38449dca9a Update dependencies (#285) 2025-04-24 11:59:26 +01:00
Adam Hathcock 764eb43838 Merge branch 'dev' into main-dev 2025-04-24 11:52:02 +01:00
Adam Hathcock a84e6d89ca chore(dev) Update to csharpier 1.0 (#284)
* Update to csharpier 1.0

* Fix check and nowarn

* format
2025-04-24 10:45:09 +00:00
Adam Hathcock a479440b66 Merge pull request #286 from specklesystems/adam/check-registration
feature (dev) check registration
2025-04-24 11:29:27 +01:00
Adam Hathcock d44b4fa52b add additional test 2025-04-24 08:33:42 +01:00
Adam Hathcock ea6ca8c555 add registration tests to SDK and ignore classes that can't be made 2025-04-23 15:57:03 +01:00
Adam Hathcock 113f0fd551 Sanitize test references 2025-04-23 15:42:57 +01:00
Adam Hathcock bcc4e25970 Merge pull request #280 from specklesystems/main-dev
Main->Dev
2025-04-23 13:04:37 +01:00
78 changed files with 1383 additions and 610 deletions
+2 -2
View File
@@ -3,9 +3,9 @@
"isRoot": true,
"tools": {
"csharpier": {
"version": "0.30.6",
"version": "1.0.1",
"commands": [
"dotnet-csharpier"
"csharpier"
],
"rollForward": false
},
+26
View File
@@ -0,0 +1,26 @@
Directory.Build.targets
Directory.Build.props
**/bin/*
**/obj/*
_ReSharper.SharpCompress/
bin/
*.suo
*.user
TestArchives/Scratch/
TestArchives/Scratch2/
TestResults/
*.nupkg
packages/*/
project.lock.json
tests/TestArchives/Scratch
.vs
tools
.vscode
.idea/
.DS_Store
*.snupkg
coverage.xml
*.received.*
+1 -1
View File
@@ -1,6 +1,6 @@
printWidth: 120
useTabs: false
tabWidth: 2
indentSize: 2
preprocessorSymbolSets:
- ""
- "DEBUG"
+8 -21
View File
@@ -1,5 +1,4 @@
<Project>
<PropertyGroup Label="Compiler Properties">
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
@@ -7,7 +6,6 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
<PropertyGroup Label="Nugetspec Package Properties">
<!-- Defines common Nugetspec properties -->
<!-- Inheriting packable projects should define the rest of the nugetspec properties (PackageId, Description) -->
@@ -22,18 +20,16 @@
<PackageTags>speckle</PackageTags>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>false</IsPackable> <!--Can be set to true in inheriting .props/.csproj files for projects that should be packed-->
<IsPackable>false</IsPackable>
<!--Can be set to true in inheriting .props/.csproj files for projects that should be packed-->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<PropertyGroup Label="Analyers">
<EnableNetAnalyzers>true</EnableNetAnalyzers>
<AnalysisLevel>latest-AllEnabledByDefault</AnalysisLevel>
@@ -41,7 +37,6 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Ingored warnings, some aspirational but too noisy for now, some by design. -->
<NoWarn>
<!--Disabled by design-->
@@ -59,28 +54,20 @@
<!-- Aspirational -->
CA1502;CA1716;NETSDK1206;
$(NoWarn)
</NoWarn>
</NoWarn
>
</PropertyGroup>
<PropertyGroup>
<!-- Expose the repository root to all projects -->
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
</PropertyGroup>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
<None
Condition="'$(IsPackable)' == 'true'"
Include="..\..\logo.png"
Pack="true"
PackagePath="\"
Visible="false"/>
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
<None Condition="'$(IsPackable)' == 'true'" Include="..\..\logo.png" Pack="true" PackagePath="\" Visible="false" />
</ItemGroup>
<ItemGroup>
<!-- This file contains the configuration for some analyzer warnings, such as cyclomatic
complexity threshold -->
<AdditionalFiles Include="$(RepositoryRoot)CodeMetricsConfig.txt"/>
<AdditionalFiles Include="$(RepositoryRoot)CodeMetricsConfig.txt" />
</ItemGroup>
</Project>
+13 -14
View File
@@ -1,18 +1,17 @@
<Project>
<PropertyGroup Condition="'$(IsTestProject)' == 'true'">
<NoWarn>
$(NoWarn);
<!-- Things we need to test -->
CS0618;CA1034;CA2201;CA1051;CA1040;CA1724;
IDE0044;IDE0130;CA1508;
<!-- Analysers that provide no tangeable value to a test project -->
CA5394;CA2007;CA1852;CA1819;CA1711;CA1063;CA1816;CA2234;CS8618;CA1054;CA1810;CA2208;CA1019;CA1831;
</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(IsTestProject)' == 'true'">
<NoWarn>
<!-- Things we need to test -->
CS0618;CA1034;CA2201;CA1051;CA1040;CA1724;
IDE0044;IDE0130;CA1508;
<!-- Analysers that provide no tangeable value to a test project -->
CA5394;CA2007;CA1852;CA1819;CA1711;CA1063;CA1816;CA2234;CS8618;CA1054;CA1810;CA2208;CA1019;CA1831;
$(NoWarn);
</NoWarn>
</PropertyGroup>
<Target Name="DeepClean">
<Message Text="Deep clean of $(MSBuildProjectName).csproj" Importance="high"/>
<RemoveDir Directories="$(BaseIntermediateOutputPath)"/>
<RemoveDir Directories="$(BaseOutputPath)"/>
<Message Text="Deep clean of $(MSBuildProjectName).csproj" Importance="high" />
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
</Project>
+4 -4
View File
@@ -11,14 +11,14 @@
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<!-- Keep at exactly 7.0.5 for side by side with V2 -->
<PackageVersion Include="Microsoft.Data.Sqlite" Version="[7.0.5,)" />
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="9.0.3" />
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="9.0.4" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0,)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[2.2.0,)" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="[2.2.0,)" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="[5.0.0,)" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Open.ChannelExtensions" Version="9.0.0" />
<PackageVersion Include="Open.ChannelExtensions" Version="9.1.0" />
<PackageVersion Include="Polly" Version="7.2.3" />
<PackageVersion Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
@@ -26,9 +26,9 @@
<PackageVersion Include="Speckle.Newtonsoft.Json" Version="13.0.2" />
<PackageVersion Include="Speckle.DoubleNumerics" Version="4.1.0" />
<PackageVersion Include="SimpleExec" Version="12.0.0" />
<PackageVersion Include="System.Threading.Channels" Version="9.0.2" />
<PackageVersion Include="System.Threading.Channels" Version="9.0.4" />
<PackageVersion Include="Verify.Quibble" Version="2.1.1" />
<PackageVersion Include="Verify.Xunit" Version="29.2.0" />
<PackageVersion Include="Verify.Xunit" Version="29.4.0" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.assert" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
+1 -1
View File
@@ -68,7 +68,7 @@ Target(
Target(RESTORE_TOOLS, () => RunAsync("dotnet", "tool restore"));
Target(FORMAT, dependsOn: [RESTORE_TOOLS], () => RunAsync("dotnet", "csharpier --check ."));
Target(FORMAT, dependsOn: [RESTORE_TOOLS], () => RunAsync("dotnet", "csharpier check ."));
Target(RESTORE, dependsOn: [FORMAT], () => RunAsync("dotnet", "restore Speckle.Sdk.sln --locked-mode"));
+1 -2
View File
@@ -1,10 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ItemGroup>
<PackageReference Include="Bullseye" />
<PackageReference Include="Glob" />
<PackageReference Include="SimpleExec" />
+2
View File
@@ -100,6 +100,8 @@ services:
POSTGRES_PASSWORD: "speckle"
POSTGRES_DB: "speckle"
ENABLE_MP: "false"
LOG_PRETTY: "true"
networks:
default:
+69
View File
@@ -0,0 +1,69 @@
using Speckle.Objects.Geometry;
using Speckle.Sdk.Models;
using Point = Speckle.Objects.Geometry.Point;
namespace Speckle.Objects.Annotation;
/// <summary>
/// Text class for representation in the viewer
/// </summary>
[SpeckleType("Objects.Annotation.Text")]
public class Text : Base
{
/// <summary>
/// Plain text, without formatting
/// </summary>
public required string value { get; set; }
/// <summary>
/// Origin point, relation to the text is defined by AlignmentHorizontal and AlignmentVertical
/// </summary>
public required Point origin { get; set; }
/// <summary>
/// Height in linear units or pixels (if Units.None)
/// </summary>
public required double height { get; set; }
/// <summary>
/// Units will be 'Units.None' if the text size is defined in pixels (stays the same size
/// independently of zooming the model). Default height in pixels is 17px (used for Viewer measurements)
/// </summary>
public required string units { get; set; }
/// <summary>
/// Horizontal alignment: Left, Center or Right
/// </summary>
public AlignmentHorizontal alignmentH { get; set; }
/// <summary>
/// Vertical alignment: Top, Center or Bottom
/// </summary>
public AlignmentVertical alignmentV { get; set; }
/// <summary>
/// Plane will be null if the text object orientation follows camera view
/// </summary>
public Plane? plane { get; set; }
/// <summary>
/// Maximum width of the text field (in 'units').
/// Text will be split into lines (wrapped) to fit into the width.
/// null, if text should not be wrapped.
/// </summary>
public double? maxWidth { get; set; }
}
public enum AlignmentHorizontal
{
Left,
Center,
Right,
}
public enum AlignmentVertical
{
Top,
Center,
Bottom,
}
-1
View File
@@ -68,7 +68,6 @@ public class Plane : Base, ITransformable<Plane>
/// Returns the values of this <see cref="Plane"/> as a list of numbers
/// </summary>
/// <returns>A list of values representing the Plane.</returns>
public List<double> ToList()
{
var list = new List<double>();
-1
View File
@@ -147,7 +147,6 @@ public class Surface : Base, IHasBoundingBox, IHasArea, ITransformable<Surface>
/// </summary>
/// <returns>A 2-dimensional array representing this <see cref="Surface"/>s control points.</returns>
/// <remarks>The ControlPoints will be ordered following directions "[u][v]"</remarks>
public List<List<ControlPoint>> GetControlPoints()
{
var matrix = new List<List<ControlPoint>>();
@@ -1,37 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Compiler Properties">
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<PolySharpExcludeGeneratedTypes>System.Runtime.CompilerServices.RequiresLocationAttribute</PolySharpExcludeGeneratedTypes>
<Configurations>Debug;Release;Local</Configurations>
</PropertyGroup>
<PropertyGroup Label="Nugetspec Package Properties">
<PackageId>Speckle.Objects</PackageId>
<Description>Objects is the default object model for Speckle</Description>
<PackageTags>$(PackageTags) objects</PackageTags>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup Label="Analyers">
<NoWarn>
$(NoWarn);
CA1819;CA1008;CA2225;
</NoWarn>
</PropertyGroup>
<ItemGroup Label="Expose internals to test projects">
<InternalsVisibleTo Include="Speckle.Objects.Tests.Unit" />
</ItemGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\Speckle.Sdk\Speckle.Sdk.csproj" />
</ItemGroup>
</Project>
@@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Compiler Properties">
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<Configurations>Debug;Release;Local</Configurations>
@@ -7,30 +6,26 @@
<ILRepackRenameInternalized>true</ILRepackRenameInternalized>
<ILRepackMergeDebugSymbols>true</ILRepackMergeDebugSymbols>
</PropertyGroup>
<PropertyGroup Label="Nugetspec Package Properties">
<PackageId>Speckle.Sdk.Dependencies</PackageId>
<Description>The .NET SDK for Speckle</Description>
<PackageTags>$(PackageTags) core sdk</PackageTags>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ILRepack.FullAuto">
<PackageReference Include="ILRepack.FullAuto">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.ObjectPool" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" PrivateAssets="all" />
<PackageReference Include="Polly" PrivateAssets="all" />
<PackageReference Include="Polly.Contrib.WaitAndRetry" PrivateAssets="all" />
<PackageReference Include="Polly.Extensions.Http" PrivateAssets="all" />
<PackageReference Include="Open.ChannelExtensions" PrivateAssets="all" />
<PackageReference Include="System.Threading.Channels" PrivateAssets="all" />
</ItemGroup>
</Project>
+26 -26
View File
@@ -13,9 +13,9 @@
},
"Microsoft.Extensions.ObjectPool": {
"type": "Direct",
"requested": "[9.0.3, )",
"resolved": "9.0.3",
"contentHash": "4uPdnj9hLRrb3ZSeVEDtwIm9nNrrT9vAXYC9o1/yTW8lGOPwTyI2QlkcICwYEGM1LESGTFidcPMFACznUZKbIQ=="
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "G7p1k2xVZ+2aVANz0JdSiafr+AHDHeS1kF8+Y0ABbIsByd0erOL59IDXBs9vcdJf3pPV/murO0mbtr4k40QxWw=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
@@ -38,13 +38,13 @@
},
"Open.ChannelExtensions": {
"type": "Direct",
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "DP+l5S6G46wcuY4I4kNXE+RDOmJr0DKuMienOdt0mMBN9z7vmLSC8YQbqCyb9i9LNjXj1tgCx5LyitJiRr/v7g==",
"requested": "[9.1.0, )",
"resolved": "9.1.0",
"contentHash": "D6c24vMGy1oZ06vmkD2/FNzWHK7ZIihuv2spDgYEeaUp+eobrILQnrNQKRoASFXD4JGfZ7nfvTM0e+AX79dt8Q==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.0",
"System.Collections.Immutable": "9.0.0",
"System.Threading.Channels": "9.0.0"
"Microsoft.Bcl.AsyncInterfaces": "9.0.4",
"System.Collections.Immutable": "9.0.4",
"System.Threading.Channels": "9.0.4"
}
},
"Polly": {
@@ -82,11 +82,11 @@
},
"System.Threading.Channels": {
"type": "Direct",
"requested": "[9.0.2, )",
"resolved": "9.0.2",
"contentHash": "pUmqkuBS9OxWHOlfNad09Oxc8gRbxgN9UQtsqHPst4jfcgZRxQetNcsT2oe+VnUpEFAtBy1FZcJZiOscrBmA7g==",
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "4qBn2H6/aXBpE/Pm3wY5yusY/pEvQz99NlWHrTUji0qCmOdbhhjaALcpmbfW2ksxlPM6i6S+QFLkpOQdyfeKYQ==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "9.0.2",
"Microsoft.Bcl.AsyncInterfaces": "9.0.4",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
@@ -117,8 +117,8 @@
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==",
"resolved": "9.0.4",
"contentHash": "wfm2NgK22MmBe5qJjp52qzpkeDZKb4l9LbdubhZSehY1z4LS+lld6R+B+UQNb2AZRHu/QJlHxEUcRst5hIEejg==",
"dependencies": {
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
@@ -155,8 +155,8 @@
"Microsoft.Bcl.AsyncInterfaces": {
"type": "CentralTransitive",
"requested": "[5.0.0, )",
"resolved": "9.0.2",
"contentHash": "1CED0BGD7dCKsbe7tDhzpPB2Qdi9x35QChu6zkBEI4s0T5bDkkttGReqQnOeOfRNSxtP2WvpX6Ik/0O93XDuMw==",
"resolved": "9.0.4",
"contentHash": "9VGI5kxIvrNG2mqLQZnUR6y/3fcnygD8eNpHR+CqfbnIXvea6nehnYknDKQTxZVPMpzpNca+7DxLBmpdB3q0Bw==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
@@ -174,9 +174,9 @@
},
"Microsoft.Extensions.ObjectPool": {
"type": "Direct",
"requested": "[9.0.3, )",
"resolved": "9.0.3",
"contentHash": "4uPdnj9hLRrb3ZSeVEDtwIm9nNrrT9vAXYC9o1/yTW8lGOPwTyI2QlkcICwYEGM1LESGTFidcPMFACznUZKbIQ=="
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "G7p1k2xVZ+2aVANz0JdSiafr+AHDHeS1kF8+Y0ABbIsByd0erOL59IDXBs9vcdJf3pPV/murO0mbtr4k40QxWw=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
@@ -190,9 +190,9 @@
},
"Open.ChannelExtensions": {
"type": "Direct",
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "DP+l5S6G46wcuY4I4kNXE+RDOmJr0DKuMienOdt0mMBN9z7vmLSC8YQbqCyb9i9LNjXj1tgCx5LyitJiRr/v7g=="
"requested": "[9.1.0, )",
"resolved": "9.1.0",
"contentHash": "D6c24vMGy1oZ06vmkD2/FNzWHK7ZIihuv2spDgYEeaUp+eobrILQnrNQKRoASFXD4JGfZ7nfvTM0e+AX79dt8Q=="
},
"Polly": {
"type": "Direct",
@@ -229,9 +229,9 @@
},
"System.Threading.Channels": {
"type": "Direct",
"requested": "[9.0.2, )",
"resolved": "9.0.2",
"contentHash": "pUmqkuBS9OxWHOlfNad09Oxc8gRbxgN9UQtsqHPst4jfcgZRxQetNcsT2oe+VnUpEFAtBy1FZcJZiOscrBmA7g=="
"requested": "[9.0.4, )",
"resolved": "9.0.4",
"contentHash": "4qBn2H6/aXBpE/Pm3wY5yusY/pEvQz99NlWHrTUji0qCmOdbhhjaALcpmbfW2ksxlPM6i6S+QFLkpOQdyfeKYQ=="
},
"ILRepack": {
"type": "Transitive",
+13
View File
@@ -1,4 +1,5 @@
using Speckle.Sdk.Api.GraphQL;
using Speckle.Sdk.Api.GraphQL.Models;
namespace Speckle.Sdk.Api;
@@ -96,3 +97,15 @@ public sealed class SpeckleGraphQLInvalidQueryException : SpeckleGraphQLExceptio
public SpeckleGraphQLInvalidQueryException(string? message, Exception? innerException)
: base(message, innerException) { }
}
/// <seealso cref="PermissionCheckResult"/>
public sealed class WorkspacePermissionException : SpeckleGraphQLException
{
public WorkspacePermissionException() { }
public WorkspacePermissionException(string? message)
: base(message) { }
public WorkspacePermissionException(string? message, Exception? innerException)
: base(message, innerException) { }
}
+2
View File
@@ -36,6 +36,7 @@ public sealed class Client : ISpeckleGraphQLClient, IClient
public ProjectInviteResource ProjectInvite { get; }
public CommentResource Comment { get; }
public SubscriptionResource Subscription { get; }
public WorkspaceResource Workspace { get; }
public Uri ServerUrl => new(Account.serverInfo.url);
@@ -69,6 +70,7 @@ public sealed class Client : ISpeckleGraphQLClient, IClient
ProjectInvite = new(this);
Comment = new(this);
Subscription = new(this);
Workspace = new(this);
HttpClient = CreateHttpClient(application, speckleHttp, account);
@@ -1,10 +1,11 @@
namespace Speckle.Sdk.Api.GraphQL.Enums;
namespace Speckle.Sdk.Api.GraphQL.Enums;
public enum ProjectVisibility
{
Private = 0,
Private,
Public,
[Obsolete("Use Unlisted instead", true)]
Public = 1,
Unlisted = 2,
[Obsolete("Use Public instead")]
Unlisted,
Workspace,
}
@@ -6,6 +6,13 @@ public sealed record ProjectCommentsFilter(bool? includeArchived, bool? loadedVe
public sealed record ProjectCreateInput(string? name, string? description, ProjectVisibility? visibility);
public sealed record WorkspaceProjectCreateInput(
string? name,
string? description,
ProjectVisibility? visibility,
string workspaceId
);
public sealed record ProjectInviteCreateInput(string? email, string? role, string? serverRole, string? userId);
public sealed record ProjectInviteUseInput(bool accept, string projectId, string token);
@@ -29,4 +36,4 @@ public sealed record ProjectUpdateInput(
public sealed record ProjectUpdateRoleInput(string userId, string projectId, string? role);
public sealed record UserProjectsFilter(string search, IReadOnlyList<string>? onlyWithRoles = null);
public sealed record WorkspaceProjectsFilter(string? search, bool? withProjectRoleOnly);
@@ -6,3 +6,13 @@ public sealed record UserUpdateInput(
string? company = null,
string? name = null
);
public sealed record UserProjectsFilter(
string? search = null,
IReadOnlyList<string>? onlyWithRoles = null,
string? workspaceId = null,
bool? personalOnly = null,
bool? includeImplicitAccess = null
);
public sealed record UserWorkspacesFilter(string? search);
@@ -0,0 +1,17 @@
namespace Speckle.Sdk.Api.GraphQL.Models;
public sealed class PermissionCheckResult
{
public bool authorized { get; init; }
public string code { get; init; }
public string message { get; init; }
/// <exception cref="SpeckleException">Throws when <see cref="PermissionCheckResult.authorized"/> is <see langword="false"/></exception>
public void EnsureAuthorised()
{
if (!authorized)
{
throw new WorkspacePermissionException(message);
}
}
}
@@ -26,3 +26,8 @@ public sealed class ProjectWithTeam : Project
public List<PendingStreamCollaborator> invitedTeam { get; init; }
public List<ProjectCollaborator> team { get; init; }
}
public sealed class ProjectWithPermissions : Project
{
public ProjectPermissionChecks permissions { get; init; }
}
@@ -0,0 +1,9 @@
namespace Speckle.Sdk.Api.GraphQL.Models;
public sealed class ProjectPermissionChecks
{
public PermissionCheckResult canCreateModel { get; init; }
public PermissionCheckResult canDelete { get; init; }
public PermissionCheckResult canLoad { get; init; }
public PermissionCheckResult canPublish { get; init; }
}
@@ -7,6 +7,8 @@ public sealed class Version
public string id { get; init; }
public string? message { get; init; }
public Uri previewUrl { get; init; }
public string referencedObject { get; init; }
/// <remarks>May be <see langword="null"/> if workspaces version history limit has been exceeded</remarks>
public string? referencedObject { get; init; }
public string? sourceApplication { get; init; }
}
@@ -0,0 +1,26 @@
namespace Speckle.Sdk.Api.GraphQL.Models;
public sealed class Workspace
{
public string id { get; init; }
public string name { get; init; }
public string role { get; init; }
public string slug { get; init; }
public string? description { get; init; }
public string? logo { get; init; }
public DateTime? createdAt { get; init; }
public DateTime? updatedAt { get; init; }
public bool? readOnly { get; init; }
public WorkspacePermissionChecks permissions { get; init; }
public WorkspaceCreationState? creationState { get; init; }
}
public sealed class WorkspaceCreationState
{
public bool completed { get; init; }
}
public sealed class WorkspacePermissionChecks
{
public PermissionCheckResult canCreateProject { get; init; }
}
@@ -85,6 +85,7 @@ public sealed class ActiveUserResource
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
/// <exception cref="SpeckleException">The ActiveUser could not be found (e.g. the client is not authenticated)</exception>
public async Task<ResourceCollection<Project>> GetProjects(
int limit = ServerLimits.DEFAULT_PAGINATION_REQUEST,
string? cursor = null,
@@ -135,7 +136,7 @@ public sealed class ActiveUserResource
if (response.data is null)
{
throw new SpeckleGraphQLException("GraphQL response indicated that the ActiveUser could not be found");
throw new SpeckleException("GraphQL response indicated that the ActiveUser could not be found");
}
return response.data.data;
@@ -199,8 +200,250 @@ public sealed class ActiveUserResource
return response.data.data;
}
/// <inheritdoc cref="GetProjectInvites"/>
[Obsolete($"Renamed to {nameof(GetProjectInvites)}")]
public async Task<List<PendingStreamCollaborator>> ProjectInvites(CancellationToken cancellationToken = default) =>
await GetProjectInvites(cancellationToken).ConfigureAwait(false);
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
/// <exception cref="SpeckleException">The ActiveUser could not be found (e.g. the client is not authenticated)</exception>
public async Task<PermissionCheckResult> CanCreatePersonalProjects(CancellationToken cancellationToken = default)
{
//language=graphql
const string QUERY = """
query CanCreatePersonalProject {
data:activeUser {
data:permissions {
data:canCreatePersonalProject {
authorized
code
message
}
}
}
}
""";
var request = new GraphQLRequest { Query = QUERY };
var response = await _client
.ExecuteGraphQLRequest<NullableResponse<RequiredResponse<RequiredResponse<PermissionCheckResult>>?>>(
request,
cancellationToken
)
.ConfigureAwait(false);
if (response.data is null)
{
throw new SpeckleException("GraphQL response indicated that the ActiveUser could not be found");
}
return response.data.data.data;
}
/// <remarks>This feature is only available on Workspace enabled servers (e.g. app.speckle.systems)</remarks>
/// <param name="limit"></param>
/// <param name="cursor"></param>
/// <param name="filter"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
/// <exception cref="SpeckleException">The ActiveUser could not be found (e.g. the client is not authenticated)</exception>
public async Task<ResourceCollection<Workspace>> GetWorkspaces(
int limit = ServerLimits.DEFAULT_PAGINATION_REQUEST,
string? cursor = null,
UserWorkspacesFilter? filter = null,
CancellationToken cancellationToken = default
)
{
//language=graphql
const string QUERY = """
query ActiveUser($limit: Int!, $cursor: String, $filter: UserWorkspacesFilter) {
data:activeUser {
data:workspaces(limit: $limit, cursor: $cursor, filter: $filter) {
cursor
totalCount
items {
id
name
role
slug
logo
createdAt
updatedAt
readOnly
description
creationState
{
completed
}
permissions {
canCreateProject {
authorized
code
message
}
}
}
}
}
}
""";
var request = new GraphQLRequest
{
Query = QUERY,
Variables = new
{
limit,
cursor,
filter,
},
};
var response = await _client
.ExecuteGraphQLRequest<NullableResponse<RequiredResponse<ResourceCollection<Workspace>>?>>(
request,
cancellationToken
)
.ConfigureAwait(false);
if (response.data is null)
{
throw new SpeckleException("GraphQL response indicated that the ActiveUser could not be found");
}
return response.data.data;
}
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
/// <exception cref="SpeckleException">The ActiveUser could not be found (e.g. the client is not authenticated)</exception>
public async Task<Workspace?> GetActiveWorkspace(CancellationToken cancellationToken = default)
{
//language=graphql
const string QUERY = """
query ActiveUser {
data:activeUser {
data:activeWorkspace {
id
name
role
slug
logo
createdAt
updatedAt
readOnly
description
creationState
{
completed
}
permissions {
canCreateProject {
authorized
code
message
}
}
}
}
}
""";
var request = new GraphQLRequest { Query = QUERY };
var response = await _client
.ExecuteGraphQLRequest<NullableResponse<NullableResponse<Workspace?>?>>(request, cancellationToken)
.ConfigureAwait(false);
if (response.data is null)
{
throw new SpeckleException("GraphQL response indicated that the ActiveUser could not be found");
}
return response.data.data;
}
/// <param name="limit">Max number of projects to fetch</param>
/// <param name="cursor">Optional cursor for pagination</param>
/// <param name="filter">Optional filter</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
/// <exception cref="SpeckleException">The ActiveUser could not be found (e.g. the client is not authenticated)</exception>
public async Task<ResourceCollection<ProjectWithPermissions>> GetProjectsWithPermissions(
int limit = ServerLimits.DEFAULT_PAGINATION_REQUEST,
string? cursor = null,
UserProjectsFilter? filter = null,
CancellationToken cancellationToken = default
)
{
//language=graphql
const string QUERY = """
query User($limit: Int!, $cursor: String, $filter: UserProjectsFilter) {
data: activeUser {
data: projects(limit: $limit, cursor: $cursor, filter: $filter) {
totalCount
cursor
items {
id
name
description
visibility
allowPublicComments
role
createdAt
updatedAt
sourceApps
workspaceId
permissions {
canCreateModel {
code
authorized
message
}
canDelete {
code
authorized
message
}
canLoad {
code
authorized
message
}
canPublish {
code
authorized
message
}
}
}
}
}
}
""";
var request = new GraphQLRequest
{
Query = QUERY,
Variables = new
{
limit,
cursor,
filter,
},
};
var response = await _client
.ExecuteGraphQLRequest<NullableResponse<RequiredResponse<ResourceCollection<ProjectWithPermissions>>?>>(
request,
cancellationToken
)
.ConfigureAwait(false);
if (response.data is null)
{
throw new SpeckleException("GraphQL response indicated that the ActiveUser could not be found");
}
return response.data.data;
}
}
@@ -47,6 +47,52 @@ public sealed class ProjectResource
return response.data;
}
/// <param name="projectId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
public async Task<ProjectPermissionChecks> GetPermissions(
string projectId,
CancellationToken cancellationToken = default
)
{
//language=graphql
const string QUERY = """
query Project($projectId: String!) {
data:project(id: $projectId) {
data:permissions {
canCreateModel {
authorized
code
message
}
canDelete {
authorized
code
message
}
canLoad {
authorized
code
message
}
canPublish {
authorized
code
message
}
}
}
}
""";
GraphQLRequest request = new() { Query = QUERY, Variables = new { projectId } };
var response = await _client
.ExecuteGraphQLRequest<RequiredResponse<RequiredResponse<ProjectPermissionChecks>>>(request, cancellationToken)
.ConfigureAwait(false);
return response.data.data;
}
/// <param name="projectId"></param>
/// <param name="modelsLimit">Max number of models to fetch</param>
/// <param name="modelsCursor">Optional cursor for pagination</param>
@@ -186,6 +232,10 @@ public sealed class ProjectResource
return response.data;
}
/// <summary>
/// Creates a non-workspace project (aka Personal Project)<br/>
/// See <see cref="ActiveUserResource.CanCreatePersonalProjects"/> to see if the user has permission
/// </summary>
/// <param name="input"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
@@ -219,6 +269,49 @@ public sealed class ProjectResource
return response.data.data;
}
/// <summary>
/// Creates a workspace project.<br/>
/// This feature is only supported on Workspace Enabled Servers (e.g. app.speckle.systems)
/// See <see cref="ActiveUserResource.CanCreatePersonalProjects"/> to see if the user has permission
/// </summary>
/// <param name="input"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
public async Task<Project> CreateInWorkspace(
WorkspaceProjectCreateInput input,
CancellationToken cancellationToken = default
)
{
//language=graphql
const string QUERY = """
mutation WorkspaceProjectCreate($input: WorkspaceProjectCreateInput!) {
data:workspaceMutations {
data:projects {
data:create(input: $input) {
id
name
description
visibility
allowPublicComments
role
createdAt
updatedAt
sourceApps
workspaceId
}
}
}
}
""";
GraphQLRequest request = new() { Query = QUERY, Variables = new { input } };
var response = await _client
.ExecuteGraphQLRequest<RequiredResponse<RequiredResponse<RequiredResponse<Project>>>>(request, cancellationToken)
.ConfigureAwait(false);
return response.data.data.data;
}
/// <param name="input"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
@@ -0,0 +1,120 @@
using GraphQL;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Api.GraphQL.Models.Responses;
namespace Speckle.Sdk.Api.GraphQL.Resources;
public sealed class WorkspaceResource
{
private readonly ISpeckleGraphQLClient _client;
internal WorkspaceResource(ISpeckleGraphQLClient client)
{
_client = client;
}
/// <param name="workspaceId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
public async Task<Workspace> Get(string workspaceId, CancellationToken cancellationToken = default)
{
//language=graphql
const string QUERY = """
query WorkspaceGet($workspaceId: String!) {
data:workspace(id: $workspaceId) {
id
name
role
slug
logo
createdAt
updatedAt
readOnly
description
creationState
{
completed
}
permissions {
canCreateProject {
authorized
code
message
}
}
}
}
""";
var request = new GraphQLRequest { Query = QUERY, Variables = new { workspaceId } };
var response = await _client
.ExecuteGraphQLRequest<RequiredResponse<Workspace>>(request, cancellationToken)
.ConfigureAwait(false);
return response.data;
}
/// <param name="workspaceId"></param>
/// <param name="limit">Max number of projects to fetch</param>
/// <param name="cursor">Optional cursor for pagination</param>
/// <param name="filter"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <inheritdoc cref="ISpeckleGraphQLClient.ExecuteGraphQLRequest{T}"/>
/// <see cref="Get"/>
public async Task<ResourceCollection<Project>> GetProjects(
string workspaceId,
int limit = ServerLimits.DEFAULT_PAGINATION_REQUEST,
string? cursor = null,
WorkspaceProjectsFilter? filter = null,
CancellationToken cancellationToken = default
)
{
//language=graphql
const string QUERY = """
query Workspace($workspaceId: String!, $limit: Int!, $cursor: String, $filter: WorkspaceProjectsFilter) {
data:workspace(id: $workspaceId) {
data:projects(limit: $limit, cursor: $cursor, filter: $filter) {
cursor
items {
allowPublicComments
createdAt
description
id
name
role
sourceApps
updatedAt
visibility
workspaceId
}
totalCount
}
}
}
""";
var request = new GraphQLRequest
{
Query = QUERY,
Variables = new
{
workspaceId,
limit,
cursor,
filter,
},
};
var response = await _client
.ExecuteGraphQLRequest<RequiredResponse<RequiredResponse<ResourceCollection<Project>>>>(
request,
cancellationToken
)
.ConfigureAwait(false);
return response.data.data;
}
}
@@ -69,6 +69,10 @@ public sealed class SerializeProcess(
NodeInfo
>();
private readonly Pool<List<Task<Dictionary<Id, NodeInfo>>>> _taskResultPool = Pools.CreateListPool<
Task<Dictionary<Id, NodeInfo>>
>();
private long _objectCount;
private long _objectsFound;
@@ -163,7 +167,7 @@ public sealed class SerializeProcess(
try
{
var tasks = new List<Task<Dictionary<Id, NodeInfo>>>();
var tasks = _taskResultPool.Get();
foreach (var child in baseChildFinder.GetChildren(obj))
{
// tmp is necessary because of the way closures close over loop variables
@@ -190,30 +194,27 @@ public sealed class SerializeProcess(
return EMPTY_CLOSURES;
}
List<Dictionary<Id, NodeInfo>> taskClosures = new();
Dictionary<Id, NodeInfo>[] taskClosures = [];
if (tasks.Count > 0)
{
var currentTasks = tasks.ToList();
do
//get child results
var childTask = Task.WhenAll(tasks);
await Task.WhenAny(childTask, Task.Delay(Timeout.InfiniteTimeSpan, _processSource.Token)).ConfigureAwait(false);
if (childTask.IsFaulted)
{
//grab when any Task is done and see if we're cancelling
var t = await Task.WhenAny(currentTasks).ConfigureAwait(false);
if (t.IsCanceled)
if (childTask.Exception is not null)
{
return EMPTY_CLOSURES;
RecordException(childTask.Exception);
}
if (t.IsFaulted)
{
if (t.Exception is not null)
{
RecordException(t.Exception);
}
return EMPTY_CLOSURES;
}
taskClosures.Add(t.Result);
currentTasks.Remove(t);
} while (currentTasks.Count > 0);
return EMPTY_CLOSURES;
}
if (!childTask.IsCompleted)
{
return EMPTY_CLOSURES;
}
taskClosures = childTask.Result;
}
_taskResultPool.Return(tasks);
if (_processSource.Token.IsCancellationRequested)
{
+32 -2
View File
@@ -1,9 +1,18 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Speckle.Sdk.Api;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Dependencies;
using Speckle.Sdk.Host;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Models.GraphTraversal;
using Speckle.Sdk.Serialisation.V2;
using Speckle.Sdk.Serialisation.V2.Receive;
using Speckle.Sdk.Serialisation.V2.Send;
using Speckle.Sdk.SQLite;
using Speckle.Sdk.Transports;
using Speckle.Sdk.Transports.ServerUtils;
namespace Speckle.Sdk;
@@ -70,18 +79,39 @@ public static class ServiceRegistration
);
serviceCollection.TryAddSingleton<ISdkActivityFactory, NullActivityFactory>();
serviceCollection.TryAddSingleton<ISdkMetricsFactory, NullSdkMetricsFactory>();
serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly());
serviceCollection.AddMatchingInterfacesAsTransient(
Assembly.GetExecutingAssembly(),
typeof(ServerTransport),
typeof(Account),
typeof(ServerApi),
typeof(SqLiteJsonCacheManager),
typeof(ServerObjectManager),
typeof(BaseSerializer),
typeof(SerializeProcess),
typeof(ObjectSaver),
typeof(ObjectSerializer),
typeof(ObjectDeserializer),
typeof(DeserializeProcess),
typeof(ObjectLoader),
typeof(TraversalRule),
typeof(Client)
);
serviceCollection.AddMatchingInterfacesAsTransient(typeof(GraphQLRetry).Assembly);
return serviceCollection;
}
public static IServiceCollection AddMatchingInterfacesAsTransient(
this IServiceCollection serviceCollection,
Assembly assembly
Assembly assembly,
params Type[] classesToIgnore
)
{
foreach (var type in assembly.ExportedTypes.Where(t => t.IsNonAbstractClass()))
{
if (classesToIgnore.Contains(type))
{
continue;
}
foreach (var matchingInterface in type.FindMatchingInterface())
{
serviceCollection.TryAddTransient(matchingInterface, type);
+5 -12
View File
@@ -1,50 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Compiler Properties">
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<Configurations>Debug;Release;Local</Configurations>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Label="Nugetspec Package Properties">
<PackageId>Speckle.Sdk</PackageId>
<Description>The .NET SDK for Speckle</Description>
<PackageTags>$(PackageTags) core sdk</PackageTags>
<NoWarn>$(NoWarn);CS8618</NoWarn>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup Label="Expose internals to test projects">
<InternalsVisibleTo Include="Speckle.Sdk.Tests.Unit" />
<InternalsVisibleTo Include="Speckle.Sdk.Tests.Integration" />
<InternalsVisibleTo Include="Speckle.Sdk.Serialization.Tests" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="GraphQL.Client"/>
<ItemGroup Label="Package References">
<PackageReference Include="GraphQL.Client" />
<PackageReference Include="Microsoft.CSharp" />
<PackageReference Include="Microsoft.Data.Sqlite"/>
<PackageReference Include="Microsoft.Data.Sqlite" />
<PackageReference Include="Speckle.DoubleNumerics" />
<PackageReference Include="Speckle.Newtonsoft.Json" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" OverrideVersion="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" OverrideVersion="8.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging" OverrideVersion="8.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Speckle.Sdk.Dependencies\Speckle.Sdk.Dependencies.csproj" />
</ItemGroup>
</Project>
@@ -1,15 +0,0 @@
namespace Speckle.Sdk;
/// <summary>
/// These are exceptions who's message is not user friendly
/// </summary>
public class SpeckleNonUserFacingException : SpeckleException
{
public SpeckleNonUserFacingException() { }
public SpeckleNonUserFacingException(string? message)
: base(message) { }
public SpeckleNonUserFacingException(string? message, Exception? innerException)
: base(message, innerException) { }
}
@@ -1,21 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
<PolySharpExcludeGeneratedTypes>System.Runtime.CompilerServices.IsExternalInit</PolySharpExcludeGeneratedTypes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="altcover" />
<PackageReference Include="AwesomeAssertions" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit.assert" />
<PackageReference Include="xunit.runner.visualstudio"/>
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Speckle.Objects\Speckle.Objects.csproj" />
<ProjectReference Include="..\Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj" />
</ItemGroup>
</Project>
@@ -60,8 +60,8 @@
},
"Argon": {
"type": "Transitive",
"resolved": "0.27.0",
"contentHash": "LtZKATYeTwDyYq1AXrgVU/ly+nI6GvE0GK1isJYFPQOnb2uHUxvDA+yh40QYaITGTLViXK7rbWhNKpbZ5pb9XA=="
"resolved": "0.28.0",
"contentHash": "78BmoFm8SK733nq4F/SjqNKkXJHdrg/MslvYfNjJX/nM/mEkltHUzPJRjBE9VI/zghsjFPQxMRPEUaqIgg98zg=="
},
"Castle.Core": {
"type": "Transitive",
@@ -73,17 +73,17 @@
},
"DiffEngine": {
"type": "Transitive",
"resolved": "16.1.0",
"contentHash": "ImEFC6BN62paN0N7v8vrLY3x/LpfbJaJy5yDtL+/L2As6FI1npGJcFZwzz1A7pdDjIYPOXE91qv6BpgEUGjDkA==",
"resolved": "16.2.1",
"contentHash": "UfMgXClqOGkPNfth210upiTY18LPCgjsfNrh0Olo5qI+QTkkCO6wHSuOwknxJdKtsWoaJ+E132Y2nzD0PiLWRw==",
"dependencies": {
"EmptyFiles": "8.8.0",
"EmptyFiles": "8.9.1",
"System.Management": "8.0.0"
}
},
"EmptyFiles": {
"type": "Transitive",
"resolved": "8.8.0",
"contentHash": "d0pgc/vMyKgQ9T3qiiJBn1uYUSZ1/OShh6tySnNSkELRSgM4A4IOrpdQhLqwCkPwYvdJqzKuxQ6wn3MQAd4GNA=="
"resolved": "8.9.1",
"contentHash": "GbGf+oH/xiI3C5vJ5TnoA4sx7x7LhtOvN00fxihRZJsj40XuXk2TMz/4m26PfNSJj8JMAqo3BUBirjvam+3xkA=="
},
"FSharp.Core": {
"type": "Transitive",
@@ -265,8 +265,8 @@
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "9.0.3",
"contentHash": "BrMGzDRLz410PE4qC8UeKeAc0hFRjBkiCUOLTwuod65NAjqg5tDNqYU7gP0A09taEXtecB+HJc1NNnnTjsKFAQ=="
"resolved": "9.0.4",
"contentHash": "WogPvgAFqQORFD8Iyha6RZ+/1QB3dsWRWxbwi8/HHVgiGQ8z0oMWpwe8Kk3Ti+Roe+P6a3sBg+WwBfEsyziZKg=="
},
"System.Management": {
"type": "Transitive",
@@ -311,13 +311,13 @@
},
"Verify": {
"type": "Transitive",
"resolved": "29.2.0",
"contentHash": "EhhwhXIeip9AJGWRPXh47NAUoiELnWzeBnAzFSl0+ryAfijTV1T+B4m6P6GbheWQ1CJ1cC1ZFLzgH276D5Bu3A==",
"resolved": "29.4.0",
"contentHash": "wlqJ6ygXORa3lrAaErTA4EWkDcK9pBG2k5iC/I5F2UpWfyV7aXw/+SwGiWYe4XSk9d7VObe4xi4+0AV9rLRsBw==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3"
"System.IO.Hashing": "9.0.4"
}
},
"xunit.abstractions": {
@@ -325,20 +325,6 @@
"resolved": "2.0.3",
"contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
},
"xunit.analyzers": {
"type": "Transitive",
"resolved": "1.18.0",
"contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
},
"xunit.core": {
"type": "Transitive",
"resolved": "2.9.3",
"contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
"dependencies": {
"xunit.extensibility.core": "[2.9.3]",
"xunit.extensibility.execution": "[2.9.3]"
}
},
"xunit.extensibility.core": {
"type": "Transitive",
"resolved": "2.9.3",
@@ -380,13 +366,10 @@
"speckle.sdk.testing": {
"type": "Project",
"dependencies": {
"Microsoft.NET.Test.Sdk": "[17.13.0, )",
"Moq": "[4.20.72, )",
"Speckle.Sdk": "[1.0.0, )",
"Verify.Quibble": "[2.1.1, )",
"Verify.Xunit": "[29.2.0, )",
"xunit": "[2.9.3, )",
"xunit.runner.visualstudio": "[3.0.2, )"
"Verify.Xunit": "[29.4.0, )"
}
},
"GraphQL.Client": {
@@ -468,29 +451,18 @@
},
"Verify.Xunit": {
"type": "CentralTransitive",
"requested": "[29.2.0, )",
"resolved": "29.2.0",
"contentHash": "MdcslVf40AzSA319ZHMzR+U4JqyquX28JFSrI9zA89yeZNaNcaSIb5PmE0XZ6p60Iy7eRYtnGEgSDimEUeXHZw==",
"requested": "[29.4.0, )",
"resolved": "29.4.0",
"contentHash": "P8HYW7aromKGm90Cgx0XKL3qKKmYZHDwHTQfBfDCCPnhNlVWevJzrpuUQ0+3vTVdRAtsts2a1OE/tD+3yjJbHA==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3",
"Verify": "29.2.0",
"System.IO.Hashing": "9.0.4",
"Verify": "29.4.0",
"xunit.abstractions": "2.0.3",
"xunit.extensibility.execution": "2.9.3"
}
},
"xunit": {
"type": "CentralTransitive",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
"dependencies": {
"xunit.analyzers": "1.18.0",
"xunit.assert": "2.9.3",
"xunit.core": "[2.9.3]"
}
}
}
}
@@ -1,11 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Speckle.Sdk\Speckle.Sdk.csproj" />
<ProjectReference Include="..\Speckle.Sdk.Tests.Performance\Speckle.Sdk.Tests.Performance.csproj" />
@@ -13,5 +12,4 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>
@@ -41,8 +41,8 @@ public class CancellationTests
new SerializeProcessOptions(true, true, false, true)
);
await cancellationSource.CancelAsync();
var ex = await Assert.ThrowsAsync<OperationCanceledException>(
async () => await serializeProcess.Serialize(testClass)
var ex = await Assert.ThrowsAsync<OperationCanceledException>(async () =>
await serializeProcess.Serialize(testClass)
);
await Verify(ex);
cancellationSource.IsCancellationRequested.Should().BeTrue();
@@ -62,8 +62,8 @@ public class CancellationTests
cancellationSource.Token,
new SerializeProcessOptions(true, true, false, true)
);
var ex = await Assert.ThrowsAsync<OperationCanceledException>(
async () => await serializeProcess.Serialize(testClass)
var ex = await Assert.ThrowsAsync<OperationCanceledException>(async () =>
await serializeProcess.Serialize(testClass)
);
await Verify(ex);
cancellationSource.IsCancellationRequested.Should().BeTrue();
@@ -83,8 +83,8 @@ public class CancellationTests
new SerializeProcessOptions(true, true, false, true)
);
var ex = await Assert.ThrowsAsync<OperationCanceledException>(
async () => await serializeProcess.Serialize(testClass)
var ex = await Assert.ThrowsAsync<OperationCanceledException>(async () =>
await serializeProcess.Serialize(testClass)
);
await Verify(ex);
cancellationSource.IsCancellationRequested.Should().BeTrue();
@@ -0,0 +1,10 @@
{
"applicationId": null,
"displayValue": null,
"id": "15168a13ce3f336dee9aa1807cbf375c",
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.ArcgisObject",
"type": null,
"units": null
}
@@ -0,0 +1,11 @@
{
"applicationId": null,
"displayValue": null,
"elements": null,
"id": "bf80e8a10eca2264f11c39bae42538da",
"level": null,
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.ArchicadObject",
"type": null
}
@@ -0,0 +1,12 @@
{
"applicationId": null,
"baseCurves": null,
"displayValue": null,
"elements": null,
"id": "76b7634117981a9fb9d3cffca5464f26",
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.Civil3dObject",
"type": null,
"units": null
}
@@ -0,0 +1,8 @@
{
"applicationId": null,
"displayValue": null,
"id": "a1567a1cf10417294c93b70bf5ca97c1",
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject"
}
@@ -0,0 +1,11 @@
{
"applicationId": null,
"displayValue": null,
"elements": null,
"id": "39d4deaa7cd20e7004812304f41a68d5",
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.EtabsObject",
"type": null,
"units": null
}
@@ -0,0 +1,9 @@
{
"applicationId": null,
"displayValue": null,
"id": "fbda4ea7bb1b3722ca28e97573742a4e",
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.NavisworksObject",
"units": null
}
@@ -0,0 +1,15 @@
{
"applicationId": null,
"category": null,
"displayValue": null,
"elements": null,
"family": null,
"id": "7e285508a71c55589bbc053451f687d2",
"level": null,
"location": null,
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.RevitObject",
"type": null,
"units": null
}
@@ -0,0 +1,11 @@
{
"applicationId": null,
"displayValue": null,
"elements": null,
"id": "c07f15678d8b4a48a7ecab9eb30e69a8",
"name": null,
"properties": null,
"speckle_type": "Objects.Data.DataObject:Objects.Data.TeklaObject",
"type": null,
"units": null
}
@@ -0,0 +1,49 @@
using System.Collections.Concurrent;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Objects.Data;
using Speckle.Objects.Geometry;
using Speckle.Sdk.Models;
using Speckle.Sdk.Serialisation;
using Speckle.Sdk.Serialisation.V2;
using Speckle.Sdk.Serialisation.V2.Send;
namespace Speckle.Sdk.Serialization.Tests;
public class DataObjectTests
{
private readonly ISerializeProcessFactory _factory;
public DataObjectTests()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSpeckleSdk(new("Tests", "test"), "v3", typeof(TestClass).Assembly, typeof(Polyline).Assembly);
var serviceProvider = serviceCollection.BuildServiceProvider();
_factory = serviceProvider.GetRequiredService<ISerializeProcessFactory>();
}
[Theory]
[InlineData(typeof(ArcgisObject))]
[InlineData(typeof(ArchicadObject))]
[InlineData(typeof(Civil3dObject))]
[InlineData(typeof(DataObject))]
[InlineData(typeof(EtabsObject))]
[InlineData(typeof(NavisworksObject))]
[InlineData(typeof(RevitObject))]
[InlineData(typeof(TeklaObject))]
public async Task ValidateDataObject(Type type)
{
Base x = (Base)(Activator.CreateInstance(type) ?? throw new Exception("Could not create instance of " + type.Name));
var json = new ConcurrentDictionary<Id, Json>();
await using var serializeProcess = _factory.CreateSerializeProcess(
new MemoryJsonCacheManager(json),
new DummyServerObjectManager(),
null,
default,
new SerializeProcessOptions(true, true, false, true)
);
await serializeProcess.Serialize(x);
await VerifyJson(json.Single().Value.Value).UseParameters(type);
}
}
@@ -1,30 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
<PolySharpExcludeGeneratedTypes>System.Runtime.CompilerServices.IsExternalInit;System.Runtime.CompilerServices.RequiresLocationAttribute</PolySharpExcludeGeneratedTypes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="altcover" />
<PackageReference Include="AwesomeAssertions" />
<PackageReference Include="HttpMultipartParser" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="RichardSzalay.MockHttp" />
<PackageReference Include="xunit.assert" />
<PackageReference Include="xunit.runner.visualstudio"/>
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj" />
<ProjectReference Include="..\..\src\Speckle.Objects\Speckle.Objects.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="RevitObject.json.gz" />
</ItemGroup>
</Project>
@@ -95,8 +95,8 @@
},
"Argon": {
"type": "Transitive",
"resolved": "0.27.0",
"contentHash": "LtZKATYeTwDyYq1AXrgVU/ly+nI6GvE0GK1isJYFPQOnb2uHUxvDA+yh40QYaITGTLViXK7rbWhNKpbZ5pb9XA=="
"resolved": "0.28.0",
"contentHash": "78BmoFm8SK733nq4F/SjqNKkXJHdrg/MslvYfNjJX/nM/mEkltHUzPJRjBE9VI/zghsjFPQxMRPEUaqIgg98zg=="
},
"Castle.Core": {
"type": "Transitive",
@@ -108,17 +108,17 @@
},
"DiffEngine": {
"type": "Transitive",
"resolved": "16.1.0",
"contentHash": "ImEFC6BN62paN0N7v8vrLY3x/LpfbJaJy5yDtL+/L2As6FI1npGJcFZwzz1A7pdDjIYPOXE91qv6BpgEUGjDkA==",
"resolved": "16.2.1",
"contentHash": "UfMgXClqOGkPNfth210upiTY18LPCgjsfNrh0Olo5qI+QTkkCO6wHSuOwknxJdKtsWoaJ+E132Y2nzD0PiLWRw==",
"dependencies": {
"EmptyFiles": "8.8.0",
"EmptyFiles": "8.9.1",
"System.Management": "8.0.0"
}
},
"EmptyFiles": {
"type": "Transitive",
"resolved": "8.8.0",
"contentHash": "d0pgc/vMyKgQ9T3qiiJBn1uYUSZ1/OShh6tySnNSkELRSgM4A4IOrpdQhLqwCkPwYvdJqzKuxQ6wn3MQAd4GNA=="
"resolved": "8.9.1",
"contentHash": "GbGf+oH/xiI3C5vJ5TnoA4sx7x7LhtOvN00fxihRZJsj40XuXk2TMz/4m26PfNSJj8JMAqo3BUBirjvam+3xkA=="
},
"FSharp.Core": {
"type": "Transitive",
@@ -310,8 +310,8 @@
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "9.0.3",
"contentHash": "BrMGzDRLz410PE4qC8UeKeAc0hFRjBkiCUOLTwuod65NAjqg5tDNqYU7gP0A09taEXtecB+HJc1NNnnTjsKFAQ=="
"resolved": "9.0.4",
"contentHash": "WogPvgAFqQORFD8Iyha6RZ+/1QB3dsWRWxbwi8/HHVgiGQ8z0oMWpwe8Kk3Ti+Roe+P6a3sBg+WwBfEsyziZKg=="
},
"System.Management": {
"type": "Transitive",
@@ -356,13 +356,13 @@
},
"Verify": {
"type": "Transitive",
"resolved": "29.2.0",
"contentHash": "EhhwhXIeip9AJGWRPXh47NAUoiELnWzeBnAzFSl0+ryAfijTV1T+B4m6P6GbheWQ1CJ1cC1ZFLzgH276D5Bu3A==",
"resolved": "29.4.0",
"contentHash": "wlqJ6ygXORa3lrAaErTA4EWkDcK9pBG2k5iC/I5F2UpWfyV7aXw/+SwGiWYe4XSk9d7VObe4xi4+0AV9rLRsBw==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3"
"System.IO.Hashing": "9.0.4"
}
},
"xunit.abstractions": {
@@ -370,20 +370,6 @@
"resolved": "2.0.3",
"contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
},
"xunit.analyzers": {
"type": "Transitive",
"resolved": "1.18.0",
"contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
},
"xunit.core": {
"type": "Transitive",
"resolved": "2.9.3",
"contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
"dependencies": {
"xunit.extensibility.core": "[2.9.3]",
"xunit.extensibility.execution": "[2.9.3]"
}
},
"xunit.extensibility.core": {
"type": "Transitive",
"resolved": "2.9.3",
@@ -425,13 +411,10 @@
"speckle.sdk.testing": {
"type": "Project",
"dependencies": {
"Microsoft.NET.Test.Sdk": "[17.13.0, )",
"Moq": "[4.20.72, )",
"Speckle.Sdk": "[1.0.0, )",
"Verify.Quibble": "[2.1.1, )",
"Verify.Xunit": "[29.2.0, )",
"xunit": "[2.9.3, )",
"xunit.runner.visualstudio": "[3.0.2, )"
"Verify.Xunit": "[29.4.0, )"
}
},
"GraphQL.Client": {
@@ -504,29 +487,18 @@
},
"Verify.Xunit": {
"type": "CentralTransitive",
"requested": "[29.2.0, )",
"resolved": "29.2.0",
"contentHash": "MdcslVf40AzSA319ZHMzR+U4JqyquX28JFSrI9zA89yeZNaNcaSIb5PmE0XZ6p60Iy7eRYtnGEgSDimEUeXHZw==",
"requested": "[29.4.0, )",
"resolved": "29.4.0",
"contentHash": "P8HYW7aromKGm90Cgx0XKL3qKKmYZHDwHTQfBfDCCPnhNlVWevJzrpuUQ0+3vTVdRAtsts2a1OE/tD+3yjJbHA==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3",
"Verify": "29.2.0",
"System.IO.Hashing": "9.0.4",
"Verify": "29.4.0",
"xunit.abstractions": "2.0.3",
"xunit.extensibility.execution": "2.9.3"
}
},
"xunit": {
"type": "CentralTransitive",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
"dependencies": {
"xunit.analyzers": "1.18.0",
"xunit.assert": "2.9.3",
"xunit.core": "[2.9.3]"
}
}
}
}
@@ -1,21 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="Verify.Quibble" />
<PackageReference Include="Verify.Xunit" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Speckle.Sdk\Speckle.Sdk.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Moq" />
<PackageReference Include="Verify.Quibble" />
<PackageReference Include="Verify.Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Speckle.Sdk\Speckle.Sdk.csproj" />
</ItemGroup>
</Project>
+21 -100
View File
@@ -2,16 +2,6 @@
"version": 2,
"dependencies": {
"net8.0": {
"Microsoft.NET.Test.Sdk": {
"type": "Direct",
"requested": "[17.13.0, )",
"resolved": "17.13.0",
"contentHash": "W19wCPizaIC9Zh47w8wWI/yxuqR7/dtABwOrc8r2jX/8mUNxM2vw4fXDh+DJTeogxV+KzKwg5jNNGQVwf3LXyA==",
"dependencies": {
"Microsoft.CodeCoverage": "17.13.0",
"Microsoft.TestPlatform.TestHost": "17.13.0"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
@@ -56,40 +46,23 @@
},
"Verify.Xunit": {
"type": "Direct",
"requested": "[29.2.0, )",
"resolved": "29.2.0",
"contentHash": "MdcslVf40AzSA319ZHMzR+U4JqyquX28JFSrI9zA89yeZNaNcaSIb5PmE0XZ6p60Iy7eRYtnGEgSDimEUeXHZw==",
"requested": "[29.4.0, )",
"resolved": "29.4.0",
"contentHash": "P8HYW7aromKGm90Cgx0XKL3qKKmYZHDwHTQfBfDCCPnhNlVWevJzrpuUQ0+3vTVdRAtsts2a1OE/tD+3yjJbHA==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3",
"Verify": "29.2.0",
"System.IO.Hashing": "9.0.4",
"Verify": "29.4.0",
"xunit.abstractions": "2.0.3",
"xunit.extensibility.execution": "2.9.3"
}
},
"xunit": {
"type": "Direct",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
"dependencies": {
"xunit.analyzers": "1.18.0",
"xunit.assert": "2.9.3",
"xunit.core": "[2.9.3]"
}
},
"xunit.runner.visualstudio": {
"type": "Direct",
"requested": "[3.0.2, )",
"resolved": "3.0.2",
"contentHash": "oXbusR6iPq0xlqoikjdLvzh+wQDkMv9If58myz9MEzldS4nIcp442Btgs2sWbYWV+caEluMe2pQCZ0hUZgPiow=="
},
"Argon": {
"type": "Transitive",
"resolved": "0.27.0",
"contentHash": "LtZKATYeTwDyYq1AXrgVU/ly+nI6GvE0GK1isJYFPQOnb2uHUxvDA+yh40QYaITGTLViXK7rbWhNKpbZ5pb9XA=="
"resolved": "0.28.0",
"contentHash": "78BmoFm8SK733nq4F/SjqNKkXJHdrg/MslvYfNjJX/nM/mEkltHUzPJRjBE9VI/zghsjFPQxMRPEUaqIgg98zg=="
},
"Castle.Core": {
"type": "Transitive",
@@ -101,17 +74,17 @@
},
"DiffEngine": {
"type": "Transitive",
"resolved": "16.1.0",
"contentHash": "ImEFC6BN62paN0N7v8vrLY3x/LpfbJaJy5yDtL+/L2As6FI1npGJcFZwzz1A7pdDjIYPOXE91qv6BpgEUGjDkA==",
"resolved": "16.2.1",
"contentHash": "UfMgXClqOGkPNfth210upiTY18LPCgjsfNrh0Olo5qI+QTkkCO6wHSuOwknxJdKtsWoaJ+E132Y2nzD0PiLWRw==",
"dependencies": {
"EmptyFiles": "8.8.0",
"EmptyFiles": "8.9.1",
"System.Management": "8.0.0"
}
},
"EmptyFiles": {
"type": "Transitive",
"resolved": "8.8.0",
"contentHash": "d0pgc/vMyKgQ9T3qiiJBn1uYUSZ1/OShh6tySnNSkELRSgM4A4IOrpdQhLqwCkPwYvdJqzKuxQ6wn3MQAd4GNA=="
"resolved": "8.9.1",
"contentHash": "GbGf+oH/xiI3C5vJ5TnoA4sx7x7LhtOvN00fxihRZJsj40XuXk2TMz/4m26PfNSJj8JMAqo3BUBirjvam+3xkA=="
},
"FSharp.Core": {
"type": "Transitive",
@@ -144,11 +117,6 @@
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.CodeCoverage": {
"type": "Transitive",
"resolved": "17.13.0",
"contentHash": "9LIUy0y+DvUmEPtbRDw6Bay3rzwqFV8P4efTrK4CZhQle3M/QwLPjISghfcolmEGAPWxuJi6m98ZEfk4VR4Lfg=="
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
@@ -210,28 +178,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.TestPlatform.ObjectModel": {
"type": "Transitive",
"resolved": "17.13.0",
"contentHash": "bt0E0Dx+iqW97o4A59RCmUmz/5NarJ7LRL+jXbSHod72ibL5XdNm1Ke+UO5tFhBG4VwHLcSjqq9BUSblGNWamw==",
"dependencies": {
"System.Reflection.Metadata": "1.6.0"
}
},
"Microsoft.TestPlatform.TestHost": {
"type": "Transitive",
"resolved": "17.13.0",
"contentHash": "9GGw08Dc3AXspjekdyTdZ/wYWFlxbgcF0s7BKxzVX+hzAwpifDOdxM+ceVaaJSQOwqt3jtuNlHn3XTpKUS9x9Q==",
"dependencies": {
"Microsoft.TestPlatform.ObjectModel": "17.13.0",
"Newtonsoft.Json": "13.0.1"
}
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
"Quibble": {
"type": "Transitive",
"resolved": "0.3.1",
@@ -293,8 +239,8 @@
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "9.0.3",
"contentHash": "BrMGzDRLz410PE4qC8UeKeAc0hFRjBkiCUOLTwuod65NAjqg5tDNqYU7gP0A09taEXtecB+HJc1NNnnTjsKFAQ=="
"resolved": "9.0.4",
"contentHash": "WogPvgAFqQORFD8Iyha6RZ+/1QB3dsWRWxbwi8/HHVgiGQ8z0oMWpwe8Kk3Ti+Roe+P6a3sBg+WwBfEsyziZKg=="
},
"System.Management": {
"type": "Transitive",
@@ -314,11 +260,6 @@
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "1.6.0",
"contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
@@ -339,13 +280,13 @@
},
"Verify": {
"type": "Transitive",
"resolved": "29.2.0",
"contentHash": "EhhwhXIeip9AJGWRPXh47NAUoiELnWzeBnAzFSl0+ryAfijTV1T+B4m6P6GbheWQ1CJ1cC1ZFLzgH276D5Bu3A==",
"resolved": "29.4.0",
"contentHash": "wlqJ6ygXORa3lrAaErTA4EWkDcK9pBG2k5iC/I5F2UpWfyV7aXw/+SwGiWYe4XSk9d7VObe4xi4+0AV9rLRsBw==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3"
"System.IO.Hashing": "9.0.4"
}
},
"xunit.abstractions": {
@@ -353,20 +294,6 @@
"resolved": "2.0.3",
"contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
},
"xunit.analyzers": {
"type": "Transitive",
"resolved": "1.18.0",
"contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
},
"xunit.core": {
"type": "Transitive",
"resolved": "2.9.3",
"contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
"dependencies": {
"xunit.extensibility.core": "[2.9.3]",
"xunit.extensibility.execution": "[2.9.3]"
}
},
"xunit.extensibility.core": {
"type": "Transitive",
"resolved": "2.9.3",
@@ -455,12 +382,6 @@
"requested": "[13.0.2, )",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
},
"xunit.assert": {
"type": "CentralTransitive",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA=="
}
}
}
@@ -48,8 +48,8 @@ public class GraphQLClientExceptionHandling : IAsyncLifetime
""";
GraphQLRequest request = new(query: QUERY);
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => await _sut.ExecuteGraphQLRequest<dynamic>(request).ConfigureAwait(false)
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
await _sut.ExecuteGraphQLRequest<dynamic>(request).ConfigureAwait(false)
);
ex.InnerExceptions.OfType<SpeckleGraphQLForbiddenException>().Count().Should().Be(1);
}
@@ -66,8 +66,8 @@ public class GraphQLClientExceptionHandling : IAsyncLifetime
}
""";
GraphQLRequest request = new(query: QUERY);
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => await _sut.ExecuteGraphQLRequest<dynamic>(request).ConfigureAwait(false)
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
await _sut.ExecuteGraphQLRequest<dynamic>(request).ConfigureAwait(false)
);
ex.InnerExceptions.OfType<SpeckleGraphQLInvalidQueryException>().Count().Should().Be(1);
}
@@ -79,8 +79,8 @@ public class GraphQLClientExceptionHandling : IAsyncLifetime
public async Task TestGraphQLLayer_BadInput()
{
ProjectUpdateRoleInput input = new(null!, null!, null);
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => await _sut.Project.UpdateRole(input).ConfigureAwait(false)
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
await _sut.Project.UpdateRole(input).ConfigureAwait(false)
);
ex.InnerExceptions.OfType<SpeckleGraphQLBadInputException>().Count().Should().Be(2);
}
@@ -91,8 +91,8 @@ public class GraphQLClientExceptionHandling : IAsyncLifetime
using CancellationTokenSource cts = new();
await cts.CancelAsync();
var ex = await Assert.ThrowsAsync<TaskCanceledException>(
async () => await _sut.ActiveUser.Get(cts.Token).ConfigureAwait(false)
var ex = await Assert.ThrowsAsync<TaskCanceledException>(async () =>
await _sut.ActiveUser.Get(cts.Token).ConfigureAwait(false)
);
ex.CancellationToken.Should().BeEquivalentTo(cts.Token);
@@ -121,8 +121,8 @@ public class GraphQLClientExceptionHandling : IAsyncLifetime
}
""";
GraphQLRequest request = new(query: QUERY);
await Assert.ThrowsAsync<JsonReaderException>(
async () => await _sut.ExecuteGraphQLRequest<int>(request).ConfigureAwait(false)
await Assert.ThrowsAsync<JsonReaderException>(async () =>
await _sut.ExecuteGraphQLRequest<int>(request).ConfigureAwait(false)
);
}
}
@@ -0,0 +1,8 @@
{
"Type": "AggregateException",
"InnerException": {
"Data": {},
"Message": "WORKSPACES_MODULE_DISABLED_ERROR: Workspaces are not enabled on this server",
"Type": "SpeckleGraphQLException"
}
}
@@ -66,12 +66,75 @@ public class ActiveUserResourceTests : IAsyncLifetime
res.items.Count.Should().Be(2);
}
[Fact]
public async Task ActiveUserGetProjectsWithPermissions()
{
var p1 = await _testUser.Project.Create(new("Project 3", null, null));
var p2 = await _testUser.Project.Create(new("Project 4", null, null));
var res = await Sut.GetProjectsWithPermissions();
res.items.Should().Contain(x => x.id == p1.id);
res.items.Should().Contain(x => x.id == p2.id);
res.items.Count.Should().Be(2);
}
[Fact]
public async Task ActiveUserGetProjects_NoAuth()
{
await FluentActions
.Invoking(async () => await Fixtures.Unauthed.ActiveUser.GetProjects())
.Should()
.ThrowAsync<SpeckleGraphQLException>();
.ThrowAsync<SpeckleException>();
}
[Fact]
public async Task ActiveUserProjectCreationPermission()
{
var res = await Sut.CanCreatePersonalProjects();
res.EnsureAuthorised();
res.authorized.Should().Be(true);
}
[Fact]
public async Task ActiveUserProjectCreationPermission_NoAuth()
{
await FluentActions
.Invoking(async () => await Fixtures.Unauthed.ActiveUser.CanCreatePersonalProjects())
.Should()
.ThrowAsync<SpeckleException>();
}
[Fact]
public async Task ActiveUserGetWorkspaces()
{
var ex = await Assert.ThrowsAsync<AggregateException>(async () => _ = await Sut.GetWorkspaces());
await Verify(ex);
}
[Fact]
public async Task ActiveUserGetWorkspaces_NoAuth()
{
await FluentActions
.Invoking(async () => await Fixtures.Unauthed.ActiveUser.GetWorkspaces())
.Should()
.ThrowAsync<SpeckleException>();
}
[Fact]
public async Task ActiveUserGetActiveWorkspace()
{
var res = await Sut.GetActiveWorkspace();
res.Should().Be(null);
}
[Fact]
public async Task ActiveUserGetActiveWorkspace_NoAuth()
{
await FluentActions
.Invoking(async () => await Fixtures.Unauthed.ActiveUser.GetActiveWorkspace())
.Should()
.ThrowAsync<SpeckleException>();
}
}
@@ -1,6 +1,7 @@
using FluentAssertions;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL;
using Speckle.Sdk.Api.GraphQL.Enums;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Common;
@@ -18,7 +19,7 @@ public class ProjectInviteResourceTests : IAsyncLifetime
{
_inviter = await Fixtures.SeedUserWithClient();
_invitee = await Fixtures.SeedUserWithClient();
_project = await _inviter.Project.Create(new("test", null, null));
_project = await _inviter.Project.Create(new("test", null, ProjectVisibility.Public));
_createdInvite = await SeedInvite();
}
@@ -54,8 +54,8 @@ public class ProjectResourceExceptionalTests : IAsyncLifetime
Project privateStream = await Sut.Create(input);
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => _ = await _unauthedUser.Project.Get(privateStream.id)
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
_ = await _unauthedUser.Project.Get(privateStream.id)
);
ex.InnerExceptions.Single().Should().BeOfType<SpeckleGraphQLForbiddenException>();
}
@@ -70,8 +70,8 @@ public class ProjectResourceExceptionalTests : IAsyncLifetime
[Fact]
public async Task ProjectUpdate_NonExistentProject()
{
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => _ = await Sut.Update(new("NonExistentProject", "My new name"))
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
_ = await Sut.Update(new("NonExistentProject", "My new name"))
);
ex.InnerExceptions.Single().Should().BeOfType<SpeckleGraphQLStreamNotFoundException>();
}
@@ -79,12 +79,23 @@ public class ProjectResourceExceptionalTests : IAsyncLifetime
[Fact]
public async Task ProjectUpdate_NoAuth()
{
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => _ = await _unauthedUser.Project.Update(new(_testProject.id, "My new name"))
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
_ = await _unauthedUser.Project.Update(new(_testProject.id, "My new name"))
);
ex.InnerExceptions.Single().Should().BeOfType<SpeckleGraphQLForbiddenException>();
}
[Fact]
public async Task ProjectCreateInWorkspace_NonWorkspaceServer()
{
var ex = await Assert.ThrowsAsync<AggregateException>(async () =>
_ = await _unauthedUser.Project.CreateInWorkspace(
new(_testProject.id, "My new name", ProjectVisibility.Public, "NonExistentWorkspace")
)
);
ex.InnerExceptions.Single().Should().BeOfType<SpeckleGraphQLException>();
}
[Theory]
[InlineData(StreamRoles.STREAM_OWNER)]
[InlineData(StreamRoles.STREAM_CONTRIBUTOR)]
@@ -107,8 +118,7 @@ public class ProjectResourceExceptionalTests : IAsyncLifetime
{
ProjectUpdateRoleInput input = new(_secondUser.Account.id.NotNull(), "NonExistentProject", newRole);
var ex = await Assert.ThrowsAsync<AggregateException>(
async () => _ = await _unauthedUser.Project.UpdateRole(input)
var ex = await Assert.ThrowsAsync<AggregateException>(async () => _ = await _unauthedUser.Project.UpdateRole(input)
);
ex.InnerExceptions.Single().Should().BeOfType<SpeckleGraphQLForbiddenException>();
}
@@ -125,6 +135,6 @@ public class ProjectResourceExceptionalTests : IAsyncLifetime
[Fact]
public async Task ProjectInvites_NoAuth()
{
await Assert.ThrowsAsync<SpeckleException>(async () => await Fixtures.Unauthed.ActiveUser.ProjectInvites());
await Assert.ThrowsAsync<SpeckleException>(async () => await Fixtures.Unauthed.ActiveUser.GetProjectInvites());
}
}
@@ -20,7 +20,7 @@ public class ProjectResourceTests
(_testUser, _testProject) = setupTask.Result;
}
private async Task<(IClient TestUser, Project TestProject)> Setup()
private static async Task<(IClient TestUser, Project TestProject)> Setup()
{
var testUser = await Fixtures.SeedUserWithClient();
var testProject = await testUser.Project.Create(new ProjectCreateInput("test project123", "desc", null));
@@ -29,7 +29,7 @@ public class ProjectResourceTests
[Theory]
[InlineData("Very private project", "My secret project", ProjectVisibility.Private)]
[InlineData("Very unlisted project", null, ProjectVisibility.Unlisted)]
[InlineData("Very unlisted project", null, ProjectVisibility.Public)]
public async Task ProjectCreate_Should_CreateProjectSuccessfully(
string name,
string? description,
@@ -70,7 +70,7 @@ public class ProjectResourceTests
// Arrange
const string NEW_NAME = "MY new name";
const string NEW_DESCRIPTION = "MY new desc";
const ProjectVisibility NEW_VISIBILITY = ProjectVisibility.Unlisted;
const ProjectVisibility NEW_VISIBILITY = ProjectVisibility.Public;
// Act
var newProject = await Sut.Update(
@@ -99,4 +99,12 @@ public class ProjectResourceTests
.Should()
.ThrowAsync<SpeckleGraphQLStreamNotFoundException>();
}
[Fact]
public async Task TestUserHasProjectPermissions()
{
var res = await Sut.GetPermissions(_testProject.id);
res.canCreateModel.authorized.Should().Be(true);
res.canDelete.authorized.Should().Be(true);
}
}
@@ -0,0 +1,8 @@
{
"Type": "AggregateException",
"InnerException": {
"Data": {},
"Message": "FORBIDDEN: Your auth token does not have the required scope: workspace:read.",
"Type": "SpeckleGraphQLForbiddenException"
}
}
@@ -0,0 +1,8 @@
{
"Type": "AggregateException",
"InnerException": {
"Data": {},
"Message": "FORBIDDEN: Your auth token does not have the required scope: workspace:read.",
"Type": "SpeckleGraphQLForbiddenException"
}
}
@@ -0,0 +1,37 @@
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Resources;
namespace Speckle.Sdk.Tests.Integration.API.GraphQL.Resources;
public class WorkspaceResourceTests
{
private readonly IClient _testUser;
private WorkspaceResource Sut => _testUser.Workspace;
public WorkspaceResourceTests()
{
var setupTask = Setup();
setupTask.Wait(); // Ensure setup runs synchronously for the constructor
_testUser = setupTask.Result;
}
private static async Task<IClient> Setup()
{
var testUser = await Fixtures.SeedUserWithClient();
return testUser;
}
[Fact]
public async Task TestGetWorkspace()
{
var ex = await Assert.ThrowsAsync<AggregateException>(async () => _ = await Sut.Get("non-existent-id"));
await Verify(ex);
}
[Fact]
public async Task TestGetProjects()
{
var ex = await Assert.ThrowsAsync<AggregateException>(async () => _ = await Sut.GetProjects("non-existent-id"));
await Verify(ex);
}
}
@@ -40,8 +40,8 @@ public class UserServerInfoTests : IAsyncLifetime
Uri serverUrl = new(_acc.serverInfo.url);
await FluentActions
.Invoking(
async () => await Fixtures.ServiceProvider.GetRequiredService<IAccountManager>().GetServerInfo(serverUrl)
.Invoking(async () =>
await Fixtures.ServiceProvider.GetRequiredService<IAccountManager>().GetServerInfo(serverUrl)
)
.Should()
.ThrowAsync<HttpRequestException>();
@@ -53,8 +53,8 @@ public class UserServerInfoTests : IAsyncLifetime
Uri serverUrl = new("http://invalidserver.local");
await FluentActions
.Invoking(
async () => await Fixtures.ServiceProvider.GetRequiredService<IAccountManager>().GetServerInfo(serverUrl)
.Invoking(async () =>
await Fixtures.ServiceProvider.GetRequiredService<IAccountManager>().GetServerInfo(serverUrl)
)
.Should()
.ThrowAsync<HttpRequestException>();
@@ -81,8 +81,8 @@ public class UserServerInfoTests : IAsyncLifetime
Uri serverUrl = new("http://invalidserver.local");
await FluentActions
.Invoking(
async () => await Fixtures.ServiceProvider.GetRequiredService<IAccountManager>().GetUserInfo("", serverUrl)
.Invoking(async () =>
await Fixtures.ServiceProvider.GetRequiredService<IAccountManager>().GetUserInfo("", serverUrl)
)
.Should()
.ThrowAsync<HttpRequestException>();
@@ -93,11 +93,10 @@ public class UserServerInfoTests : IAsyncLifetime
{
Uri serverUrl = new(_acc.serverInfo.url);
await FluentActions
.Invoking(
async () =>
await Fixtures
.ServiceProvider.GetRequiredService<IAccountManager>()
.GetUserInfo("Bearer 08913c3c1e7ac65d779d1e1f11b942a44ad9672ca9", serverUrl)
.Invoking(async () =>
await Fixtures
.ServiceProvider.GetRequiredService<IAccountManager>()
.GetUserInfo("Bearer 08913c3c1e7ac65d779d1e1f11b942a44ad9672ca9", serverUrl)
)
.Should()
.ThrowAsync<GraphQLHttpRequestException>();
@@ -11,7 +11,6 @@ using Speckle.Sdk.Common;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Host;
using Speckle.Sdk.Models;
using Speckle.Sdk.Tests.Unit.Serialisation;
using Speckle.Sdk.Transports;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
@@ -26,7 +25,7 @@ public static class Fixtures
static Fixtures()
{
TypeLoader.Reset();
TypeLoader.Initialize(typeof(Base).Assembly, typeof(IgnoreTest).Assembly);
TypeLoader.Initialize(typeof(Base).Assembly);
ServiceProvider = TestServiceSetup.GetServiceProvider();
}
@@ -1,21 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
<PolySharpExcludeGeneratedTypes>System.Runtime.CompilerServices.IsExternalInit</PolySharpExcludeGeneratedTypes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="altcover" />
<PackageReference Include="AwesomeAssertions" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio"/>
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Speckle.Sdk\Speckle.Sdk.csproj" />
<ProjectReference Include="..\Speckle.Sdk.Tests.Unit\Speckle.Sdk.Tests.Unit.csproj" />
<ProjectReference Include="..\Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,20 @@
using System.Runtime.CompilerServices;
namespace Speckle.Sdk.Tests.Integration;
public static class SpeckleVerify
{
private static bool s_initialized;
[ModuleInitializer]
public static void Initialize()
{
if (s_initialized)
{
return;
}
Testing.SpeckleVerify.Initialize();
s_initialized = true;
}
}
@@ -8,6 +8,21 @@
"resolved": "9.0.1",
"contentHash": "aadciFNDT5bnylaYUkKal+s5hF7yU/lmZxImQWAlk1438iPqK1Uf79H5ylELpyLIU49HL5ql+tnWBihp3WVLCA=="
},
"AwesomeAssertions": {
"type": "Direct",
"requested": "[8.1.0, )",
"resolved": "8.1.0",
"contentHash": "IfNC4cpXPi9tclWvuNO9lfkuIxJsUTLTS1NXto55jDrAUQJYl0zLI9ByISrfkbBE2Xtg+IWaAXQ6jnUx3anDuw=="
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Direct",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
}
},
"Microsoft.NET.Test.Sdk": {
"type": "Direct",
"requested": "[17.13.0, )",
@@ -59,8 +74,8 @@
},
"Argon": {
"type": "Transitive",
"resolved": "0.27.0",
"contentHash": "LtZKATYeTwDyYq1AXrgVU/ly+nI6GvE0GK1isJYFPQOnb2uHUxvDA+yh40QYaITGTLViXK7rbWhNKpbZ5pb9XA=="
"resolved": "0.28.0",
"contentHash": "78BmoFm8SK733nq4F/SjqNKkXJHdrg/MslvYfNjJX/nM/mEkltHUzPJRjBE9VI/zghsjFPQxMRPEUaqIgg98zg=="
},
"Castle.Core": {
"type": "Transitive",
@@ -72,17 +87,17 @@
},
"DiffEngine": {
"type": "Transitive",
"resolved": "16.1.0",
"contentHash": "ImEFC6BN62paN0N7v8vrLY3x/LpfbJaJy5yDtL+/L2As6FI1npGJcFZwzz1A7pdDjIYPOXE91qv6BpgEUGjDkA==",
"resolved": "16.2.1",
"contentHash": "UfMgXClqOGkPNfth210upiTY18LPCgjsfNrh0Olo5qI+QTkkCO6wHSuOwknxJdKtsWoaJ+E132Y2nzD0PiLWRw==",
"dependencies": {
"EmptyFiles": "8.8.0",
"EmptyFiles": "8.9.1",
"System.Management": "8.0.0"
}
},
"EmptyFiles": {
"type": "Transitive",
"resolved": "8.8.0",
"contentHash": "d0pgc/vMyKgQ9T3qiiJBn1uYUSZ1/OShh6tySnNSkELRSgM4A4IOrpdQhLqwCkPwYvdJqzKuxQ6wn3MQAd4GNA=="
"resolved": "8.9.1",
"contentHash": "GbGf+oH/xiI3C5vJ5TnoA4sx7x7LhtOvN00fxihRZJsj40XuXk2TMz/4m26PfNSJj8JMAqo3BUBirjvam+3xkA=="
},
"FSharp.Core": {
"type": "Transitive",
@@ -264,8 +279,8 @@
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "9.0.3",
"contentHash": "BrMGzDRLz410PE4qC8UeKeAc0hFRjBkiCUOLTwuod65NAjqg5tDNqYU7gP0A09taEXtecB+HJc1NNnnTjsKFAQ=="
"resolved": "9.0.4",
"contentHash": "WogPvgAFqQORFD8Iyha6RZ+/1QB3dsWRWxbwi8/HHVgiGQ8z0oMWpwe8Kk3Ti+Roe+P6a3sBg+WwBfEsyziZKg=="
},
"System.Management": {
"type": "Transitive",
@@ -310,13 +325,13 @@
},
"Verify": {
"type": "Transitive",
"resolved": "29.2.0",
"contentHash": "EhhwhXIeip9AJGWRPXh47NAUoiELnWzeBnAzFSl0+ryAfijTV1T+B4m6P6GbheWQ1CJ1cC1ZFLzgH276D5Bu3A==",
"resolved": "29.4.0",
"contentHash": "wlqJ6ygXORa3lrAaErTA4EWkDcK9pBG2k5iC/I5F2UpWfyV7aXw/+SwGiWYe4XSk9d7VObe4xi4+0AV9rLRsBw==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3"
"System.IO.Hashing": "9.0.4"
}
},
"xunit.abstractions": {
@@ -373,35 +388,12 @@
"speckle.sdk.testing": {
"type": "Project",
"dependencies": {
"Microsoft.NET.Test.Sdk": "[17.13.0, )",
"Moq": "[4.20.72, )",
"Speckle.Sdk": "[1.0.0, )",
"Verify.Quibble": "[2.1.1, )",
"Verify.Xunit": "[29.2.0, )",
"xunit": "[2.9.3, )",
"xunit.runner.visualstudio": "[3.0.2, )"
"Verify.Xunit": "[29.4.0, )"
}
},
"speckle.sdk.tests.unit": {
"type": "Project",
"dependencies": {
"AwesomeAssertions": "[8.1.0, )",
"Microsoft.Extensions.DependencyInjection": "[2.2.0, )",
"Microsoft.NET.Test.Sdk": "[17.13.0, )",
"RichardSzalay.MockHttp": "[7.0.0, )",
"Speckle.DoubleNumerics": "[4.1.0, )",
"Speckle.Sdk": "[1.0.0, )",
"Speckle.Sdk.Testing": "[1.0.0, )",
"altcover": "[9.0.1, )",
"xunit.runner.visualstudio": "[3.0.2, )"
}
},
"AwesomeAssertions": {
"type": "CentralTransitive",
"requested": "[8.1.0, )",
"resolved": "8.1.0",
"contentHash": "IfNC4cpXPi9tclWvuNO9lfkuIxJsUTLTS1NXto55jDrAUQJYl0zLI9ByISrfkbBE2Xtg+IWaAXQ6jnUx3anDuw=="
},
"GraphQL.Client": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
@@ -429,15 +421,6 @@
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
@@ -465,12 +448,6 @@
"Castle.Core": "5.1.1"
}
},
"RichardSzalay.MockHttp": {
"type": "CentralTransitive",
"requested": "[7.0.0, )",
"resolved": "7.0.0",
"contentHash": "QwnauYiaywp65QKFnP+wvgiQ2D8Pv888qB2dyfd7MSVDF06sIvxqASenk+RxsWybyyt+Hu1Y251wQxpHTv3UYg=="
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
@@ -496,15 +473,15 @@
},
"Verify.Xunit": {
"type": "CentralTransitive",
"requested": "[29.2.0, )",
"resolved": "29.2.0",
"contentHash": "MdcslVf40AzSA319ZHMzR+U4JqyquX28JFSrI9zA89yeZNaNcaSIb5PmE0XZ6p60Iy7eRYtnGEgSDimEUeXHZw==",
"requested": "[29.4.0, )",
"resolved": "29.4.0",
"contentHash": "P8HYW7aromKGm90Cgx0XKL3qKKmYZHDwHTQfBfDCCPnhNlVWevJzrpuUQ0+3vTVdRAtsts2a1OE/tD+3yjJbHA==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3",
"Verify": "29.2.0",
"System.IO.Hashing": "9.0.4",
"Verify": "29.4.0",
"xunit.abstractions": "2.0.3",
"xunit.extensibility.execution": "2.9.3"
}
@@ -27,7 +27,6 @@ public class GeneralDeserializer : IDisposable
private const string streamId = "a3ac1b2706";
private const string rootId = "7d53bcf28c6696ecac8781684a0aa006";*/
private const string url = "https://latest.speckle.systems/projects/2099ac4b5f/models/da511c4d1e"; //perf?
private const string streamId = "2099ac4b5f";
private const string rootId = "30fb4cbe6eb2202b9e7b4a4fcc3dd2b6";
@@ -22,7 +22,6 @@ public class GeneralReceiveTest : IDisposable
private const string streamId = "a3ac1b2706";S
private const string rootId = "7d53bcf28c6696ecac8781684a0aa006";*/
private const string url = "https://latest.speckle.systems/projects/2099ac4b5f/models/da511c4d1e"; //perf?
private readonly Uri _baseUrl = new("https://latest.speckle.systems");
private const string streamId = "2099ac4b5f";
@@ -57,7 +57,7 @@ public class GeneralSendTest
client = TestDataHelper.ServiceProvider.GetRequiredService<IClientFactory>().Create(acc);
_project = await client.Project.Create(
new($"General Send Test run {Guid.NewGuid()}", null, ProjectVisibility.Unlisted)
new($"General Send Test run {Guid.NewGuid()}", null, ProjectVisibility.Public)
);
_remote = TestDataHelper.ServiceProvider.GetRequiredService<IServerTransportFactory>().Create(acc, _project.id);
}
@@ -1,22 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<ProjectReference Include="..\..\src\Speckle.Objects\Speckle.Objects.csproj" />
<!-- <PackageReference Include="Speckle.Objects" VersionOverride="3.1.0-dev.133"/> -->
<!-- <PackageReference Include="Speckle.Objects" VersionOverride="3.1.0-dev.109"/> -->
<!-- <PackageReference Include="Speckle.Objects" VersionOverride="3.0.0-dev.51"/> &lt;!&ndash;Pre-optimisation&ndash;&gt;-->
</ItemGroup>
<!-- <PackageReference Include="Speckle.Objects" VersionOverride="3.1.0-dev.133"/> -->
<!-- <PackageReference Include="Speckle.Objects" VersionOverride="3.1.0-dev.109"/> -->
<!-- <PackageReference Include="Speckle.Objects" VersionOverride="3.0.0-dev.51"/> &lt;!&ndash;Pre-optimisation&ndash;&gt;-->
</ItemGroup>
</Project>
@@ -37,16 +37,15 @@ public sealed class GraphQLClientTests : IDisposable
{
var tokenSource = new CancellationTokenSource();
tokenSource.Cancel();
await _client.ExecuteWithResiliencePolicies(
async () =>
await Task.Run(
async () =>
{
await Task.Delay(1000);
return "foo";
},
tokenSource.Token
)
await _client.ExecuteWithResiliencePolicies(async () =>
await Task.Run(
async () =>
{
await Task.Delay(1000);
return "foo";
},
tokenSource.Token
)
);
});
timer.Stop();
@@ -24,12 +24,11 @@ public class GraphQLErrorHandlerTests
[MemberData(nameof(ErrorCases))]
public void TestExceptionThrowingFromGraphQLErrors(Type exType, Map extensions)
{
var ex = Assert.Throws<AggregateException>(
() =>
new GraphQLResponse<GraphQLClientTests.FakeGqlResponseModel>
{
Errors = [new() { Extensions = extensions }],
}.EnsureGraphQLSuccess()
var ex = Assert.Throws<AggregateException>(() =>
new GraphQLResponse<GraphQLClientTests.FakeGqlResponseModel>
{
Errors = [new() { Extensions = extensions }],
}.EnsureGraphQLSuccess()
);
ex.InnerExceptions.Count.Should().Be(1);
ex.InnerExceptions[0].Should().BeOfType(exType);
@@ -36,8 +36,7 @@ public class SpeckleHttpTests : MoqTest
var uri = new Uri("https://speckle.xyz");
mockHttp.When(uri.AbsoluteUri).Respond(HttpStatusCode.Unauthorized);
await Assert.ThrowsAsync<HttpRequestException>(
async () => await speckleHttp.HttpPing(uri, mockHttp.ToHttpClient())
await Assert.ThrowsAsync<HttpRequestException>(async () => await speckleHttp.HttpPing(uri, mockHttp.ToHttpClient())
);
}
@@ -0,0 +1,12 @@
{
"applicationId": "ajsdf",
"arr": null,
"attachedProp": null,
"crazyProp": null,
"detachedProp": null,
"DynamicPropertyKeys": [],
"id": null,
"IgnoredSchemaProp": null,
"list": [],
"speckle_type": "Speckle.Core.Tests.Unit.Models.BaseTests+SampleObject"
}
@@ -134,6 +134,16 @@ public class BaseTests
names.Should().Contain(nameof(@base.attachedProp));
}
[Fact(
DisplayName = $"Checks that all instance members are returned including ones on super classes (e.g. {nameof(Base)}"
)]
public async Task CanGetMembers_BaseMembers()
{
var @base = new SampleObject { applicationId = "ajsdf" };
var members = @base.GetMembers();
await Verify(members);
}
[Fact(DisplayName = "Checks that only dynamic properties are returned")]
public void CanGetMembers_OnlyDynamic()
{
@@ -9,8 +9,8 @@ public class SqLiteJsonCacheExceptionTests
public void ExpectedExceptionFires_Void()
{
using var pool = new CacheDbCommandPool("DataSource=:memory:", 1);
Assert.Throws<SqLiteJsonCacheException>(
() => pool.Use(CacheOperation.Get, new Action<SqliteCommand>(_ => throw new SqliteException("test", 1, 1)))
Assert.Throws<SqLiteJsonCacheException>(() =>
pool.Use(CacheOperation.Get, new Action<SqliteCommand>(_ => throw new SqliteException("test", 1, 1)))
);
}
@@ -18,8 +18,8 @@ public class SqLiteJsonCacheExceptionTests
public void ExpectedExceptionFires_Return()
{
using var pool = new CacheDbCommandPool("DataSource=:memory:", 1);
Assert.Throws<SqLiteJsonCacheException>(
() => pool.Use(CacheOperation.Get, new Func<SqliteCommand, bool>(_ => throw new SqliteException("test", 1, 1)))
Assert.Throws<SqLiteJsonCacheException>(() =>
pool.Use(CacheOperation.Get, new Func<SqliteCommand, bool>(_ => throw new SqliteException("test", 1, 1)))
);
}
}
@@ -0,0 +1,27 @@
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
namespace Speckle.Sdk.Tests.Unit;
public class ServiceRegistrationTests
{
[Fact]
public void RegisterDependencies_Validation()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSpeckleSdk(new("Tests", "test"), "v3");
var serviceProvider = serviceCollection.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true });
serviceProvider.Should().NotBeNull();
}
[Fact]
public void RegisterDependencies_Scopes()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSpeckleSdk(new("Tests", "test"), "v3");
var serviceProvider = serviceCollection.BuildServiceProvider(
new ServiceProviderOptions { ValidateScopes = true, ValidateOnBuild = true }
);
serviceProvider.Should().NotBeNull();
}
}
@@ -1,24 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
<IsTestProject>true</IsTestProject>
<PolySharpExcludeGeneratedTypes>System.Runtime.CompilerServices.IsExternalInit;System.Runtime.CompilerServices.RequiresLocationAttribute</PolySharpExcludeGeneratedTypes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="altcover" />
<PackageReference Include="AwesomeAssertions" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="RichardSzalay.MockHttp" />
<PackageReference Include="Speckle.DoubleNumerics" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="xunit.runner.visualstudio"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" VersionOverride="8.0.0" />
<PackageReference Include="xunit.assert" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Speckle.Sdk\Speckle.Sdk.csproj" />
<ProjectReference Include="..\Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,20 @@
using System.Runtime.CompilerServices;
namespace Speckle.Sdk.Tests.Unit;
public static class SpeckleVerify
{
private static bool _initialized;
[ModuleInitializer]
public static void Initialize()
{
if (_initialized)
{
return;
}
global::Speckle.Sdk.Testing.SpeckleVerify.Initialize();
_initialized = true;
}
}
@@ -1,4 +1,4 @@
namespace Speckle.Sdk.Testing;
namespace Speckle.Sdk.Tests.Unit;
public class VerifyTests
{
+34 -62
View File
@@ -16,11 +16,11 @@
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Direct",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0"
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
}
},
"Microsoft.NET.Test.Sdk": {
@@ -67,6 +67,12 @@
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"xunit.assert": {
"type": "Direct",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA=="
},
"xunit.runner.visualstudio": {
"type": "Direct",
"requested": "[3.0.2, )",
@@ -75,8 +81,8 @@
},
"Argon": {
"type": "Transitive",
"resolved": "0.27.0",
"contentHash": "LtZKATYeTwDyYq1AXrgVU/ly+nI6GvE0GK1isJYFPQOnb2uHUxvDA+yh40QYaITGTLViXK7rbWhNKpbZ5pb9XA=="
"resolved": "0.28.0",
"contentHash": "78BmoFm8SK733nq4F/SjqNKkXJHdrg/MslvYfNjJX/nM/mEkltHUzPJRjBE9VI/zghsjFPQxMRPEUaqIgg98zg=="
},
"Castle.Core": {
"type": "Transitive",
@@ -88,17 +94,17 @@
},
"DiffEngine": {
"type": "Transitive",
"resolved": "16.1.0",
"contentHash": "ImEFC6BN62paN0N7v8vrLY3x/LpfbJaJy5yDtL+/L2As6FI1npGJcFZwzz1A7pdDjIYPOXE91qv6BpgEUGjDkA==",
"resolved": "16.2.1",
"contentHash": "UfMgXClqOGkPNfth210upiTY18LPCgjsfNrh0Olo5qI+QTkkCO6wHSuOwknxJdKtsWoaJ+E132Y2nzD0PiLWRw==",
"dependencies": {
"EmptyFiles": "8.8.0",
"EmptyFiles": "8.9.1",
"System.Management": "8.0.0"
}
},
"EmptyFiles": {
"type": "Transitive",
"resolved": "8.8.0",
"contentHash": "d0pgc/vMyKgQ9T3qiiJBn1uYUSZ1/OShh6tySnNSkELRSgM4A4IOrpdQhLqwCkPwYvdJqzKuxQ6wn3MQAd4GNA=="
"resolved": "8.9.1",
"contentHash": "GbGf+oH/xiI3C5vJ5TnoA4sx7x7LhtOvN00fxihRZJsj40XuXk2TMz/4m26PfNSJj8JMAqo3BUBirjvam+3xkA=="
},
"FSharp.Core": {
"type": "Transitive",
@@ -280,8 +286,8 @@
},
"System.IO.Hashing": {
"type": "Transitive",
"resolved": "9.0.3",
"contentHash": "BrMGzDRLz410PE4qC8UeKeAc0hFRjBkiCUOLTwuod65NAjqg5tDNqYU7gP0A09taEXtecB+HJc1NNnnTjsKFAQ=="
"resolved": "9.0.4",
"contentHash": "WogPvgAFqQORFD8Iyha6RZ+/1QB3dsWRWxbwi8/HHVgiGQ8z0oMWpwe8Kk3Ti+Roe+P6a3sBg+WwBfEsyziZKg=="
},
"System.Management": {
"type": "Transitive",
@@ -326,13 +332,13 @@
},
"Verify": {
"type": "Transitive",
"resolved": "29.2.0",
"contentHash": "EhhwhXIeip9AJGWRPXh47NAUoiELnWzeBnAzFSl0+ryAfijTV1T+B4m6P6GbheWQ1CJ1cC1ZFLzgH276D5Bu3A==",
"resolved": "29.4.0",
"contentHash": "wlqJ6ygXORa3lrAaErTA4EWkDcK9pBG2k5iC/I5F2UpWfyV7aXw/+SwGiWYe4XSk9d7VObe4xi4+0AV9rLRsBw==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3"
"System.IO.Hashing": "9.0.4"
}
},
"xunit.abstractions": {
@@ -340,20 +346,6 @@
"resolved": "2.0.3",
"contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg=="
},
"xunit.analyzers": {
"type": "Transitive",
"resolved": "1.18.0",
"contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ=="
},
"xunit.core": {
"type": "Transitive",
"resolved": "2.9.3",
"contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==",
"dependencies": {
"xunit.extensibility.core": "[2.9.3]",
"xunit.extensibility.execution": "[2.9.3]"
}
},
"xunit.extensibility.core": {
"type": "Transitive",
"resolved": "2.9.3",
@@ -389,13 +381,10 @@
"speckle.sdk.testing": {
"type": "Project",
"dependencies": {
"Microsoft.NET.Test.Sdk": "[17.13.0, )",
"Moq": "[4.20.72, )",
"Speckle.Sdk": "[1.0.0, )",
"Verify.Quibble": "[2.1.1, )",
"Verify.Xunit": "[29.2.0, )",
"xunit": "[2.9.3, )",
"xunit.runner.visualstudio": "[3.0.2, )"
"Verify.Xunit": "[29.4.0, )"
}
},
"GraphQL.Client": {
@@ -428,8 +417,8 @@
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
"resolved": "8.0.0",
"contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
@@ -471,35 +460,18 @@
},
"Verify.Xunit": {
"type": "CentralTransitive",
"requested": "[29.2.0, )",
"resolved": "29.2.0",
"contentHash": "MdcslVf40AzSA319ZHMzR+U4JqyquX28JFSrI9zA89yeZNaNcaSIb5PmE0XZ6p60Iy7eRYtnGEgSDimEUeXHZw==",
"requested": "[29.4.0, )",
"resolved": "29.4.0",
"contentHash": "P8HYW7aromKGm90Cgx0XKL3qKKmYZHDwHTQfBfDCCPnhNlVWevJzrpuUQ0+3vTVdRAtsts2a1OE/tD+3yjJbHA==",
"dependencies": {
"Argon": "0.27.0",
"DiffEngine": "16.1.0",
"Argon": "0.28.0",
"DiffEngine": "16.2.1",
"SimpleInfoName": "3.1.0",
"System.IO.Hashing": "9.0.3",
"Verify": "29.2.0",
"System.IO.Hashing": "9.0.4",
"Verify": "29.4.0",
"xunit.abstractions": "2.0.3",
"xunit.extensibility.execution": "2.9.3"
}
},
"xunit": {
"type": "CentralTransitive",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==",
"dependencies": {
"xunit.analyzers": "1.18.0",
"xunit.assert": "2.9.3",
"xunit.core": "[2.9.3]"
}
},
"xunit.assert": {
"type": "CentralTransitive",
"requested": "[2.9.3, )",
"resolved": "2.9.3",
"contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA=="
}
}
}