From e02c6c274b6b6a9f084118488b81002c063bd235 Mon Sep 17 00:00:00 2001 From: devendra-bruno Date: Wed, 21 May 2025 13:45:06 +0530 Subject: [PATCH] Fix/svg render respone panel (#4655) * Refactor getContentType in utils * Add testcases for getContentType * Refactor getContent * Refactor getContent * Refactor getContent * Added testcase of case insensitivity * Added content-type case in sensitive * Refactor testcase spec * Added testcases for empty content-type --- packages/bruno-app/src/utils/common/index.js | 51 +++++++++++-------- .../bruno-app/src/utils/common/index.spec.js | 43 +++++++++++++++- 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/packages/bruno-app/src/utils/common/index.js b/packages/bruno-app/src/utils/common/index.js index 7c1165ed9..937e1a3b5 100644 --- a/packages/bruno-app/src/utils/common/index.js +++ b/packages/bruno-app/src/utils/common/index.js @@ -83,29 +83,40 @@ export const normalizeFileName = (name) => { }; export const getContentType = (headers) => { - const headersArray = typeof headers === 'object' ? Object.entries(headers) : []; - if (headersArray.length > 0) { - let contentType = headersArray - .filter((header) => header[0].toLowerCase() === 'content-type') - .map((header) => { - return header[1]; - }); - if (contentType && contentType.length) { - if (typeof contentType[0] == 'string' && /^[\w\-]+\/([\w\-]+\+)?json/.test(contentType[0])) { - return 'application/ld+json'; - } else if (typeof contentType[0] === 'string' && /^image\/svg\+xml/i.test(contentType[0])) { - return 'image/svg+xml'; - } else if (typeof contentType[0] == 'string' && /^[\w\-]+\/([\w\-]+\+)?xml/.test(contentType[0])) { - return 'application/xml'; - } - - return contentType[0]; - } + // Return empty string for invalid headers + if (!headers || typeof headers !== 'object' || Object.keys(headers).length === 0) { + return ''; } - return ''; -}; + // Get content-type header value + const contentTypeHeader = Object.entries(headers) + .find(([key]) => key.toLowerCase() === 'content-type'); + + const contentType = contentTypeHeader && contentTypeHeader[1]; + + // Return empty string if no content-type or not a string + if (!contentType || typeof contentType !== 'string') { + return ''; + } + // This pattern matches content types like application/json, application/ld+json, text/json, etc. + const JSON_PATTERN = /^[\w\-]+\/([\w\-]+\+)?json/; + // This pattern matches content types like image/svg. + const SVG_PATTERN = /^image\/svg/i; + // This pattern matches content types like application/xml, text/xml, application/atom+xml, etc. + const XML_PATTERN = /^[\w\-]+\/([\w\-]+\+)?xml/; + + if (JSON_PATTERN.test(contentType)) { + return 'application/ld+json'; + } else if (SVG_PATTERN.test(contentType)) { + return 'image/svg+xml'; + } else if (XML_PATTERN.test(contentType)) { + return 'application/xml'; + } + + return contentType; +} + export const startsWith = (str, search) => { if (!str || !str.length || typeof str !== 'string') { diff --git a/packages/bruno-app/src/utils/common/index.spec.js b/packages/bruno-app/src/utils/common/index.spec.js index 39f3dff0a..81153674a 100644 --- a/packages/bruno-app/src/utils/common/index.spec.js +++ b/packages/bruno-app/src/utils/common/index.spec.js @@ -1,6 +1,6 @@ const { describe, it, expect } = require('@jest/globals'); -import { normalizeFileName, startsWith, humanizeDate, relativeDate } from './index'; +import { normalizeFileName, startsWith, humanizeDate, relativeDate, getContentType } from './index'; describe('common utils', () => { describe('normalizeFileName', () => { @@ -107,4 +107,45 @@ describe('common utils', () => { expect(relativeDate(date)).toBe('2 months ago'); }); }); + + describe('getContentType', () => { + it('should handle JSON content types correctly', () => { + expect(getContentType({ 'content-type': 'application/json' })).toBe('application/ld+json'); + expect(getContentType({ 'content-type': 'text/json' })).toBe('application/ld+json'); + expect(getContentType({ 'content-type': 'application/ld+json' })).toBe('application/ld+json'); + }); + + it('should handle XML content types correctly', () => { + expect(getContentType({ 'content-type': 'text/xml' })).toBe('application/xml'); + expect(getContentType({ 'content-type': 'application/xml' })).toBe('application/xml'); + expect(getContentType({ 'content-type': 'application/atom+xml' })).toBe('application/xml'); + }); + + it('should handle image content types correctly', () => { + expect(getContentType({ 'content-type': 'image/svg+xml;charset=utf-8' })).toBe('image/svg+xml'); + expect(getContentType({ 'content-type': 'IMAGE/SVG+xml' })).toBe('image/svg+xml'); + }); + + it('should return original content type when no pattern matches', () => { + expect(getContentType({ 'content-type': 'image/jpeg' })).toBe('image/jpeg'); + expect(getContentType({ 'content-type': 'application/pdf' })).toBe('application/pdf'); + }); + + it('should not be case sensitive', () => { + expect(getContentType({ 'content-type': 'text/json' })).toBe('application/ld+json'); + expect(getContentType({ 'Content-Type': 'text/json' })).toBe('application/ld+json'); + }); + + it('should handle empty content type', () => { + expect(getContentType({ 'content-type': '' })).toBe(''); + expect(getContentType({ 'content-type': null })).toBe(''); + expect(getContentType({ 'content-type': undefined })).toBe(''); + }); + + it('should handle empty or invalid inputs', () => { + expect(getContentType({})).toBe(''); + expect(getContentType(null)).toBe(''); + expect(getContentType(undefined)).toBe(''); + }); + }); });