Skip to content

Commit 45a782b

Browse files
authored
fix: translated button loading crash (#5896)
1 parent 360a417 commit 45a782b

8 files changed

Lines changed: 69 additions & 41 deletions

File tree

packages/shared/src/components/Feed.spec.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,15 +1172,14 @@ describe('Feed logged in', () => {
11721172
'Off-topic or wrong tags',
11731173
);
11741174
fireEvent.click(irrelevantTagsBtn);
1175-
const submitBtn = await screen.findByText('Submit report');
1175+
const submitBtn = await screen.findByRole('button', {
1176+
name: 'Submit report',
1177+
});
11761178
expect(submitBtn).toBeDisabled();
1177-
const javascriptElements = await screen.findAllByText('#javascript');
1178-
const javascriptBtn = javascriptElements.find(
1179-
(item) => item.tagName === 'BUTTON',
1180-
);
1181-
fireEvent.click(
1182-
getRequiredValue(javascriptBtn, 'Expected javascript report tag button'),
1183-
);
1179+
const javascriptBtn = await screen.findByRole('button', {
1180+
name: '#javascript',
1181+
});
1182+
fireEvent.click(javascriptBtn);
11841183
expect(submitBtn).toBeEnabled();
11851184
fireEvent.click(submitBtn);
11861185

@@ -1211,14 +1210,13 @@ describe('Feed logged in', () => {
12111210
'Off-topic or wrong tags',
12121211
);
12131212
fireEvent.click(irrelevantTagsBtn);
1214-
const submitBtn = await screen.findByText('Submit report');
1215-
const javascriptElements = await screen.findAllByText('#javascript');
1216-
const javascriptBtn = javascriptElements.find(
1217-
(item) => item.tagName === 'BUTTON',
1218-
);
1219-
fireEvent.click(
1220-
getRequiredValue(javascriptBtn, 'Expected javascript report tag button'),
1221-
);
1213+
const submitBtn = await screen.findByRole('button', {
1214+
name: 'Submit report',
1215+
});
1216+
const javascriptBtn = await screen.findByRole('button', {
1217+
name: '#javascript',
1218+
});
1219+
fireEvent.click(javascriptBtn);
12221220
expect(submitBtn).toBeEnabled();
12231221

12241222
const brokenLinkBtn = await screen.findByText('Broken link');

packages/shared/src/components/buttons/Button.spec.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,28 @@ describe('Button', () => {
119119
expect(await screen.findByTestId('buttonLoader')).toBeInTheDocument();
120120
});
121121

122+
it('keeps the same label wrapper when toggling loading', () => {
123+
const { rerender } = render(
124+
<Button variant={ButtonVariant.Primary}>Button</Button>,
125+
);
126+
127+
const initialLabel = screen.getByRole('button').querySelector('.btn-label');
128+
129+
expect(initialLabel).toBeInTheDocument();
130+
expect(initialLabel).not.toHaveClass('invisible');
131+
132+
rerender(
133+
<Button variant={ButtonVariant.Primary} loading>
134+
Button
135+
</Button>,
136+
);
137+
138+
const loadingLabel = screen.getByRole('button').querySelector('.btn-label');
139+
140+
expect(loadingLabel).toBe(initialLabel);
141+
expect(loadingLabel).toHaveClass('invisible');
142+
});
143+
122144
it('should set aria-pressed when pressed is true', async () => {
123145
renderComponent({ children: 'Button', pressed: true });
124146
expect(await screen.findByRole('button')).toHaveAttribute(

packages/shared/src/components/buttons/Button.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ function ButtonComponent<TagName extends AllowedTags>(
8383
}: ButtonProps<TagName>,
8484
ref?: Ref<ButtonElementType<TagName>>,
8585
): ReactElement {
86-
const iconOnly = icon && isNullOrUndefined(children);
86+
const hasChildren = !isNullOrUndefined(children);
87+
const iconOnly = icon && !hasChildren;
8788
const getIconWithSize = useGetIconWithSize(
8889
size,
8990
iconOnly ?? false,
@@ -126,7 +127,11 @@ function ButtonComponent<TagName extends AllowedTags>(
126127
iconPosition,
127128
) &&
128129
getIconWithSize(icon, iconSecondaryOnHover ? isHovering : false)}
129-
{loading ? <span className="invisible">{children}</span> : children}
130+
{hasChildren && (
131+
<span className={classNames('btn-label', loading && 'invisible')}>
132+
{children}
133+
</span>
134+
)}
130135
{icon &&
131136
iconPosition === ButtonIconPosition.Right &&
132137
getIconWithSize(icon, iconSecondaryOnHover ? isHovering : false)}

packages/shared/src/components/modals/user/CookieConsentModal.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ export const CookieConsentModal = ({
3232
}: CookieConsentModalProps): ReactElement => {
3333
const { onRequestClose } = modalProps;
3434

35-
const onAcceptPreferences = (e: React.FormEvent) => {
36-
e.preventDefault();
37-
// get the form
38-
const formData = new FormData((e.target as HTMLInputElement).form);
35+
const submitAcceptedPreferences = (form: HTMLFormElement) => {
36+
const formData = new FormData(form);
3937
const formProps = Object.fromEntries(formData);
4038
const keys = Object.keys(formProps);
4139
const acceptedConsents = keys.filter(
@@ -47,6 +45,11 @@ export const CookieConsentModal = ({
4745
(option) => !acceptedConsents.includes(option),
4846
);
4947
onAcceptCookies(acceptedConsents, rejectedConsents);
48+
};
49+
50+
const onAcceptPreferences = (e: React.FormEvent<HTMLFormElement>) => {
51+
e.preventDefault();
52+
submitAcceptedPreferences(e.currentTarget);
5053

5154
onRequestClose(null);
5255
};
@@ -61,6 +64,17 @@ export const CookieConsentModal = ({
6164
onRequestClose(e);
6265
};
6366

67+
const onSavePreferences = (e: React.MouseEvent<HTMLButtonElement>) => {
68+
const { form } = e.currentTarget;
69+
70+
if (!form) {
71+
throw new Error('Cookie consent form is missing');
72+
}
73+
74+
submitAcceptedPreferences(form);
75+
onRequestClose(e);
76+
};
77+
6478
return (
6579
<Modal
6680
{...modalProps}
@@ -120,7 +134,7 @@ export const CookieConsentModal = ({
120134
<Button
121135
variant={ButtonVariant.Primary}
122136
size={ButtonSize.Small}
123-
onClick={onAcceptPreferences}
137+
onClick={onSavePreferences}
124138
form="consent_form"
125139
className="ml-auto"
126140
type="submit"

packages/shared/src/components/widgets/BestDiscussions.spec.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ it('should show number comments', async () => {
4545

4646
it('should set feeling lucky link to the first post', async () => {
4747
renderComponent();
48-
const el = await screen.findByText(`I'm feeling lucky`);
49-
// eslint-disable-next-line testing-library/no-node-access
48+
const el = await screen.findByRole('link', { name: `I'm feeling lucky` });
5049
expect(el).toHaveAttribute('href', defaultPosts[0].commentsPermalink);
5150
});

packages/shared/src/features/onboarding/steps/FunnelPricing/FunnelPricingV2.spec.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -240,18 +240,8 @@ const renderComponent = (props = {}, initialState: InitialState = {}) => {
240240
describe('FunnelPricingV2', () => {
241241
let dateMock: DateMock;
242242
const initialDate = new Date('2023-01-01T00:00:00Z');
243-
const getProceedButton = (): HTMLElement => {
244-
const proceedButton = screen
245-
.getAllByText('Get my plan')
246-
.filter((button) => button.tagName === 'BUTTON')
247-
.at(0);
248-
249-
if (!proceedButton) {
250-
throw new Error('Expected pricing CTA button');
251-
}
252-
253-
return proceedButton;
254-
};
243+
const getProceedButton = (): HTMLElement =>
244+
screen.getAllByRole('button', { name: 'Get my plan' })[0];
255245

256246
const getMonthlyPlanRadio = (): HTMLElement => {
257247
const monthlyPlan = screen

packages/webapp/__tests__/PostPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,8 @@ describe('downvote flow', () => {
899899

900900
it('should prevent user to click block if no tags are selected', async () => {
901901
await prepareDownvote();
902-
const block = await screen.findByText<HTMLButtonElement>('Block');
903-
expect(block?.disabled).toBe(true);
902+
const block = await screen.findByRole('button', { name: 'Block' });
903+
expect(block.disabled).toBe(true);
904904
});
905905

906906
it('should display the option to never see the selection again if close panel', async () => {

packages/webapp/components/banner/CookieBanner.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('CookieBanner outside GDPR', () => {
5555
it('should render just a single button to accept all when outside GDPR coverage', async () => {
5656
renderComponent();
5757
await nextTick();
58-
const el = await screen.findByText('I understand');
58+
const el = await screen.findByRole('button', { name: 'I understand' });
5959
expect(el.tagName).toBe('BUTTON');
6060
});
6161

@@ -83,7 +83,7 @@ describe('CookieBanner outside GDPR', () => {
8383
renderComponent();
8484

8585
await screen.findByTestId('cookie_content');
86-
const button = await screen.findByText('I understand');
86+
const button = await screen.findByRole('button', { name: 'I understand' });
8787
await act(() => fireEvent.click(button));
8888
await nextTick();
8989
const cookies = getCookies([GdprConsentKey.Necessary]);

0 commit comments

Comments
 (0)