wix-style-react
Version:
437 lines (349 loc) • 15 kB
JavaScript
import React from 'react';
import { createUniDriverFactory } from 'wix-ui-test-utils/uni-driver-factory';
import eventually from 'wix-eventually';
import RichTextInputArea from '../RichTextInputArea';
import richTextInputAreaPrivateDriverFactory from '../RichTextInputArea.private.uni.driver';
import { createRendererWithUniDriver } from '../../../test/utils/react';
import { scrollBehaviorPolyfill } from '../../../testkit/polyfills';
import { cleanup } from '../../../test/utils/unit';
describe('RichTextInputArea', () => {
afterEach(() => {
cleanup();
});
const createDriver = createUniDriverFactory(
richTextInputAreaPrivateDriverFactory,
);
// Keeps the parsed HTML value on prop change
let currentValue;
beforeAll(() => {
scrollBehaviorPolyfill.install();
});
afterAll(() => {
scrollBehaviorPolyfill.uninstall();
});
describe('Editor', () => {
it('should render the text when `initialValue` prop is plain text', async () => {
const text = 'Some text';
const driver = createDriver(<RichTextInputArea initialValue={text} />);
expect(await driver.exists()).toBe(true);
expect(await driver.getContent()).toBe(text);
});
it('should render the text when `value` prop contains HTML elements', async () => {
const texts = ['Some', 'text'];
const expectedText = texts.join(' ');
const driver = createDriver(
<RichTextInputArea
initialValue={`<p>${texts[0]} <strong>${texts[1]}</strong></p>`}
/>,
);
expect(await driver.exists()).toBe(true);
expect(await driver.getContent()).toBe(expectedText);
});
it('should keep newlines when `initialValue` prop contains empty HTML elements', async () => {
const driver = createDriver(
<RichTextInputArea
initialValue={`<p>hello<br/></br><p></p>world</p>`}
/>,
);
const content = await driver.getContent();
expect(content).toEqual('hello\n\n\nworld');
});
describe('onChange', () => {
it('should invoke with correct params after typing text', async () => {
const callback = jest.fn();
const text = 'Some text';
const expectedHtmlValue = `<p>${text}</p>`;
const driver = createDriver(<RichTextInputArea onChange={callback} />);
await driver.enterText(text);
expect(callback).toHaveBeenCalledWith(expectedHtmlValue, {
plainText: text,
});
});
it('should not invoke with extra line-break', async () => {
const callback = jest.fn();
const text = '\n';
const expectedHtmlValue = `<p>${text}</p>`;
const driver = createDriver(<RichTextInputArea onChange={callback} />);
await driver.enterText(text);
expect(callback).toHaveBeenCalledWith(expectedHtmlValue, {
plainText: text,
});
});
});
it('should render a placeholder', async () => {
const placeholderText = 'Placeholder';
const driver = createDriver(
<RichTextInputArea placeholder={placeholderText} />,
);
expect(await driver.getContent()).toBe('');
expect(await driver.getPlaceholder()).toBe(placeholderText);
});
it('should not render the placeholder after inserting text', async () => {
const expectedText = 'Some text';
const driver = createDriver(
<RichTextInputArea placeholder="Placeholder" />,
);
await driver.enterText(expectedText);
expect(await driver.getContent()).toBe(expectedText);
expect(await driver.hasPlaceholder()).toBe(false);
});
});
it('should render as disabled', async () => {
const driver = createDriver(<RichTextInputArea disabled />);
expect(await driver.isDisabled()).toBe(true);
});
describe('status attribute', () => {
it('should have no status', async () => {
const render = createRendererWithUniDriver(
richTextInputAreaPrivateDriverFactory,
);
const { driver } = render(<RichTextInputArea />);
expect(await driver.hasStatus('error')).toBe(false);
});
it('should not render the status indicator when disabled', async () => {
const driver = createDriver(
<RichTextInputArea disabled status="error" />,
);
expect(await driver.hasStatus()).toBe(false);
});
it.each([
{ status: 'error' },
{ status: 'warning' },
{ status: 'loading' },
])('should display status when %p', async test => {
const render = createRendererWithUniDriver(
richTextInputAreaPrivateDriverFactory,
);
const { driver } = render(<RichTextInputArea {...test} />);
expect(await driver.hasStatus(test.status)).toBe(true);
expect(await driver.getStatusMessage()).toBeNull();
});
it.each([
{ status: 'error', statusMessage: 'Error Message' },
{ status: 'warning', statusMessage: 'Warning Message' },
{ status: 'loading', statusMessage: 'Loading Message' },
])('should display status with message when %p', async test => {
const render = createRendererWithUniDriver(
richTextInputAreaPrivateDriverFactory,
);
const { driver } = render(<RichTextInputArea {...test} />);
expect(await driver.hasStatus(test.status)).toBe(true);
expect(await driver.getStatusMessage()).toBe(test.statusMessage);
});
});
describe('Toolbar', () => {
it('should render all supported buttons', async () => {
const buttons = [
'bold',
'italic',
'underline',
'link',
'unordered-list-item',
'ordered-list-item',
];
const driver = createDriver(<RichTextInputArea />);
expect(await driver.getButtonTypes()).toEqual(buttons);
});
describe('Bold', () => {
const sampleText = 'Bold';
const sampleValue = `<p><strong>${sampleText}</strong></p>`;
it('should render text as bold after clicking the bold button', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
await driver.clickBoldButton();
await driver.enterText(sampleText);
expect(currentValue).toBe(sampleValue);
});
it('should render the bold button as active after clicking the button', async () => {
const driver = createDriver(<RichTextInputArea />);
const button = await driver.getBoldButton();
expect(await driver.isActive(button)).toBe(false);
await driver.clickBoldButton();
expect(await driver.isActive(button)).toBe(true);
});
});
describe('Italic', () => {
const sampleText = 'Italic';
const sampleValue = `<p><em>${sampleText}</em></p>`;
it('should render text as italic after clicking the italic button', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
await driver.clickItalicButton();
await driver.enterText(sampleText);
expect(currentValue).toBe(sampleValue);
});
it('should render the italic button as active after clicking the button', async () => {
const driver = createDriver(<RichTextInputArea />);
const button = await driver.getItalicButton();
expect(await driver.isActive(button)).toBe(false);
await driver.clickItalicButton();
expect(await driver.isActive(button)).toBe(true);
});
});
describe('Underline', () => {
const sampleText = 'Underline';
const sampleValue = `<p><u>${sampleText}</u></p>`;
it('should render text with underline after clicking the underline button', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
await driver.clickUnderlineButton();
await driver.enterText(sampleText);
expect(currentValue).toBe(sampleValue);
});
it('should render the underline button as active after clicking the button', async () => {
const driver = createDriver(<RichTextInputArea />);
const button = await driver.getUnderlineButton();
expect(await driver.isActive(button)).toBe(false);
await driver.clickUnderlineButton();
expect(await driver.isActive(button)).toBe(true);
});
});
describe('Bulleted List', () => {
const sampleText = 'Text';
const sampleValue = `<ul>\n <li>${sampleText}</li>\n</ul>`;
it('should render text as bulleted list after clicking the bulleted list button', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
await driver.clickBulletedListButton();
await driver.enterText(sampleText);
expect(currentValue).toBe(sampleValue);
});
it('should render the bulleted list button as active after clicking the button', async () => {
const driver = createDriver(<RichTextInputArea />);
const button = await driver.getBulletedListButton();
expect(await driver.isActive(button)).toBe(false);
await driver.clickBulletedListButton();
expect(await driver.isActive(button)).toBe(true);
});
});
describe('Numbered List', () => {
const sampleText = 'Text';
const sampleValue = `<ol>\n <li>${sampleText}</li>\n</ol>`;
it('should render text as numbered list after clicking the numbered list button', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
await driver.clickNumberedListButton();
await driver.enterText(sampleText);
expect(currentValue).toBe(sampleValue);
});
it('should render the numbered list button as active after clicking the button', async () => {
const driver = createDriver(<RichTextInputArea />);
const button = await driver.getNumberedListButton();
expect(await driver.isActive(button)).toBe(false);
await driver.clickNumberedListButton();
expect(await driver.isActive(button)).toBe(true);
});
});
describe('Link', () => {
const sampleText = 'Link';
const sampleUrl = 'wix.com';
it('should render text as link without protocol after clicking the button and inserting required data if prependHTTP prop is not provided', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
const sampleValue = `<p><a rel=\"noopener noreferrer\" target=\"_blank\" href=\"${sampleUrl}\">${sampleText}</a></p>`;
await driver.clickLinkButton();
const isFormDisplayed = await driver.isFormDisplayed();
await driver.insertLink(sampleText, sampleUrl);
const linkElement = await driver.getLink(sampleText, sampleUrl);
expect(isFormDisplayed).toBe(true);
expect(currentValue).toBe(sampleValue);
await eventually(async () => {
expect(await driver.isFormDisplayed()).toBe(false);
});
expect(await linkElement.attr('target')).toBe('_blank');
expect(await linkElement.attr('rel')).toContain('noopener noreferrer');
});
it('should render text as link with protocol after clicking the button and inserting required data if prependHTTP prop is provided', async () => {
const driver = createDriver(
<RichTextInputArea
prependHTTP
onChange={value => (currentValue = value)}
/>,
);
const sampleValue = `<p><a rel=\"noopener noreferrer\" target=\"_blank\" href=\"http://${sampleUrl}\">${sampleText}</a></p>`;
await driver.clickLinkButton();
const isFormDisplayed = await driver.isFormDisplayed();
await driver.insertLink(sampleText, sampleUrl);
const linkElement = await driver.getLink(sampleText, sampleUrl);
expect(isFormDisplayed).toBe(true);
expect(currentValue).toBe(sampleValue);
await eventually(async () => {
expect(await driver.isFormDisplayed()).toBe(false);
});
expect(await linkElement.attr('target')).toBe('_blank');
expect(await linkElement.attr('rel')).toContain('noopener noreferrer');
});
it('should render the link button as active after clicking the button', async () => {
const driver = createDriver(<RichTextInputArea />);
const button = await driver.getLinkButton();
expect(await driver.isActive(button)).toBe(false);
await driver.clickLinkButton();
expect(await driver.isActive(button)).toBe(true);
});
it('should render text without link after clicking the button, when the selected text contains a link', async () => {
const driver = createDriver(
<RichTextInputArea onChange={value => (currentValue = value)} />,
);
const sampleValue = `<p>${sampleText}</p>`;
await driver.clickLinkButton();
await driver.insertLink(sampleText, sampleUrl);
await driver.clickLinkButton();
await eventually(async () => {
expect(await driver.isFormDisplayed()).toBe(false);
});
expect(currentValue).toBe(sampleValue);
});
});
it('should disable the confirm button within the insertion form when url is empty', async () => {
const driver = createDriver(<RichTextInputArea />);
await driver.clickLinkButton();
expect(await driver.isFormConfirmButtonDisabled()).toBe(true);
});
it('should hide the insertion form after clicking the cancel button', async () => {
const driver = createDriver(<RichTextInputArea />);
await driver.clickLinkButton();
await driver.clickFormCancelButton();
await eventually(async () => {
expect(await driver.isFormDisplayed()).toBe(false);
});
});
it('should set value to given value', async () => {
const onChange = jest.fn();
let myRef = null;
const driver = createDriver(
<RichTextInputArea
initialValue={'something old'}
ref={ref => {
myRef = ref;
}}
onChange={onChange}
/>,
);
expect(await driver.getContent()).toEqual('something old');
myRef.setValue('something new');
expect(await driver.getContent()).toEqual('something new');
});
it('should set value to empty value', async () => {
const onChange = jest.fn();
let myRef = null;
const driver = createDriver(
<RichTextInputArea
initialValue={'something old'}
ref={ref => {
myRef = ref;
}}
onChange={onChange}
/>,
);
expect(await driver.getContent()).toEqual('something old');
myRef.setValue('');
expect(await driver.getContent()).toEqual('');
});
});
});