From 1f083b4d0485db2d834e000678dba38e671b8d2e Mon Sep 17 00:00:00 2001 From: Alisson Fabiano Date: Fri, 12 Aug 2022 12:05:31 +0100 Subject: [PATCH] chore: includes units tests for readme converter Signed-off-by: Alisson Fabiano --- .../src/utils/azure-devops-utils.test.ts | 128 ++++++++++++++++++ .../src/utils/azure-devops-utils.ts | 30 ++-- 2 files changed, 144 insertions(+), 14 deletions(-) diff --git a/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts b/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts index 8aed436710..c9bde296f6 100644 --- a/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts +++ b/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts @@ -21,9 +21,13 @@ import { } from '@backstage/plugin-azure-devops-common'; import { convertDashboardPullRequest, + extractAssets, + extractPartsFromAsset, getArtifactId, getAvatarUrl, + getMimeByExtension, getPullRequestLink, + replaceReadme, } from './azure-devops-utils'; import { GitPullRequest } from 'azure-devops-node-api/interfaces/GitInterfaces'; @@ -159,3 +163,127 @@ describe('getArtifactId', () => { expect(result).toBe('vstfs:///CodeReview/CodeReviewId/project1/1'); }); }); + +describe('extractAssets', () => { + it('should return assets', () => { + const readme = ` + ## Images + ![Image 1](./images/sample-4(2).png) + ![Image 2](./images/cdCSj+-012340.jpg) + ![Image 3](/images/test-4(2)))).jpeg) + ![Image 4](./images/test-2211jd.webp) + ![Image 5](/images/sa)mple.gif) + `; + const result = extractAssets(readme); + expect(result).toEqual([ + '[Image 1](./images/sample-4(2).png)', + '[Image 2](./images/cdCSj+-012340.jpg)', + '[Image 3](/images/test-4(2)))).jpeg)', + '[Image 4](./images/test-2211jd.webp)', + '[Image 5](/images/sa)mple.gif)', + ]); + }); +}); + +describe('extractPartsFromAsset', () => { + it('should return parts from asset - PNG', () => { + const result = extractPartsFromAsset('[Image 1](./images/sample-4(2).png)'); + expect(result).toEqual({ + label: 'Image 1', + path: '/images/sample-4(2)', + ext: '.png', + }); + }); + + it('should return parts from asset - JPG', () => { + const result = extractPartsFromAsset( + '[Image 2](./images/cdCSj+-012340.jpg)', + ); + expect(result).toEqual({ + label: 'Image 2', + path: '/images/cdCSj+-012340', + ext: '.jpg', + }); + }); + + it('should return parts from asset - JPEG', () => { + const result = extractPartsFromAsset( + '[Image 2](/images/test-4(2)))).jpeg)', + ); + expect(result).toEqual({ + label: 'Image 2', + path: '/images/test-4(2))))', + ext: '.jpeg', + }); + }); + + it('should return parts from asset - WEBP', () => { + const result = extractPartsFromAsset('[Image 2](/images/test-2211jd.webp)'); + expect(result).toEqual({ + label: 'Image 2', + path: '/images/test-2211jd', + ext: '.webp', + }); + }); + + it('should return parts from asset - GIF', () => { + const result = extractPartsFromAsset('[Image 2](/images/test-4(2)))).gif)'); + expect(result).toEqual({ + label: 'Image 2', + path: '/images/test-4(2))))', + ext: '.gif', + }); + }); +}); + +describe('getMimeByExtension', () => { + it('should return mime type', () => { + expect(getMimeByExtension('.png')).toBe('image/png'); + expect(getMimeByExtension('.jpg')).toBe('image/jpeg'); + expect(getMimeByExtension('.jpeg')).toBe('image/jpeg'); + expect(getMimeByExtension('.webp')).toBe('image/webp'); + expect(getMimeByExtension('.gif')).toBe('image/gif'); + }); +}); + +describe('replaceReadme', () => { + it('should return mime type', async () => { + const readme = ` + ## Images + ![Image 1](./images/sample-4(2).png) + ![Image 2](./images/cdCSj+-012340.jpg) + ![Image 3](/images/test-4(2)))).jpeg) + ![Image 4](./images/test-2211jd.webp) + ![Image 5](/images/sa)mple.gif) + `; + + async function mockFileContent( + path: string, + encoding?: BufferEncoding, + ): Promise<{ + url: string; + content: string; + }> { + expect(encoding).toBe('base64'); + return new Promise(resolve => + resolve({ + url: '', + content: Buffer.from(path).toString(encoding), + }), + ); + } + + const result = await replaceReadme(readme, mockFileContent); + + const expected = ` + ## Images + ![Image 1](data:image/png;base64,L2ltYWdlcy9zYW1wbGUtNCgyKS5wbmc=) + ![Image 2](data:image/jpeg;base64,L2ltYWdlcy9jZENTaistMDEyMzQwLmpwZw==) + ![Image 3](data:image/jpeg;base64,L2ltYWdlcy90ZXN0LTQoMikpKSkuanBlZw==) + ![Image 4](data:image/webp;base64,L2ltYWdlcy90ZXN0LTIyMTFqZC53ZWJw) + ![Image 5](data:image/gif;base64,L2ltYWdlcy9zYSltcGxlLmdpZg==) + `; + + expect(expected).toBe(result); + }); +}); diff --git a/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts b/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts index bf82ed265b..ab5a4113d2 100644 --- a/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts +++ b/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts @@ -216,17 +216,19 @@ export async function replaceReadme( }>, ) { const filesPath = extractAssets(readme); - let content = readme; - for (const filePath of filesPath) { - const { label, path, ext } = extractPartsFromAsset(filePath); - const mime = getMimeByExtension(ext); - const { content: base64 } = await getFileContent(path + ext, 'base64'); - content = content.replace( - filePath, - `[${label}](data:${mime};base64,${base64})`, - ); - } - return content; + return await filesPath.reduce( + async (promise: Promise, filePath: string) => + promise.then(async content => { + const { label, path, ext } = extractPartsFromAsset(filePath); + const mime = getMimeByExtension(ext); + const file = await getFileContent(path + ext, 'base64'); + return content.replace( + filePath, + `[${label}](data:${mime};base64,${file.content})`, + ); + }), + Promise.resolve(readme), + ); } function convertReviewer( @@ -288,13 +290,13 @@ function hasAutoComplete(pullRequest: GitPullRequest): boolean { return pullRequest.isDraft !== true && !!pullRequest.completionOptions; } -function extractAssets(content: string) { +export function extractAssets(content: string) { const regExp = /\[([^\[\]]*)\]\((?!https?:\/\/)(.*?)(\.png|\.jpg|\.jpeg|\.gif|\.webp)(.*)\)/gim; return content.match(regExp) || []; } -function extractPartsFromAsset(content: string): { +export function extractPartsFromAsset(content: string): { label: string; path: string; ext: string; @@ -309,7 +311,7 @@ function extractPartsFromAsset(content: string): { }; } -function getMimeByExtension(ext: string): string { +export function getMimeByExtension(ext: string): string { return ( { '.png': 'image/png',