From 74548dbb73014aea0a5fd0a162b4bdd1d68093f1 Mon Sep 17 00:00:00 2001 From: alexandra vargas Date: Wed, 7 Jan 2026 17:40:34 +0100 Subject: [PATCH] fix api endpoint witht correct path, using getApiNamespace --- .../DashboardLibrary/CompatibilityModal.tsx | 2 ++ .../api/compatibilityApi.test.ts | 25 ++++++++++--------- .../DashboardLibrary/api/compatibilityApi.ts | 13 +++++----- 3 files changed, 21 insertions(+), 19 deletions(-) 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