datajunction-ui 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/app/components/__tests__/NodeMaterializationDelete.test.jsx +263 -0
- package/src/app/components/__tests__/QueryInfo.test.jsx +174 -46
- package/src/app/components/__tests__/Search.test.jsx +300 -56
- package/src/app/pages/AddEditNodePage/FormikSelect.jsx +15 -2
- package/src/app/pages/NamespacePage/Explorer.jsx +192 -21
- package/src/app/pages/NamespacePage/__tests__/AddNamespacePopover.test.jsx +283 -0
- package/src/app/pages/NamespacePage/__tests__/index.test.jsx +74 -41
- package/src/app/pages/NamespacePage/index.jsx +13 -7
- package/src/app/pages/NodePage/AddComplexDimensionLinkPopover.jsx +367 -0
- package/src/app/pages/NodePage/LinkDimensionPopover.jsx +1 -1
- package/src/app/pages/NodePage/ManageDimensionLinksDialog.jsx +526 -0
- package/src/app/pages/NodePage/NodeColumnTab.jsx +223 -58
- package/src/app/pages/NodePage/__tests__/AddComplexDimensionLinkPopover.test.jsx +459 -0
- package/src/app/pages/NodePage/__tests__/EditColumnPopover.test.jsx +2 -6
- package/src/app/pages/NodePage/__tests__/LinkDimensionPopover.test.jsx +19 -48
- package/src/app/pages/NodePage/__tests__/ManageDimensionLinksDialog.test.jsx +390 -0
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +22 -12
- package/src/app/pages/RegisterTablePage/__tests__/RegisterTablePage.test.jsx +4 -2
- package/src/app/services/DJService.js +46 -6
- package/src/app/services/__tests__/DJService.test.jsx +551 -5
- package/webpack.config.js +1 -0
|
@@ -776,7 +776,7 @@ describe('DataJunctionAPI', () => {
|
|
|
776
776
|
'Content-Type': 'application/json',
|
|
777
777
|
},
|
|
778
778
|
body: JSON.stringify({
|
|
779
|
-
|
|
779
|
+
dimension_node: dimensionNode,
|
|
780
780
|
role: null,
|
|
781
781
|
}),
|
|
782
782
|
method: 'DELETE',
|
|
@@ -794,10 +794,10 @@ describe('DataJunctionAPI', () => {
|
|
|
794
794
|
'Content-Type': 'application/json',
|
|
795
795
|
},
|
|
796
796
|
body: JSON.stringify({
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
797
|
+
dimension_node: dimensionNode,
|
|
798
|
+
join_type: null,
|
|
799
|
+
join_on: joinOn,
|
|
800
|
+
join_cardinality: null,
|
|
801
801
|
role: null,
|
|
802
802
|
}),
|
|
803
803
|
method: 'POST',
|
|
@@ -1569,4 +1569,550 @@ describe('DataJunctionAPI', () => {
|
|
|
1569
1569
|
);
|
|
1570
1570
|
expect(result).toEqual({ status: 200, json: mockResponse });
|
|
1571
1571
|
});
|
|
1572
|
+
|
|
1573
|
+
// Reference dimension links
|
|
1574
|
+
it('calls addReferenceDimensionLink correctly', async () => {
|
|
1575
|
+
const mockResponse = { message: 'Success' };
|
|
1576
|
+
fetch.mockResponseOnce(JSON.stringify(mockResponse));
|
|
1577
|
+
const result = await DataJunctionAPI.addReferenceDimensionLink(
|
|
1578
|
+
'default.node1',
|
|
1579
|
+
'column1',
|
|
1580
|
+
'default.dimension1',
|
|
1581
|
+
'dimension_col',
|
|
1582
|
+
);
|
|
1583
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1584
|
+
`${DJ_URL}/nodes/default.node1/columns/column1/link?dimension_node=default.dimension1&dimension_column=dimension_col`,
|
|
1585
|
+
expect.objectContaining({
|
|
1586
|
+
method: 'POST',
|
|
1587
|
+
headers: {
|
|
1588
|
+
'Content-Type': 'application/json',
|
|
1589
|
+
},
|
|
1590
|
+
credentials: 'include',
|
|
1591
|
+
}),
|
|
1592
|
+
);
|
|
1593
|
+
expect(result).toEqual({ status: 200, json: mockResponse });
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1596
|
+
it('calls removeReferenceDimensionLink correctly', async () => {
|
|
1597
|
+
fetch.mockResponseOnce(JSON.stringify({ message: 'Success' }));
|
|
1598
|
+
const result = await DataJunctionAPI.removeReferenceDimensionLink(
|
|
1599
|
+
'default.node1',
|
|
1600
|
+
'column1',
|
|
1601
|
+
);
|
|
1602
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1603
|
+
`${DJ_URL}/nodes/default.node1/columns/column1/link`,
|
|
1604
|
+
expect.objectContaining({
|
|
1605
|
+
method: 'DELETE',
|
|
1606
|
+
}),
|
|
1607
|
+
);
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1610
|
+
// Materialization
|
|
1611
|
+
it('calls deleteMaterialization with nodeVersion correctly', async () => {
|
|
1612
|
+
fetch.mockResponseOnce(JSON.stringify({ message: 'Success' }));
|
|
1613
|
+
await DataJunctionAPI.deleteMaterialization(
|
|
1614
|
+
'default.node1',
|
|
1615
|
+
'mat1',
|
|
1616
|
+
'v1.0',
|
|
1617
|
+
);
|
|
1618
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1619
|
+
'http://localhost:8000/nodes/default.node1/materializations?materialization_name=mat1&node_version=v1.0',
|
|
1620
|
+
expect.objectContaining({ method: 'DELETE' }),
|
|
1621
|
+
);
|
|
1622
|
+
});
|
|
1623
|
+
|
|
1624
|
+
it('calls deleteMaterialization without nodeVersion correctly', async () => {
|
|
1625
|
+
fetch.mockResponseOnce(JSON.stringify({ message: 'Success' }));
|
|
1626
|
+
await DataJunctionAPI.deleteMaterialization('default.node1', 'mat1');
|
|
1627
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1628
|
+
'http://localhost:8000/nodes/default.node1/materializations?materialization_name=mat1',
|
|
1629
|
+
expect.objectContaining({ method: 'DELETE' }),
|
|
1630
|
+
);
|
|
1631
|
+
});
|
|
1632
|
+
|
|
1633
|
+
// Notifications
|
|
1634
|
+
it('calls getNotificationPreferences correctly', async () => {
|
|
1635
|
+
fetch.mockResponseOnce(JSON.stringify([]));
|
|
1636
|
+
await DataJunctionAPI.getNotificationPreferences({ entity_type: 'node' });
|
|
1637
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1638
|
+
'http://localhost:8000/notifications/?entity_type=node',
|
|
1639
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
1640
|
+
);
|
|
1641
|
+
});
|
|
1642
|
+
|
|
1643
|
+
it('calls subscribeToNotifications correctly', async () => {
|
|
1644
|
+
fetch.mockResponseOnce(JSON.stringify({ status: 'subscribed' }));
|
|
1645
|
+
await DataJunctionAPI.subscribeToNotifications({
|
|
1646
|
+
entity_type: 'node',
|
|
1647
|
+
entity_name: 'default.node1',
|
|
1648
|
+
activity_types: ['create'],
|
|
1649
|
+
alert_types: ['email'],
|
|
1650
|
+
});
|
|
1651
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1652
|
+
'http://localhost:8000/notifications/subscribe',
|
|
1653
|
+
expect.objectContaining({
|
|
1654
|
+
method: 'POST',
|
|
1655
|
+
body: expect.any(String),
|
|
1656
|
+
}),
|
|
1657
|
+
);
|
|
1658
|
+
});
|
|
1659
|
+
|
|
1660
|
+
it('calls unsubscribeFromNotifications correctly', async () => {
|
|
1661
|
+
fetch.mockResponseOnce(JSON.stringify({ status: 'unsubscribed' }));
|
|
1662
|
+
await DataJunctionAPI.unsubscribeFromNotifications({
|
|
1663
|
+
entity_type: 'node',
|
|
1664
|
+
entity_name: 'default.node1',
|
|
1665
|
+
});
|
|
1666
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1667
|
+
expect.stringContaining('/notifications/unsubscribe'),
|
|
1668
|
+
expect.objectContaining({ method: 'DELETE' }),
|
|
1669
|
+
);
|
|
1670
|
+
});
|
|
1671
|
+
|
|
1672
|
+
// materializeCube (lines 1323-1339)
|
|
1673
|
+
it('calls materializeCube correctly', async () => {
|
|
1674
|
+
fetch.mockResponseOnce(JSON.stringify({ message: 'Success' }));
|
|
1675
|
+
const result = await DataJunctionAPI.materializeCube(
|
|
1676
|
+
'default.cube1',
|
|
1677
|
+
'spark_sql',
|
|
1678
|
+
'incremental_time',
|
|
1679
|
+
'0 0 * * *',
|
|
1680
|
+
'1 day',
|
|
1681
|
+
);
|
|
1682
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1683
|
+
'http://localhost:8000/nodes/default.cube1/materialization',
|
|
1684
|
+
expect.objectContaining({
|
|
1685
|
+
method: 'POST',
|
|
1686
|
+
body: expect.stringContaining('lookback_window'),
|
|
1687
|
+
}),
|
|
1688
|
+
);
|
|
1689
|
+
expect(result).toEqual({ status: 200, json: { message: 'Success' } });
|
|
1690
|
+
});
|
|
1691
|
+
|
|
1692
|
+
// runBackfill
|
|
1693
|
+
it('calls runBackfill correctly', async () => {
|
|
1694
|
+
fetch.mockResponseOnce(JSON.stringify({ message: 'Success' }));
|
|
1695
|
+
const result = await DataJunctionAPI.runBackfill('default.node1', 'mat1', [
|
|
1696
|
+
{
|
|
1697
|
+
columnName: 'date',
|
|
1698
|
+
range: ['2023-01-01', '2023-12-31'],
|
|
1699
|
+
values: [],
|
|
1700
|
+
},
|
|
1701
|
+
]);
|
|
1702
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1703
|
+
'http://localhost:8000/nodes/default.node1/materializations/mat1/backfill',
|
|
1704
|
+
expect.objectContaining({
|
|
1705
|
+
method: 'POST',
|
|
1706
|
+
body: expect.stringContaining('column_name'),
|
|
1707
|
+
}),
|
|
1708
|
+
);
|
|
1709
|
+
expect(result).toEqual({ status: 200, json: { message: 'Success' } });
|
|
1710
|
+
});
|
|
1711
|
+
|
|
1712
|
+
// addReferenceDimensionLink with role parameter
|
|
1713
|
+
it('calls addReferenceDimensionLink with role correctly', async () => {
|
|
1714
|
+
const mockResponse = { message: 'Success' };
|
|
1715
|
+
fetch.mockResponseOnce(JSON.stringify(mockResponse));
|
|
1716
|
+
const result = await DataJunctionAPI.addReferenceDimensionLink(
|
|
1717
|
+
'default.node1',
|
|
1718
|
+
'column1',
|
|
1719
|
+
'default.dimension1',
|
|
1720
|
+
'dimension_col',
|
|
1721
|
+
'birth_date',
|
|
1722
|
+
);
|
|
1723
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1724
|
+
expect.stringContaining('role=birth_date'),
|
|
1725
|
+
expect.objectContaining({
|
|
1726
|
+
method: 'POST',
|
|
1727
|
+
}),
|
|
1728
|
+
);
|
|
1729
|
+
expect(result).toEqual({ status: 200, json: mockResponse });
|
|
1730
|
+
});
|
|
1731
|
+
|
|
1732
|
+
// Test getNotificationPreferences without params
|
|
1733
|
+
it('calls getNotificationPreferences without params correctly', async () => {
|
|
1734
|
+
fetch.mockResponseOnce(JSON.stringify([]));
|
|
1735
|
+
await DataJunctionAPI.getNotificationPreferences();
|
|
1736
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1737
|
+
'http://localhost:8000/notifications/',
|
|
1738
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
1739
|
+
);
|
|
1740
|
+
});
|
|
1741
|
+
|
|
1742
|
+
// Test listMetricMetadata
|
|
1743
|
+
it('calls listMetricMetadata correctly', async () => {
|
|
1744
|
+
fetch.mockResponseOnce(JSON.stringify([{ name: 'metric1' }]));
|
|
1745
|
+
const result = await DataJunctionAPI.listMetricMetadata();
|
|
1746
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1747
|
+
'http://localhost:8000/metrics/metadata',
|
|
1748
|
+
expect.objectContaining({
|
|
1749
|
+
method: 'GET',
|
|
1750
|
+
headers: {
|
|
1751
|
+
'Content-Type': 'application/json',
|
|
1752
|
+
},
|
|
1753
|
+
}),
|
|
1754
|
+
);
|
|
1755
|
+
expect(result).toEqual([{ name: 'metric1' }]);
|
|
1756
|
+
});
|
|
1757
|
+
|
|
1758
|
+
// Test materializationInfo
|
|
1759
|
+
it('calls materializationInfo correctly', async () => {
|
|
1760
|
+
fetch.mockResponseOnce(JSON.stringify({ info: 'test' }));
|
|
1761
|
+
const result = await DataJunctionAPI.materializationInfo();
|
|
1762
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1763
|
+
'http://localhost:8000/materialization/info',
|
|
1764
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
1765
|
+
);
|
|
1766
|
+
expect(result).toEqual({ info: 'test' });
|
|
1767
|
+
});
|
|
1768
|
+
|
|
1769
|
+
// Test revalidate
|
|
1770
|
+
it('calls revalidate correctly', async () => {
|
|
1771
|
+
fetch.mockResponseOnce(JSON.stringify({ status: 'valid' }));
|
|
1772
|
+
const result = await DataJunctionAPI.revalidate('default.node1');
|
|
1773
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1774
|
+
'http://localhost:8000/nodes/default.node1/validate',
|
|
1775
|
+
expect.objectContaining({
|
|
1776
|
+
method: 'POST',
|
|
1777
|
+
headers: {
|
|
1778
|
+
'Content-Type': 'application/json',
|
|
1779
|
+
},
|
|
1780
|
+
}),
|
|
1781
|
+
);
|
|
1782
|
+
expect(result).toEqual({ status: 'valid' });
|
|
1783
|
+
});
|
|
1784
|
+
|
|
1785
|
+
// Test getMetric (lines 322-360) - this is a GraphQL query
|
|
1786
|
+
it('calls getMetric correctly', async () => {
|
|
1787
|
+
fetch.mockResponseOnce(
|
|
1788
|
+
JSON.stringify({
|
|
1789
|
+
data: {
|
|
1790
|
+
findNodes: [
|
|
1791
|
+
{
|
|
1792
|
+
name: 'system.test.metric',
|
|
1793
|
+
current: {
|
|
1794
|
+
metricMetadata: { direction: 'higher_is_better' },
|
|
1795
|
+
},
|
|
1796
|
+
},
|
|
1797
|
+
],
|
|
1798
|
+
},
|
|
1799
|
+
}),
|
|
1800
|
+
);
|
|
1801
|
+
|
|
1802
|
+
const result = await DataJunctionAPI.getMetric('system.test.metric');
|
|
1803
|
+
expect(result).toHaveProperty('name');
|
|
1804
|
+
});
|
|
1805
|
+
|
|
1806
|
+
// Test system metrics APIs
|
|
1807
|
+
it('calls system.node_counts_by_active correctly', async () => {
|
|
1808
|
+
fetch.mockResponseOnce(
|
|
1809
|
+
JSON.stringify([
|
|
1810
|
+
[
|
|
1811
|
+
{ col: 'system.dj.is_active.active_id', value: true },
|
|
1812
|
+
{ col: 'system.dj.number_of_nodes', value: 100 },
|
|
1813
|
+
],
|
|
1814
|
+
]),
|
|
1815
|
+
);
|
|
1816
|
+
|
|
1817
|
+
const result = await DataJunctionAPI.system.node_counts_by_active();
|
|
1818
|
+
expect(result).toEqual([{ name: 'true', value: 100 }]);
|
|
1819
|
+
});
|
|
1820
|
+
|
|
1821
|
+
it('calls system.node_counts_by_type correctly', async () => {
|
|
1822
|
+
fetch.mockResponseOnce(
|
|
1823
|
+
JSON.stringify([
|
|
1824
|
+
[
|
|
1825
|
+
{ col: 'system.dj.node_type.type', value: 'metric' },
|
|
1826
|
+
{ col: 'system.dj.number_of_nodes', value: 50 },
|
|
1827
|
+
],
|
|
1828
|
+
]),
|
|
1829
|
+
);
|
|
1830
|
+
|
|
1831
|
+
const result = await DataJunctionAPI.system.node_counts_by_type();
|
|
1832
|
+
expect(result).toEqual([{ name: 'metric', value: 50 }]);
|
|
1833
|
+
});
|
|
1834
|
+
|
|
1835
|
+
it('calls system.node_counts_by_status correctly', async () => {
|
|
1836
|
+
fetch.mockResponseOnce(
|
|
1837
|
+
JSON.stringify([
|
|
1838
|
+
[
|
|
1839
|
+
{ col: 'system.dj.nodes.status', value: 'valid' },
|
|
1840
|
+
{ col: 'system.dj.number_of_nodes', value: 80 },
|
|
1841
|
+
],
|
|
1842
|
+
]),
|
|
1843
|
+
);
|
|
1844
|
+
|
|
1845
|
+
const result = await DataJunctionAPI.system.node_counts_by_status();
|
|
1846
|
+
expect(result).toEqual([{ name: 'valid', value: 80 }]);
|
|
1847
|
+
});
|
|
1848
|
+
|
|
1849
|
+
it('calls system.nodes_without_description correctly', async () => {
|
|
1850
|
+
fetch.mockResponseOnce(
|
|
1851
|
+
JSON.stringify([
|
|
1852
|
+
[
|
|
1853
|
+
{ col: 'system.dj.node_type.type', value: 'transform' },
|
|
1854
|
+
{ col: 'system.dj.node_without_description', value: 10 },
|
|
1855
|
+
],
|
|
1856
|
+
]),
|
|
1857
|
+
);
|
|
1858
|
+
|
|
1859
|
+
const result = await DataJunctionAPI.system.nodes_without_description();
|
|
1860
|
+
expect(result).toEqual([{ name: 'transform', value: 10 }]);
|
|
1861
|
+
});
|
|
1862
|
+
|
|
1863
|
+
it('calls system.materialization_counts_by_type correctly', async () => {
|
|
1864
|
+
fetch.mockResponseOnce(
|
|
1865
|
+
JSON.stringify([
|
|
1866
|
+
[
|
|
1867
|
+
{ col: 'system.dj.node_type.type', value: 'cube' },
|
|
1868
|
+
{ col: 'system.dj.number_of_materializations', value: 5 },
|
|
1869
|
+
],
|
|
1870
|
+
]),
|
|
1871
|
+
);
|
|
1872
|
+
|
|
1873
|
+
const result =
|
|
1874
|
+
await DataJunctionAPI.system.materialization_counts_by_type();
|
|
1875
|
+
expect(result).toEqual([{ name: 'cube', value: 5 }]);
|
|
1876
|
+
});
|
|
1877
|
+
|
|
1878
|
+
it('calls system.dimensions correctly', async () => {
|
|
1879
|
+
fetch.mockResponseOnce(JSON.stringify(['dim1', 'dim2']));
|
|
1880
|
+
|
|
1881
|
+
const result = await DataJunctionAPI.system.dimensions();
|
|
1882
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
1883
|
+
'http://localhost:8000/system/dimensions',
|
|
1884
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
1885
|
+
);
|
|
1886
|
+
expect(result).toEqual(['dim1', 'dim2']);
|
|
1887
|
+
});
|
|
1888
|
+
|
|
1889
|
+
it('calls system.node_trends correctly', async () => {
|
|
1890
|
+
fetch.mockResponseOnce(
|
|
1891
|
+
JSON.stringify([
|
|
1892
|
+
[
|
|
1893
|
+
{ col: 'system.dj.nodes.created_at_week', value: 20240101 },
|
|
1894
|
+
{ col: 'system.dj.node_type.type', value: 'metric' },
|
|
1895
|
+
{ col: 'system.dj.number_of_nodes', value: 10 },
|
|
1896
|
+
],
|
|
1897
|
+
]),
|
|
1898
|
+
);
|
|
1899
|
+
|
|
1900
|
+
const result = await DataJunctionAPI.system.node_trends();
|
|
1901
|
+
expect(result.length).toBeGreaterThan(0);
|
|
1902
|
+
expect(result[0]).toHaveProperty('date');
|
|
1903
|
+
expect(result[0]).toHaveProperty('metric');
|
|
1904
|
+
});
|
|
1905
|
+
|
|
1906
|
+
// Test querySystemMetricSingleDimension edge cases
|
|
1907
|
+
it('handles missing values in querySystemMetricSingleDimension', async () => {
|
|
1908
|
+
fetch.mockResponseOnce(
|
|
1909
|
+
JSON.stringify([
|
|
1910
|
+
[
|
|
1911
|
+
{ col: 'some_dimension', value: null },
|
|
1912
|
+
{ col: 'some_metric', value: undefined },
|
|
1913
|
+
],
|
|
1914
|
+
]),
|
|
1915
|
+
);
|
|
1916
|
+
|
|
1917
|
+
const result = await DataJunctionAPI.querySystemMetricSingleDimension({
|
|
1918
|
+
metric: 'some_metric',
|
|
1919
|
+
dimension: 'some_dimension',
|
|
1920
|
+
});
|
|
1921
|
+
|
|
1922
|
+
expect(result[0].name).toBe('unknown');
|
|
1923
|
+
expect(result[0].value).toBe(0);
|
|
1924
|
+
});
|
|
1925
|
+
|
|
1926
|
+
// Test getNodeForEditing (lines 266-319)
|
|
1927
|
+
it('calls getNodeForEditing correctly', async () => {
|
|
1928
|
+
fetch.mockResponseOnce(
|
|
1929
|
+
JSON.stringify({
|
|
1930
|
+
data: {
|
|
1931
|
+
findNodes: [
|
|
1932
|
+
{
|
|
1933
|
+
name: 'default.node1',
|
|
1934
|
+
type: 'transform',
|
|
1935
|
+
current: {
|
|
1936
|
+
displayName: 'Node 1',
|
|
1937
|
+
description: 'Test node',
|
|
1938
|
+
query: 'SELECT * FROM table',
|
|
1939
|
+
},
|
|
1940
|
+
},
|
|
1941
|
+
],
|
|
1942
|
+
},
|
|
1943
|
+
}),
|
|
1944
|
+
);
|
|
1945
|
+
|
|
1946
|
+
const result = await DataJunctionAPI.getNodeForEditing('default.node1');
|
|
1947
|
+
expect(result).toHaveProperty('name', 'default.node1');
|
|
1948
|
+
});
|
|
1949
|
+
|
|
1950
|
+
it('returns null when getNodeForEditing finds no nodes', async () => {
|
|
1951
|
+
fetch.mockResponseOnce(
|
|
1952
|
+
JSON.stringify({
|
|
1953
|
+
data: {
|
|
1954
|
+
findNodes: [],
|
|
1955
|
+
},
|
|
1956
|
+
}),
|
|
1957
|
+
);
|
|
1958
|
+
|
|
1959
|
+
const result = await DataJunctionAPI.getNodeForEditing('nonexistent');
|
|
1960
|
+
expect(result).toBeNull();
|
|
1961
|
+
});
|
|
1962
|
+
|
|
1963
|
+
// Test getCubeForEditing (lines 363-410)
|
|
1964
|
+
it('calls getCubeForEditing correctly', async () => {
|
|
1965
|
+
fetch.mockResponseOnce(
|
|
1966
|
+
JSON.stringify({
|
|
1967
|
+
data: {
|
|
1968
|
+
findNodes: [
|
|
1969
|
+
{
|
|
1970
|
+
name: 'default.cube1',
|
|
1971
|
+
type: 'cube',
|
|
1972
|
+
current: {
|
|
1973
|
+
displayName: 'Cube 1',
|
|
1974
|
+
description: 'Test cube',
|
|
1975
|
+
cubeMetrics: [{ name: 'metric1' }],
|
|
1976
|
+
cubeDimensions: [{ name: 'dim1', attribute: 'attr1' }],
|
|
1977
|
+
},
|
|
1978
|
+
},
|
|
1979
|
+
],
|
|
1980
|
+
},
|
|
1981
|
+
}),
|
|
1982
|
+
);
|
|
1983
|
+
|
|
1984
|
+
const result = await DataJunctionAPI.getCubeForEditing('default.cube1');
|
|
1985
|
+
expect(result).toHaveProperty('name', 'default.cube1');
|
|
1986
|
+
expect(result.current.cubeMetrics).toHaveLength(1);
|
|
1987
|
+
});
|
|
1988
|
+
|
|
1989
|
+
it('returns null when getCubeForEditing finds no nodes', async () => {
|
|
1990
|
+
fetch.mockResponseOnce(
|
|
1991
|
+
JSON.stringify({
|
|
1992
|
+
data: {
|
|
1993
|
+
findNodes: [],
|
|
1994
|
+
},
|
|
1995
|
+
}),
|
|
1996
|
+
);
|
|
1997
|
+
|
|
1998
|
+
const result = await DataJunctionAPI.getCubeForEditing('nonexistent');
|
|
1999
|
+
expect(result).toBeNull();
|
|
2000
|
+
});
|
|
2001
|
+
|
|
2002
|
+
// Test logout (lines 225-230)
|
|
2003
|
+
it('calls logout correctly', async () => {
|
|
2004
|
+
fetch.mockResponseOnce('', { status: 200 });
|
|
2005
|
+
|
|
2006
|
+
await DataJunctionAPI.logout();
|
|
2007
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
2008
|
+
'http://localhost:8000/logout/',
|
|
2009
|
+
expect.objectContaining({
|
|
2010
|
+
method: 'POST',
|
|
2011
|
+
credentials: 'include',
|
|
2012
|
+
}),
|
|
2013
|
+
);
|
|
2014
|
+
});
|
|
2015
|
+
|
|
2016
|
+
// Test catalogs (lines 232-238)
|
|
2017
|
+
it('calls catalogs correctly', async () => {
|
|
2018
|
+
fetch.mockResponseOnce(
|
|
2019
|
+
JSON.stringify([{ name: 'catalog1' }, { name: 'catalog2' }]),
|
|
2020
|
+
);
|
|
2021
|
+
|
|
2022
|
+
const result = await DataJunctionAPI.catalogs();
|
|
2023
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
2024
|
+
'http://localhost:8000/catalogs',
|
|
2025
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
2026
|
+
);
|
|
2027
|
+
expect(result).toHaveLength(2);
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
// Test sql with array filters (lines 755-756)
|
|
2031
|
+
it('handles array filters in sql correctly', async () => {
|
|
2032
|
+
fetch.mockResponseOnce(JSON.stringify({ sql: 'SELECT * FROM table' }));
|
|
2033
|
+
|
|
2034
|
+
await DataJunctionAPI.sql('default.metric1', {
|
|
2035
|
+
dimensions: ['dim1', 'dim2'],
|
|
2036
|
+
filters: ['filter1', 'filter2'],
|
|
2037
|
+
});
|
|
2038
|
+
|
|
2039
|
+
const callUrl = fetch.mock.calls[0][0];
|
|
2040
|
+
expect(callUrl).toContain('dimensions=dim1');
|
|
2041
|
+
expect(callUrl).toContain('filters=filter1');
|
|
2042
|
+
});
|
|
2043
|
+
|
|
2044
|
+
// Test nodeData with null selection (lines 831-835)
|
|
2045
|
+
it('handles null selection in nodeData', async () => {
|
|
2046
|
+
fetch.mockResponseOnce(JSON.stringify({ data: [] }));
|
|
2047
|
+
|
|
2048
|
+
await DataJunctionAPI.nodeData('default.node1', null);
|
|
2049
|
+
|
|
2050
|
+
const callUrl = fetch.mock.calls[0][0];
|
|
2051
|
+
expect(callUrl).toContain('limit=1000');
|
|
2052
|
+
expect(callUrl).toContain('async_=true');
|
|
2053
|
+
});
|
|
2054
|
+
|
|
2055
|
+
// Test streamNodeData with null selection (lines 889-893) - just test it returns EventSource
|
|
2056
|
+
it('handles null selection in streamNodeData', async () => {
|
|
2057
|
+
const eventSource = await DataJunctionAPI.streamNodeData(
|
|
2058
|
+
'default.node1',
|
|
2059
|
+
null,
|
|
2060
|
+
);
|
|
2061
|
+
|
|
2062
|
+
expect(eventSource).toBeInstanceOf(EventSource);
|
|
2063
|
+
|
|
2064
|
+
// EventSource mock might not have close method in test environment
|
|
2065
|
+
if (typeof eventSource.close === 'function') {
|
|
2066
|
+
eventSource.close();
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
|
|
2070
|
+
// Test setColumnDescription (lines 1027-1036)
|
|
2071
|
+
it('calls setColumnDescription correctly', async () => {
|
|
2072
|
+
fetch.mockResponseOnce(JSON.stringify({ message: 'success' }));
|
|
2073
|
+
|
|
2074
|
+
await DataJunctionAPI.setColumnDescription(
|
|
2075
|
+
'default.node1',
|
|
2076
|
+
'column1',
|
|
2077
|
+
'New description',
|
|
2078
|
+
);
|
|
2079
|
+
|
|
2080
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
2081
|
+
expect.stringContaining(
|
|
2082
|
+
'/nodes/default.node1/columns/column1/description',
|
|
2083
|
+
),
|
|
2084
|
+
expect.objectContaining({
|
|
2085
|
+
method: 'PATCH',
|
|
2086
|
+
credentials: 'include',
|
|
2087
|
+
}),
|
|
2088
|
+
);
|
|
2089
|
+
});
|
|
2090
|
+
|
|
2091
|
+
// Test nodeDimensions (lines 1046-1050)
|
|
2092
|
+
it('calls nodeDimensions correctly', async () => {
|
|
2093
|
+
fetch.mockResponseOnce(JSON.stringify(['dim1', 'dim2']));
|
|
2094
|
+
|
|
2095
|
+
const result = await DataJunctionAPI.nodeDimensions('default.node1');
|
|
2096
|
+
|
|
2097
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
2098
|
+
'http://localhost:8000/nodes/default.node1/dimensions',
|
|
2099
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
2100
|
+
);
|
|
2101
|
+
expect(result).toEqual(['dim1', 'dim2']);
|
|
2102
|
+
});
|
|
2103
|
+
|
|
2104
|
+
// Test users (lines 1194-1198)
|
|
2105
|
+
it('calls users correctly', async () => {
|
|
2106
|
+
fetch.mockResponseOnce(
|
|
2107
|
+
JSON.stringify([{ username: 'user1' }, { username: 'user2' }]),
|
|
2108
|
+
);
|
|
2109
|
+
|
|
2110
|
+
const result = await DataJunctionAPI.users();
|
|
2111
|
+
|
|
2112
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
2113
|
+
'http://localhost:8000/users?with_activity=true',
|
|
2114
|
+
expect.objectContaining({ credentials: 'include' }),
|
|
2115
|
+
);
|
|
2116
|
+
expect(result).toHaveLength(2);
|
|
2117
|
+
});
|
|
1572
2118
|
});
|