-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create reusable plugin (#3706)
- Loading branch information
1 parent
be41e57
commit c0db0f6
Showing
21 changed files
with
581 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import React, { useState } from 'react' | ||
import type { | ||
RichTextEditorProps, | ||
UploadedImage, | ||
} from '@toptal/picasso-rich-text-editor' | ||
import { ImagePlugin, RichTextEditor } from '@toptal/picasso-rich-text-editor' | ||
import { Container } from '@toptal/picasso' | ||
|
||
const editorTestId = 'editor' | ||
const imageUploadButtonTestId = 'image-upload-button' | ||
const resultContainerTestId = 'result-container' | ||
|
||
const defaultProps = { | ||
id: 'foo', | ||
onChange: () => {}, | ||
placeholder: 'placeholder', | ||
testIds: { | ||
editor: editorTestId, | ||
imageUploadButton: imageUploadButtonTestId, | ||
}, | ||
} | ||
|
||
const editorSelector = `#${defaultProps.id}` | ||
|
||
const Editor = (props: RichTextEditorProps) => { | ||
const [value, setValue] = useState('') | ||
|
||
return ( | ||
<Container style={{ maxWidth: '600px' }} padded='small'> | ||
<RichTextEditor {...props} onChange={value => setValue(value)} /> | ||
<Container padded='small' data-testid={resultContainerTestId}> | ||
{value} | ||
</Container> | ||
</Container> | ||
) | ||
} | ||
|
||
const component = 'RichTextEditor' | ||
|
||
const setAliases = () => { | ||
cy.get(editorSelector).as('editor') | ||
cy.getByTestId(imageUploadButtonTestId).as('imageUploadButton') | ||
cy.getByTestId(resultContainerTestId).as('resultContainer') | ||
cy.contains('placeholder').as('placeholder') | ||
} | ||
|
||
const getSubmitButton = () => | ||
cy.get('button').contains('Confirm').closest('button') | ||
|
||
describe('ImagePlugin', () => { | ||
describe('when image upload is successful', () => { | ||
it('inserts image into rich text editor', () => { | ||
const uploadedFileName = 'uploaded-image.png' | ||
const uploadedFileContent = | ||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAANklEQVR42u3OMQ0AAAgDsM2/aFBBwtEqaJOZPFZBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQcEbC6LIT9nCVOrVAAAAAElFTkSuQmCC' | ||
const uploadedFileAltText = 'alt text' | ||
|
||
cy.mount( | ||
<Editor | ||
{...{ | ||
...defaultProps, | ||
plugins: [ | ||
<ImagePlugin | ||
data-testid={imageUploadButtonTestId} | ||
onUpload={(file: UploadedImage) => | ||
new Promise<UploadedImage>(resolve => { | ||
setTimeout( | ||
() => | ||
resolve({ | ||
...file, | ||
url: uploadedFileContent, | ||
}), | ||
200 | ||
) | ||
}) | ||
} | ||
/>, | ||
], | ||
}} | ||
/> | ||
) | ||
setAliases() | ||
|
||
cy.get('@editor').click() | ||
cy.get('@imageUploadButton').click() | ||
|
||
cy.getByRole('dialog').contains('No file chosen') | ||
|
||
getSubmitButton().should('be.disabled') | ||
|
||
cy.get('input[type=file]').selectFile( | ||
{ | ||
contents: Cypress.Buffer.from(''), | ||
fileName: uploadedFileName, | ||
}, | ||
{ force: true } | ||
) | ||
|
||
cy.getByRole('dialog').contains('Uploading ' + uploadedFileName) | ||
cy.getByRole('dialog').contains(uploadedFileName) | ||
cy.get('[placeholder="An Image Description"]').type(uploadedFileAltText) | ||
|
||
getSubmitButton().should('not.be.disabled') | ||
getSubmitButton().click() | ||
|
||
cy.get('@resultContainer').contains( | ||
`<p><img src="${uploadedFileContent}" alt="${uploadedFileAltText}"></p>` | ||
) | ||
|
||
cy.get('body').happoScreenshot({ | ||
component, | ||
variant: 'image-plugin/successful-upload', | ||
}) | ||
}) | ||
}) | ||
|
||
describe('when image upload fails', () => { | ||
it('shows error', () => { | ||
const fileUploadErrorMessage = 'Upload failed' | ||
|
||
cy.mount( | ||
<Editor | ||
{...{ | ||
...defaultProps, | ||
plugins: [ | ||
<ImagePlugin | ||
data-testid={imageUploadButtonTestId} | ||
onUpload={() => | ||
new Promise<UploadedImage>((resolve, reject) => { | ||
setTimeout(() => reject(fileUploadErrorMessage), 200) | ||
}) | ||
} | ||
/>, | ||
], | ||
}} | ||
/> | ||
) | ||
setAliases() | ||
|
||
cy.get('@editor').click() | ||
cy.get('@imageUploadButton').click() | ||
|
||
cy.get('input[type=file]').selectFile( | ||
{ | ||
contents: Cypress.Buffer.from('file contents'), | ||
fileName: 'test.png', | ||
}, | ||
{ force: true } | ||
) | ||
|
||
cy.get('p').contains(fileUploadErrorMessage) | ||
|
||
cy.get('body').happoScreenshot({ | ||
component, | ||
variant: 'image-plugin/failed-upload', | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
packages/picasso-rich-text-editor/src/RichTextEditor/story/ImageUpload.example.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import React, { useState } from 'react' | ||
import { Container, Radio } from '@toptal/picasso' | ||
import type { UploadedImage } from '@toptal/picasso-rich-text-editor' | ||
import { ImagePlugin, RichTextEditor } from '@toptal/picasso-rich-text-editor' | ||
|
||
import type { RichTextEditorChangeHandler } from '../types' | ||
|
||
// Imitate file upload function that sets image URL | ||
const onUploadSucceeded = (uploadedImage: UploadedImage) => | ||
new Promise<UploadedImage>(resolve => { | ||
setTimeout(() => { | ||
const fileUrl = `./jacqueline/128x128.jpg?originalFileName=${encodeURIComponent( | ||
uploadedImage.file.name | ||
)}` | ||
|
||
resolve({ ...uploadedImage, url: fileUrl }) | ||
}, 2000) | ||
}) | ||
|
||
// Imitate failure during upload | ||
const onUploadFailed = () => | ||
new Promise<UploadedImage>((resolve, reject) => { | ||
setTimeout(() => { | ||
reject('Upload failed') | ||
}, 2000) | ||
}) | ||
|
||
const Example = () => { | ||
const [value, setValue] = useState<string | undefined>() | ||
const [useSuccessfulUpload, setUseSuccessfullUpload] = useState('true') | ||
|
||
const handleChange: RichTextEditorChangeHandler = newValue => | ||
setValue(newValue) | ||
|
||
return ( | ||
<> | ||
<Container bottom='medium'> | ||
<Radio.Group | ||
name='onUploadCase' | ||
onChange={(event: React.ChangeEvent<{ value: string }>) => { | ||
setUseSuccessfullUpload(event.target.value) | ||
}} | ||
value={useSuccessfulUpload} | ||
> | ||
<Radio label='Simulate successful upload' value='true' /> | ||
<Radio label='Simulate failing upload' value='false' /> | ||
</Radio.Group> | ||
</Container> | ||
<RichTextEditor | ||
id='editor' | ||
onChange={handleChange} | ||
placeholder='Write some cool rich text' | ||
plugins={[ | ||
<ImagePlugin | ||
onUpload={ | ||
useSuccessfulUpload === 'true' | ||
? onUploadSucceeded | ||
: onUploadFailed | ||
} | ||
/>, | ||
]} | ||
/> | ||
<Container | ||
padded='small' | ||
top='large' | ||
style={{ | ||
fontFamily: "Consolas, 'Courier New', monospace", | ||
background: 'lightyellow', | ||
}} | ||
> | ||
{value} | ||
</Container> | ||
</> | ||
) | ||
} | ||
|
||
export default Example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 24 additions & 36 deletions
60
packages/picasso-rich-text-editor/src/plugins/ImagePlugin/ImagePlugin.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.