Skip to content

Commit

Permalink
feat(post-input): create and add new post input component with media …
Browse files Browse the repository at this point in the history
…selection functionality (#2238)
  • Loading branch information
domw30 authored Sep 5, 2024
1 parent c0ceae3 commit 829e305
Show file tree
Hide file tree
Showing 8 changed files with 485 additions and 181 deletions.
104 changes: 0 additions & 104 deletions src/components/messenger/feed/components/create-post/index.tsx

This file was deleted.

This file was deleted.

61 changes: 61 additions & 0 deletions src/components/messenger/feed/components/post-input/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { RefObject } from 'react';

import { RootState } from '../../../../../store/reducer';
import { connectContainer } from '../../../../../store/redux-container';
import { AuthenticationState } from '../../../../../store/authentication/types';

import { PostInput } from '.';

// should move this to a shared location
import { Media } from '../../../../message-input/utils';

export interface PublicProperties {
id?: string;
initialValue?: string;
isSubmitting?: boolean;

onSubmit: (message: string, media: Media[]) => void;
onPostInputRendered?: (textareaRef: RefObject<HTMLTextAreaElement>) => void;
}

export interface Properties extends PublicProperties {
user: AuthenticationState['user'];
}

export class Container extends React.Component<Properties> {
static mapState(state: RootState): Partial<Properties> {
const {
authentication: { user },
} = state;

return { user };
}

static mapActions(_props: Properties): Partial<Properties> {
return {};
}

onPostInputRendered = (textareaRef: RefObject<HTMLTextAreaElement>) => {
const activeConversationId = this.props.id;
if (textareaRef && textareaRef.current) {
if ((activeConversationId && activeConversationId === textareaRef.current.id) || !activeConversationId) {
textareaRef.current.focus();
}
}
};

render() {
return (
<PostInput
id={this.props.id}
initialValue={this.props.initialValue}
isSubmitting={this.props.isSubmitting}
onSubmit={this.props.onSubmit}
onPostInputRendered={this.onPostInputRendered}
avatarUrl={this.props.user.data?.profileSummary.profileImage}
/>
);
}
}

export const PostInputContainer = connectContainer<PublicProperties>(Container);
104 changes: 104 additions & 0 deletions src/components/messenger/feed/components/post-input/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react';
import { shallow } from 'enzyme';
import { PostInput, Properties } from '.';
import { Key } from '../../../../../lib/keyboard-search';
import Dropzone from 'react-dropzone';
import { config } from '../../../../../config';
import { Button } from '@zero-tech/zui/components';

describe('PostInput', () => {
const subject = (props: Partial<Properties>, child: any = <div />) => {
const allProps: Properties = {
onSubmit: () => undefined,
onPostInputRendered: () => undefined,
clipboard: {
addPasteListener: (_) => {},
removePasteListener: (_) => {},
},
...props,
};

return shallow(<PostInput {...allProps}>{child}</PostInput>);
};

it('does not submit post when post state is empty', () => {
const onSubmit = jest.fn();
const wrapper = subject({ onSubmit });
const dropzone = wrapper.find(Dropzone).shallow();

const textarea = dropzone.find('textarea');
textarea.simulate('keydown', { preventDefault() {}, key: Key.Enter, shiftKey: false });

expect(onSubmit).not.toHaveBeenCalled();
});

it('submits post when Enter is pressed', () => {
const onSubmit = jest.fn();
const wrapper = subject({ onSubmit });
const dropzone = wrapper.find(Dropzone).shallow();

const textarea = dropzone.find('textarea');
textarea.simulate('change', { target: { value: 'Hello' } });
textarea.simulate('keydown', { preventDefault() {}, key: Key.Enter, shiftKey: false });

expect(onSubmit).toHaveBeenCalledTimes(1);
expect(onSubmit).toHaveBeenCalledWith('Hello', []);
});

it('submits post when Enter is pressed and images have been added', () => {
const onSubmit = jest.fn();
const dropzoneToMedia = (files) => files;
const wrapper = subject({ onSubmit, dropzoneToMedia });
const dropzone = wrapper.find(Dropzone).shallow();

const textarea = dropzone.find('textarea');
wrapper.find(Dropzone).simulate('drop', [{ name: 'image1' }]);
textarea.simulate('keydown', { preventDefault() {}, key: Key.Enter, shiftKey: false });

expect(onSubmit).toHaveBeenCalledTimes(1);
expect(onSubmit).toHaveBeenCalledWith('', [{ name: 'image1' }]);
});

it('submits post when submit button is clicked', () => {
const onSubmit = jest.fn();
const wrapper = subject({ onSubmit });
const dropzone = wrapper.find(Dropzone).shallow();

dropzone.find('textarea').simulate('change', { target: { value: 'Hello' } });
dropzone.find(Button).simulate('press');

expect(onSubmit).toHaveBeenCalledTimes(1);
expect(onSubmit).toHaveBeenCalledWith('Hello', []);
});

it('submits post when submit button is clicked and images have been added', () => {
const onSubmit = jest.fn();
const dropzoneToMedia = (files) => files;
const wrapper = subject({ onSubmit, dropzoneToMedia });
const dropzone = wrapper.find(Dropzone).shallow();

wrapper.find(Dropzone).simulate('drop', [{ name: 'image1' }]);
dropzone.find(Button).simulate('press');

expect(onSubmit).toHaveBeenCalledTimes(1);
expect(onSubmit).toHaveBeenCalledWith('', [{ name: 'image1' }]);
});

it('renders Dropzone with correct mime types and max size', () => {
const wrapper = subject({});
const dropZone = wrapper.find(Dropzone);

expect(dropZone.prop('accept')).toEqual({ 'image/*': [] });
expect(dropZone.prop('maxSize')).toEqual(config.cloudinary.max_file_size);
});

it('call after render', () => {
const onPostInputRendered = jest.fn();

subject({ onPostInputRendered });

expect(onPostInputRendered).toHaveBeenCalledWith({
current: null,
});
});
});
Loading

0 comments on commit 829e305

Please sign in to comment.