cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.98k stars 3.18k forks source link

Cypress cannot show the useTranslation string correctly #30363

Open angie-wei opened 3 weeks ago

angie-wei commented 3 weeks ago

Current behavior

The code uses the react-intl package for text translation, but it displays the label name instead of the defined translation string.

image

Desired behavior

expect

Test code to reproduce

video_text.tsx

import React from 'react';
import { useTranslation as t } from '@utils/hooks';

export default function App() {
  const MORE_VIDEOS = t('label_more_videos');
  return (
    <div className='App'>
      <p data-test-id='more-video-title'>{MORE_VIDEOS}</p>
    </div>
  );
}

useTranslation.ts

import { useIntl } from 'react-intl';

const useTranslation = (
  id: string,
  values?: Record<string, string | number>
): string => {
  const { formatMessage } = useIntl();

  return formatMessage({ id }, values);
};

export default useTranslation;

locale/en.ts

const generic = {
  label_more_videos: 'More Videos',
  label_now_playing: 'Now Playing',
}

Cypress Version

13.6.0

Node version

v18.18.0

Operating System

Windows 11

Debug Logs

Use Cypress will show the below error, but the regular browser will show the translation normally.

Error: [@formatjs/intl Error MISSING_TRANSLATION] Missing message: "label_more_videos" for locale "en", using id as fallback. 

    at new MissingTranslationError (error.js:76:1)
    at formatMessage (message.js:65:1)
    at formatMessage (provider.js:46:18)
    at useTranslation (useTranslation.ts:9:10)
    at VideoCarousel (VideoCarousel.tsx:45:24)
    at renderWithHooks (react-dom.development.js:16305:1)
    at updateFunctionComponent (react-dom.development.js:19588:1)
    at updateSimpleMemoComponent (react-dom.development.js:19425:1)
    at beginWork (react-dom.development.js:21678:1)
    at beginWork$1 (react-dom.development.js:27426:1)

Other

No response

angie-wei commented 3 days ago

I encountered an issue where translation is not working under Cypress; the text checks will fail the test.

video.cy.tsx

import { IntlProvider } from 'react-intl';
import VideoPropsBuilder from '../../cypress/support/builders/ComponentProps/VideoProps';

describe('Video Component Tests', () => {
  it('Displays the "More Videos" section title', () => {
    const props = new VideoPropsBuilder()
      .setVideoArray(uploadedVideos)
      .setBackground('transparent')
      .setIsCompact(false)
      .getProps();

    cy.mount(
      <IntlProvider locale="en" defaultLocale="en">
        <Video {...props} />
      </IntlProvider>
    );

    cy.getByDataID(selectors.moreVideoTitle).should(
      'have.text',
      'More Videos'
    );
  });
}
angie-wei commented 3 days ago

If anyone has time, below is the CodeSandbox link to my demo project. I’d appreciate any advice or discussion.

https://codesandbox.io/p/sandbox/ykvrf7

I'm trying to create an online project to reproduce the issue, but even using the simple useIntl() function from react-intl is causing an error.

/utils/hooks/useTranslation.ts:7:36
const { formatMessage } = useIntl();
                                 ^
[React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.

This error never appears in my local environment, and I haven’t found any solution so far, other than trying to wrap the entire app with <IntlProvider>, but that still doesn’t resolve the issue for me.