diff options
author | Maksim Sukharev <antreesy.web@gmail.com> | 2024-03-13 20:31:21 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-13 20:31:21 +0100 |
commit | 462a5605010d79011ae5e5cf1f249b01c54ae076 (patch) | |
tree | 218b92a832cba9bd768d7f1665a0d4375e387078 | |
parent | b7c6b77b741aea74d01ec1d9c056c2fa317ba966 (diff) | |
parent | beca0c322fa3daf7942b749a369426fe5dba4ba2 (diff) |
Merge pull request #11786 from nextcloud/chore/noid/migrate-utils-to-typescript
chore(typescript): migrate utils to TS
18 files changed, 226 insertions, 49 deletions
diff --git a/src/components/CallView/shared/EmptyCallView.vue b/src/components/CallView/shared/EmptyCallView.vue index 2c74052b2..61e667df7 100644 --- a/src/components/CallView/shared/EmptyCallView.vue +++ b/src/components/CallView/shared/EmptyCallView.vue @@ -43,7 +43,7 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' import { CONVERSATION, PARTICIPANT } from '../../../constants.js' -import { copyConversationLinkToClipboard } from '../../../services/urlService.js' +import { copyConversationLinkToClipboard } from '../../../utils/handleUrl.ts' export default { diff --git a/src/components/ConversationSettings/LinkShareSettings.vue b/src/components/ConversationSettings/LinkShareSettings.vue index a4c7c4fe9..07efe28d9 100644 --- a/src/components/ConversationSettings/LinkShareSettings.vue +++ b/src/components/ConversationSettings/LinkShareSettings.vue @@ -103,7 +103,7 @@ import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadi import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js' import { CONVERSATION } from '../../constants.js' -import { copyConversationLinkToClipboard } from '../../services/urlService.js' +import { copyConversationLinkToClipboard } from '../../utils/handleUrl.ts' export default { name: 'LinkShareSettings', diff --git a/src/components/LeftSidebar/ConversationsList/Conversation.vue b/src/components/LeftSidebar/ConversationsList/Conversation.vue index 60c712e1f..4cfdf3334 100644 --- a/src/components/LeftSidebar/ConversationsList/Conversation.vue +++ b/src/components/LeftSidebar/ConversationsList/Conversation.vue @@ -146,7 +146,7 @@ import ConversationIcon from './../../ConversationIcon.vue' import { useConversationInfo } from '../../../composables/useConversationInfo.js' import { PARTICIPANT } from '../../../constants.js' -import { copyConversationLinkToClipboard } from '../../../services/urlService.js' +import { copyConversationLinkToClipboard } from '../../../utils/handleUrl.ts' export default { name: 'Conversation', diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.vue b/src/components/MessagesList/MessagesGroup/Message/Message.vue index 2c7692b70..079a9ec4b 100644 --- a/src/components/MessagesList/MessagesGroup/Message/Message.vue +++ b/src/components/MessagesList/MessagesGroup/Message/Message.vue @@ -123,7 +123,7 @@ import Reactions from './MessagePart/Reactions.vue' import { CONVERSATION, PARTICIPANT } from '../../../../constants.js' import { EventBus } from '../../../../services/EventBus.js' import { useChatExtrasStore } from '../../../../stores/chatExtras.js' -import { getItemTypeFromMessage } from '../../../../utils/getItemTypeFromMessage.js' +import { getItemTypeFromMessage } from '../../../../utils/getItemTypeFromMessage.ts' const isTranslationAvailable = getCapabilities()?.spreed?.config?.chat?.['has-translation-providers'] // Fallback for the desktop client when connecting to Talk 17 diff --git a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue index bb3a1fb6d..09eacbcd0 100644 --- a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue +++ b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue @@ -304,9 +304,9 @@ import NcEmojiPicker from '@nextcloud/vue/dist/Components/NcEmojiPicker.js' import { PARTICIPANT, CONVERSATION, ATTENDEE } from '../../../../../constants.js' import { getMessageReminder, removeMessageReminder, setMessageReminder } from '../../../../../services/remindersService.js' -import { copyConversationLinkToClipboard } from '../../../../../services/urlService.js' import { useIntegrationsStore } from '../../../../../stores/integrations.js' import { useReactionsStore } from '../../../../../stores/reactions.js' +import { copyConversationLinkToClipboard } from '../../../../../utils/handleUrl.ts' import { parseMentions } from '../../../../../utils/textParse.ts' const EmojiIndex = new EmojiIndexFactory(data) diff --git a/src/components/NewConversationDialog/NewConversationDialog.vue b/src/components/NewConversationDialog/NewConversationDialog.vue index 2a8a81c08..fe1f434a0 100644 --- a/src/components/NewConversationDialog/NewConversationDialog.vue +++ b/src/components/NewConversationDialog/NewConversationDialog.vue @@ -148,7 +148,7 @@ import { setConversationPassword, } from '../../services/conversationsService.js' import { addParticipant } from '../../services/participantsService.js' -import { copyConversationLinkToClipboard } from '../../services/urlService.js' +import { copyConversationLinkToClipboard } from '../../utils/handleUrl.ts' const NEW_CONVERSATION = { token: '', diff --git a/src/components/RightSidebar/Participants/Participant.vue b/src/components/RightSidebar/Participants/Participant.vue index c8d5171ab..aeae82f0c 100644 --- a/src/components/RightSidebar/Participants/Participant.vue +++ b/src/components/RightSidebar/Participants/Participant.vue @@ -378,7 +378,7 @@ import { callSIPSendDTMF, } from '../../../services/callsService.js' import { formattedTime } from '../../../utils/formattedTime.ts' -import { readableNumber } from '../../../utils/readableNumber.js' +import { readableNumber } from '../../../utils/readableNumber.ts' import { getStatusMessage } from '../../../utils/userStatus.js' export default { diff --git a/src/components/RightSidebar/SipSettings.vue b/src/components/RightSidebar/SipSettings.vue index a4967494f..91854c4ba 100644 --- a/src/components/RightSidebar/SipSettings.vue +++ b/src/components/RightSidebar/SipSettings.vue @@ -35,7 +35,7 @@ <script> import { loadState } from '@nextcloud/initial-state' -import { readableNumber } from '../../utils/readableNumber.js' +import { readableNumber } from '../../utils/readableNumber.ts' export default { name: 'SipSettings', diff --git a/src/components/TopBar/TopBarMenu.vue b/src/components/TopBar/TopBarMenu.vue index 8dfdbd10b..3867a7567 100644 --- a/src/components/TopBar/TopBarMenu.vue +++ b/src/components/TopBar/TopBarMenu.vue @@ -190,7 +190,7 @@ import PromotedView from '../../assets/missingMaterialDesignIcons/PromotedView.v import { useIsInCall } from '../../composables/useIsInCall.js' import { CALL, CONVERSATION, PARTICIPANT } from '../../constants.js' -import { generateAbsoluteUrl } from '../../services/urlService.js' +import { generateAbsoluteUrl } from '../../utils/handleUrl.ts' import { callParticipantCollection } from '../../utils/webrtc/index.js' export default { diff --git a/src/stores/sharedItems.js b/src/stores/sharedItems.js index b3de307fb..1225842a4 100644 --- a/src/stores/sharedItems.js +++ b/src/stores/sharedItems.js @@ -25,7 +25,7 @@ import { defineStore } from 'pinia' import Vue from 'vue' import { getSharedItemsOverview, getSharedItems } from '../services/sharedItemsService.js' -import { getItemTypeFromMessage } from '../utils/getItemTypeFromMessage.js' +import { getItemTypeFromMessage } from '../utils/getItemTypeFromMessage.ts' /** * @typedef {'media'|'file'|'voice'|'audio'|'location'|'deckcard'|'other'} Type diff --git a/src/types/index.ts b/src/types/index.ts index d2f1f48ec..7459dccf7 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -45,7 +45,7 @@ export type Mention = ParamObject & { 'call-type'?: string, 'icon-url'?: string, } -type File = ParamObject & { +export type File = ParamObject & { 'size': number, 'path': string, 'link': string, diff --git a/src/utils/__tests__/formattedTime.spec.js b/src/utils/__tests__/formattedTime.spec.js new file mode 100644 index 000000000..23493141e --- /dev/null +++ b/src/utils/__tests__/formattedTime.spec.js @@ -0,0 +1,19 @@ +import { formattedTime } from '../formattedTime.ts' + +const TIME = (61 * 60 + 5) * 1000 // 1 hour, 1 minute, 5 seconds in ms + +describe('formattedTime', () => { + it('should return the formatted time with optional spacing and padded minutes / seconds', () => { + const result = formattedTime(TIME) + expect(result).toBe('1 : 01 : 05') + const resultCondensed = formattedTime(TIME, true) + expect(resultCondensed).toBe('1:01:05') + }) + + it('should return fallback string when time value is falsy', () => { + const result = formattedTime(0) + expect(result).toBe('-- : --') + const resultCondensed = formattedTime(0, true) + expect(resultCondensed).toBe('--:--') + }) +}) diff --git a/src/utils/__tests__/getItemTypeFromMessage.spec.js b/src/utils/__tests__/getItemTypeFromMessage.spec.js new file mode 100644 index 000000000..e7d484ac2 --- /dev/null +++ b/src/utils/__tests__/getItemTypeFromMessage.spec.js @@ -0,0 +1,41 @@ +import { SHARED_ITEM } from '../../constants.js' +import { getItemTypeFromMessage } from '../getItemTypeFromMessage.ts' + +describe('getItemTypeFromMessage', () => { + it('should return the correct item type for a messages', () => { + const messages = { + 1: { messageType: 'comment', messageParameters: { object: { type: 'geo-location' } } }, + 2: { messageType: 'comment', messageParameters: { object: { type: 'deck-card' } } }, + 3: { messageType: 'comment', messageParameters: { object: { type: 'talk-poll' } } }, + 4: { messageType: 'comment', messageParameters: { object: { type: 'some-type' } } }, + 5: { messageType: 'record-audio', messageParameters: { file: { mimetype: 'audio/mp3' } } }, + 6: { messageType: 'record-video', messageParameters: { file: { mimetype: 'video/mp4' } } }, + 7: { messageType: 'voice-message', messageParameters: { file: { mimetype: 'audio/mp3' } } }, + 8: { messageType: 'comment', messageParameters: { file: { mimetype: 'audio/mp3' } } }, + 9: { messageType: 'comment', messageParameters: { file: { mimetype: 'image/jpg' } } }, + 10: { messageType: 'comment', messageParameters: { file: { mimetype: 'video/mp4' } } }, + 11: { messageType: 'comment', messageParameters: { file: { mimetype: 'text/markdown' } } }, + 12: { messageType: 'comment', message: 'simple message' }, + } + + const outputTypes = { + 1: SHARED_ITEM.TYPES.LOCATION, + 2: SHARED_ITEM.TYPES.DECK_CARD, + 3: SHARED_ITEM.TYPES.POLL, + 4: SHARED_ITEM.TYPES.OTHER, + 5: SHARED_ITEM.TYPES.RECORDING, + 6: SHARED_ITEM.TYPES.RECORDING, + 7: SHARED_ITEM.TYPES.VOICE, + 8: SHARED_ITEM.TYPES.AUDIO, + 9: SHARED_ITEM.TYPES.MEDIA, + 10: SHARED_ITEM.TYPES.MEDIA, + 11: SHARED_ITEM.TYPES.FILE, + 12: SHARED_ITEM.TYPES.OTHER, + } + + for (const i in messages) { + const type = i + ': ' + getItemTypeFromMessage(messages[i]) + expect(type).toBe(i + ': ' + outputTypes[i]) + } + }) +}) diff --git a/src/utils/__tests__/handleUrl.spec.js b/src/utils/__tests__/handleUrl.spec.js new file mode 100644 index 000000000..d6550915f --- /dev/null +++ b/src/utils/__tests__/handleUrl.spec.js @@ -0,0 +1,63 @@ +import { showError, showSuccess } from '@nextcloud/dialogs' + +import { + generateAbsoluteUrl, + generateFullConversationLink, + copyConversationLinkToClipboard, +} from '../handleUrl.ts' + +jest.mock('@nextcloud/dialogs', () => ({ + showSuccess: jest.fn(), + showError: jest.fn(), +})) + +describe('handleUrl', () => { + describe('generateAbsoluteUrl', () => { + it('should generate url with IS_DESKTOP=false correctly', () => { + const output = generateAbsoluteUrl('/path') + expect(output).toBe('http://localhost/nc-webroot/path') + }) + + it('should generate url with IS_DESKTOP=true correctly', () => { + const originalIsDesktop = global.IS_DESKTOP + global.IS_DESKTOP = true + + const output = generateAbsoluteUrl('/path') + expect(output).toBe('/nc-webroot/path') + + global.IS_DESKTOP = originalIsDesktop + }) + }) + + describe('generateFullConversationLink', () => { + it('should generate links with given token', () => { + const link = generateFullConversationLink('TOKEN') + expect(link).toBe('http://localhost/nc-webroot/call/TOKEN') + }) + + it('should generate links with given token and message id', () => { + const link = generateFullConversationLink('TOKEN', '123') + expect(link).toBe('http://localhost/nc-webroot/call/TOKEN#message_123') + }) + }) + + describe('copyConversationLinkToClipboard', () => { + it('should copy the conversation link and show success message', async () => { + Object.assign(navigator, { clipboard: { writeText: jest.fn().mockResolvedValueOnce() } }) + + await copyConversationLinkToClipboard('TOKEN', '123') + + expect(navigator.clipboard.writeText).toHaveBeenCalledWith('http://localhost/nc-webroot/call/TOKEN#message_123') + expect(showSuccess).toHaveBeenCalled() + }) + + it('should show error message when copying fails', async () => { + Object.assign(navigator, { clipboard: { writeText: jest.fn().mockRejectedValueOnce() } }) + + await copyConversationLinkToClipboard('TOKEN', '123') + + expect(navigator.clipboard.writeText).toHaveBeenCalledWith('http://localhost/nc-webroot/call/TOKEN#message_123') + expect(showError).toHaveBeenCalled() + }) + }) +}) diff --git a/src/utils/__tests__/readableNumber.spec.js b/src/utils/__tests__/readableNumber.spec.js new file mode 100644 index 000000000..e412a317b --- /dev/null +++ b/src/utils/__tests__/readableNumber.spec.js @@ -0,0 +1,61 @@ +import { readableNumber, stringChop } from '../readableNumber.ts' + +describe('readableNumber', () => { + describe('stringChop', () => { + it('should return the correct array of numbers', () => { + const numbers = { + 1: { number: '123456789', size: 3 }, + 2: { number: '12345678', size: 3 }, + 3: { number: '1234567', size: 3 }, + 4: { number: '123456', size: 2 }, + 5: { number: '123456', size: 1 }, + 6: { number: '123456', size: 0 }, + 7: { number: '123456', size: 6 }, + 8: { number: '123456', size: 7 }, + 9: { number: '', size: 3 }, + } + + const outputTypes = { + 1: ['123', '456', '789'], + 2: ['123', '456', '78'], + 3: ['123', '456', '7'], + 4: ['12', '34', '56'], + 5: ['1', '2', '3', '4', '5', '6'], + 6: ['123456'], + 7: ['123456'], + 8: ['123456'], + 9: [''], + } + + for (const i in numbers) { + const output = i + ': ' + stringChop(numbers[i].number, numbers[i].size) + expect(output).toBe(i + ': ' + outputTypes[i]) + } + }) + }) + + describe('readableNumber', () => { + it('should return the correct readable number', () => { + const numbers = { + 1: 123456789, + 2: '123456789', + 3: '12345678', + 4: '1234567', + 5: '', + } + + const outputTypes = { + 1: '123 456 789', + 2: '123 456 789', + 3: '123 456 78', + 4: '123 4567', + 5: '', + } + + for (const i in numbers) { |