Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export default function HighlightsSettingsForm({
placeholder: t('environment, release, my-tag'),
label: t('Highlighted Tags'),
help: t('Separate tag keys with a newline.'),
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
{
name: 'highlightContext',
Expand Down
8 changes: 4 additions & 4 deletions static/app/data/forms/apiApplication.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ const forms: JsonFormObject[] = [
placeholder: 'e.g. https://example.com/oauth/complete',
label: 'Authorized Redirect URIs',
help: 'Separate multiple entries with a newline.',
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
{
name: 'allowedOrigins',
Expand All @@ -64,8 +64,8 @@ const forms: JsonFormObject[] = [
placeholder: 'e.g. example.com',
label: 'Authorized JavaScript Origins',
help: 'Separate multiple entries with a newline.',
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ const formGroups: JsonFormObject[] = [
saveMessage: t(
'Changes to your scrubbing configuration will apply to all new events.'
),
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
{
name: 'safeFields',
Expand All @@ -183,8 +183,8 @@ const formGroups: JsonFormObject[] = [
saveMessage: t(
'Changes to your scrubbing configuration will apply to all new events.'
),
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
{
name: 'scrubIPAddresses',
Expand Down
23 changes: 2 additions & 21 deletions static/app/data/forms/projectGeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,27 +152,8 @@ export const fields = {
</Hovercard>
),
}),
getValue: (val: unknown) => {
if (typeof val === 'string') {
return extractMultilineFields(val);
}

if (Array.isArray(val) && val.every(item => typeof item === 'string')) {
return val;
}

return [];
},
setValue: (val: unknown) => {
if (
typeof val === 'string' ||
(Array.isArray(val) && val.every(item => typeof item === 'string'))
) {
return convertMultilineFieldValue(val);
}

return '';
},
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
scrapeJavaScript: {
name: 'scrapeJavaScript',
Expand Down
8 changes: 4 additions & 4 deletions static/app/data/forms/projectSecurityAndPrivacyGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ const formGroups: JsonFormObject[] = [
'aria-label': t(
'Enter additional field names to match against when scrubbing data. Separate multiple entries with a newline'
),
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
{
name: 'safeFields',
Expand All @@ -187,8 +187,8 @@ const formGroups: JsonFormObject[] = [
'aria-label': t(
'Enter field names which data scrubbers should ignore. Separate multiple entries with a newline'
),
getValue: val => extractMultilineFields(val),
setValue: val => convertMultilineFieldValue(val),
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
],
},
Expand Down
7 changes: 3 additions & 4 deletions static/app/data/forms/sentryApplication.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ExternalLink} from 'sentry/components/core/link';
import type {Field} from 'sentry/components/forms/types';
import {tct} from 'sentry/locale';
import {extractMultilineFields} from 'sentry/utils';
import {convertMultilineFieldValue, extractMultilineFields} from 'sentry/utils';

const getPublicFormFields = (): Field[] => [
{
Expand Down Expand Up @@ -113,9 +113,8 @@ const getPublicFormFields = (): Field[] => [
placeholder: 'e.g. example.com',
label: 'Authorized JavaScript Origins',
help: 'Separate multiple entries with a newline.',
getValue: (val: string) => extractMultilineFields(val),
setValue: (val: string[] | undefined | null) =>
(val && typeof val.join === 'function' && val.join('\n')) || '',
getValue: extractMultilineFields,
setValue: convertMultilineFieldValue,
},
];

Expand Down
37 changes: 32 additions & 5 deletions static/app/utils.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
convertMultilineFieldValue,
descopeFeatureName,
escapeDoubleQuotes,
escapeIssueTagKey,
Expand All @@ -24,14 +25,10 @@ describe('utils.escapeIssueTagKey', () => {
});

describe('utils.extractMultilineFields', () => {
it('should work for basic, simple values', () => {
it('should split string by newlines', () => {
expect(extractMultilineFields('one\ntwo\nthree')).toEqual(['one', 'two', 'three']);
});

it('should return an empty array if only whitespace', () => {
expect(extractMultilineFields(' \n \n\n\n \n')).toEqual([]);
});

it('should trim values and ignore empty lines', () => {
expect(
extractMultilineFields(
Expand All @@ -45,6 +42,36 @@ five`
)
).toEqual(['one', 'two', 'three', 'four', 'five']);
});

it('should return string array as-is', () => {
expect(extractMultilineFields(['one', 'two', 'three'])).toEqual([
'one',
'two',
'three',
]);
});

it('should return empty array for invalid input', () => {
expect(extractMultilineFields(null)).toEqual([]);
expect(extractMultilineFields(undefined)).toEqual([]);
expect(extractMultilineFields(['one', 2, 'three'])).toEqual([]);
});
});

describe('utils.convertMultilineFieldValue', () => {
it('should return string as-is', () => {
expect(convertMultilineFieldValue('one\ntwo\nthree')).toBe('one\ntwo\nthree');
});

it('should join string array with newlines', () => {
expect(convertMultilineFieldValue(['one', 'two', 'three'])).toBe('one\ntwo\nthree');
});

it('should return empty string for invalid input', () => {
expect(convertMultilineFieldValue(null)).toBe('');
expect(convertMultilineFieldValue(undefined)).toBe('');
expect(convertMultilineFieldValue(['one', 2, 'three'])).toBe('');
});
});

describe('utils.explodeSlug', () => {
Expand Down
40 changes: 23 additions & 17 deletions static/app/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,30 +41,36 @@ export function percent(value: number, totalValue: number): number {
}

/**
* Converts a multi-line textarea input value into an array,
* eliminating empty lines
* Converts a multi-line textarea input value into an array, eliminating empty lines.
* Safely handles unknown input types for form field getValue callbacks.
*/
export function extractMultilineFields(value: string): string[] {
return value
.split('\n')
.map(f => f.trim())
.filter(f => f !== '');
export function extractMultilineFields(value: unknown): string[] {
// User input
if (typeof value === 'string') {
return value
.split('\n')
.map(f => f.trim())
.filter(f => f !== '');
}
// API response / undo form save action
if (Array.isArray(value) && value.every(item => typeof item === 'string')) {
return value;
}

return [];
}

/**
* If the value is of type Array, converts it to type string, keeping the line breaks, if there is any
* Converts a value to a multi-line string for display in textarea.
* Safely handles unknown input types for form field setValue callbacks.
*/
export function convertMultilineFieldValue<T extends string | string[]>(
value: T
): string {
if (Array.isArray(value)) {
return value.join('\n');
}

export function convertMultilineFieldValue(value: unknown): string {
if (typeof value === 'string') {
return value.split('\n').join('\n');
return value;
}
if (Array.isArray(value) && value.every(item => typeof item === 'string')) {
return value.join('\n');
}

return '';
}

Expand Down
Loading