/* * Wire * Copyright (C) 2022 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import {act, fireEvent, render, waitFor} from '@testing-library/react'; import {InputBar} from 'Components/InputBar/index'; import {withTheme} from 'src/script/auth/util/test/TestUtil'; import {Config} from 'src/script/Config'; import {PropertiesService} from 'src/script/properties/PropertiesService'; import {SelfService} from 'src/script/self/SelfService'; import {createUuid} from 'Util/uuid'; import {TestFactory} from '../../../../test/helper/TestFactory'; import {AssetRepository} from '../../assets/AssetRepository'; import {ConversationRepository} from '../../conversation/ConversationRepository'; import {MessageRepository} from '../../conversation/MessageRepository'; import {Conversation} from '../../entity/Conversation'; import {User} from '../../entity/User'; import {EventRepository} from '../../event/EventRepository'; import {PropertiesRepository} from '../../properties/PropertiesRepository'; import {SearchRepository} from '../../search/SearchRepository'; import {StorageRepository} from '../../storage'; import {TeamState} from '../../team/TeamState'; const testFactory = new TestFactory(); let eventRepository: EventRepository; let searchRepository: SearchRepository; let storageRepository: StorageRepository; beforeAll(async () => { await testFactory.exposeEventActors().then(factory => { eventRepository = factory; return eventRepository; }); await testFactory.exposeSearchActors().then(factory => { searchRepository = factory; return searchRepository; }); await testFactory.exposeStorageActors().then(factory => { storageRepository = factory; return storageRepository; }); spyOn(Config, 'getConfig').and.returnValue({ ALLOWED_IMAGE_TYPES: [], FEATURE: {ALLOWED_FILE_UPLOAD_EXTENSIONS: ['*']}, }); }); describe('InputBar', () => { let propertiesRepository: PropertiesRepository; const getDefaultProps = () => ({ assetRepository: new AssetRepository(), conversation: new Conversation(createUuid()), conversationRepository: { sendTypingStart: jest.fn(), sendTypingStop: jest.fn(), } as unknown as ConversationRepository, eventRepository, messageRepository: {} as MessageRepository, openGiphy: jest.fn(), propertiesRepository, searchRepository, storageRepository, teamState: new TeamState(), selfUser: new User('id'), onShiftTab: jest.fn(), uploadDroppedFiles: jest.fn(), uploadImages: jest.fn(), uploadFiles: jest.fn(), }); beforeEach(() => { const propertiesService = new PropertiesService(); const selfService = new SelfService(); propertiesRepository = new PropertiesRepository(propertiesService, selfService); }); afterEach(() => { jest.clearAllMocks(); }); const testMessage = 'text'; const pngFile = new File(['(⌐□_□)'], 'wire-example-image.png', {type: 'image/png'}); it('has passed value', async () => { const props = getDefaultProps(); const {getByTestId} = render(withTheme()); await new Promise(resolve => setTimeout(resolve)); const inputBar = getByTestId('input-message'); expect(inputBar).not.toBeNull(); await act(async () => { fireEvent.input(inputBar, {data: testMessage}); }); expect(inputBar.textContent).toBe(testMessage); }); it.skip('typing request is sent if the typing indicator mode is enabled and user is typing', async () => { const props = getDefaultProps(); const {getByTestId, container} = render(withTheme()); const inputBar = getByTestId('input-message'); fireEvent.keyDown(container, {key: 'Enter', code: 'Enter'}); act(() => { fireEvent.input(inputBar, {data: testMessage}); fireEvent.keyPress(inputBar, {key: 'Enter', code: 'Enter'}); }); await waitFor(() => { expect(inputBar.textContent).toBe(testMessage); }); const property = PropertiesRepository.CONFIG.WIRE_TYPING_INDICATOR_MODE; const defaultValue = property.defaultValue; expect(propertiesRepository.typingIndicatorMode()).toBe(defaultValue); expect(props.conversationRepository.sendTypingStart).toHaveBeenCalledTimes(1); }); it('typing request is not sent when user is typing but the typing indicator mode is disabled', async () => { const props = getDefaultProps(); const {getByTestId} = render(withTheme()); const inputBar = getByTestId('input-message'); const property = PropertiesRepository.CONFIG.WIRE_TYPING_INDICATOR_MODE; const defaultValue = property.defaultValue; act(() => { propertiesRepository.setProperty(property.key, !defaultValue); }); expect(propertiesRepository.typingIndicatorMode()).not.toBe(defaultValue); await new Promise(resolve => setTimeout(resolve)); await act(async () => { fireEvent.input(inputBar, {data: testMessage}); }); await waitFor(() => { expect(inputBar.textContent).toBe(testMessage); }); expect(props.conversationRepository.sendTypingStart).not.toHaveBeenCalled(); expect(props.conversationRepository.sendTypingStop).not.toHaveBeenCalled(); }); it('has pasted image', async () => { const promise = Promise.resolve(); const props = getDefaultProps(); const {getByTestId, queryByTestId} = render(withTheme()); await promise; const textArea = getByTestId('input-message'); expect(textArea).not.toBeNull(); expect(queryByTestId('pasted-file-controls')).toBeNull(); fireEvent.paste(document, { clipboardData: { files: [pngFile], types: ['image/png'], }, }); await waitFor(() => { const pastedFileControls = getByTestId('pasted-file-controls'); expect(pastedFileControls).toBeDefined(); }); }); });