cypress/e2e/pages/storyPage/tests.js

Summary

Maintainability
B
4 hrs
Test Coverage
/* eslint-disable import/prefer-default-export */
import pathOr from 'ramda/src/pathOr';
import path from 'ramda/src/path';
import paths from 'ramda/src/paths';
import getDataUrl from '../../../support/helpers/getDataUrl';
import { crossPlatform as mostReadAssertions } from '../mostReadPage/mostReadAssertions';
import getAppEnv from '../../../support/helpers/getAppEnv';

const twoYearsAgo = new Date().getFullYear() - 2;

const isArticleLessThanTwoYearsOld = () => {
  return cy
    .get(`main time`)
    .invoke('attr', 'datetime')
    .then(fullDate => {
      const isNewArticle = Number(fullDate.split('-')[0]) > Number(twoYearsAgo);
      return isNewArticle && getAppEnv() === 'live';
    });
};

const getContentBlocks = body => {
  const contentBlock = body.data.article.content;

  const [cpsAssetBlocks, cafBlocks] = paths(
    [['blocks'], ['model', 'blocks']],
    contentBlock,
  );
  return cpsAssetBlocks || cafBlocks;
};

// For testing features that may differ across services but share a common logic e.g. translated strings.
export const testsThatFollowSmokeTestConfig = ({
  service,
  pageType,
  isAmp,
  variant,
}) => {
  describe(`testsThatFollowSmokeTestConfig to run for ${service} ${variant} ${pageType} `, () => {
    it('should render a description for the page', () => {
      cy.getPageData({ service, pageType: 'article', variant }).then(
        ({ body }) => {
          const contentBlocks = getContentBlocks(body);
          const descriptionBlock = contentBlocks.find(
            block => block.role === 'introduction',
          );
          // Condition added because introduction is non-mandatory
          if (descriptionBlock) {
            const descriptionHtml = pathOr({}, ['text'], descriptionBlock);
            // strip html from the description, so we get description as plain text
            const elem = document.createElement('div');
            elem.innerHTML = descriptionHtml;
            const description = elem.innerText;
            cy.get('main p').should('contain', description);
          }
        },
      );
    });

    it('should render paragraph text for the page', () => {
      cy.getPageData({ service, pageType: 'article', variant }).then(
        ({ body }) => {
          const contentBlocks = getContentBlocks(body);
          const paragraphBlock = contentBlocks.find(
            block => block.type === 'paragraph',
          );
          // Conditional because in test assets the data model structure is sometimes variable and unusual
          // so cannot be accessed in the same way across assets
          if (paragraphBlock) {
            const descriptionHtml = pathOr({}, ['text'], paragraphBlock);
            // strip html from the description, so we get description as plain text
            const elem = document.createElement('div');
            elem.innerHTML = descriptionHtml;
            const paragraph = elem.innerText;
            cy.get('main p').should('contain', paragraph);
          }
        },
      );
    });
    it.skip('should render podcast promo if in json and should navigate to correct podcast page', () => {
      cy.log(service);
      if (Cypress.env('APP_ENV') !== 'local') {
        cy.getToggles(service);
        cy.url().then(url => {
          const urlForData = url.replace('.amp', '');

          const firstVisitedPage = url;

          cy.request(getDataUrl(urlForData)).then(() => {
            cy.fixture(`toggles/${service}.json`).then(toggles => {
              const podcastPromoIsEnabled = path(
                ['podcastPromo', 'enabled'],
                toggles,
              );
              cy.log(
                `Story page is configured for podcast promo? ${podcastPromoIsEnabled}`,
              );
              if (podcastPromoIsEnabled) {
                // Gets the podcast promo name
                cy.get(
                  `section[aria-labelledby*='podcast-promo'] > div:nth-child(2) > div:nth-child(2) > h3 > a`,
                ).then($tag => {
                  const podcastTitle = $tag.text();
                  cy.wrap(podcastTitle).as('podcastTitle');
                });
                // Clicks on the podcast promo link
                cy.get(
                  `section[aria-labelledby*='podcast-promo'] > div:nth-child(2) > div:nth-child(2) > h3 > a`,
                ).click();

                // Waits for page load to allow Cypress to retrieve url
                // eslint-disable-next-line cypress/no-unnecessary-waiting
                cy.wait(1000);

                cy.url().then(urlTwo => {
                  const isPodcastBrandPage = urlTwo.includes('/podcasts/');

                  // If link leads to a Podcast brand page, check the title is as expected
                  // If link leads to a Podcast aggregate page, check the first link leads to podcast page
                  if (isPodcastBrandPage) {
                    cy.get('@podcastTitle').then(title => {
                      cy.get('h1').should('contain', title);
                    });
                  } else {
                    // This could fail if editorial chooses a MAP page to be the first promo link instead of a podcast page
                    cy.get('[data-e2e=story-promo]')
                      .first()
                      .find('a')
                      .invoke('attr', 'href')
                      .should('contain', '/podcasts/');
                  }
                });
                cy.visit(firstVisitedPage);
              } else {
                cy.log('Podcast promo is not enabled in toggles');
              }
            });
          });
        });
      } else {
        cy.log('Service is run in local.');
      }
    });

    /**
     * Most Read Component
     */
    mostReadAssertions({ service, variant });
  });

  describe(`Recommendations on ${service} ${pageType}`, () => {
    it('Recommendations have images', () => {
      isArticleLessThanTwoYearsOld().then(runRecommendationTests => {
        if (runRecommendationTests) {
          cy.getToggles(service);
          cy.fixture(`toggles/${service}.json`).then(toggles => {
            const recommendationsEnabled = path(
              ['cpsRecommendations', 'enabled'],
              toggles,
            );
            cy.log(`Recommendations enabled? ${recommendationsEnabled}`);
            if (recommendationsEnabled) {
              cy.get(`[data-e2e=recommendations-heading]`).scrollIntoView();
              cy.get('[data-e2e=recommendations-heading] > div > ul > li').each(
                (item, index) => {
                  cy.wrap(item).within(() => {
                    cy.log(`List item number: ${index}`);
                    cy.log(`isAmp= ${isAmp}`);
                    if (isAmp) {
                      cy.get(
                        `[data-e2e=story-promo-wrapper] > div > [data-e2e=image-placeholder] > amp-img`,
                      ).should('have.attr', 'width');
                    } else {
                      cy.get(
                        `[data-e2e=story-promo-wrapper] > div > [data-e2e=image-placeholder] > div > img`,
                      ).should('have.attr', 'width');
                    }
                  });
                },
              );
            }
          });
        } else {
          cy.log(
            'Only tests on live and for articles less than 2 years old due to lack of test data',
          );
        }
      });
    });

    it('Recommendations have titles', () => {
      isArticleLessThanTwoYearsOld().then(runRecommendationTests => {
        if (runRecommendationTests) {
          cy.getToggles(service);
          cy.fixture(`toggles/${service}.json`).then(toggles => {
            const recommendationsEnabled = path(
              ['cpsRecommendations', 'enabled'],
              toggles,
            );
            cy.log(`Recommendations enabled? ${recommendationsEnabled}`);
            if (recommendationsEnabled) {
              cy.get(`[data-e2e=recommendations-heading]`).scrollIntoView();
              cy.get('[data-e2e=recommendations-heading] > div > ul > li').each(
                (item, index) => {
                  cy.wrap(item).within(() => {
                    cy.log(`List item number: ${index + 1}`);
                    cy.get(`[data-e2e=story-promo-wrapper] > div > div > a`)
                      .invoke('text')
                      .then(text => {
                        expect(text.length).to.be.at.least(1);
                      });
                  });
                },
              );
            }
          });
        } else {
          cy.log(
            'Only tests on live and for articles less than 2 years old due to lack of test data',
          );
        }
      });
    });
  });
};