diff --git a/e2e/Sandbox/DashboardCreators/SnowFlakeDashboard.cs b/e2e/Sandbox/DashboardCreators/SnowFlakeDashboard.cs new file mode 100644 index 00000000..a54c8b70 --- /dev/null +++ b/e2e/Sandbox/DashboardCreators/SnowFlakeDashboard.cs @@ -0,0 +1,50 @@ +using Reveal.Sdk.Dom; +using Reveal.Sdk.Dom.Data; +using Reveal.Sdk.Dom.Visualizations; +using System.Collections.Generic; + +namespace Sandbox.DashboardFactories +{ + internal class SnowflakeDashboard : IDashboardCreator + { + public string Name => "Snowflake Data Source"; + + public RdashDocument CreateDashboard() + { + var snowflakeDS = new SnowflakeDataSource() + { + Id = "SnowflakeDSId", + Title = "Snowflake Data source", + Subtitle = "Snowflake Subtitle", + Account = "pqwkobs-xb90908", + DefaultRefreshRate = "120", + Host = "gpiskyj-al16914.snowflakecomputing.com", + Database = "SNOWFLAKE_SAMPLE_DATA", + Warehouse = "COMPUTE_WH", + Schema = "TPCDS_SF100TCL" + }; + + var snowflakeDSI = new SnowflakeDataSourceItem("Snowflake DSI Title", snowflakeDS) + { + Id = "SnowflakeDSItemId", + Title = "Snowflake data source Item", + Subtitle = "Snowflake data source Item Subtitle", + Schema = "TPCH_SF10", + Table = "ORDERS", + Database = "SNOWFLAKE_SAMPLE_DATA", + Fields = new List + { + new NumberField("O_ORDERKEY"), + new NumberField("O_CUSTKEY"), + new TextField("O_ORDERPRIORITY"), + } + }; + + var document = new RdashDocument("Snowflake Dashboard"); + + document.Visualizations.Add(new PieChartVisualization("Snowflake Order Priorities", snowflakeDSI) + .SetLabel("O_ORDERPRIORITY").SetValues("O_CUSTKEY")); + return document; + } + } +} diff --git a/e2e/Sandbox/MainWindow.xaml.cs b/e2e/Sandbox/MainWindow.xaml.cs index d907f340..ecb8d6e5 100644 --- a/e2e/Sandbox/MainWindow.xaml.cs +++ b/e2e/Sandbox/MainWindow.xaml.cs @@ -51,6 +51,7 @@ public partial class MainWindow : Window new PostgresqlDashboard(), new RestDataSourceDashboard(), new SalesDashboard(), + new SnowflakeDashboard(), new SqlServerDataSourceDashboards(), }; @@ -61,6 +62,7 @@ public MainWindow() RevealSdkSettings.DataSourceProvider = new DataSourceProvider(); RevealSdkSettings.AuthenticationProvider = new AuthenticationProvider(); RevealSdkSettings.DataSources.RegisterMicrosoftSqlServer().RegisterMicrosoftAnalysisServices().RegisterPostgreSQL(); + RevealSdkSettings.DataSources.RegisterSnowflake(); LoadDashboards(); diff --git a/e2e/Sandbox/Reveal/AuthenticationProvider.cs b/e2e/Sandbox/Reveal/AuthenticationProvider.cs index a3621387..c32e92d0 100644 --- a/e2e/Sandbox/Reveal/AuthenticationProvider.cs +++ b/e2e/Sandbox/Reveal/AuthenticationProvider.cs @@ -1,6 +1,7 @@ -using Reveal.Sdk.Data; +using Reveal.Sdk.Data; using Reveal.Sdk.Data.Microsoft.AnalysisServices; using Reveal.Sdk.Data.Microsoft.SqlServer; +using Reveal.Sdk.Data.Snowflake; using Reveal.Sdk.Data.PostgreSQL; using System.Threading.Tasks; @@ -19,6 +20,10 @@ public Task ResolveCredentialsAsync(RVDashboardDataSour { userCredential = new RVUsernamePasswordDataSourceCredential("username", "password", "domain"); } + else if (dataSource is RVSnowflakeDataSource) + { + userCredential = new RVUsernamePasswordDataSourceCredential("snow-flake-username", "snow-flake-password"); + } else if (dataSource is RVPostgresDataSource) { userCredential = new RVUsernamePasswordDataSourceCredential("postgres", "postgres"); diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/SnowflakeDataSourceItemFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/SnowflakeDataSourceItemFixture.cs index 20d8b767..9763900d 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/SnowflakeDataSourceItemFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSourceItems/SnowflakeDataSourceItemFixture.cs @@ -1,4 +1,6 @@ -using Reveal.Sdk.Dom.Core.Extensions; +using Newtonsoft.Json.Linq; +using Reveal.Sdk.Dom.Core.Constants; +using Reveal.Sdk.Dom.Core.Extensions; using Reveal.Sdk.Dom.Data; using Xunit; @@ -7,49 +9,103 @@ namespace Reveal.Sdk.Dom.Tests.Data.DataSourceItems public class SnowflakeDataSourceItemFixture { [Theory] - [InlineData("Test Item")] - [InlineData(null)] - public void Constructor_SetsTitleAndDataSource_WhenCalled(string title) + [InlineData("DS Title", "DS Title", "DSI Title", "DSI Title")] + [InlineData(null, "DSI Title", "DSI Title", "DSI Title")] + public void Constructor_CreateSnowFlakeDSI_WithTitleAndDataSource(string dsTitle, string expectedDSTitle, string dsiTitle, string expectedDSITitle) { // Arrange - var dataSource = new SnowflakeDataSource(); + var dataSource = new DataSource() { Title = dsTitle }; // Act - var item = new SnowflakeDataSourceItem(title, dataSource); + var item = new SnowflakeDataSourceItem(dsiTitle, dataSource); // Assert - Assert.Equal(title, item.Title); - Assert.Equal(dataSource, item.DataSource); + Assert.Equal(SchemaTypeNames.DataSourceItemType, item.SchemaTypeName); + Assert.Equal(expectedDSTitle, item.DataSource.Title); + Assert.Equal(dataSource.Id, item.DataSource.Id); + Assert.Equal(dataSource.Id, item.DataSourceId); + Assert.IsType(item.DataSource); + Assert.NotSame(dataSource, item.DataSource); + Assert.Equal(expectedDSITitle, item.Title); } [Theory] - [InlineData("Test Item")] - [InlineData(null)] - public void Constructor_SetsTitleAndDataSource_WhenConstructedWithGenericDataSource(string title) + [InlineData("DS Title", "DS Title", "DSI Title", "DSI Title")] + [InlineData(null, "DSI Title", "DSI Title", "DSI Title")] + public void Constructor_CreateSnowFlakeDSI_WithTitleAndSnowFlakeDataSource(string dsTitle, string expectedDSTitle, string dsiTitle, string expectedDSITitle) { // Arrange - var dataSource = new DataSource(); + var dataSource = new SnowflakeDataSource() { Title = dsTitle }; // Act - var item = new SnowflakeDataSourceItem(title, dataSource); + var item = new SnowflakeDataSourceItem(dsiTitle, dataSource); // Assert - Assert.Equal(title, item.Title); + Assert.Equal(SchemaTypeNames.DataSourceItemType, item.SchemaTypeName); + Assert.Equal(expectedDSTitle, item.DataSource.Title); + Assert.Equal(dataSource.Id, item.DataSource.Id); + Assert.Equal(dataSource.Id, item.DataSourceId); Assert.IsType(item.DataSource); + Assert.Same(dataSource, item.DataSource); + Assert.Equal(expectedDSITitle, item.Title); } [Fact] - public void ProcessDataOnServer_ShouldSetAndGetValue_WithInputs() + public void GetProcessDataOnServer_ReturnSameValue_AfterSet() { // Arrange var item = new SnowflakeDataSourceItem("Test Item", new SnowflakeDataSource()); + var expectedProcessDataOnServer = true; + + // Act + item.ProcessDataOnServer = expectedProcessDataOnServer; + + // Assert + Assert.Equal(expectedProcessDataOnServer, item.ProcessDataOnServer); + Assert.Equal(expectedProcessDataOnServer, item.Properties.GetValue("ServerAggregation")); + } + + [Fact] + public void ToJsonString_CreatesFormattedJson_NoConditions() + { + // Arrange + var expectedJson = """ + { + "_type": "DataSourceItemType", + "Id": "a60ab508-0ed4-46e4-8d90-c3a9c09c29b8", + "Title": "SnowFlake DSI", + "DataSourceId": "snowflake_ds", + "HasTabularData": true, + "HasAsset": false, + "Properties": { + "ServerAggregation": true, + "Table": "CALL_CENTER", + "Schema": "TPCDS_SF100TCL" + }, + "Parameters": {} + } + """; + var dataSource = new SnowflakeDataSource() + { + Id = "snowflake_ds", + }; + var dataSourceItem = new SnowflakeDataSourceItem("SnowFlake DSI", dataSource) + { + Id = "a60ab508-0ed4-46e4-8d90-c3a9c09c29b8", + HasTabularData = true, + HasAsset = false, + ProcessDataOnServer = true, + Table = "CALL_CENTER", + Schema = "TPCDS_SF100TCL", + }; + var expectedJObject = JObject.Parse(expectedJson); // Act - item.ProcessDataOnServer = true; + var json = dataSourceItem.ToJsonString(); + var actualJObject = JObject.Parse(json); // Assert - Assert.True(item.ProcessDataOnServer); - Assert.True(item.Properties.GetValue("ServerAggregation")); + Assert.Equal(expectedJObject, actualJObject); } } } diff --git a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/SnowflakeDataSourceFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/SnowflakeDataSourceFixture.cs index 1803b905..4680fd0a 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/DataSources/SnowflakeDataSourceFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/DataSources/SnowflakeDataSourceFixture.cs @@ -1,4 +1,5 @@ -using Reveal.Sdk.Dom.Core.Extensions; +using Newtonsoft.Json.Linq; +using Reveal.Sdk.Dom.Core.Extensions; using Reveal.Sdk.Dom.Data; using Xunit; @@ -7,7 +8,7 @@ namespace Reveal.Sdk.Dom.Tests.Data.DataSources public class SnowflakeDataSourceFixture { [Fact] - public void SnowflakeDataSource_ShouldSetProviderToSnowflake() + public void Constructor_SetDefaultProvider_WithoutParameter() { // Act var dataSource = new SnowflakeDataSource(); @@ -19,7 +20,7 @@ public void SnowflakeDataSource_ShouldSetProviderToSnowflake() [Theory] [InlineData("testAccount")] [InlineData(null)] - public void Account_ShouldSetAndGetValue_WithDifferentInputs(string account) + public void GetAccount_ReturnSameValue_AfterSetAccount(string account) { // Arrange var dataSource = new SnowflakeDataSource(); @@ -35,7 +36,7 @@ public void Account_ShouldSetAndGetValue_WithDifferentInputs(string account) [Theory] [InlineData("testRole")] [InlineData(null)] - public void Role_ShouldSetAndGetValue_WithDifferentInputs(string role) + public void GetRole_ReturnSameValue_AfterSetRole(string role) { // Arrange var dataSource = new SnowflakeDataSource(); @@ -51,7 +52,7 @@ public void Role_ShouldSetAndGetValue_WithDifferentInputs(string role) [Theory] [InlineData("testWarehouse")] [InlineData(null)] - public void Warehouse_ShouldSetAndGetValue_WithDifferentInputs(string warehouse) + public void SetWarehouse_ReturnSameValue_AfterSetWarehouse(string warehouse) { // Arrange var dataSource = new SnowflakeDataSource(); @@ -63,5 +64,54 @@ public void Warehouse_ShouldSetAndGetValue_WithDifferentInputs(string warehouse) Assert.Equal(warehouse, dataSource.Warehouse); Assert.Equal(warehouse, dataSource.Properties.GetValue("Warehouse")); } + + [Fact] + public void ToJsonString_CreatesFormattedJson_NoConditions() + { + // Arrange + var expectedJson = """ + { + "_type": "DataSourceType", + "Id": "snowflake_ds", + "Provider": "SNOWFLAKE", + "Description": "Snowflake TEST", + "Subtitle": "Snowflake TEST Subtitle", + "Properties": { + "ServerAggregationDefault": true, + "ServerAggregationReadOnly": false, + "Host": "gpiskyj-al16914.snowflakecomputing.com", + "Database": "SNOWFLAKE_SAMPLE_DATA", + "Account": "pqwkobs-xb90908", + "Warehouse": "COMPUTE_WH", + "Schema": "TPCDS_SF100TCL" + }, + "Settings": { + "DefaultRefreshRate": 180 + } + } + """; + var dataSource = new SnowflakeDataSource() + { + Id = "snowflake_ds", + Title = "Snowflake TEST", + Subtitle = "Snowflake TEST Subtitle", + ProcessDataOnServerDefaultValue = true, + ProcessDataOnServerReadOnly = false, + Host = "gpiskyj-al16914.snowflakecomputing.com", + Database = "SNOWFLAKE_SAMPLE_DATA", + Account = "pqwkobs-xb90908", + Warehouse = "COMPUTE_WH", + Schema = "TPCDS_SF100TCL", + DefaultRefreshRate = "180" + }; + var expectedJObject = JObject.Parse(expectedJson); + + // Act + var json = dataSource.ToJsonString(); + var actualJObject = JObject.Parse(json); + + // Assert + Assert.Equal(expectedJObject, actualJObject); + } } } diff --git a/src/Reveal.Sdk.Dom.Tests/Data/TableDataSourceltemFixture.cs b/src/Reveal.Sdk.Dom.Tests/Data/TableDataSourceltemFixture.cs index a357293e..75654770 100644 --- a/src/Reveal.Sdk.Dom.Tests/Data/TableDataSourceltemFixture.cs +++ b/src/Reveal.Sdk.Dom.Tests/Data/TableDataSourceltemFixture.cs @@ -1,4 +1,5 @@ using Moq; +using Reveal.Sdk.Dom.Core.Extensions; using Reveal.Sdk.Dom.Data; using Xunit; @@ -39,6 +40,7 @@ public void GetTable_ReturnSameValue_WithSetValue() // Assert Assert.Equal(expectedTable, tableDataSourceItem.Table); + Assert.Equal(expectedTable, tableDataSourceItem.Properties.GetValue("Table")); } } } diff --git a/src/Reveal.Sdk.Dom/Data/DataSources/SnowflakeDataSource.cs b/src/Reveal.Sdk.Dom/Data/DataSources/SnowflakeDataSource.cs index a9679506..b2857916 100644 --- a/src/Reveal.Sdk.Dom/Data/DataSources/SnowflakeDataSource.cs +++ b/src/Reveal.Sdk.Dom/Data/DataSources/SnowflakeDataSource.cs @@ -3,7 +3,7 @@ namespace Reveal.Sdk.Dom.Data { - public class SnowflakeDataSource : ProcessDataSource + public class SnowflakeDataSource : SchemaDataSource { public SnowflakeDataSource() {