diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/CompatibilityModal.tsx b/public/app/features/dashboard/dashgrid/DashboardLibrary/CompatibilityModal.tsx
index 3a725045787..c45198dafb5 100644
--- a/public/app/features/dashboard/dashgrid/DashboardLibrary/CompatibilityModal.tsx
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/CompatibilityModal.tsx
@@ -126,6 +126,8 @@ export const CompatibilityModal = ({ isOpen, onDismiss, dashboardJson, datasourc
{result.compatibilityScore}%
+
+ {JSON.stringify(result)}
{/* Feature #12: CompatibilityScoreDisplay with color coding */}
diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.test.ts b/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.test.ts
index fbfbc1d44ec..4dd856ecb58 100644
--- a/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.test.ts
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.test.ts
@@ -1,3 +1,4 @@
+import { getAPINamespace } from '@grafana/api-clients';
import { BackendSrv, getBackendSrv } from '@grafana/runtime';
import { DataQuery } from '@grafana/schema';
import { DashboardJson } from 'app/features/manage-dashboards/types';
@@ -9,13 +10,12 @@ jest.mock('@grafana/runtime', () => ({
getBackendSrv: jest.fn(),
}));
-jest.mock('app/core/services/context_srv', () => ({
- contextSrv: {
- user: { orgId: 1 },
- },
+jest.mock('@grafana/api-clients', () => ({
+ getAPINamespace: jest.fn(),
}));
const mockGetBackendSrv = getBackendSrv as jest.MockedFunction;
+const mockGetAPINamespace = getAPINamespace as jest.MockedFunction;
// Helper to create mock BackendSrv
const createMockBackendSrv = (overrides: Partial = {}): BackendSrv =>
@@ -94,6 +94,8 @@ describe('compatibilityApi', () => {
post: mockPost,
})
);
+ // Mock getAPINamespace to return 'default' (typical dev environment)
+ mockGetAPINamespace.mockReturnValue('default');
// Mock console.error to prevent test failures
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
});
@@ -151,7 +153,7 @@ describe('compatibilityApi', () => {
expect(result).toEqual(mockResponse);
expect(mockPost).toHaveBeenCalledWith(
- '/api/apps/dashvalidator/v1alpha1/org-1/check',
+ '/apis/dashvalidator.grafana.app/v1alpha1/namespaces/default/check',
{
dashboardJson: dashboard,
datasourceMappings: mappings,
@@ -297,7 +299,7 @@ describe('compatibilityApi', () => {
await expect(checkDashboardCompatibility(dashboard, mappings)).rejects.toEqual(networkError);
});
- it('should construct correct namespace for different orgIds', async () => {
+ it('should use namespace from getAPINamespace()', async () => {
const mockResponse: CompatibilityCheckResult = {
compatibilityScore: 100,
datasourceResults: [],
@@ -305,9 +307,8 @@ describe('compatibilityApi', () => {
mockPost.mockResolvedValue(mockResponse);
- // Change orgId via contextSrv mock
- const { contextSrv } = require('app/core/services/context_srv');
- contextSrv.user.orgId = 42;
+ // Change namespace returned by getAPINamespace
+ mockGetAPINamespace.mockReturnValue('custom-namespace');
const dashboard = createMockDashboard();
const mappings = createMockDatasourceMappings();
@@ -315,13 +316,13 @@ describe('compatibilityApi', () => {
await checkDashboardCompatibility(dashboard, mappings);
expect(mockPost).toHaveBeenCalledWith(
- '/api/apps/dashvalidator/v1alpha1/org-42/check',
+ '/apis/dashvalidator.grafana.app/v1alpha1/namespaces/custom-namespace/check',
expect.any(Object),
expect.any(Object)
);
- // Reset orgId for other tests
- contextSrv.user.orgId = 1;
+ // Reset namespace for other tests
+ mockGetAPINamespace.mockReturnValue('default');
});
it('should handle generic error without proper structure', async () => {
diff --git a/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.ts b/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.ts
index b8cc51e3665..51c1989ae47 100644
--- a/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.ts
+++ b/public/app/features/dashboard/dashgrid/DashboardLibrary/api/compatibilityApi.ts
@@ -1,5 +1,5 @@
+import { getAPINamespace } from '@grafana/api-clients';
import { getBackendSrv } from '@grafana/runtime';
-import { contextSrv } from 'app/core/services/context_srv';
import { DashboardJson } from 'app/features/manage-dashboards/types';
/**
@@ -111,11 +111,9 @@ export async function checkDashboardCompatibility(
dashboardJson: DashboardJson,
datasourceMappings: DatasourceMapping[]
): Promise {
- // Get current organization ID from user context
- const orgId = contextSrv.user.orgId;
-
- // Construct namespace in the format expected by the backend: org-{orgID}
- const namespace = `org-${orgId}`;
+ // Get namespace from global config (typically 'default' in development)
+ // This follows Kubernetes API convention for Grafana app plugins
+ const namespace = getAPINamespace();
// Build request body matching backend schema
const requestBody: CheckCompatibilityRequest = {
@@ -125,8 +123,9 @@ export async function checkDashboardCompatibility(
try {
// Make POST request to the dashboard validator app's /check endpoint
+ // Following Kubernetes API path convention: /apis/{group}/{version}/namespaces/{namespace}/{resource}
const response = await getBackendSrv().post(
- `/api/apps/dashvalidator/v1alpha1/${namespace}/check`,
+ `/apis/dashvalidator.grafana.app/v1alpha1/namespaces/${namespace}/check`,
requestBody,
{
// Disable automatic error alerts - we'll handle errors in the UI