Skip to content

Commit

Permalink
fix: Updating channel naming logic (#2307)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardtorres314 committed Mar 6, 2024
1 parent fe169ac commit 38b007e
Show file tree
Hide file tree
Showing 15 changed files with 31 additions and 105 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

# Fixes:

* Fixes channel name creation logic
* Remove duplicate introduction messages once again
* Prevent channel creation with names that start with special character, then a hyphen
* Choose random ports for Tor services (iOS)
Expand Down
14 changes: 5 additions & 9 deletions packages/common/src/naming.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ import { parseName } from './naming'

describe('Naming policy utility functions', () => {
it.each([
['double-hyp--hens', 'double-hyp-hens'],
['triple-hyp---hens', 'triple-hyp-hens'],
['-start-with-hyphen', 'start-with-hyphen'],
[' start-with-space', 'start-with-space'],
['end-with-hyphen-', 'end-with-hyphen'],
['end-with-space ', 'end-with-space'],
['UpperCaseToLowerCase', 'uppercasetolowercase'],
['spaces to hyphens', 'spaces-to-hyphens'],
['.-.-.-.', ''],
['---', '---'],
[' ', '-'],
['UPPERCASE', 'uppercase'],
['lowercase', 'lowercase'],
['!@#$%^&*()', '----------'],
])('name "%s" gets corrected to "%s"', async (name: string, corrected: string) => {
expect(parseName(name)).toEqual(corrected)
})
Expand Down
14 changes: 6 additions & 8 deletions packages/common/src/naming.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// Removes prepended and appended hyphens, then replaces multiple hyphens with a single hyphen
const trimHyphen = (input: string) => input.replace(/^[\s-]+|[\s-]$/g, '').replace(/(-)\1+/g, '$1')

/* eslint-disable */
export const specialCharsRegex = /[&\/\\#\]\[,+()!@$%^&*=_~`.'":;|?<>{}]/g

/**
* Parses a name, replacing special characters with a hyphen
* @param name string to be parsed
* @returns string with special characters replaced with a hyphen
*/
export const parseName = (name = '') => {
const sanitizedName = name.toLowerCase().replace(/ +/g, '-').replace(specialCharsRegex, '')
return trimHyphen(sanitizedName)
return name.replace(/[^\w._-]/g, '-').toLowerCase()
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { ModalName } from '../../../sagas/modals/modals.types'
import { modalsActions } from '../../../sagas/modals/modals.slice'

import { getFactory, identity, publicChannels } from '@quiet/state-manager'
import { FieldErrors } from '../../../forms/fieldsErrors'

describe('Add new channel', () => {
let socket: MockedSocket
Expand Down Expand Up @@ -64,7 +63,7 @@ describe('Add new channel', () => {

function* testSubmittedChannelName(): Generator {
const createChannelAction = yield* take(publicChannels.actions.createChannel)
expect(createChannelAction.payload.channel.name).toEqual('some-channel-name')
expect(createChannelAction.payload.channel.name).toEqual('some-channel-name--')
}
})

Expand All @@ -86,14 +85,9 @@ describe('Add new channel', () => {
})

it.each([
['double-hyp--hens', 'double-hyp-hens'],
['-start-with-hyphen', 'start-with-hyphen'],
[' start-with-space', 'start-with-space'],
['end-with-hyphen-', 'end-with-hyphen'],
['end-with-space ', 'end-with-space'],
['UpperCaseToLowerCase', 'uppercasetolowercase'],
['spaces to hyphens', 'spaces-to-hyphens'],
['!@#start-with-exclaim-at-hash', 'start-with-exclaim-at-hash'],
['!@#$%^&*()', '----------'],
])('user inserting wrong channel name "%s" gets corrected "%s"', async (name: string, corrected: string) => {
renderComponent(
<CreateChannelComponent
Expand All @@ -111,29 +105,4 @@ describe('Add new channel', () => {
`Your channel will be created as #${corrected}`
)
})

it.each([
[' whitespaces', FieldErrors.Whitespaces],
['----hyphens', FieldErrors.Whitespaces],
])('user inserting invalid channel name "%s" should see "%s" error', async (name: string, error: string) => {
const createChannel = jest.fn()

renderComponent(
<CreateChannelComponent
open={true}
createChannel={createChannel}
handleClose={() => {}}
clearErrorsDispatch={() => {}}
/>
)

const input = screen.getByPlaceholderText('Enter a channel name')
const button = screen.getByText('Create Channel')

await userEvent.type(input, name)
await userEvent.click(button)

const message = await screen.findByText(error)
expect(message).toBeVisible()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import CreateUsername from '../../CreateUsername/CreateUsername'
import JoinCommunity from '../JoinCommunity/JoinCommunity'
import CreateCommunity from './CreateCommunity'
import { CreateCommunityDictionary, JoinCommunityDictionary } from '../community.dictionary'
import { CommunityNameErrors, FieldErrors } from '../../../forms/fieldsErrors'
import { CommunityNameErrors } from '../../../forms/fieldsErrors'
import PerformCommunityActionComponent from '../PerformCommunityActionComponent'
import { identity, communities, StoreKeys as StateManagerStoreKeys } from '@quiet/state-manager'
import { CommunityOwnership } from '@quiet/types'
Expand Down Expand Up @@ -131,13 +131,9 @@ describe('Create community', () => {
})

it.each([
['double-hyp--hens', 'double-hyp-hens'],
['-start-with-hyphen', 'start-with-hyphen'],
[' start-with-space', 'start-with-space'],
['end-with-hyphen-', 'end-with-hyphen'],
['end-with-space ', 'end-with-space'],
['UpperCaseToLowerCase', 'uppercasetolowercase'],
['spaces to hyphens', 'spaces-to-hyphens'],
['!@#$%^&*()', '----------'],
])('user inserting wrong community name "%s" gets corrected "%s"', async (name: string, corrected: string) => {
renderComponent(
<PerformCommunityActionComponent
Expand All @@ -160,13 +156,10 @@ describe('Create community', () => {
)
})

it.each([
[' whitespaces', FieldErrors.Whitespaces],
['----hyphens', FieldErrors.Whitespaces],
['!@#', CommunityNameErrors.WrongCharacter],
['too-long-community-name', CommunityNameErrors.NameTooLong],
])('user inserting invalid community name "%s" should see "%s" error', async (name: string, error: string) => {
it('user inserting invalid community name should see an error', async () => {
const handleCommunityAction = jest.fn()
const name = 'too-long-community-name'
const error = CommunityNameErrors.NameTooLong

renderComponent(
<PerformCommunityActionComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@ import { screen, waitFor } from '@testing-library/dom'
import { renderComponent } from '../../testUtils/renderComponent'

import CreateUsernameComponent from './CreateUsernameComponent'
import { FieldErrors, UsernameErrors } from '../../forms/fieldsErrors'
import { UsernameErrors } from '../../forms/fieldsErrors'

describe('Create username', () => {
it.each([
['double-hyp--hens', 'double-hyp-hens'],
['-start-with-hyphen', 'start-with-hyphen'],
[' start-with-space', 'start-with-space'],
['end-with-hyphen-', 'end-with-hyphen'],
['end-with-space ', 'end-with-space'],
['UpperCaseToLowerCase', 'uppercasetolowercase'],
['spaces to hyphens', 'spaces-to-hyphens'],
['----hyphens', 'hyphens'],
['!@#$%^&*()', '----------'],
])('user inserting wrong name "%s" gets corrected "%s"', async (name: string, corrected: string) => {
renderComponent(<CreateUsernameComponent open={true} registerUsername={() => {}} handleClose={() => {}} />)

Expand All @@ -28,10 +23,9 @@ describe('Create username', () => {
)
})

it.each([
[' whitespaces', FieldErrors.Whitespaces],
['!@#', UsernameErrors.WrongCharacter],
])('user inserting invalid name "%s" should see "%s" error', async (name: string, error: string) => {
it('user inserting invalid name "%s" should see "%s" error', async () => {
const name = '!@#'
const error = UsernameErrors.WrongCharacter
const registerUsername = jest.fn()

renderComponent(<CreateUsernameComponent open={true} registerUsername={registerUsername} handleClose={() => {}} />)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FieldErrors, CommunityNameErrors, InviteLinkErrors } from '../fieldsErrors'
import { FieldErrors, CommunityNameErrors } from '../fieldsErrors'
import { FieldData } from '../types'

export const communityNameField = (name = 'name'): FieldData => {
Expand All @@ -19,9 +19,6 @@ export const communityNameField = (name = 'name'): FieldData => {
value: /^[-a-zA-Z0-9 ]+$/g,
message: CommunityNameErrors.WrongCharacter,
},
validate: {
whitespaces: value => /^(?![\s-])[\w\s-]+$/.test(value) || FieldErrors.Whitespaces,
},
},
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ export const channelNameField = (name = 'channelName'): FieldData => {
value: 20,
message: ChannelNameErrors.NameTooLong,
},
/* eslint-disable */
validate: {
whitespaces: value =>
/^(?![\s-])[\w&\/\\#\]\[,+()!@$%^&*=_~`.'":;|?<>{}\s-]+$/.test(value) ||
FieldErrors.Whitespaces
}
}
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ export const userNameField = (name = 'userName'): FieldData => {
value: /^[-a-zA-Z0-9 ]+$/g,
message: UsernameErrors.WrongCharacter,
},
validate: {
whitespaces: value => /^(?![\s])[\w\s-]+$/.test(value) || FieldErrors.Whitespaces,
},
},
}
}
1 change: 0 additions & 1 deletion packages/desktop/src/renderer/forms/fieldsErrors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export enum FieldErrors {
Required = 'Required field',
Whitespaces = 'Name cannot begin with whitespaces or dashes',
}

export enum UsernameErrors {
Expand Down
9 changes: 4 additions & 5 deletions packages/desktop/src/rtl-tests/channel.add.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe('Add new channel', () => {
const alice = await factory.create<ReturnType<typeof identity.actions.addNewIdentity>['payload']>('Identity', {
nickname: 'alice',
})
const channelName = { input: 'my-Super Channel ', output: 'my-super-channel' }
const channelName = { input: 'my-Super Channel ', output: 'my-super-channel-' }

const mockImpl = async (...input: [SocketActionTypes, ...socketEventData<[any]>]) => {
const action = input[0]
Expand Down Expand Up @@ -234,7 +234,7 @@ describe('Add new channel', () => {
})

it('Bug reproduction - open and close modal and check there are any errors', async () => {
const channelName = '---'
const channelName = ''
const { store } = await prepareStore(
{},
socket // Fork state manager's sagas
Expand Down Expand Up @@ -262,13 +262,12 @@ describe('Add new channel', () => {

const user = userEvent.setup()
const input = screen.getByPlaceholderText('Enter a channel name')
await user.type(input, channelName)
expect(input).toHaveValue(channelName)

const button = screen.getByText('Create Channel')
await userEvent.click(button)

const error = await screen.findByText(FieldErrors.Whitespaces)
const error = await screen.findByText(FieldErrors.Required)
expect(error).toBeVisible()

const closeChannel = screen.getByTestId('ModalActions').querySelector('button')
Expand All @@ -283,7 +282,7 @@ describe('Add new channel', () => {
const title2 = await screen.findByText('Create a new public channel')
expect(title2).toBeVisible()

const isErrorStillExist = screen.queryByText(FieldErrors.Whitespaces)
const isErrorStillExist = screen.queryByText(FieldErrors.Required)
expect(isErrorStillExist).toBeNull()
})

Expand Down
3 changes: 0 additions & 3 deletions packages/desktop/src/rtl-tests/community.join.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import MockedSocket from 'socket.io-mock'
import { ioMock } from '../shared/setupTests'
import { socketEventData } from '../renderer/testUtils/socket'
import {
identity,
communities,
RegisterUserCertificatePayload,
InitCommunityPayload,
Expand All @@ -26,7 +25,6 @@ import {
} from '@quiet/state-manager'
import Channel from '../renderer/components/Channel/Channel'
import LoadingPanel from '../renderer/components/LoadingPanel/LoadingPanel'
import { createUserCertificateTestHelper } from '@quiet/identity'
import { AnyAction } from 'redux'
import {
InvitationData,
Expand All @@ -35,7 +33,6 @@ import {
ErrorPayload,
type NetworkInfo,
ResponseLaunchCommunityPayload,
SendOwnerCertificatePayload,
SocketActionTypes,
} from '@quiet/types'
import { composeInvitationShareUrl } from '@quiet/common'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { AnyAction } from 'redux'
import { identity, publicChannels, getFactory, ChannelsReplicatedPayload } from '@quiet/state-manager'
import { SocketActionTypes } from '@quiet/types'
import Channel from '../renderer/components/Channel/Channel'
import { waitFor } from '@testing-library/dom'

jest.setTimeout(20_000)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@ import { CreateChannelScreen } from './CreateChannel.screen'

describe('Create channel', () => {
it.each([
['double-hyp--hens', 'double-hyp-hens'],
['-start-with-hyphen', 'start-with-hyphen'],
[' start-with-space', 'start-with-space'],
['end-with-hyphen-', 'end-with-hyphen'],
['end-with-space ', 'end-with-space'],
['UpperCaseToLowerCase', 'uppercasetolowercase'],
['spaces to hyphens', 'spaces-to-hyphens'],
['!@#start-with-exclaim-at-hash', 'start-with-exclaim-at-hash'],
['!@#$%^&*()', '----------'],
])('user inserting wrong channel name "%s" gets corrected "%s"', async (name: string, corrected: string) => {
renderComponent(<CreateChannelScreen />)

Expand Down
2 changes: 0 additions & 2 deletions packages/mobile/src/tests/deep.linking.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ describe('Deep linking', () => {
"Communities/addNewCommunity",
"Communities/setCurrentCommunity",
"Init/deepLink",
"Init/resetDeepLink",
"Navigation/replaceScreen",
]
`)

Expand Down

0 comments on commit 38b007e

Please sign in to comment.