Skip to content

Commit

Permalink
refactor: use builder to write our code snippets (#1527)
Browse files Browse the repository at this point in the history
* feat: write new helpers for code snippets

* fix: update helper for code snippets

fix: update helper for code snippets

test: add more tests to handle undefined values

* improve: remove comment when copying code
  • Loading branch information
keellyp authored Jun 4, 2024
1 parent 093913e commit c6deec9
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/components/CodeSnippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const CodeSnippet = memo(
variant="secondary"
startIcon="duplicate"
onClick={() => {
copyToClipboard(code)
copyToClipboard(code, { ignoreComment: true })

addToast({
severity: 'info',
Expand Down
10 changes: 10 additions & 0 deletions src/core/utils/__tests__/copyToClipboard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,14 @@ describe('copyToClipboard', () => {
'the text that needs to be copied',
)
})

it('should filter out comments', () => {
const value = `# comment
the text that needs to be copied`

copyToClipboard(value, { ignoreComment: true })
expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith(
'the text that needs to be copied',
)
})
})
127 changes: 127 additions & 0 deletions src/core/utils/__tests__/snippetBuilder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { snippetBuilder } from '~/core/utils/snippetBuilder'

describe('SnippetBuilder', () => {
it('should work properly', () => {
const result = snippetBuilder({
title: 'My title',
url: `url`,
method: 'POST',
headers: [{ Authorization: 'Bearer ' }, { 'Content-Type': 'application/json' }],
data: {
snippet: {
name: 'name',
code: 'code',
nested: {
nestedName: 'nestedName',
nestedCode: 'nestedCode',
},
nestedArray: [
{
id: '1',
name: 'test',
},
],
},
},
footerComment: 'To use the snippet, don’t forget to edit your __YOUR_API_KEY__',
})

expect(result).toBe(`# My title
curl --location --request POST "url" \\
--header "Authorization: Bearer " \\
--header "Content-Type: application/json" \\
--data-raw '{
"snippet": {
"name": "name",
"code": "code",
"nested": {
"nestedName": "nestedName",
"nestedCode": "nestedCode"
},
"nestedArray": [
{
"id": "1",
"name": "test"
}
]
}
}'
# To use the snippet, don’t forget to edit your __YOUR_API_KEY__`)
})

it('should work properly with no data', () => {
const result = snippetBuilder({
title: 'My title',
url: `url`,
method: 'POST',
headers: [{ Authorization: 'Bearer ' }, { 'Content-Type': 'application/json' }],
data: {},
})

expect(result).toBe(`# My title
curl --location --request POST "url" \\
--header "Authorization: Bearer " \\
--header "Content-Type: application/json" \\
--data-raw '{}'
`)
})

it('should work properly with conditional data and undefined values', () => {
const shouldRender: boolean = false
const state: string = ''

const result = snippetBuilder({
title: 'My title',
url: `url`,
method: 'POST',
headers: [{ Authorization: 'Bearer ' }, { 'Content-Type': 'application/json' }],
data: {
snippet: {
...(!!state && { state: 'active' }),
...(!!state && { state: null }),
name: undefined,
title: 'title',
nested: {
nestedName: 'nestedName',
nestedCode: 'nestedCode',
},
nestedArray: [
{
id: '1',
name: 'test',
},
],
...(shouldRender ? { withFalse: 'true' } : false),
...(shouldRender ? { withEmptyObj: 'true' } : {}),
...(shouldRender ? { withText: 'true' } : ''),
...(shouldRender ? { withUndefined: 'true' } : undefined),
...(shouldRender ? { withNull: 'true' } : null),
},
},
footerComment: 'To use the snippet, don’t forget to edit your __YOUR_API_KEY__',
})

expect(result).toBe(`# My title
curl --location --request POST "url" \\
--header "Authorization: Bearer " \\
--header "Content-Type: application/json" \\
--data-raw '{
"snippet": {
"title": "title",
"nested": {
"nestedName": "nestedName",
"nestedCode": "nestedCode"
},
"nestedArray": [
{
"id": "1",
"name": "test"
}
]
}
}'
# To use the snippet, don’t forget to edit your __YOUR_API_KEY__`)
})
})
16 changes: 14 additions & 2 deletions src/core/utils/copyToClipboard.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { addToast } from '~/core/apolloClient'

export const copyToClipboard: (value: string) => void = (value) => {
const filterComment = (value: string) => {
return value
.split('\n')
.filter((line) => !line.startsWith('#'))
.join('\n')
}

export const copyToClipboard: (value: string, options?: { ignoreComment?: boolean }) => void = (
value,
ignoreComment,
) => {
const serializedValue = ignoreComment ? filterComment(value) : value

try {
navigator.clipboard.writeText(value)
navigator.clipboard.writeText(serializedValue)
} catch (error) {
addToast({
severity: 'danger',
Expand Down
50 changes: 50 additions & 0 deletions src/core/utils/snippetBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const serializeDataToString = (data: DataType): string => {
const extractedDataString = JSON.stringify(data, null, 2)
const extractedDataStringIndented = extractedDataString.replace(/^(?=.)/gm, ' ').trimStart()

return extractedDataStringIndented
}

type DataType = Record<string, unknown>

interface CurlCommand {
title: string
url: string
method: 'POST' | 'PUT'
headers: Array<Record<string, string>>
data: DataType
footerComment?: string
}

export enum SnippetVariables {
EXTERNAL_CUSTOMER_ID = '__EXTERNAL_CUSTOMER_ID__',
MUST_BE_DEFINED = '__MUST_BE_DEFINED__',
API_KEY = '__YOUR_API_KEY__',
}

/**
* Helper function to build a curl command snippet
* @returns string
*/
export const snippetBuilder = (curlCommand: CurlCommand): string => {
const { title, url, method, headers, data, footerComment } = curlCommand

return `\
# ${title}
curl --location --request ${method} "${url}" \\
${headers
.map((header) => {
const [key] = Object.keys(header)
return ` --header "${key}: ${header[key]}" \\`
})
.join('\n')}
--data-raw '${serializeDataToString(data)}'
${
footerComment
? `
# ${footerComment}`
: ''
}\
`
}

0 comments on commit c6deec9

Please sign in to comment.