import React from 'react';
import Chatbox from './chatbox';
import {
createClient,
mockClient,
mockRegisterRequest,
mockInitCrypto,
mockStartClient,
mockSetPowerLevel,
mockCreateRoom,
mockLeave,
mockDeactivateAccount,
mockStopClient,
mockClearStores,
mockOn,
mockOnce,
mockSendTextMessage,
mockIsCryptoEnabled,
mockIsRoomEncrypted,
} from "matrix-js-sdk";
import { mount, shallow } from 'enzyme';
import { createWaitForElement } from 'enzyme-wait';
import { config } from 'react-transition-group';
import waitForExpect from 'wait-for-expect'
config.disabled = true
var testConfig = {
matrixServerUrl: 'https://matrix.rhok.space',
botId: '@help-bot:rhok.space',
roomName: 'Support Chat',
termsUrl: 'https://tosdr.org/',
introMessage: 'This chat application does not collect any of your personal data or any data from your use of this service.',
agreementMessage: 'Do you want to continue?',
confirmationMessage: 'Waiting for a facilitator to join the chat...',
exitMessage: 'The chat is closed. You may close this window.',
chatUnavailableMessage: 'The chat service is not available right now. Please try again later.',
anonymousDisplayName: 'Anonymous',
}
describe('Chatbox', () => {
beforeEach(() => {
createClient.mockClear()
mockInitCrypto.mockClear()
mockStartClient.mockClear()
mockRegisterRequest.mockClear()
mockSetPowerLevel.mockClear()
mockCreateRoom.mockClear()
mockLeave.mockClear()
mockDeactivateAccount.mockClear()
mockStopClient.mockClear()
mockClearStores.mockClear()
mockOnce.mockClear()
mockOn.mockClear()
mockSendTextMessage.mockClear()
mockIsCryptoEnabled.mockClear()
mockIsRoomEncrypted.mockClear()
})
test('chat window should open and close', async () => {
const chatbox = mount()
let dock = chatbox.find('button.dock')
let chatWindow = chatbox.find('.widget')
expect(dock.length).toEqual(1)
expect(chatWindow.hasClass('widget-exited')).toEqual(true)
// open chat window
dock.simulate('click')
const openChatWindow = await createWaitForElement('.widget-entered')(chatbox)
dock = chatbox.find('button.dock')
expect(openChatWindow.length).toEqual(1)
expect(dock.length).toEqual(0)
// close chat window
const closeButton = chatbox.find('button.widget-header-close')
closeButton.simulate('click')
chatWindow = chatbox.find('.widget')
dock = chatbox.find('button.dock')
expect(dock.length).toEqual(1)
expect(chatWindow.hasClass('widget-exited')).toEqual(true)
})
test('chat window should contain the right messages', () => {
const chatbox = mount()
const props = chatbox.props()
const messages = chatbox.find('.messages')
expect(messages.text()).toContain(props.introMessage)
expect(messages.html()).toContain(props.termsUrl)
expect(messages.text()).toContain(props.agreementMessage)
});
test('agreeing to terms should start encrypted chat', async () => {
const chatbox = mount()
const dock = chatbox.find('button.dock')
dock.simulate('click')
const openChatWindow = await createWaitForElement('.widget-entered')(chatbox)
let acceptButton = await createWaitForElement('button#accept')(chatbox)
acceptButton = chatbox.find('button#accept')
acceptButton.simulate('click')
const ready = await createWaitForElement('.loader')(chatbox)
expect(ready.length).toEqual(1)
expect(createClient).toHaveBeenCalled()
expect(mockInitCrypto).toHaveBeenCalled()
expect(mockStartClient).toHaveBeenCalled()
expect(mockCreateRoom).toHaveBeenCalled()
expect(mockSetPowerLevel).toHaveBeenCalled()
expect(mockOn).toHaveBeenCalled()
})
test('rejecting terms should not start chat', async () => {
const chatbox = mount()
const dock = chatbox.find('button.dock')
dock.simulate('click')
const openChatWindow = await createWaitForElement('.widget-entered')(chatbox)
let rejectButton = await createWaitForElement('button#reject')(chatbox)
rejectButton = chatbox.find('button#reject')
rejectButton.simulate('click')
expect(createClient.mock.calls.length).toEqual(0)
})
test('submitted messages should be sent to matrix', async () => {
const chatbox = mount()
const dock = chatbox.find('button.dock')
dock.simulate('click')
let acceptButton = await createWaitForElement('button#accept')(chatbox)
acceptButton = chatbox.find('button#accept')
acceptButton.simulate('click')
await waitForExpect(() => {
expect(mockCreateRoom).toHaveBeenCalled()
});
const input = chatbox.find('#message-input')
const form = chatbox.find('form')
const message = 'Hello'
input.simulate('change', { target: { value: message }})
await waitForExpect(() => {
chatbox.update()
expect(chatbox.state().inputValue).toEqual(message)
})
form.simulate('submit')
await waitForExpect(() => {
expect(mockSendTextMessage).toHaveBeenCalledWith(chatbox.state().roomId, message)
});
})
test('decryption failure should lead to a new unencrypted chat', async () => {
const chatbox = mount()
const dock = chatbox.find('button.dock')
const instance = chatbox.instance()
dock.simulate('click')
const openChatWindow = await createWaitForElement('.widget-entered')(chatbox)
let acceptButton = await createWaitForElement('button#accept')(chatbox)
acceptButton = chatbox.find('button#accept')
acceptButton.simulate('click')
await waitForExpect(() => {
expect(mockCreateRoom).toHaveBeenCalled()
});
jest.spyOn(instance, 'initializeUnencryptedChat')
instance.handleDecryptionError()
await waitForExpect(() => {
expect(mockLeave).toHaveBeenCalled()
});
await waitForExpect(() => {
expect(mockStopClient).toHaveBeenCalled()
});
await waitForExpect(() => {
expect(mockClearStores).toHaveBeenCalled()
});
expect(instance.initializeUnencryptedChat).toHaveBeenCalled()
})
test('creating an unencrypted chat', async () => {
const chatbox = mount()
const instance = chatbox.instance()
instance.initializeUnencryptedChat()
await waitForExpect(() => {
expect(createClient).toHaveBeenCalled()
})
await waitForExpect(() => {
expect(mockStartClient).toHaveBeenCalled()
})
await waitForExpect(() => {
expect(mockInitCrypto).not.toHaveBeenCalled()
})
})
test('exiting the chat should leave the room and destroy client', async () => {
const chatbox = mount()
const dock = chatbox.find('button.dock')
dock.simulate('click')
const openChatWindow = await createWaitForElement('.widget-entered')(chatbox)
let acceptButton = await createWaitForElement('button#accept')(chatbox)
acceptButton = chatbox.find('button#accept')
acceptButton.simulate('click')
await waitForExpect(() => {
expect(mockCreateRoom).toHaveBeenCalled()
});
const exitButton = chatbox.find('button.widget-header-close')
exitButton.simulate('click')
let closed = await createWaitForElement('button.dock')
expect(closed.length).toEqual(1)
await waitForExpect(() => {
expect(mockLeave).toHaveBeenCalled()
});
await waitForExpect(() => {
expect(mockDeactivateAccount).toHaveBeenCalled()
});
await waitForExpect(() => {
expect(mockStopClient).toHaveBeenCalled()
});
await waitForExpect(() => {
expect(mockClearStores).toHaveBeenCalled()
});
})
test('notification should appear when facilitator joins chat', () => {
//
})
test('received messages should appear in chat window', () => {
//
})
});