diff --git a/Directory.Packages.props b/Directory.Packages.props
index 311d122b1d..c4dda76e86 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -10,6 +10,7 @@
+
diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandImportExistingCataloguesIntoExternalDatasetProviderTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandImportExistingCataloguesIntoExternalDatasetProviderTests.cs
index 414a1009aa..1d5ed54bff 100644
--- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandImportExistingCataloguesIntoExternalDatasetProviderTests.cs
+++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandImportExistingCataloguesIntoExternalDatasetProviderTests.cs
@@ -21,7 +21,8 @@ public void TestImportInternalCataloguesOnly()
var _cata2 = new Catalogue(GetMockActivator().RepositoryLocator.CatalogueRepository, "Dataset2");
_cata1.SaveToDatabase();
_cata2.SaveToDatabase();
-
+ var ext = new ExtractableDataSet(GetMockActivator().RepositoryLocator.DataExportRepository, _cata2);
+ ext.SaveToDatabase();
var configuration = new DatasetProviderConfiguration(GetMockActivator().RepositoryLocator.CatalogueRepository, "test", "test", "test",1,"test");
var provider = new InternalDatasetProvider(GetMockActivator(),configuration,null);
var cmd = new ExecuteCommandImportExistingCataloguesIntoExternalDatasetProvider(GetMockActivator(), provider, false,true, false, false,false);
@@ -52,7 +53,8 @@ public void TestImportDeprecatedCataloguesOnly()
var _cata2 = new Catalogue(GetMockActivator().RepositoryLocator.CatalogueRepository, "Dataset2");
_cata1.SaveToDatabase();
_cata2.SaveToDatabase();
-
+ var ext = new ExtractableDataSet(GetMockActivator().RepositoryLocator.DataExportRepository, _cata2);
+ ext.SaveToDatabase();
var configuration = new DatasetProviderConfiguration(GetMockActivator().RepositoryLocator.CatalogueRepository, "test", "test", "test", 1, "test");
var provider = new InternalDatasetProvider(GetMockActivator(), configuration, null);
var cmd = new ExecuteCommandImportExistingCataloguesIntoExternalDatasetProvider(GetMockActivator(), provider, false, false, false, true, false);
diff --git a/Rdmp.Core.Tests/Datasets/Jira/JiraDatasetProviderTests.cs b/Rdmp.Core.Tests/Datasets/Jira/JiraDatasetProviderTests.cs
new file mode 100644
index 0000000000..1b673f5c20
--- /dev/null
+++ b/Rdmp.Core.Tests/Datasets/Jira/JiraDatasetProviderTests.cs
@@ -0,0 +1,334 @@
+using Amazon.Runtime.Internal.Endpoints.StandardLibrary;
+using JustEat.HttpClientInterception;
+using NUnit.Framework;
+using Org.BouncyCastle.Asn1.X509;
+using Rdmp.Core.CommandExecution;
+using Rdmp.Core.Curation.Data;
+using Rdmp.Core.Curation.Data.Datasets;
+using Rdmp.Core.Curation.Data.Datasets.Jira;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using Tests.Common;
+using static System.Net.WebRequestMethods;
+
+namespace Rdmp.Core.Tests.Datasets.Jira;
+
+class JiraDatasetProviderTests : DatabaseTests
+{
+
+ private DatasetProviderConfiguration _configuration;
+ private JiraDatasetProvider _provider;
+ private Catalogue _catalogue;
+ private HttpClient _mockHttp;
+ private HttpClientInterceptorOptions options = new HttpClientInterceptorOptions { ThrowOnMissingRegistration = true };
+
+ [TearDown]
+ public void OneTimeTeardown()
+ {
+ _mockHttp.Dispose();
+ }
+
+ [OneTimeSetUp]
+ public void OneTimeSetup()
+ {
+ var dataAccessCredentials = new DataAccessCredentials(CatalogueRepository, "name")
+ {
+ Username = "test",
+ Password = "test"
+ };
+ dataAccessCredentials.SaveToDatabase();
+
+ _configuration = new DatasetProviderConfiguration(CatalogueRepository, "Test Provider", typeof(JiraDatasetProvider).ToString(), "4", dataAccessCredentials.ID, "1234");
+
+ _configuration.SaveToDatabase();
+
+ _provider = new JiraDatasetProvider(new ThrowImmediatelyActivator(RepositoryLocator), _configuration, _mockHttp);
+ _catalogue = new Catalogue(CatalogueRepository, "Jira test Catalogue");
+ _catalogue.SaveToDatabase();
+
+ }
+
+ private void SetupHttpClient(HttpRequestInterceptionBuilder builder)
+ {
+ builder.RegisterWith(options);
+ _mockHttp = options.CreateHttpClient();
+ _provider = new JiraDatasetProvider(new ThrowImmediatelyActivator(RepositoryLocator), _configuration, _mockHttp);
+ }
+
+ [Test]
+ public void CreateProviderTest()
+ {
+ Assert.DoesNotThrow(() => _configuration.GetProviderInstance(new ThrowImmediatelyActivator(RepositoryLocator)));
+ }
+
+ //AddExistingDataset
+ [Test]
+ public void AddExistingDatasetTest_Success()
+ {
+ var url = "999";
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/{url}")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessResponseString);
+ SetupHttpClient(builder);
+ string name = "AddExistingDatasetTest_Success";
+ Assert.DoesNotThrow(() => _provider.AddExistingDataset(name, url));
+ var dataset = CatalogueRepository.GetAllObjects().FirstOrDefault(d => d.Name == name);
+ Assert.That(dataset, Is.Not.Null);
+ dataset.DeleteInDatabase();
+ }
+ [Test]
+ public void AddExistingDatasetTest_BadRemote()
+ {
+ var url = "999";
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/{url}")
+ .Responds()
+ .WithStatus(400);
+ SetupHttpClient(builder);
+ string name = "AddExistingDatasetTest_BadRemote";
+ Assert.Throws(() => _provider.AddExistingDataset(name, url));
+ var dataset = CatalogueRepository.GetAllObjects().FirstOrDefault(d => d.Name == name);
+ Assert.That(dataset, Is.Null);
+ }
+ //AddExistingDatasetWithReturn
+ [Test]
+ public void AddExistingDatasetWithReturnTest_Success()
+ {
+ var url = "999";
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/{url}")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessResponseString);
+ SetupHttpClient(builder);
+ string name = "AddExistingDatasetWithReturnTest_Success";
+ Assert.DoesNotThrow(() => _provider.AddExistingDatasetWithReturn(name, url));
+ var dataset = CatalogueRepository.GetAllObjects().FirstOrDefault(d => d.Name == name);
+ Assert.That(dataset, Is.Not.Null);
+ dataset.DeleteInDatabase();
+ }
+ [Test]
+ public void AddExistingDatasetWithReturnTest_BadRemote()
+ {
+ var url = "999";
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/{url}")
+ .Responds()
+ .WithStatus(400);
+ SetupHttpClient(builder);
+ string name = "AddExistingDatasetWithReturnTest_BadRemote";
+ Assert.Throws(() => _provider.AddExistingDatasetWithReturn(name, url));
+ var dataset = CatalogueRepository.GetAllObjects().FirstOrDefault(d => d.Name == name);
+ Assert.That(dataset, Is.Null);
+ }
+
+ [Test]
+ public void CreateDataset_BadObjectType()
+ {
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/objectschema/4/objecttypes")
+ .Responds()
+ .WithStatus(400);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForPost()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/create")
+ .Responds()
+ .WithStatus(201).WithJsonContent(SucessCreateString);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests().ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/objecttype/1/attributes")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SuccessObjectTypeAttributes);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/999")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessResponseString);
+ SetupHttpClient(builder);
+
+ var catalogue = new Catalogue(CatalogueRepository, "CreateDataset_Success");
+ catalogue.SaveToDatabase();
+ var e = Assert.Throws(() => _provider.Create(catalogue));
+ Assert.That(e.Message, Is.EqualTo("BadRequest: Unable to fetch Object Types"));
+ }
+
+ [Test]
+ public void CreateDataset_UnableToCreate()
+ {
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/objectschema/4/objecttypes")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessObjectTypesString);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForPost()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/create")
+ .Responds()
+ .WithStatus(400);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests().ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/objecttype/1/attributes")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SuccessObjectTypeAttributes);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/999")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessResponseString);
+ SetupHttpClient(builder);
+
+ var catalogue = new Catalogue(CatalogueRepository, "CreateDataset_Success");
+ catalogue.SaveToDatabase();
+ var e = Assert.Throws(() => _provider.Create(catalogue));
+ Assert.That(e.Message, Is.EqualTo("BadRequest: Unable to create Dataset"));
+ }
+
+ [Test]
+ public void CreateDataset_NoMatchingSchema()
+ {
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/objectschema/4/objecttypes")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessObjectTypesString);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForPost()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/create")
+ .Responds()
+ .WithStatus(201).WithJsonContent(SucessCreateString);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests().ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/objecttype/1/attributes")
+ .Responds()
+ .WithStatus(400);
+ SetupHttpClient(builder);
+
+ builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/999")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessResponseString);
+ SetupHttpClient(builder);
+
+ var catalogue = new Catalogue(CatalogueRepository, "CreateDataset_Success");
+ catalogue.SaveToDatabase();
+ var e = Assert.Throws(() => _provider.Create(catalogue));
+ Assert.That(e.Message, Is.EqualTo("BadRequest: Unable to fetch Object Attributes for Schema 4"));
+ }
+ //FetchDatasetByID
+ [Test]
+ public void FetchDatasetByIDTest_Success()
+ {
+ var url = "999";
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/{url}")
+ .Responds()
+ .WithStatus(200).WithJsonContent(SucessResponseString);
+ SetupHttpClient(builder);
+ Assert.DoesNotThrow(() => _provider.FetchDatasetByID(int.Parse(url)));
+ }
+ [Test]
+ public void FetchDatasetByIDTest_BadRemote()
+ {
+ var url = "999";
+ var builder = new HttpRequestInterceptionBuilder()
+ .Requests()
+ .ForHttps()
+ .ForHost("api.atlassian.com/jsm/assets/workspace")
+ .ForPath($"/1234/v1/object/{url}")
+ .Responds()
+ .WithStatus(400);
+ SetupHttpClient(builder);
+ Assert.Throws(() => _provider.FetchDatasetByID(int.Parse(url)));
+ }
+
+ private object SucessResponseString = new
+ {
+ id = "22",
+ name = "AddExistingDatasetWithReturnTest_Success",
+ type = "Dataset",
+ url = "22",
+ source = "Jira",
+ _links = new
+ {
+ self = "https://api.atlassian.com/jsm/assets/workspace/1234/v1/object/22",
+ }
+ };
+
+ private object SucessCreateString = new
+ {
+
+ };
+
+ private List