Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions semcore/base-components/__tests__/ellipsis.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,22 @@ test.describe(`${TAG.FUNCTIONAL}`, () => {
});
});

test('Verify observe with undefined init value', {
tag: [TAG.PRIORITY_HIGH, '@ellipsis'],
}, async ({ page }) => {
const link = 'https://developer.semrush.com/intergalactic/components/ellipsis/ellipsis';

await loadPage(page, 'stories/components/base-components/ellipsis/tests/examples/async_init.tsx', 'en');

const textElement = locators.link(page);
await expect(textElement).toHaveText('');

await expect(textElement).toHaveText(link, { timeout: 1000 });

await textElement.hover();
await expect(locators.hint(page)).toHaveText(link);
});

test('Verify observe children truncation', {
tag: [TAG.PRIORITY_MEDIUM, TAG.MOUSE, '@ellipsis'],
}, async ({ page }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ class EllipsisManager {
const mutation = mutations[0];
const addedNodes = mutation.addedNodes;
const removedNodes = mutation.removedNodes;
if (addedNodes.length === 1 && addedNodes[0] instanceof Text && removedNodes.length === 2 && removedNodes[0] instanceof HTMLSpanElement && removedNodes[1] instanceof HTMLSpanElement) {

if (removedNodes.length === 0 && addedNodes.length === 1 && addedNodes[0] instanceof Text) {
text = addedNodes[0];
} else if (addedNodes.length === 1 && addedNodes[0] instanceof Text && removedNodes.length === 2 && removedNodes[0] instanceof HTMLSpanElement && removedNodes[1] instanceof HTMLSpanElement) {
text = addedNodes[0];
}
}
Expand Down
69 changes: 69 additions & 0 deletions semcore/side-panel/__tests__/side-panel.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,28 @@ export const locators = {
title: (page: Page) => page.locator('h6[data-ui-name="SidePanel.Title"]'),
back: (page: Page) => page.locator('[data-ui-name="SidePanel.Back"]'),
dialog: (page: Page) => page.getByRole('dialog'),
hint: (page: Page) => page.locator('[data-ui-name="Hint"]'),

};

const collectRuntimeErrors = (page: Page) => {
const errors: string[] = [];

page.on('console', (msg) => {
const text = msg.text();

if (msg.type() === 'error' && !text.includes('ReactDOM.render is no longer supported')) {
errors.push(text);
}
});

page.on('pageerror', (error) => {
errors.push(error.message);
});

return errors;
};

/* =====================================================
@visual
Visual states, hover and focus styles, paddings, margins, and snapshots.
Expand Down Expand Up @@ -411,4 +430,54 @@ test.describe(`${TAG.FUNCTIONAL} `, () => {
await page.getByText('Close').waitFor({ state: 'visible' });
await expect(locators.header(page)).toHaveCSS('flex-shrink', '0');
});

test('Verify SidePanel title appears asynchronously in header', {
tag: [TAG.PRIORITY_HIGH,
TAG.MOUSE,
'@side-panel',
'@ellipsis'],
}, async ({ page }) => {
const asyncTitle = 'My Article Title';
const errors = collectRuntimeErrors(page);

await loadPage(page, 'stories/components/side-panel/tests/examples/async-title-in-header.tsx', 'en');

await page.getByRole('button', { name: 'Show SidePanel with async title' }).click();
const dialog = locators.dialog(page);
const title = dialog.locator('h6[data-ui-name="SidePanel.Title"]');

await dialog.waitFor({ state: 'visible' });
await expect(title).toHaveText('', { timeout: 1000 });

await expect(title).toHaveText(asyncTitle, { timeout: 2000 });

await title.hover();
await expect(locators.hint(page)).toHaveText(asyncTitle);

expect(errors).toEqual([]);
});

test('Verify SidePanel title clears asynchronously in header', {
tag: [TAG.PRIORITY_HIGH,
TAG.MOUSE,
'@side-panel',
'@ellipsis'],
}, async ({ page }) => {
const initialTitle = 'My Article Title';
const errors = collectRuntimeErrors(page);

await loadPage(page, 'stories/components/side-panel/tests/examples/async-title-in-header.tsx', 'en');

await page.getByRole('button', { name: 'Show SidePanel with cleared title' }).click();
const dialog = locators.dialog(page);
const title = dialog.locator('h6[data-ui-name="SidePanel.Title"]');

await dialog.waitFor({ state: 'visible' });
await expect(title).toHaveText(initialTitle, { timeout: 1000 });

await expect(title).toHaveText('', { timeout: 2000 });
await expect(locators.hint(page)).toHaveCount(0);

expect(errors).toEqual([]);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react-vite';

import AdvancedFeaturesDemoExample from './examples/advanced_features_demo';
import AsyncInitExample from './examples/async_init';
import CopyFullTextExample from './examples/copy_full_text';
import TableLinkExample from './examples/in_table_with_link';
import LinkExample, { defaultProps as LinkExampleProps } from './examples/link_with_ellipsis';
Expand Down Expand Up @@ -108,3 +109,7 @@ export const AdvancedFeaturesDemo: StoryObj = {
export const ObserveChildrenMutations: StoryObj = {
render: ObserveChildrenMutationsExample,
};

export const AsyncInit: StoryObj = {
render: AsyncInitExample,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Link from '@semcore/ui/link';
import React from 'react';

const link = 'https://developer.semrush.com/intergalactic/components/ellipsis/ellipsis';

const Demo = () => {
const [linkText, setLinkText] = React.useState('');

React.useEffect(() => {
const t = setTimeout(() => setLinkText(link), 500);
return () => clearTimeout(t);
}, []);

return (
<Link
href={link}
>
<Link.Text
ellipsis:observeChildrenMutations
w={120}
size={200}
>
{linkText}
</Link.Text>
</Link>
);
};

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Button from '@semcore/ui/button';
import SidePanel from '@semcore/ui/side-panel';
import React, { useEffect, useState } from 'react';

const title = 'My Article Title';

type AsyncTitleProps = {
initialTitle: string | null;
title: string | null;
};

function AsyncTitle({ initialTitle, title }: AsyncTitleProps) {
const [text, setText] = useState<string | null>(initialTitle);
const [initialized, setInitialized] = useState(false);

useEffect(() => {
const timeout = window.setTimeout(() => {
setText(title);
setInitialized(true);
}, 500);

return () => window.clearTimeout(timeout);
}, []);

const titleText = initialized ? text ?? '' : initialTitle ?? '';
const titleKey = initialized ? 'text' : 'initText';

return (
<SidePanel.Title key={titleKey} w={80} ellipsis:observeChildrenMutations>
{titleText}
</SidePanel.Title>
);
}

type DemoProps = {
name: string;
title: React.ReactNode;
};

function Demo({ name, title }: DemoProps) {
const [visible, setVisible] = useState(false);

return (
<div>
<Button onClick={() => setVisible(true)}>{name}</Button>
<SidePanel visible={visible} onClose={() => setVisible(false)}>
<SidePanel.Panel>
<SidePanel.Header>
{title}
</SidePanel.Header>
<div style={{ padding: 24 }}>Content</div>
</SidePanel.Panel>
</SidePanel>
</div>
);
}

export function App() {
return (
<>
<Demo
name='Show SidePanel with cleared title'
title={<AsyncTitle initialTitle={title} title={null} />}
/>
<Demo
name='Show SidePanel with async title'
title={<AsyncTitle initialTitle={null} title={title} />}
/>
</>
);
}

export default App;
6 changes: 6 additions & 0 deletions stories/components/side-panel/tests/side-panel.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import SidePanel from '@semcore/ui/side-panel';
import type { Meta, StoryObj } from '@storybook/react-vite';

import AdditionalContentExample from './examples/additional-content-in-header';
import AsyncTitleInHeaderExample from './examples/async-title-in-header';
import type { defaultSidePanelDemoProps } from './examples/side-panel-additional-states';
import AdditionalStatesExample from './examples/side-panel-additional-states';

Expand All @@ -28,3 +29,8 @@ export const AdditionalContent = {
render: AdditionalContentExample,

};

export const AsyncTitleInHeader = {
render: AsyncTitleInHeaderExample,

};
Loading