diff --git a/.github/workflows/simorgh-e2e-pages.yml b/.github/workflows/simorgh-e2e-pages.yml deleted file mode 100644 index 98f5a54eccb..00000000000 --- a/.github/workflows/simorgh-e2e-pages.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Cypress E2E - Pages -on: - pull_request: - branches: - - '**' -permissions: - contents: read - -jobs: - cypress-run: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [22.x] - env: - CI: true - LOG_LEVEL: 'error' - CYPRESS_SKIP_EU: true - CYPRESS_SMOKE: true - CYPRESS_APP_ENV: 'local' - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Add bbc.com domain - run: sudo echo "127.0.0.1 localhost.bbc.com" | sudo tee -a /etc/hosts - - - name: Install Cypress dependency - run: | - chmod +x ./scripts/installCypress.sh - ./scripts/installCypress.sh - - - name: Install Cypress binary - run: yarn cypress:install - - - name: Run Simorgh E2Es (Pages) - uses: cypress-io/github-action@v6 - with: - install: false - build: yarn build - start: yarn start - command: yarn cypress:pages diff --git a/cypress/e2e/pages/testsForAllAMPPages.js b/cypress/e2e/pages/testsForAllAMPPages.js deleted file mode 100644 index 9af93cdac9f..00000000000 --- a/cypress/e2e/pages/testsForAllAMPPages.js +++ /dev/null @@ -1,31 +0,0 @@ -// For testing features that may differ across services but share a common logic e.g. translated strings. -export default ({ service, pageType }) => { - describe(`testsForAllAMPPages to run for ${service} ${pageType}`, () => { - describe('Header Tests', () => { - // limit number to Zhongwen for navigation toggling - const testMobileNav = service === 'zhongwen'; - if (testMobileNav) { - it('should show dropdown menu and hide scrollable menu when menu button is clicked', () => { - cy.viewport(320, 480); - cy.get('nav') - .find('[data-e2e="scrollable-nav"]') - .should('be.visible'); - - cy.get('nav') - .find('[data-e2e="dropdown-nav"] ul') - .should('not.be.visible'); - - cy.get('nav button').click(); - - cy.get('nav') - .find('[data-e2e="scrollable-nav"]') - .should('not.be.visible'); - - cy.get('nav') - .find('[data-e2e="dropdown-nav"] ul') - .should('be.visible'); - }); - } - }); - }); -}; diff --git a/cypress/e2e/pages/testsForAllCanonicalPages.js b/cypress/e2e/pages/testsForAllCanonicalPages.js deleted file mode 100644 index fd47ff117ea..00000000000 --- a/cypress/e2e/pages/testsForAllCanonicalPages.js +++ /dev/null @@ -1,44 +0,0 @@ -import envConfig from '../../support/config/envs'; - -// For testing features that may differ across services but share a common logic e.g. translated strings. -export default ({ service, pageType }) => { - if (pageType !== 'errorPage404') { - describe(`Running testsForAllCanonicalPages for ${service} ${pageType}`, () => { - if (Cypress.env('SMOKE')) { - describe( - 'ATI', - { - retries: 3, - }, - () => { - it('should have a noscript img tag with the ati url', () => { - cy.hasNoscriptImgAtiUrl(envConfig.atiUrl); - }); - }, - ); - } - }); - } - - describe('Header Tests', () => { - // limit number to Zhongwen for navigation toggling - const testMobileNav = service === 'zhongwen'; - - if (testMobileNav) { - it('should show dropdown menu and hide scrollable menu when menu button is clicked', () => { - cy.viewport(320, 480); - cy.get('nav').find('[data-e2e="scrollable-nav"]').should('be.visible'); - - cy.get('nav') - .find('[data-e2e="dropdown-nav"] ul') - .should('not.be.visible'); - - cy.get('nav button').click(); - - cy.get('nav').find('[data-e2e="scrollable-nav"]').should('not.exist'); - - cy.get('nav').find('[data-e2e="dropdown-nav"] ul').should('be.visible'); - }); - } - }); -}; diff --git a/cypress/e2e/pages/testsForAllPages.js b/cypress/e2e/pages/testsForAllPages.js deleted file mode 100644 index 459b946d684..00000000000 --- a/cypress/e2e/pages/testsForAllPages.js +++ /dev/null @@ -1,73 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -/* eslint-disable cypress/no-unnecessary-waiting */ - -// For testing important features that differ between services, e.g. Timestamps. -// We recommend using inline conditional logic to limit tests to services which differ. -import topicTagsTest from '../../support/helpers/topicTagsTest'; -import checkA11y from '../../support/helpers/checkA11y'; - -export default ({ service, variant, pageType }) => { - describe(`testForAllPages to run for ${service} ${pageType}`, () => { - it('should have no detectable a11y violations on page load', () => { - checkA11y(); - }); - - it('should render topic tags if they are in the json, and they should navigate to correct topic page', () => { - // topicTagsTest(service, variant, pageType); - if ( - service !== 'sport' && - service !== 'newsround' && - service !== 'news' && - Cypress.env('APP_ENV') !== 'local' - ) { - topicTagsTest(service, variant, pageType); - } else { - cy.log('Topic tags currently disabled on Sport and Newsround'); - } - }); - - describe( - 'Image Tests', - { - retries: 3, - }, - () => { - const pageTypesNoImages = ['liveRadio', 'errorPage404']; - // live radio pages and error pages do not have an image - if (!pageTypesNoImages.includes(pageType)) { - it('should have webp images on pages', () => { - cy.document().then(doc => { - const images = doc.querySelectorAll( - 'amp-img[src*="ichef."], img[src*="ichef."]', - ); - if (images.length === 0) { - cy.log('No images on page'); - } else { - // on amp there are hidden embed images, so we check only ichef ones - cy.get('amp-img[src*="ichef."], img[src*="ichef."]').each( - $img => { - // when you use a .each loop or other JS function that take a callback function (here with $img that is executed for each image element) - // you leave the Cypress command queue and are using plain JS. Using .wrap converts - // the JQuery element into a Cypress wrapped element so we can execute Cypress commands on it - - // Images are lazy loaded so we need to scroll to them, check they have loaded before getting currentSrc - // eslint-disable-next-line cypress/unsafe-to-chain-command - cy.wrap($img) - .scrollIntoView() - .should('be.visible') - .then($visibleImg => { - const src = $visibleImg.attr('src'); - cy.log(src); - // eslint-disable-next-line no-unused-expressions - expect(src.endsWith('.webp')).to.be.true; - }); - }, - ); - } - }); - }); - } - }, - ); - }); -}; diff --git a/package.json b/package.json index 9fa538f7634..cf207642128 100644 --- a/package.json +++ b/package.json @@ -32,13 +32,10 @@ "build:storybook": "yarn build && storybook build -c .storybook -o storybook_dist", "build:test": "cp envConfig/test.env .env && NODE_ENV=production webpack", "build:test:debug": "rm -rf build && awk '{sub(/LOG_DIR=.+/,\"LOG_DIR='log'\")}1' envConfig/test.env > .env && NODE_ENV=production webpack", - "cypress:pages": "cypress run --browser chrome --spec ./cypress/e2e/pages", "cypress:special-features": "cypress run --browser chrome --spec ./cypress/e2e/specialFeatures", - "cypress": "run-p --print-name --aggregate-output --continue-on-error cypress:pages cypress:special-features", + "cypress": "run-p --print-name --aggregate-output --continue-on-error cypress:special-features", "cypress:install": "cypress install", - "cypress:onefile": "CYPRESS_APP_ENV=live CYPRESS_SMOKE=false cypress run --spec './cypress/e2e/pages/storyPage/*'", "cypress:oneservice": "CYPRESS_APP_ENV=live CYPRESS_SMOKE=false CYPRESS_ONLY_SERVICE=mundo cypress run", - "cypress:oneserviceandonefile": "CYPRESS_APP_ENV=live CYPRESS_SMOKE=false CYPRESS_ONLY_SERVICE=mundo cypress run --spec './cypress/e2e/pages/storyPage/*'", "cypress:interactive": "cypress open", "setupDevEnv": "cp envConfig/local.env .env && rm -rf envConfig/secret.env && ./scripts/checkSecretEnvVariables.sh", "dependencyFreshness": "node ./scripts/dependencyFreshness", diff --git a/src/app/pages/LiveRadioPage/LiveRadioPage.tsx b/src/app/pages/LiveRadioPage/LiveRadioPage.tsx index ad97ae25123..b7042e11635 100644 --- a/src/app/pages/LiveRadioPage/LiveRadioPage.tsx +++ b/src/app/pages/LiveRadioPage/LiveRadioPage.tsx @@ -9,9 +9,9 @@ import ATIAnalytics from '../../components/ATIAnalytics'; import ChartbeatAnalytics from '../../components/ChartbeatAnalytics'; import MetadataContainer from '../../components/Metadata'; import LinkedData from '../../components/LinkedData'; -import { LiveRadioPageData } from './types'; +import { LiveRadioPageProps } from './types'; -const LiveRadioPage = ({ pageData }: { pageData: LiveRadioPageData }) => { +const LiveRadioPage = ({ pageData }: { pageData: LiveRadioPageProps }) => { const { language, name, diff --git a/src/app/pages/LiveRadioPage/index.test.tsx b/src/app/pages/LiveRadioPage/index.test.tsx index d72d2a18e5b..ff10cd001b6 100644 --- a/src/app/pages/LiveRadioPage/index.test.tsx +++ b/src/app/pages/LiveRadioPage/index.test.tsx @@ -9,10 +9,10 @@ import { data as kyrgyzPageData } from '#data/kyrgyz/bbc_kyrgyz_radio/liveradio. import { render } from '../../components/react-testing-library-with-providers'; import { ServiceContextProvider } from '../../contexts/ServiceContext'; import LiveRadioPage from './LiveRadioPage'; -import { LiveRadioPageData } from './types'; +import { LiveRadioPageProps } from './types'; type Props = { - pageData: LiveRadioPageData; + pageData: LiveRadioPageProps; service: Services; lang: string; }; @@ -44,7 +44,7 @@ describe('Radio Page Main', () => { it('should match snapshot for Canonical', () => { const { container } = render( , @@ -57,7 +57,7 @@ describe('Radio Page Main', () => { it('should show the title for the Live Radio page', () => { const { getByText } = render( , @@ -70,7 +70,7 @@ describe('Radio Page Main', () => { it('should show the summary for the Live Radio page', () => { const { getByText } = render( , @@ -115,7 +115,7 @@ describe('Radio Page Main', () => { { ...afriquePageData.data, mediaBlock: mockMediaBlock, - } as unknown as LiveRadioPageData + } as unknown as LiveRadioPageProps } service="afrique" lang="fr" @@ -132,7 +132,7 @@ describe('Radio Page Main', () => { it('should show the radio schedule for the Live Radio page on canonical', () => { const { getByText } = render( , @@ -150,7 +150,7 @@ describe('Radio Page Main', () => { it('should not show the radio schedule for services without a schedule', async () => { const { container } = render( , diff --git a/src/app/pages/LiveRadioPage/types.ts b/src/app/pages/LiveRadioPage/types.ts index ba119436db8..2f4c37a3b35 100644 --- a/src/app/pages/LiveRadioPage/types.ts +++ b/src/app/pages/LiveRadioPage/types.ts @@ -2,7 +2,7 @@ import { ATIData } from '#app/components/ATIAnalytics/types'; import { ChartbeatProps } from '#app/components/ChartbeatAnalytics/types'; import { LiveRadioBlock } from '#app/models/types/media'; -export type LiveRadioPageData = { +export type LiveRadioPageProps = { language: string; name: string; summary: string; diff --git a/src/app/routes/utils/constructPageFetchUrl/index.ts b/src/app/routes/utils/constructPageFetchUrl/index.ts index 146ed84ba0d..23d58886b13 100644 --- a/src/app/routes/utils/constructPageFetchUrl/index.ts +++ b/src/app/routes/utils/constructPageFetchUrl/index.ts @@ -299,9 +299,14 @@ const constructPageFetchUrl = ({ ); break; } - case LIVE_RADIO_PAGE: - fetchUrl = Url(`${pathname}`); + case LIVE_RADIO_PAGE: { + if (process.env?.NEXTJS) { + fetchUrl = Url(`${host}${port}/api/local${pathname}`); + } else { + fetchUrl = Url(`${pathname}`); + } break; + } case LIVE_TV_PAGE: { fetchUrl = Url(`${host}${port}/api/local/${service}/watch/${id}/live`); break; diff --git a/src/integration/utils/runTests/index.js b/src/integration/utils/runTests/index.js index f83d90fcb59..6ff27e36ce9 100644 --- a/src/integration/utils/runTests/index.js +++ b/src/integration/utils/runTests/index.js @@ -75,6 +75,7 @@ const runExpressTests = () => '--colors', '--detectOpenHandles', '--forceExit', + '--passWithNoTests', // Allows the test suite to pass now all page types are migrated to NextJS ...getJestArgs(), ], { diff --git a/cypress/e2e/pages/liveRadio/index.cy.js b/ws-nextjs-app/cypress/e2e/liveRadioPage/index.cy.ts similarity index 90% rename from cypress/e2e/pages/liveRadio/index.cy.js rename to ws-nextjs-app/cypress/e2e/liveRadioPage/index.cy.ts index b65337f9456..ffca820b10c 100644 --- a/cypress/e2e/pages/liveRadio/index.cy.js +++ b/ws-nextjs-app/cypress/e2e/liveRadioPage/index.cy.ts @@ -1,12 +1,14 @@ -import runTestsForPage from '#nextjs/cypress/support/helpers/runTestsForPage'; +import runTestsForPage, { + TestDataType, +} from '../../support/helpers/runTestsForPage'; import e2eTests from './tests'; import testsForAllPages from '../testsForAllPages'; import testsForAllCanonicalPages from '../testsForAllCanonicalPages'; -import { assertPageView } from '../../specialFeatures/atiAnalytics/assertions'; +import { assertPageView } from '../specialFeatures/atiAnalytics/assertions'; import { assertRadioScheduleComponentClick, assertRadioScheduleComponentView, -} from '../../specialFeatures/atiAnalytics/assertions/radioSchedule'; +} from '../specialFeatures/atiAnalytics/assertions/radioSchedule'; const pageType = 'liveRadio'; @@ -103,7 +105,7 @@ const testSuites = [ runforEnv: ['local', 'test', 'live'], tests, }, -]; +] as unknown as TestDataType[]; const atiAnalyticsTestSuites = [ { @@ -120,7 +122,7 @@ const atiAnalyticsTestSuites = [ assertRadioScheduleComponentClick, ], }, -]; +] as unknown as TestDataType[]; runTestsForPage({ pageType, diff --git a/cypress/e2e/pages/liveRadio/tests.js b/ws-nextjs-app/cypress/e2e/liveRadioPage/tests.ts similarity index 74% rename from cypress/e2e/pages/liveRadio/tests.js rename to ws-nextjs-app/cypress/e2e/liveRadioPage/tests.ts index 30a74231f6d..1f6e85385da 100644 --- a/cypress/e2e/pages/liveRadio/tests.js +++ b/ws-nextjs-app/cypress/e2e/liveRadioPage/tests.ts @@ -1,7 +1,6 @@ /* eslint-disable import/prefer-default-export */ -import path from 'ramda/src/path'; -import chartbeatTests from '../../../support/helpers/chartbeatTests'; +import chartbeatTests from '../../support/helpers/chartbeatTests'; // For testing features that may differ across services but share a common logic e.g. translated strings. export default ({ service, pageType }) => describe(`Tests for ${service} ${pageType}`, () => { @@ -34,26 +33,23 @@ export default ({ service, pageType }) => describe('Radio Schedule', () => { it('should be displayed if there is enough schedule data', function test() { cy.fixture(`toggles/${service}.json`).then(toggles => { - const scheduleIsEnabled = path( - ['liveRadioSchedule', 'enabled'], - toggles, - ); + const scheduleIsEnabled = toggles?.liveRadioSchedule?.enabled; cy.log( `Live Radio Page configured for Radio Schedule? ${scheduleIsEnabled}`, ); if (scheduleIsEnabled) { - cy.getPageDataFromWindow().then(data => { - const { pageData } = data; - const schedules = pageData.radioScheduleData; + cy.getPageDataFromWindow().then(pageData => { + const { radioScheduleData } = pageData; - if (schedules) { + if (radioScheduleData) { cy.log('Schedule has enough data'); cy.get('[data-e2e=radio-schedule]').should('exist'); - } else { - cy.get('[data-e2e=radio-schedule]').should('not.exist'); } }); + } else { + cy.get('[data-e2e=radio-schedule]').should('not.exist'); + cy.log('Radio schedule is not toggled on for this service'); } }); }); diff --git a/src/integration/pages/liveRadio/canonicalTests.js b/ws-nextjs-app/integration/pages/liveRadio/canonicalTests.ts similarity index 81% rename from src/integration/pages/liveRadio/canonicalTests.js rename to ws-nextjs-app/integration/pages/liveRadio/canonicalTests.ts index 2b79e67340a..8b57785c579 100644 --- a/src/integration/pages/liveRadio/canonicalTests.js +++ b/ws-nextjs-app/integration/pages/liveRadio/canonicalTests.ts @@ -6,7 +6,13 @@ import { runMediaPlayerAudioTests, } from '../../common'; -export default ({ service, hasRadioSchedule }) => { +export default ({ + service, + hasRadioSchedule, +}: { + service: string; + hasRadioSchedule?: boolean; +}) => { runCoreCanonicalTests(); runCanonicalAnalyticsTests(); runRadioScheduleTests(hasRadioSchedule); @@ -15,7 +21,7 @@ export default ({ service, hasRadioSchedule }) => { describe('Summary', () => { const summaryEl = document.querySelector('main p'); - const summaryText = summaryEl.textContent; + const summaryText = summaryEl?.textContent; it('should be in the document', () => { expect(summaryEl).toBeInTheDocument(); diff --git a/src/integration/pages/liveRadio/gahuza/__snapshots__/canonical.test.js.snap b/ws-nextjs-app/integration/pages/liveRadio/gahuza/__snapshots__/canonical.test.ts.snap similarity index 95% rename from src/integration/pages/liveRadio/gahuza/__snapshots__/canonical.test.js.snap rename to ws-nextjs-app/integration/pages/liveRadio/gahuza/__snapshots__/canonical.test.ts.snap index f0743c9392b..227e7a34a6c 100644 --- a/src/integration/pages/liveRadio/gahuza/__snapshots__/canonical.test.js.snap +++ b/ws-nextjs-app/integration/pages/liveRadio/gahuza/__snapshots__/canonical.test.ts.snap @@ -128,20 +128,20 @@ exports[`Canonical Live Radio Main heading should match text 1`] = `"Radio BBC G exports[`Canonical Live Radio Media Loader renders a valid container 1`] = `