@newskit-render/core 0.0.0-d55b7d88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ci/trigger-circleci-workflow.sh +37 -0
- package/.eslintignore +23 -0
- package/.eslintrc +74 -0
- package/.prettierignore +19 -0
- package/.prettierrc +7 -0
- package/CHANGELOG.md +7638 -0
- package/Dockerfile +14 -0
- package/Dockerfile.withNewRelic +15 -0
- package/README.md +274 -0
- package/__tests__/pages/__snapshots__/brightcove.test.tsx.snap +20 -0
- package/__tests__/pages/__snapshots__/home.test.tsx.snap +1195 -0
- package/__tests__/pages/brightcove.test.tsx +34 -0
- package/__tests__/pages/empty.test.tsx +10 -0
- package/__tests__/pages/home.test.tsx +16 -0
- package/app-context/InstrumentationContextProvider.tsx +36 -0
- package/assets/fontFamily.ts +416 -0
- package/assets/fonts/Graphik-Black-App.ttf +0 -0
- package/assets/fonts/Graphik-BlackItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Bold-App.ttf +0 -0
- package/assets/fonts/Graphik-BoldItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Extralight-App.ttf +0 -0
- package/assets/fonts/Graphik-ExtralightItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Light-App.ttf +0 -0
- package/assets/fonts/Graphik-LightItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Medium-App.ttf +0 -0
- package/assets/fonts/Graphik-Medium-Web.woff2 +0 -0
- package/assets/fonts/Graphik-MediumItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Regular-App.ttf +0 -0
- package/assets/fonts/Graphik-Regular-Web.woff2 +0 -0
- package/assets/fonts/Graphik-RegularItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Semibold-App.ttf +0 -0
- package/assets/fonts/Graphik-Semibold-Web.woff2 +0 -0
- package/assets/fonts/Graphik-SemiboldItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Super-App.ttf +0 -0
- package/assets/fonts/Graphik-SuperItalic-App.ttf +0 -0
- package/assets/fonts/Graphik-Thin-App.ttf +0 -0
- package/assets/fonts/Graphik-ThinItalic-App.ttf +0 -0
- package/assets/fonts/Montserrat-Black.ttf +0 -0
- package/assets/fonts/Montserrat-BlackItalic.ttf +0 -0
- package/assets/fonts/Montserrat-Bold.ttf +0 -0
- package/assets/fonts/Montserrat-BoldItalic.ttf +0 -0
- package/assets/fonts/Montserrat-ExtraBold.ttf +0 -0
- package/assets/fonts/Montserrat-ExtraBoldItalic.ttf +0 -0
- package/assets/fonts/Montserrat-ExtraLight.ttf +0 -0
- package/assets/fonts/Montserrat-ExtraLightItalic.ttf +0 -0
- package/assets/fonts/Montserrat-Italic.ttf +0 -0
- package/assets/fonts/Montserrat-Light.ttf +0 -0
- package/assets/fonts/Montserrat-LightItalic.ttf +0 -0
- package/assets/fonts/Montserrat-Medium.ttf +0 -0
- package/assets/fonts/Montserrat-MediumItalic.ttf +0 -0
- package/assets/fonts/Montserrat-Regular.ttf +0 -0
- package/assets/fonts/Montserrat-SemiBold.ttf +0 -0
- package/assets/fonts/Montserrat-SemiBoldItalic.ttf +0 -0
- package/assets/fonts/Montserrat-Thin.ttf +0 -0
- package/assets/fonts/Montserrat-ThinItalic.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Black-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-BlackItalic-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Bold-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Bold-Web.woff2 +0 -0
- package/assets/fonts/PublicoHeadline-BoldItalic-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Extrabold-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-ExtraboldItalic-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Italic-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Light-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-LightItalic-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Medium-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-MediumItalic-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Roman-App.ttf +0 -0
- package/assets/fonts/PublicoHeadline-Roman-Web.woff2 +0 -0
- package/assets/fonts/PublicoText-Bold-App.ttf +0 -0
- package/assets/fonts/PublicoText-BoldItalic-App.ttf +0 -0
- package/assets/fonts/PublicoText-Italic-App.ttf +0 -0
- package/assets/fonts/PublicoText-Italic-Web.woff2 +0 -0
- package/assets/fonts/PublicoText-Roman-App.ttf +0 -0
- package/assets/fonts/PublicoText-Roman-Web.woff2 +0 -0
- package/assets/fonts/PublicoText-Semibold-App.ttf +0 -0
- package/assets/fonts/PublicoText-SemiboldItalic-App.ttf +0 -0
- package/assets/fonts/Roboto-Bold.ttf +0 -0
- package/assets/fonts/Roboto-Light.ttf +0 -0
- package/assets/fonts/Roboto-Medium.ttf +0 -0
- package/assets/fonts/Roboto-Regular.ttf +0 -0
- package/assets/fonts/TheSun-Bold.ttf +0 -0
- package/assets/fonts/TheSun-BoldItalic.ttf +0 -0
- package/assets/fonts/TheSun-HeavyCondensed.ttf +0 -0
- package/assets/fonts/TheSun-HeavyNarrow.ttf +0 -0
- package/assets/fonts/TheSun-Italic.ttf +0 -0
- package/assets/fonts/TheSun-Medium.ttf +0 -0
- package/assets/fonts/TheSun-MediumItalic.ttf +0 -0
- package/assets/fonts/TheSun-Regular.ttf +0 -0
- package/assets/fonts/TimesDigital-Bold.ttf +0 -0
- package/assets/fonts/TimesDigital-BoldItalic.ttf +0 -0
- package/assets/fonts/TimesDigital-BoldSC.ttf +0 -0
- package/assets/fonts/TimesDigital-Italic.ttf +0 -0
- package/assets/fonts/TimesDigital-Regular.ttf +0 -0
- package/assets/fonts/TimesDigital-RegularSC.ttf +0 -0
- package/assets/fonts/TimesDigitalW04-Bold.ttf +0 -0
- package/assets/fonts/TimesDigitalW04-BoldItalic.ttf +0 -0
- package/assets/fonts/TimesDigitalW04-BoldSC.ttf +0 -0
- package/assets/fonts/TimesDigitalW04-Italic.ttf +0 -0
- package/assets/fonts/TimesDigitalW04-Regular.ttf +0 -0
- package/assets/fonts/TimesDigitalW04-RegularSC.ttf +0 -0
- package/assets/fonts/TimesModern-Regular.otf +0 -0
- package/assets/fonts/attribuitions.mdx +35 -0
- package/assets/fonts/bitter-medium.woff +0 -0
- package/assets/fonts/bitter-medium.woff2 +0 -0
- package/assets/fonts/bitter-mediumitalic.woff +0 -0
- package/assets/fonts/bitter-mediumitalic.woff2 +0 -0
- package/assets/fonts/bitter-regular.woff +0 -0
- package/assets/fonts/bitter-regular.woff2 +0 -0
- package/assets/fonts/bitter-semibold.woff +0 -0
- package/assets/fonts/bitter-semibold.woff2 +0 -0
- package/assets/fonts/dmmono-medium.woff +0 -0
- package/assets/fonts/dmmono-medium.woff2 +0 -0
- package/assets/fonts/dmsans-bold-webfont.woff +0 -0
- package/assets/fonts/dmsans-bold-webfont.woff2 +0 -0
- package/assets/fonts/dmsans-bolditalic-webfont.woff +0 -0
- package/assets/fonts/dmsans-bolditalic-webfont.woff2 +0 -0
- package/assets/fonts/dmsans-italic-webfont.woff +0 -0
- package/assets/fonts/dmsans-italic-webfont.woff2 +0 -0
- package/assets/fonts/dmsans-medium-webfont.woff +0 -0
- package/assets/fonts/dmsans-medium-webfont.woff2 +0 -0
- package/assets/fonts/dmsans-mediumitalic-webfont.woff +0 -0
- package/assets/fonts/dmsans-mediumitalic-webfont.woff2 +0 -0
- package/assets/fonts/dmsans-regular-webfont.woff +0 -0
- package/assets/fonts/dmsans-regular-webfont.woff2 +0 -0
- package/assets/fonts/notosans-bold-webfont.woff +0 -0
- package/assets/fonts/notosans-bold-webfont.woff2 +0 -0
- package/assets/fonts/notosans-italic-webfont.woff +0 -0
- package/assets/fonts/notosans-italic-webfont.woff2 +0 -0
- package/assets/fonts/notosans-medium-webfont.woff +0 -0
- package/assets/fonts/notosans-medium-webfont.woff2 +0 -0
- package/assets/fonts/notosans-regular-webfont.woff +0 -0
- package/assets/fonts/notosans-regular-webfont.woff2 +0 -0
- package/assets/fonts/poppins-bold-webfont.woff +0 -0
- package/assets/fonts/poppins-bold-webfont.woff2 +0 -0
- package/assets/fonts/poppins-bolditalic-webfont.woff +0 -0
- package/assets/fonts/poppins-bolditalic-webfont.woff2 +0 -0
- package/assets/fonts/poppins-extrabold-webfont.woff +0 -0
- package/assets/fonts/poppins-extrabold-webfont.woff2 +0 -0
- package/assets/fonts/poppins-extrabolditalic-webfont.woff +0 -0
- package/assets/fonts/poppins-extrabolditalic-webfont.woff2 +0 -0
- package/assets/fonts/poppins-italic-webfont.woff +0 -0
- package/assets/fonts/poppins-italic-webfont.woff2 +0 -0
- package/assets/fonts/poppins-light-webfont.woff +0 -0
- package/assets/fonts/poppins-light-webfont.woff2 +0 -0
- package/assets/fonts/poppins-lightitalic-webfont.woff +0 -0
- package/assets/fonts/poppins-lightitalic-webfont.woff2 +0 -0
- package/assets/fonts/poppins-medium-webfont.woff +0 -0
- package/assets/fonts/poppins-medium-webfont.woff2 +0 -0
- package/assets/fonts/poppins-mediumitalic-webfont.woff +0 -0
- package/assets/fonts/poppins-mediumitalic-webfont.woff2 +0 -0
- package/assets/fonts/poppins-regular-webfont.woff +0 -0
- package/assets/fonts/poppins-regular-webfont.woff2 +0 -0
- package/assets/fonts/poppins-semibold-webfont.woff +0 -0
- package/assets/fonts/poppins-semibold-webfont.woff2 +0 -0
- package/assets/fonts/poppins-semibolditalic-webfont.woff +0 -0
- package/assets/fonts/poppins-semibolditalic-webfont.woff2 +0 -0
- package/assets/fonts/source-serif-pro-600.woff +0 -0
- package/assets/fonts/source-serif-pro-600.woff2 +0 -0
- package/assets/fonts/source-serif-pro-600italic.woff +0 -0
- package/assets/fonts/source-serif-pro-600italic.woff2 +0 -0
- package/assets/fonts/source-serif-pro-700.woff +0 -0
- package/assets/fonts/source-serif-pro-700.woff2 +0 -0
- package/assets/fonts/source-serif-pro-700italic.woff +0 -0
- package/assets/fonts/source-serif-pro-700italic.woff2 +0 -0
- package/assets/fonts/source-serif-pro-italic.woff +0 -0
- package/assets/fonts/source-serif-pro-italic.woff2 +0 -0
- package/assets/fonts/source-serif-pro-regular.woff +0 -0
- package/assets/fonts/source-serif-pro-regular.woff2 +0 -0
- package/components/AccountDropdown/AccountDropdown.tsx +65 -0
- package/components/AccountDropdown/__tests__/AcountDropdown.test.tsx +83 -0
- package/components/AccountDropdown/accounts.ts +47 -0
- package/components/AccountDropdown/index.tsx +2 -0
- package/components/AccountDropdown/utils.ts +21 -0
- package/components/ErrorPage/ErrorPage.tsx +135 -0
- package/components/ad/index.tsx +35 -0
- package/components/article/Highlights.tsx +77 -0
- package/components/article/MetaBox.tsx +50 -0
- package/components/article/RelatedArticles.tsx +53 -0
- package/components/article/RelatedTopics.tsx +59 -0
- package/components/article/ShareBarComponent.tsx +53 -0
- package/components/article/__tests__/__snapshots__/index.test.tsx.snap +1568 -0
- package/components/article/__tests__/index.test.tsx +171 -0
- package/components/article/__tests__/mocks.ts +105 -0
- package/components/article/index.tsx +320 -0
- package/components/common/BackToHomepage.tsx +37 -0
- package/components/common/NavLink.tsx +26 -0
- package/components/common/NewskitLogo.tsx +52 -0
- package/components/common/NewskitLogoShort.tsx +48 -0
- package/components/common/SectionTitleBar.tsx +57 -0
- package/components/common/ShareButton.tsx +18 -0
- package/components/common/ViewMoreButton.tsx +20 -0
- package/components/common/iconNavLink/IconNavLink.tsx +70 -0
- package/components/common/iconNavLink/__tests__/IconNavLink.test.tsx +35 -0
- package/components/common/iconNavLink/index.ts +3 -0
- package/components/common/iconNavLink/types.ts +24 -0
- package/components/common/icons/IconAccount.tsx +13 -0
- package/components/common/icons/IconFilledTwitter.tsx +14 -0
- package/components/common/icons/StyledIconFilledChevronRight.tsx +12 -0
- package/components/footer/__snapshots__/index.test.tsx.snap +192 -0
- package/components/footer/index.test.tsx +13 -0
- package/components/footer/index.tsx +151 -0
- package/components/header/banner-messages.ts +39 -0
- package/components/header/index.tsx +52 -0
- package/components/header/navigation-links.ts +20 -0
- package/components/layout/Gutter.tsx +11 -0
- package/components/layout/LayoutTemplate.tsx +26 -0
- package/components/layout/MainGrid.tsx +66 -0
- package/components/layout/index.tsx +3 -0
- package/components/layout/layoutTypes.ts +13 -0
- package/components/section/ArticleSlice.tsx +35 -0
- package/components/section/CollectionBlock.tsx +54 -0
- package/components/section/SectionContext.tsx +9 -0
- package/components/section/__tests__/ArticleSlice.test.tsx +128 -0
- package/components/section/__tests__/CollectionBlock.test.tsx +83 -0
- package/components/section/__tests__/pageBlock.test.tsx +24 -0
- package/components/section/__tests__/sectionUtils.test.ts +94 -0
- package/components/section/index.tsx +39 -0
- package/components/section/layouts/Block.tsx +79 -0
- package/components/section/layouts/FallBack.tsx +24 -0
- package/components/section/layouts/Lead.tsx +43 -0
- package/components/section/layouts/Rows.tsx +82 -0
- package/components/section/layouts/SectionTitle.tsx +57 -0
- package/components/section/layouts/__tests__/Lead.test.tsx +37 -0
- package/components/section/layouts/__tests__/Rows.test.tsx +40 -0
- package/components/section/layouts/__tests__/SectionTitle.test.tsx +37 -0
- package/components/section/layouts/__tests__/__snapshots__/Lead.test.tsx.snap +180 -0
- package/components/section/layouts/__tests__/__snapshots__/SectionTitle.test.tsx.snap +354 -0
- package/components/section/layouts/gridUtils.ts +21 -0
- package/components/section/layouts/index.tsx +4 -0
- package/components/section/layouts/types.ts +13 -0
- package/components/section/pageBlock.tsx +23 -0
- package/components/section/sectionUtils.ts +61 -0
- package/components/teaser/index.test.tsx +50 -0
- package/components/teaser/index.tsx +64 -0
- package/components/teaser/teaserVariants.ts +33 -0
- package/components/teaser/variant-types.ts +49 -0
- package/components/teaser/variants/featureVariant.ts +42 -0
- package/components/teaser/variants/horizontal.ts +14 -0
- package/components/teaser/variants/titleTeaserVariant.ts +32 -0
- package/components/teaser/variants/titleVertical.ts +24 -0
- package/components/utils/index.test.ts +12 -0
- package/components/utils/index.ts +6 -0
- package/config/__tests__/index.test.ts +54 -0
- package/config/environment.ts +80 -0
- package/config/index.ts +2 -0
- package/config/multiTenancy.ts +11 -0
- package/constants/index.ts +2 -0
- package/context/app-context/AppContext.test.tsx +56 -0
- package/context/app-context/holidayStopListContextOverrides.ts +18 -0
- package/context/app-context/index.tsx +34 -0
- package/context/app-context/paymentMethodContext.tsx +70 -0
- package/context/index.tsx +2 -0
- package/context/multi-tenancy/MultiTenancy.test.tsx +48 -0
- package/context/multi-tenancy/index.tsx +32 -0
- package/css/index.ts +15 -0
- package/cypress/axe/terminal-log.js +19 -0
- package/cypress/config/visual.config.ts +11 -0
- package/cypress/config/visual.skip.config.ts +10 -0
- package/cypress/e2e/account/accessibility.cy.js +88 -0
- package/cypress/e2e/account/banners.cy.js +169 -0
- package/cypress/e2e/account/cancellation.cy.js +219 -0
- package/cypress/e2e/account/holiday-stops.cy.js +109 -0
- package/cypress/e2e/account/main-api.cy.js +102 -0
- package/cypress/e2e/account/newsletters-and-alerts.cy.js +149 -0
- package/cypress/e2e/account/newsletters-page.cy.js +69 -0
- package/cypress/e2e/account/payment-page.cy.js +98 -0
- package/cypress/e2e/account/personal-details.cy.js +1161 -0
- package/cypress/e2e/account/subscription-and-billing.cy.js +434 -0
- package/cypress/e2e/checkout/account-creation.cy.js +8 -0
- package/cypress/e2e/checkout/payment-details.cy.js +19 -0
- package/cypress/e2e/core/home-page.cy.js +6 -0
- package/cypress/e2e/help-hub/accessibility.cy.js +35 -0
- package/cypress/e2e/help-hub/article-page.cy.js +115 -0
- package/cypress/e2e/help-hub/landing-page.cy.js +94 -0
- package/cypress/e2e/help-hub/result-page.cy.js +117 -0
- package/cypress/fixtures/empty.html +10 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/fixtures/holiday-stops.json +40 -0
- package/cypress/fixtures/paymentFailure.js +24 -0
- package/cypress/fixtures/testDates.js +26 -0
- package/cypress/support/commands.js +125 -0
- package/cypress/support/consentValues.js +5839 -0
- package/cypress/support/e2e.js +22 -0
- package/cypress/support/users.js +58 -0
- package/cypress/visual/account/print-visual-regression.cy.js +9 -0
- package/cypress/visual/account/visual-regression.cy.js +40 -0
- package/cypress/visual/empty/empty.cy.js +5 -0
- package/cypress.config.ts +38 -0
- package/helpers/__tests__/getUser.test.ts +45 -0
- package/helpers/__tests__/logger.test.ts +62 -0
- package/helpers/__tests__/useThemeDropdownObject.test.ts +49 -0
- package/helpers/a11y.ts +7 -0
- package/helpers/addCacheHeaders.ts +8 -0
- package/helpers/getUser.ts +37 -0
- package/helpers/getYear.ts +1 -0
- package/helpers/global-types.ts +186 -0
- package/helpers/logger/getWinstonLogger.ts +19 -0
- package/helpers/logger/index.ts +20 -0
- package/helpers/logger/replaceConsoleWithLogger.ts +14 -0
- package/helpers/mocks/articleMock.ts +50 -0
- package/helpers/mocks/getPageMock.ts +369 -0
- package/helpers/mocks/getRadioPostMock.ts +71 -0
- package/helpers/mocks/getRadioPostsMock.ts +26 -0
- package/helpers/mocks/getRecommendationsMock.ts +20 -0
- package/helpers/mocks/index.ts +7 -0
- package/helpers/multiTenancy.ts +19 -0
- package/helpers/setupTests.ts +5 -0
- package/helpers/test-utils.tsx +33 -0
- package/helpers/useThemeDropdownObject.tsx +73 -0
- package/infrastructure/.circleci/config.yml +1187 -0
- package/infrastructure/INFRASTRUCTURE.md +142 -0
- package/infrastructure/build_and_deploy.png +0 -0
- package/infrastructure/helm/Chart.yaml +21 -0
- package/infrastructure/helm/templates/_helpers.tpl +87 -0
- package/infrastructure/helm/templates/deployment.yaml +45 -0
- package/infrastructure/helm/templates/horizontalpodautoscaler.yaml +21 -0
- package/infrastructure/helm/templates/ingress.yaml +31 -0
- package/infrastructure/helm/templates/networkpolicy.yaml +26 -0
- package/infrastructure/helm/templates/secret.yaml +12 -0
- package/infrastructure/helm/templates/service.yaml +15 -0
- package/infrastructure/helm/values-dev.yaml +39 -0
- package/infrastructure/helm/values-local.yaml +30 -0
- package/infrastructure/helm/values-pr.yaml +40 -0
- package/infrastructure/helm/values-prod.yaml +39 -0
- package/infrastructure/helm/values-staging.yaml +39 -0
- package/infrastructure/helm/values.yaml +44 -0
- package/infrastructure/pull_request.png +0 -0
- package/infrastructure/release-documentation-cli.config.json +18 -0
- package/infrastructure/remove_pr.png +0 -0
- package/infrastructure/terraform-ecr/dev.tfvars +3 -0
- package/infrastructure/terraform-ecr/ecr.tf +69 -0
- package/infrastructure/terraform-ecr/main.tf +3 -0
- package/infrastructure/terraform-ecr/variables.tf +19 -0
- package/infrastructure/terraform-ecr/versions.tf +12 -0
- package/infrastructure/terraform-newrelic/alerts.tf +290 -0
- package/infrastructure/terraform-newrelic/dashboards.tf +347 -0
- package/infrastructure/terraform-newrelic/dev.tfvars +3 -0
- package/infrastructure/terraform-newrelic/lighthouse-script-dev.js +53 -0
- package/infrastructure/terraform-newrelic/lighthouse-script-prod.js +54 -0
- package/infrastructure/terraform-newrelic/lighthouse-script-stage.js +54 -0
- package/infrastructure/terraform-newrelic/main.tf +11 -0
- package/infrastructure/terraform-newrelic/monitors.tf +11 -0
- package/infrastructure/terraform-newrelic/prod.tfvars +3 -0
- package/infrastructure/terraform-newrelic/staging.tfvars +3 -0
- package/infrastructure/terraform-newrelic/variables.tf +33 -0
- package/infrastructure/terraform-newrelic/versions.tf +18 -0
- package/jest.config.js +40 -0
- package/jest.config.pact.js +18 -0
- package/newrelic.js +86 -0
- package/next-env.d.ts +5 -0
- package/next.config.js +95 -0
- package/package.json +127 -0
- package/pages/_app.tsx +117 -0
- package/pages/_document.tsx +112 -0
- package/pages/_error.tsx +68 -0
- package/pages/account/add/[field].tsx +34 -0
- package/pages/account/cancellation/index.tsx +22 -0
- package/pages/account/delete/confirm/index.tsx +16 -0
- package/pages/account/delete/error/index.tsx +16 -0
- package/pages/account/delete/index.tsx +16 -0
- package/pages/account/delete/success/index.tsx +16 -0
- package/pages/account/dream-team/index.tsx +19 -0
- package/pages/account/edit/[field].tsx +45 -0
- package/pages/account/family/index.tsx +19 -0
- package/pages/account/holiday-stop/index.tsx +19 -0
- package/pages/account/holiday-stop/previous-holiday-stops.tsx +19 -0
- package/pages/account/holiday-stop/upcoming-holiday-stops.tsx +19 -0
- package/pages/account/index.tsx +33 -0
- package/pages/account/newsletters/index.tsx +19 -0
- package/pages/account/newsletters-and-alerts/index.tsx +24 -0
- package/pages/account/payment/[paymentMethod].tsx +37 -0
- package/pages/account/payment/index.tsx +23 -0
- package/pages/account/payment-methods/index.tsx +21 -0
- package/pages/account/subscription-and-billing/index.tsx +29 -0
- package/pages/api/account/get-session/index.ts +33 -0
- package/pages/api/account/invoice/index.ts +35 -0
- package/pages/api/account/mutate/index.ts +8 -0
- package/pages/api/account/query/index.ts +7 -0
- package/pages/api/auth/[...nextauth].ts +11 -0
- package/pages/api/competitions-sitemap.ts +19 -0
- package/pages/api/feed.ts +23 -0
- package/pages/api/health-check.ts +7 -0
- package/pages/api/news-sitemap.ts +18 -0
- package/pages/api/pages-sitemap.ts +27 -0
- package/pages/api/robots.ts +19 -0
- package/pages/api/sitemap.ts +24 -0
- package/pages/checkout/account-creation/index.tsx +13 -0
- package/pages/checkout/payment-details/index.tsx +10 -0
- package/pages/empty.tsx +6 -0
- package/pages/help-hub/article/[title]/index.tsx +25 -0
- package/pages/help-hub/error.tsx +23 -0
- package/pages/help-hub/index.tsx +51 -0
- package/pages/help-hub/results.tsx +25 -0
- package/pages/index.tsx +19 -0
- package/pages/player/brightcove.tsx +19 -0
- package/pages/rss/create/index.tsx +18 -0
- package/pages/rss/feed/[feedId]/index.tsx +21 -0
- package/pages/rss/index.tsx +18 -0
- package/public/ads.min.js +8175 -0
- package/public/assets/display-base-header.svg +25 -0
- package/public/assets/display-personalDetails-header-sun.svg +55 -0
- package/public/assets/display-personalDetails-header-times.svg +90 -0
- package/public/assets/display-personalDetails-header-vr.svg +46 -0
- package/public/assets/dream-team.svg +10 -0
- package/public/assets/navigationPrimary-brandMark-sun.svg +9 -0
- package/public/assets/navigationPrimary-brandMark-times.svg +18 -0
- package/public/assets/navigationPrimary-brandMark-vr.svg +10 -0
- package/public/assets/newsletters/bestoftimes-101.png +0 -0
- package/public/assets/newsletters/books-115.png +0 -0
- package/public/assets/newsletters/environment-140.png +0 -0
- package/public/assets/newsletters/fashion-108.png +0 -0
- package/public/assets/newsletters/food-106.png +0 -0
- package/public/assets/newsletters/football-111.png +0 -0
- package/public/assets/newsletters/ireland-152.png +0 -0
- package/public/assets/newsletters/law-121.png +0 -0
- package/public/assets/newsletters/money-107.png +0 -0
- package/public/assets/newsletters/moneymentor-150.png +0 -0
- package/public/assets/newsletters/placeholder.png +0 -0
- package/public/assets/newsletters/politics-119.png +0 -0
- package/public/assets/newsletters/property-113.png +0 -0
- package/public/assets/newsletters/puzzles-125.png +0 -0
- package/public/assets/newsletters/scotland-134.png +0 -0
- package/public/assets/newsletters/theatre-127.png +0 -0
- package/public/assets/newsletters/travel-149.png +0 -0
- package/public/assets/newsletters/tv-133.png +0 -0
- package/public/assets/newsletters/us-153.png +0 -0
- package/public/assets/no-subscription.svg +15 -0
- package/public/assets/pending-activation.svg +16 -0
- package/public/assets/personal-details-header.svg +91 -0
- package/public/assets/plchldr150x100.png +0 -0
- package/public/assets/previous-subscription.svg +15 -0
- package/public/assets/primary-navigation-logo-white.svg +6 -0
- package/public/assets/primary-navigation-logo.svg +6 -0
- package/public/assets/tls-logo-white.svg +3 -0
- package/public/favicon.ico +0 -0
- package/public/icon.png +0 -0
- package/public/prebid.min.js +1 -0
- package/queries/getPage.ts +100 -0
- package/queries/getRadioPost.ts +61 -0
- package/queries/getRadioPosts.ts +16 -0
- package/queries/getUserSubscription.ts +9 -0
- package/queries/index.ts +3 -0
- package/scripts/k8s-local.sh +137 -0
- package/scripts/nr-exports.sh +7 -0
- package/temp/_app.tsx +15 -0
- package/temp/_document.tsx +61 -0
- package/temp/app-context-test.tsx +51 -0
- package/temp/app-context.tsx +25 -0
- package/temp/config-index.ts +1 -0
- package/temp/context-index.tsx +1 -0
- package/temp/header.tsx +45 -0
- package/temp/next.config.js +56 -0
- package/tsconfig.json +51 -0
- package/tsconfig.test.json +6 -0
- package/validation/index.tsx +24 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
// eslint-disable-next-line react/no-deprecated
|
|
3
|
+
import { render } from 'react-dom'
|
|
4
|
+
import { timesTheme } from '@newskit-render/shared-components'
|
|
5
|
+
import { Publisher } from '@newskit-render/api'
|
|
6
|
+
import { AppContext, AppContextProvider } from '../app-context'
|
|
7
|
+
import MultiTenancyProvider, { useMultiTenancy } from '.'
|
|
8
|
+
|
|
9
|
+
const container = document.createElement('div')
|
|
10
|
+
document.body.appendChild(container)
|
|
11
|
+
|
|
12
|
+
const TestComponent = ({ mockFunction }) => {
|
|
13
|
+
const accountData = useMultiTenancy()
|
|
14
|
+
mockFunction(accountData)
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('Multi-Tenancy context', () => {
|
|
19
|
+
it('should select the correct theme based on the tenant', () => {
|
|
20
|
+
render(
|
|
21
|
+
<MultiTenancyProvider tenant={Publisher.TIMES}>
|
|
22
|
+
<AppContextProvider>
|
|
23
|
+
<AppContext.Consumer>
|
|
24
|
+
{({ theme }) => <div>{JSON.stringify(theme)}</div>}
|
|
25
|
+
</AppContext.Consumer>
|
|
26
|
+
</AppContextProvider>
|
|
27
|
+
</MultiTenancyProvider>,
|
|
28
|
+
container
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
expect(container.textContent).toBe(JSON.stringify(timesTheme))
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should receive proper context', () => {
|
|
35
|
+
const mockFunction = jest.fn()
|
|
36
|
+
render(
|
|
37
|
+
<MultiTenancyProvider tenant={Publisher.DEMO}>
|
|
38
|
+
<TestComponent mockFunction={mockFunction} />
|
|
39
|
+
</MultiTenancyProvider>,
|
|
40
|
+
container
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
expect(mockFunction).toHaveBeenCalledWith({
|
|
44
|
+
tenant: Publisher.DEMO,
|
|
45
|
+
getTenantString: expect.any(Function),
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react'
|
|
2
|
+
import get from 'lodash.get'
|
|
3
|
+
import { Publisher } from '@newskit-render/api'
|
|
4
|
+
import { translationsMap } from '../../config'
|
|
5
|
+
|
|
6
|
+
export interface MultiTenancyContextProps {
|
|
7
|
+
children?: React.ReactNode
|
|
8
|
+
tenant?: Publisher
|
|
9
|
+
getTenantString?: (key: string, defaultValue?: string) => string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const MultiTenancyContext = createContext<MultiTenancyContextProps>({})
|
|
13
|
+
|
|
14
|
+
const MultiTenancyProvider: React.FC<MultiTenancyContextProps> = ({
|
|
15
|
+
tenant,
|
|
16
|
+
children,
|
|
17
|
+
}) => (
|
|
18
|
+
<MultiTenancyContext.Provider
|
|
19
|
+
value={{
|
|
20
|
+
tenant,
|
|
21
|
+
getTenantString: (key: string, defaultValue: string = ''): string => {
|
|
22
|
+
const data = translationsMap[tenant]
|
|
23
|
+
return get(data, key, defaultValue)
|
|
24
|
+
},
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</MultiTenancyContext.Provider>
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
export const useMultiTenancy = () => useContext(MultiTenancyContext)
|
|
32
|
+
export default MultiTenancyProvider
|
package/css/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { css } from 'newskit'
|
|
2
|
+
|
|
3
|
+
export const GlobalStyling = css`
|
|
4
|
+
html,
|
|
5
|
+
body {
|
|
6
|
+
padding: 0;
|
|
7
|
+
margin: 0;
|
|
8
|
+
font-family: 'Noto Sans', -apple-system, BlinkMacSystemFont, Segoe UI,
|
|
9
|
+
Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,
|
|
10
|
+
sans-serif;
|
|
11
|
+
}
|
|
12
|
+
* {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const terminalLog = (violations) => {
|
|
2
|
+
cy.task(
|
|
3
|
+
'log',
|
|
4
|
+
`${violations.length} accessibility violation${
|
|
5
|
+
violations.length === 1 ? '' : 's'
|
|
6
|
+
} ${violations.length === 1 ? 'was' : 'were'} detected`
|
|
7
|
+
)
|
|
8
|
+
// pluck specific keys to keep the table readable
|
|
9
|
+
const violationData = violations.map(
|
|
10
|
+
({ id, impact, description, nodes }) => ({
|
|
11
|
+
id,
|
|
12
|
+
impact,
|
|
13
|
+
description,
|
|
14
|
+
nodes: nodes.length,
|
|
15
|
+
})
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
cy.task('table', violationData)
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineConfig } from 'cypress'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
e2e: {
|
|
5
|
+
defaultCommandTimeout: 20000,
|
|
6
|
+
baseUrl: 'http://localhost:3000',
|
|
7
|
+
video: false,
|
|
8
|
+
screenshotOnRunFailure: false,
|
|
9
|
+
specPattern: './cypress/visual/**/*.cy.{js,jsx,ts,tsx}',
|
|
10
|
+
},
|
|
11
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { terminalLog } from '../../axe/terminal-log'
|
|
2
|
+
|
|
3
|
+
const pages = [
|
|
4
|
+
{ url: '/account', name: 'Personal Details' },
|
|
5
|
+
{ url: '/account/edit/name', name: 'Name form' },
|
|
6
|
+
{ url: '/account/edit/displayName', name: 'Display Name form' },
|
|
7
|
+
{ url: '/account/edit/email', name: 'Email form' },
|
|
8
|
+
{ url: '/account/edit/password', name: 'Password form' },
|
|
9
|
+
{ url: '/account/edit/mobile', name: 'Mobile phone form' },
|
|
10
|
+
{ url: '/account/edit/landline', name: 'Landline phone form' },
|
|
11
|
+
{
|
|
12
|
+
url: '/account/edit/address',
|
|
13
|
+
name: 'Address form',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
url: '/account/subscription-and-billing',
|
|
17
|
+
name: 'Subscription and Billing',
|
|
18
|
+
},
|
|
19
|
+
// TODO: Urgerntly find the reason why this state is failing! Uncomment immediately after that
|
|
20
|
+
// {
|
|
21
|
+
// url: '/account/payment',
|
|
22
|
+
// name: 'Payment form',
|
|
23
|
+
// skip: { skipFailures: true },
|
|
24
|
+
// error being caused by Stripe, ignore at this time
|
|
25
|
+
// },
|
|
26
|
+
{
|
|
27
|
+
url: '/account/newsletters-and-alerts',
|
|
28
|
+
name: 'Newsletters and Alerts',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
url: '/account/edit/commenting-notifications',
|
|
32
|
+
name: 'Commenting Notifications form',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
url: '/account/edit/delivery-instructions',
|
|
36
|
+
name: 'Delivery Instructions form',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
url: '/account/holiday-stop',
|
|
40
|
+
name: 'Holiday Stops',
|
|
41
|
+
},
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
describe('Page accessibility', () => {
|
|
45
|
+
pages.forEach(({ url, name, skip }) => {
|
|
46
|
+
it(`Should pass a11y tests: ${name}`, () => {
|
|
47
|
+
cy.mockConsentAndVisit(url)
|
|
48
|
+
const isAddressForm = name === 'Address form'
|
|
49
|
+
if (isAddressForm) {
|
|
50
|
+
cy.get('[data-testid="full-address"]').should('be.visible')
|
|
51
|
+
}
|
|
52
|
+
cy.injectAxe()
|
|
53
|
+
if (isAddressForm) {
|
|
54
|
+
cy.configureAxe({
|
|
55
|
+
rules: [
|
|
56
|
+
{
|
|
57
|
+
id: 'autocomplete-valid',
|
|
58
|
+
enabled: false,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
cy.checkA11y(
|
|
64
|
+
{
|
|
65
|
+
exclude: ['meta[name="viewport"]'],
|
|
66
|
+
},
|
|
67
|
+
null,
|
|
68
|
+
terminalLog,
|
|
69
|
+
skip
|
|
70
|
+
)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('SkipToContent', () => {
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
cy.GetAcsSession()
|
|
78
|
+
cy.mockConsentAndVisit('/account')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('should take the user to the beginning of the main area', () => {
|
|
82
|
+
cy.get('[data-testid="skip-to-content"]').as('skiptocontentBtn')
|
|
83
|
+
cy.get('@skiptocontentBtn').focus()
|
|
84
|
+
cy.get('@skiptocontentBtn').should('contain', 'Skip to main content')
|
|
85
|
+
cy.get('@skiptocontentBtn').click()
|
|
86
|
+
cy.focused().should('have.id', 'main')
|
|
87
|
+
})
|
|
88
|
+
})
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
paymentFailureFirstNotice,
|
|
3
|
+
paymentFailureSecondNotice,
|
|
4
|
+
paymentFailureTerminatedNotice,
|
|
5
|
+
serviceCancellationDate,
|
|
6
|
+
} from '../../fixtures/paymentFailure'
|
|
7
|
+
|
|
8
|
+
describe('Banners', () => {
|
|
9
|
+
it('Should show first notice', () => {
|
|
10
|
+
cy.GetTnlAcsSession('tnl')
|
|
11
|
+
cy.mockConsent()
|
|
12
|
+
cy.visitAndOverrideNextData(
|
|
13
|
+
'/account',
|
|
14
|
+
'props.pageProps.user.paymentFailure',
|
|
15
|
+
paymentFailureFirstNotice
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
cy.get('[data-testid="past-due-banner"]').should('be.visible')
|
|
19
|
+
cy.contains("We haven't been able to take payment")
|
|
20
|
+
cy.contains(
|
|
21
|
+
'You may need to update your payment details to keep your subscription.'
|
|
22
|
+
)
|
|
23
|
+
cy.get('[data-testid="buttonLink"]').should('be.visible')
|
|
24
|
+
cy.get('[data-testid="banner-close-button"]').should('be.visible')
|
|
25
|
+
cy.contains('Update payment details')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('Should show second notice', () => {
|
|
29
|
+
cy.GetTnlAcsSession('tnl')
|
|
30
|
+
cy.mockConsent()
|
|
31
|
+
cy.visitAndOverrideNextData(
|
|
32
|
+
'/account',
|
|
33
|
+
'props.pageProps.user.paymentFailure',
|
|
34
|
+
paymentFailureSecondNotice
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
cy.get('[data-testid="past-due-banner"]').should('be.visible')
|
|
38
|
+
cy.contains('Act now to keep your subscription')
|
|
39
|
+
cy.contains(
|
|
40
|
+
'We’ve tried several times, but haven’t been able to take payment. Please update your payment details to keep your subscription.'
|
|
41
|
+
)
|
|
42
|
+
cy.get('[data-testid="buttonLink"]').should('be.visible')
|
|
43
|
+
cy.get('[data-testid="banner-close-button"]').should('be.visible')
|
|
44
|
+
cy.contains('Update payment details')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('Should show terminated notice', () => {
|
|
48
|
+
cy.GetTnlAcsSession('tnl')
|
|
49
|
+
cy.mockConsent()
|
|
50
|
+
cy.visitAndOverrideNextData(
|
|
51
|
+
'/account',
|
|
52
|
+
'props.pageProps.user.paymentFailure',
|
|
53
|
+
paymentFailureTerminatedNotice
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
cy.get('[data-testid="past-due-banner"]').should('be.visible')
|
|
57
|
+
cy.contains('Your subscription has been terminated')
|
|
58
|
+
cy.contains(
|
|
59
|
+
'We didn’t receive payment for your subscription. To reactivate it, please call XXXX-XXX-XXXX. Or click here.'
|
|
60
|
+
)
|
|
61
|
+
cy.get('[data-testid="banner-close-button"]').should('be.visible')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('Should show to be cancelled notice', () => {
|
|
65
|
+
cy.GetTnlAcsSession('tnl')
|
|
66
|
+
cy.mockConsent()
|
|
67
|
+
cy.visitAndOverrideNextData(
|
|
68
|
+
'/account',
|
|
69
|
+
'props.pageProps.user.subscriptions[0].serviceCancellationDate',
|
|
70
|
+
serviceCancellationDate
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
cy.get('[data-testid="past-due-banner"]').should('be.visible')
|
|
74
|
+
cy.contains('Your subscription will end soon.')
|
|
75
|
+
cy.contains(
|
|
76
|
+
`You have cancelled your subscription and will lose access to all benefits on ${new Date(
|
|
77
|
+
serviceCancellationDate
|
|
78
|
+
).getDate()}/${
|
|
79
|
+
new Date(serviceCancellationDate).getMonth() + 1
|
|
80
|
+
}/${new Date(
|
|
81
|
+
serviceCancellationDate
|
|
82
|
+
).getFullYear()}. To re-activate your subscription call XXXX-XXX-XXXX.`
|
|
83
|
+
)
|
|
84
|
+
cy.get('[data-testid="banner-close-button"]').should('be.visible')
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('Should show expired subscription view with terminated notice', () => {
|
|
88
|
+
cy.GetAcsSession('expiredSub')
|
|
89
|
+
cy.mockConsent()
|
|
90
|
+
const date = new Date(Date.now() - 24 * 35 * 3600 * 1000)
|
|
91
|
+
cy.visit('/account/subscription-and-billing', {
|
|
92
|
+
onBeforeLoad: (win) => {
|
|
93
|
+
let nextData
|
|
94
|
+
|
|
95
|
+
Object.defineProperty(win, '__NEXT_DATA__', {
|
|
96
|
+
set(o) {
|
|
97
|
+
// eslint-disable-next-line no-param-reassign
|
|
98
|
+
o.props.pageProps.user.paymentFailure = {
|
|
99
|
+
active: true,
|
|
100
|
+
startDate: date.toISOString(),
|
|
101
|
+
}
|
|
102
|
+
// eslint-disable-next-line no-param-reassign
|
|
103
|
+
o.props.pageProps.user.subscriptions[0].serviceCancellationDate =
|
|
104
|
+
date.toISOString()
|
|
105
|
+
nextData = o
|
|
106
|
+
},
|
|
107
|
+
get() {
|
|
108
|
+
return nextData
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
Cypress.on('uncaught:exception', (err, runnable) => {
|
|
114
|
+
return false
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
cy.contains('You’ve previously had a subscription that has now expired')
|
|
118
|
+
|
|
119
|
+
cy.contains(
|
|
120
|
+
`On ${date.toLocaleDateString(
|
|
121
|
+
'en-GB'
|
|
122
|
+
)} your Digital subscription expired. You can re-subscribe by confirming a few details or view other packages that are available.`
|
|
123
|
+
)
|
|
124
|
+
cy.get('[data-testid="primary-button"]')
|
|
125
|
+
.should('have.attr', 'href', '/title-re-subscribe')
|
|
126
|
+
.contains('Re-subscribe')
|
|
127
|
+
cy.get('[data-testid="secondary-button"]')
|
|
128
|
+
.should('have.attr', 'href', '/title-subscription-options')
|
|
129
|
+
.contains('View subscription options')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('Should not show banner once it has been dismissed', () => {
|
|
133
|
+
cy.GetAcsSession('withSub')
|
|
134
|
+
cy.mockConsent()
|
|
135
|
+
const date = new Date(Date.now() + 20 * 30 * 3600 * 1000)
|
|
136
|
+
|
|
137
|
+
cy.visitAndOverrideNextData(
|
|
138
|
+
'/account/subscription-and-billing',
|
|
139
|
+
'props.pageProps.user.subscriptions[0].serviceCancellationDate',
|
|
140
|
+
date.toISOString()
|
|
141
|
+
)
|
|
142
|
+
cy.get('[data-testid="past-due-banner"]').should('be.visible')
|
|
143
|
+
cy.contains('Your subscription will end soon.').should('exist')
|
|
144
|
+
cy.get('[data-testid="banner-close-button"]').filter(':visible').click()
|
|
145
|
+
cy.reload()
|
|
146
|
+
cy.get('[data-testid="past-due-banner"]').should('not.exist')
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('Should not display banner if set date is passed current date', () => {
|
|
150
|
+
cy.GetAcsSession('withSub')
|
|
151
|
+
cy.mockConsent()
|
|
152
|
+
const date = new Date(Date.now() - 24 * 35 * 3600 * 1000)
|
|
153
|
+
cy.visitAndOverrideNextData(
|
|
154
|
+
'/account/subscription-and-billing',
|
|
155
|
+
'props.pageProps.user.subscriptions[0].serviceCancellationDate',
|
|
156
|
+
date.toISOString()
|
|
157
|
+
)
|
|
158
|
+
cy.get('[data-testid="past-due-banner"]').should('be.visible')
|
|
159
|
+
cy.contains('Your subscription has been cancelled.').then(() => {
|
|
160
|
+
window.localStorage.setItem(
|
|
161
|
+
'cancelledBanner',
|
|
162
|
+
new Date(new Date().setDate(new Date().getDate() - 7)).toDateString()
|
|
163
|
+
)
|
|
164
|
+
})
|
|
165
|
+
cy.reload()
|
|
166
|
+
cy.get('[data-testid="past-due-banner"]').should('not.exist')
|
|
167
|
+
cy.clearLocalStorage()
|
|
168
|
+
})
|
|
169
|
+
})
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { paymentFailure } from '../../fixtures/paymentFailure'
|
|
2
|
+
|
|
3
|
+
import { serviceCancellationDate } from '../../fixtures/paymentFailure'
|
|
4
|
+
|
|
5
|
+
describe('Cancellation page', () => {
|
|
6
|
+
describe('Find a better name', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
cy.GetTnlAcsSession('digitalCard')
|
|
9
|
+
cy.mockConsentAndVisit('/account/cancellation')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('Should show user cancellation reasons', () => {
|
|
13
|
+
cy.contains('Please tell us why you want to cancel')
|
|
14
|
+
cy.contains(
|
|
15
|
+
'We value your opinion and this information will help us understand how we can improve our product and the services we provide.'
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
cy.contains('Select one option from the list below.')
|
|
19
|
+
|
|
20
|
+
cy.contains(
|
|
21
|
+
'label',
|
|
22
|
+
'I only subscribed to read a specific article/redeem an offer'
|
|
23
|
+
)
|
|
24
|
+
cy.contains(
|
|
25
|
+
'label',
|
|
26
|
+
'I cannot justify paying for my current subscription'
|
|
27
|
+
)
|
|
28
|
+
cy.contains(
|
|
29
|
+
'label',
|
|
30
|
+
'I do not have enough time to read the edition everyday'
|
|
31
|
+
)
|
|
32
|
+
cy.contains('label', 'I prefer another news subscription service')
|
|
33
|
+
cy.contains('label', 'I do not enjoy the journalism')
|
|
34
|
+
cy.contains('label', 'I am travelling or moving abroad')
|
|
35
|
+
cy.contains('label', 'Other')
|
|
36
|
+
cy.contains('label', 'Prefer not to say')
|
|
37
|
+
|
|
38
|
+
cy.contains('[data-testid="primary-button"]', 'Continue cancellation')
|
|
39
|
+
cy.contains('[data-testid="secondary-button"]', 'Keep subscription')
|
|
40
|
+
|
|
41
|
+
//Redirects to Subscription and Billing page
|
|
42
|
+
cy.get('[data-testid="secondary-button"]').click()
|
|
43
|
+
cy.location().should((loc) => {
|
|
44
|
+
expect(loc.pathname).to.eq('/account/subscription-and-billing')
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
it('Should show user text field when selecting Other as option', () => {
|
|
48
|
+
cy.contains('Select one option from the list below.')
|
|
49
|
+
cy.get('[type="radio"]').check('Other')
|
|
50
|
+
cy.contains('(please state)')
|
|
51
|
+
|
|
52
|
+
cy.get('textarea[name="other"]').clear()
|
|
53
|
+
cy.get('textarea[name="other"]').type('Thanks my business') //There is no validation for the text area
|
|
54
|
+
cy.get('[data-testid="primary-button"]').click()
|
|
55
|
+
|
|
56
|
+
cy.contains('Are you sure you want to cancel your subscription?')
|
|
57
|
+
cy.contains('Cancel subscription')
|
|
58
|
+
})
|
|
59
|
+
it('Should cancel user subscription', () => {
|
|
60
|
+
cy.contains('Select one option from the list below.')
|
|
61
|
+
cy.contains(
|
|
62
|
+
'I only subscribed to read a specific article/redeem an offer'
|
|
63
|
+
).click()
|
|
64
|
+
cy.get('[data-testid="primary-button"]').click()
|
|
65
|
+
|
|
66
|
+
//Cancelation confirmation modal
|
|
67
|
+
cy.contains('Are you sure you want to cancel your subscription?')
|
|
68
|
+
cy.contains(
|
|
69
|
+
'You will lose unlimited access to exclusive content and benefits.'
|
|
70
|
+
)
|
|
71
|
+
cy.contains('Please note:')
|
|
72
|
+
cy.contains(
|
|
73
|
+
'Your subscription full access will be revoked by the end of your current bill cycle.'
|
|
74
|
+
)
|
|
75
|
+
cy.contains('Cancel subscription')
|
|
76
|
+
cy.contains('Keep subscription')
|
|
77
|
+
|
|
78
|
+
cy.intercept('POST', '/api/account/mutate', {
|
|
79
|
+
statusCode: 200,
|
|
80
|
+
body: { data: { cancelSubscription: { success: true } } },
|
|
81
|
+
})
|
|
82
|
+
cy.get('[data-testid="primary-button"]').click()
|
|
83
|
+
|
|
84
|
+
cy.contains(
|
|
85
|
+
'[data-testid="toast-container"]',
|
|
86
|
+
'Cancelling your subscription'
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// Post-cancellation modal
|
|
90
|
+
cy.get('[data-testid="dialog-content"]').should('be.visible')
|
|
91
|
+
cy.contains('Subscription cancelled')
|
|
92
|
+
cy.contains(
|
|
93
|
+
'Sorry to see you go, cancellation will be effective immediately and any current subscription benefits will be removed from your account.'
|
|
94
|
+
)
|
|
95
|
+
cy.contains(
|
|
96
|
+
'If you change your mind or cancelled by mistake, speak to one of our advisors on XXXX-XXX-XXXX.'
|
|
97
|
+
)
|
|
98
|
+
cy.contains('Back to account')
|
|
99
|
+
|
|
100
|
+
cy.get('[data-testid="centered-button"]').click()
|
|
101
|
+
|
|
102
|
+
cy.location().should((loc) => {
|
|
103
|
+
expect(loc.pathname).to.eq('/account/subscription-and-billing')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
cy.visitAndOverrideNextData(
|
|
107
|
+
'/account/subscription-and-billing',
|
|
108
|
+
'props.pageProps.user.subscriptions[0].serviceCancellationDate',
|
|
109
|
+
serviceCancellationDate
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
cy.get('[data-testid="inline-message"]').contains(
|
|
113
|
+
'Your subscription will end soon'
|
|
114
|
+
)
|
|
115
|
+
cy.get('[data-testid="inline-message"]').contains(
|
|
116
|
+
'If you change your mind or cancelled by mistake, speak to one of our advisors on XXXX-XXX-XXXX.'
|
|
117
|
+
)
|
|
118
|
+
cy.get('a[href="/account/cancellation"]').should('not.exist')
|
|
119
|
+
})
|
|
120
|
+
it('Should show validation error messages when user tries to cancell subscription without selecting a cancellation reason', () => {
|
|
121
|
+
cy.contains('Select one option from the list below.')
|
|
122
|
+
cy.get('[data-testid="primary-button"]').click()
|
|
123
|
+
cy.contains('Please, select one option')
|
|
124
|
+
})
|
|
125
|
+
it('Should select only one cancellation reason', () => {
|
|
126
|
+
cy.contains('Select one option from the list below.')
|
|
127
|
+
|
|
128
|
+
cy.contains(
|
|
129
|
+
'I only subscribed to read a specific article/redeem an offer'
|
|
130
|
+
).click()
|
|
131
|
+
|
|
132
|
+
cy.get(
|
|
133
|
+
'input[value="I only subscribed to read a specific article/redeem an offer"]'
|
|
134
|
+
).should('be.checked')
|
|
135
|
+
cy.get(
|
|
136
|
+
'input[value="I cannot justify paying for my current subscription"]'
|
|
137
|
+
).should('not.be.checked')
|
|
138
|
+
cy.get(
|
|
139
|
+
'input[value="I do not have enough time to read the edition everyday"]'
|
|
140
|
+
).should('not.be.checked')
|
|
141
|
+
cy.get(
|
|
142
|
+
'input[value="I prefer another news subscription service"]'
|
|
143
|
+
).should('not.be.checked')
|
|
144
|
+
cy.get('input[value="I do not enjoy the journalism"]').should(
|
|
145
|
+
'not.be.checked'
|
|
146
|
+
)
|
|
147
|
+
cy.get('input[value="I am travelling or moving abroad"]').should(
|
|
148
|
+
'not.be.checked'
|
|
149
|
+
)
|
|
150
|
+
cy.get('input[value="Other"]').should('not.be.checked')
|
|
151
|
+
cy.get('input[value="Prefer not to say"]').should('not.be.checked')
|
|
152
|
+
|
|
153
|
+
cy.contains('I prefer another news subscription service').click()
|
|
154
|
+
|
|
155
|
+
cy.get(
|
|
156
|
+
'input[value="I only subscribed to read a specific article/redeem an offer"]'
|
|
157
|
+
).should('not.be.checked')
|
|
158
|
+
cy.get(
|
|
159
|
+
'input[value="I cannot justify paying for my current subscription"]'
|
|
160
|
+
).should('not.be.checked')
|
|
161
|
+
cy.get(
|
|
162
|
+
'input[value="I do not have enough time to read the edition everyday"]'
|
|
163
|
+
).should('not.be.checked')
|
|
164
|
+
cy.get(
|
|
165
|
+
'input[value="I prefer another news subscription service"]'
|
|
166
|
+
).should('be.checked')
|
|
167
|
+
cy.get('input[value="I do not enjoy the journalism"]').should(
|
|
168
|
+
'not.be.checked'
|
|
169
|
+
)
|
|
170
|
+
cy.get('input[value="I am travelling or moving abroad"]').should(
|
|
171
|
+
'not.be.checked'
|
|
172
|
+
)
|
|
173
|
+
cy.get('input[value="Other"]').should('not.be.checked')
|
|
174
|
+
cy.get('input[value="Prefer not to say"]').should('not.be.checked')
|
|
175
|
+
})
|
|
176
|
+
it('Should show error toast when canceling subscription if internal server error occures', () => {
|
|
177
|
+
cy.intercept('POST', '/api/account/mutate', { statusCode: 500 })
|
|
178
|
+
|
|
179
|
+
cy.contains('Select one option from the list below.')
|
|
180
|
+
cy.contains('I am travelling or moving abroad').click()
|
|
181
|
+
cy.get('[data-testid="primary-button"]').click()
|
|
182
|
+
|
|
183
|
+
cy.contains(
|
|
184
|
+
'You will lose unlimited access to exclusive content and benefits.'
|
|
185
|
+
)
|
|
186
|
+
cy.get('[data-testid="primary-button"]').click()
|
|
187
|
+
|
|
188
|
+
cy.contains(
|
|
189
|
+
'[data-testid="toast-container"]',
|
|
190
|
+
"Sorry, we're unable to save your cancellation right now. Please try again or come back later."
|
|
191
|
+
)
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('Should show outstanding payment modal for user in payment failure', () => {
|
|
196
|
+
cy.GetTnlAcsSession('digitalCard')
|
|
197
|
+
cy.mockConsent()
|
|
198
|
+
cy.visitAndOverrideNextData(
|
|
199
|
+
'/account/subscription-and-billing',
|
|
200
|
+
'props.pageProps.user.paymentFailure',
|
|
201
|
+
paymentFailure
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
cy.get('a[href="/account/cancellation"]').should('be.visible').click()
|
|
205
|
+
|
|
206
|
+
cy.contains('You have outstanding payments')
|
|
207
|
+
cy.contains(
|
|
208
|
+
'If you wish to cancel your subscription update your payment details or speak to one of our advisors on XXXX-XXX-XXXX.'
|
|
209
|
+
)
|
|
210
|
+
cy.contains('Update payment details')
|
|
211
|
+
|
|
212
|
+
cy.get('[data-testid="centered-button"]').click()
|
|
213
|
+
|
|
214
|
+
cy.location().should((loc) => {
|
|
215
|
+
expect(loc.pathname).to.eq('/account/payment')
|
|
216
|
+
})
|
|
217
|
+
cy.contains('Edit your payment method')
|
|
218
|
+
})
|
|
219
|
+
})
|