@newskit-render/core 1.42.3 → 1.45.0

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.
@@ -255,7 +255,7 @@ exports[`Footer tests should render footer 1`] = `
255
255
  >
256
256
  <svg
257
257
  class="emotion-5"
258
- height="40px"
258
+ height="48px"
259
259
  viewBox="0 0 244 40"
260
260
  >
261
261
  <title>
@@ -263,15 +263,17 @@ exports[`Footer tests should render footer 1`] = `
263
263
  </title>
264
264
  <path
265
265
  d="M61.846.936c3.35.413 4.944 4.005 4.92 8.746l.017-.013c-5.497 4.462-16.323 7.515-26.958 1.71l.011-.016c1.568.832 3.224 1.475 5.172 1.715 2.386.294 4.303-1.023 6.043-2.889l.124-.134.062-.068.123-.137.123-.138.122-.14.121-.142.061-.071.121-.144.12-.145.146-.178.073-.09.182-.226.181-.228.144-.184.144-.185.143-.185.215-.279 1.091-1.431.209-.271.209-.269.14-.178.14-.177.14-.175.141-.173.141-.172.113-.136.113-.135.114-.133.114-.132.057-.065.114-.13.057-.064.115-.127.173-.187.116-.123.175-.18.117-.118C58.328 1.663 59.933.7 61.846.936z"
266
- fill="#aebfff"
266
+ fill="white"
267
267
  />
268
268
  <path
269
269
  d="M26.763 28.981l.011.013c-1.414-.671-2.883-1.176-4.519-1.378-1.738-.214-3.244.513-4.634 1.704l-.11.095-.163.146-.108.1-.108.101-.268.261-.106.107-.106.109-.106.11-.053.056-.105.112-.053.057-.125.136-.124.138-.124.139-.062.07-.123.142-.123.143-.122.145-.122.146-.061.073-.15.183-.075.092-.149.185-.075.093-.149.187-.149.188-.223.283-.296.38-.671.866-.222.285-.222.283-.148.188-.223.28-.149.185-.149.183-.149.182-.15.18-.117.139-.118.138-.118.136-.118.135-.119.133-.119.132-.119.13-.06.064-.12.127-.1.104-.1.103-.1.101-.151.15-.101.098-.102.096-.051.048-.102.094-.206.183-.103.089-.052.044-.104.086c-1.302 1.066-2.706 1.698-4.305 1.5-3.321-.41-4.98-3.93-5.064-8.601l-.097.09c6.351-5.963 17.155-6.757 26.506-2.264z"
270
- fill="#3358cc"
270
+ fill="white"
271
+ fill-opacity="0.4"
271
272
  />
272
273
  <path
273
274
  d="M42.216 35.925c-2.861-.398-5.212-1.275-7.302-2.318l-.189-.095-.188-.096-.186-.097-.231-.122-.229-.123-.182-.099-.226-.125-.224-.126-.178-.101-.177-.102-.264-.153-.349-.205-.278-.166-.276-.166-.411-.249-1.214-.738-.334-.201-.333-.199-2.669-1.45-.012-.013c-9.258-4.447-19.94-3.714-26.315 2.087l-.095.088C.156 20.101 8.779 2.598 25.068 4.608c2.854.352 5.141 1.176 7.14 2.181l.178.09.177.091.175.092.087.046.173.093.172.094.17.095.085.048.211.12.209.121.166.097.165.098.164.098.163.099.162.099.161.099.16.1.261.164.13.082.258.164.256.164 1.137.733.25.161.25.159.312.197.312.194a31.02 31.02 0 0 0 1.568.911l.199.106c10.506 5.694 21.166 2.775 26.7-1.604l.149-.12c-.055 10.998-8.815 28.185-24.55 26.243z"
274
- fill="#577ffb"
275
+ fill="white"
276
+ fill-opacity="0.701961"
275
277
  />
276
278
  </svg>
277
279
  </div>
@@ -53,4 +53,21 @@ describe('Header tests', () => {
53
53
  '/section-three'
54
54
  )
55
55
  })
56
+
57
+ test('render Account link if there is user data', () => {
58
+ const user = {
59
+ firstName: '',
60
+ lastName: '',
61
+ cpn: '',
62
+ email: '',
63
+ hash: '',
64
+ mobile: '',
65
+ phoneNumber: '',
66
+ dateOfBirth: '',
67
+ subscriptions: [],
68
+ paymentFailure: { active: false },
69
+ }
70
+ const { getByTestId } = renderWithTheme(Header, { user })
71
+ expect(getByTestId('account-link')).toBeInTheDocument()
72
+ })
56
73
  })
@@ -31,12 +31,14 @@ import NewsKitLogoShort from '../common/NewskitLogoShort'
31
31
  import NavLink from '../common/NavLink'
32
32
  import { AppContext } from '../../app-context/AppContext'
33
33
  import { handleEnterKeyPress } from '../../helpers/a11y'
34
+ import IconNavLink from '../common/iconNavLink'
35
+ import { IconAccount } from '../common/icons/IconAccount'
34
36
 
35
- export const headerSize = 'sizing090'
37
+ export const headerSize = 'sizing100'
36
38
 
37
39
  const StyledHeader = styled.div`
38
40
  ${getSizingCssFromTheme('height', headerSize)}
39
- ${getColorCssFromTheme('backgroundColor', 'customInterfaceBrand')};
41
+ ${getColorCssFromTheme('backgroundColor', 'interfaceBrand010')};
40
42
  a,
41
43
  a:visited:not(:disabled) {
42
44
  ${getColorCssFromTheme('color', 'white')};
@@ -44,14 +46,14 @@ const StyledHeader = styled.div`
44
46
  line-height: ${getFontsFromTheme('fontLineHeight040')};
45
47
  }
46
48
  ${getMediaQueryFromTheme('xs')} {
47
- ${getSizingCssFromTheme('paddingTop', 'sizing030')};
48
- ${getSizingCssFromTheme('paddingBottom', 'sizing030')};
49
+ ${getSizingCssFromTheme('paddingTop', 'sizing040')};
50
+ ${getSizingCssFromTheme('paddingBottom', 'sizing040')};
49
51
  ${getSizingCssFromTheme('paddingLeft', 'sizing000')};
50
52
  ${getSizingCssFromTheme('paddingRight', 'sizing000')};
51
53
  }
52
54
  ${getMediaQueryFromTheme('lg')} {
53
- ${getSizingCssFromTheme('paddingTop', 'sizing030')};
54
- ${getSizingCssFromTheme('paddingBottom', 'sizing030')};
55
+ ${getSizingCssFromTheme('paddingTop', 'sizing040')};
56
+ ${getSizingCssFromTheme('paddingBottom', 'sizing040')};
55
57
  ${getSizingCssFromTheme('paddingLeft', 'sizing090')};
56
58
  ${getSizingCssFromTheme('paddingRight', 'sizing090')};
57
59
  }
@@ -111,14 +113,14 @@ const NavigationContainer = styled.div<NavigationProps>`
111
113
  overflow: auto;
112
114
  width: 100%;
113
115
  min-height: 100vh;
114
- ${getColorCssFromTheme('backgroundColor', 'neutral100')};
116
+ ${getColorCssFromTheme('backgroundColor', 'interfaceBrand010')};
115
117
  left: 0;
116
118
  ${getSizingCssFromTheme('top', headerSize)}
117
- z-index: 1;
119
+ z-index: 2;
118
120
  display: ${(props) => (props.show ? 'block' : 'none')};
119
121
 
120
122
  ${getMediaQueryFromTheme('md')} {
121
- display: block;
123
+ display: flex;
122
124
  position: relative;
123
125
  overflow: hidden;
124
126
  width: initial;
@@ -127,6 +129,7 @@ const NavigationContainer = styled.div<NavigationProps>`
127
129
  left: initial;
128
130
  top: initial;
129
131
  z-index: 1;
132
+ ${getSizingCssFromTheme('height', 'sizing080')}
130
133
  }
131
134
  `
132
135
 
@@ -146,12 +149,10 @@ const Navigation = styled.div`
146
149
  const NavButton = ({
147
150
  buttonText,
148
151
  href,
149
- isMobile,
150
152
  ariaLabel,
151
153
  }: {
152
154
  buttonText: string
153
155
  href: string
154
- isMobile: boolean
155
156
  isLast?: boolean
156
157
  ariaLabel?: string
157
158
  }) => (
@@ -159,9 +160,12 @@ const NavButton = ({
159
160
  as="span"
160
161
  spaceInline={{
161
162
  xs: 'space000',
162
- md: 'space050',
163
+ md: 'space040',
164
+ }}
165
+ spaceStack={{
166
+ xs: 'space050',
167
+ md: 'space000',
163
168
  }}
164
- spaceStack={isMobile ? 'space050' : ''}
165
169
  >
166
170
  <NavLink href={href} ariaLabel={ariaLabel} buttonText={buttonText} />
167
171
  </Block>
@@ -228,8 +232,11 @@ const Header: React.FC<{ user: UserData }> = ({ user }) => {
228
232
  stackDistribution="flex-end"
229
233
  wrap="nowrap"
230
234
  >
231
- <NavigationContainer show={showMenu}>
232
- <Navigation>
235
+ <NavigationContainer
236
+ show={showMenu}
237
+ data-testid="NavigationContainer"
238
+ >
239
+ <Navigation data-testid="Navigation">
233
240
  {showMenu && (
234
241
  <Block
235
242
  spaceStack="space050"
@@ -239,21 +246,28 @@ const Header: React.FC<{ user: UserData }> = ({ user }) => {
239
246
  <NavButton
240
247
  buttonText="Section One"
241
248
  href="/section-one"
242
- isMobile={showMenu}
243
249
  ariaLabel="Section One Link"
244
250
  />
245
251
  <NavButton
246
252
  buttonText="Section Two"
247
253
  href="/section-two"
248
- isMobile={showMenu}
249
254
  ariaLabel="Section Two Link"
250
255
  />
251
256
  <NavButton
252
257
  buttonText="Section Three"
253
258
  href="/section-three"
254
- isMobile={showMenu}
255
259
  ariaLabel="Section Three Link"
256
260
  />
261
+ {user && (
262
+ <IconNavLink
263
+ icon={<IconAccount data-testid="account-link" />}
264
+ href="/account"
265
+ text="Account"
266
+ spaceInline="space040"
267
+ typographyPreset="utilityMeta020"
268
+ stylePreset="linkStandaloneInverse"
269
+ />
270
+ )}
257
271
  </Navigation>
258
272
  </NavigationContainer>
259
273
  <Visible xs sm>
@@ -1,3 +1,25 @@
1
+ describe('Account without user', () => {
2
+ beforeEach(() => {
3
+ cy.mockConsentAndVisit('/account')
4
+ })
5
+
6
+ it('Should Display default fallback values', () => {
7
+ cy.get('[data-testid="ContentListIntroduction"]').should('have.length', 3)
8
+ cy.get('[data-testid="ContentListItems"]').should('have.length', 3)
9
+ cy.contains('Please enter your name')
10
+ cy.contains('Please call customer service on xxxx-xxx-xxxx')
11
+ cy.contains('Please enter your display name')
12
+ cy.contains(
13
+ 'Your display name is used across our websites or apps when leaving comments on articles'
14
+ )
15
+ cy.contains('[email@address]')
16
+ cy.contains('******************')
17
+ cy.contains('Please enter your mobile telephone number')
18
+ cy.contains('Please enter your landline telephone number')
19
+ cy.contains('Please enter your address')
20
+ })
21
+ })
22
+
1
23
  describe('My account personal details', () => {
2
24
  beforeEach(() => {
3
25
  cy.GetAcsSession()
@@ -77,6 +99,10 @@ describe('My account personal details', () => {
77
99
  )
78
100
  })
79
101
 
102
+ it.only('Should Display date of birth', () => {
103
+ cy.contains('21/03/1988')
104
+ })
105
+
80
106
  it('Should go to edit page and change display name ', () => {
81
107
  cy.get('a[href="/account/edit/displayName"]')
82
108
  .should('be.visible')
@@ -176,7 +202,7 @@ describe('My account personal details', () => {
176
202
  .children()
177
203
  .should(
178
204
  'contain',
179
- 'Email sent to temp.account@tempaccount.com with a password reset link. If you haven’t received it in a couple of minutes, you may request a new link by clicking on the button below.'
205
+ 'Email sent to render.e2e.default@yopmail.com with a password reset link. If you haven’t received it in a couple of minutes, you may request a new link by clicking on the button below.'
180
206
  )
181
207
  })
182
208
 
@@ -219,4 +219,49 @@ describe('Account Subscription & Cancellation', () => {
219
219
  cy.get('[data-testid="banner-container"]').should('not.exist')
220
220
  cy.clearLocalStorage()
221
221
  })
222
+
223
+ it('should show modal when Cancel subscription link is clicked but user is in payment failure', () => {
224
+ cy.GetAcsSession('withSub')
225
+ cy.mockConsent()
226
+ cy.visit('/account/subscription-and-billing', {
227
+ onBeforeLoad: (win) => {
228
+ let nextData
229
+
230
+ Object.defineProperty(win, '__NEXT_DATA__', {
231
+ set(o) {
232
+ // eslint-disable-next-line no-param-reassign
233
+ o.props.pageProps.user.paymentFailure = {
234
+ active: true,
235
+ startDate: new Date().toISOString(),
236
+ }
237
+ nextData = o
238
+ },
239
+ get() {
240
+ return nextData
241
+ },
242
+ })
243
+ },
244
+ })
245
+ cy.get('a[href="/account/cancellation"]').should('be.visible').click()
246
+
247
+ cy.contains('You have outstanding payments')
248
+ })
249
+
250
+ it('should show paypal subscription', () => {
251
+ cy.GetAcsSession('paypalSub')
252
+ cy.mockConsentAndVisit('/account/subscription-and-billing')
253
+ cy.contains('[data-testid="payment-type"]', 'Paypal account')
254
+ })
255
+
256
+ it('should show inline message for paypal subscription', () => {
257
+ cy.GetAcsSession('paypalSub')
258
+ cy.mockConsentAndVisit('/account/subscription-and-billing')
259
+ cy.get('a[href="/account/payment"]')
260
+ .should('be.visible')
261
+ .click({ force: true })
262
+ cy.contains(
263
+ '[data-testid="Zuora-inline"]',
264
+ 'To update your Paypal credentials, please speak to one of our advisors on xxxx-xxx-xxxx or add a new payment method via credit/debit card using the form below.'
265
+ )
266
+ })
222
267
  })
@@ -21,7 +21,7 @@ describe('MAIN API', () => {
21
21
  cy.get('@mutateUser').then((updatedUser) => {
22
22
  expect(updatedUser.status).to.eq(200)
23
23
  expect(updatedUser.body.data.updateUser.email).to.eq(
24
- 'temp.account@tempaccount.com'
24
+ 'render.e2e.default@yopmail.com'
25
25
  )
26
26
  })
27
27
  })
@@ -43,7 +43,7 @@ describe('MAIN API', () => {
43
43
  cy.get('@mutateUser').then((updatedUser) => {
44
44
  expect(updatedUser.status).to.eq(200)
45
45
  expect(updatedUser.body.data.updateUser.email).to.eq(
46
- 'temp.account@tempaccount.com'
46
+ 'render.e2e.default@yopmail.com'
47
47
  )
48
48
  })
49
49
  })
@@ -63,7 +63,7 @@ describe('MAIN API', () => {
63
63
  }).as('user')
64
64
  cy.get('@user').then((response) => {
65
65
  expect(response.status).to.eq(200)
66
- expect(response.body.email).to.eq('temp.account@tempaccount.com')
66
+ expect(response.body.email).to.eq('render.e2e.default@yopmail.com')
67
67
  expect(response.body.mobile).to.eq('+447777777778')
68
68
  expect(response.body.firstName).to.eq('John')
69
69
  expect(response.body.lastName).to.eq('Smith')
@@ -85,7 +85,7 @@ describe('MAIN API', () => {
85
85
  }).as('userSubscription')
86
86
  cy.get('@userSubscription').then((response) => {
87
87
  expect(response.status).to.eq(200)
88
- expect(response.body.cpn).to.eq('4AAA038732032')
88
+ expect(response.body.cpn).to.eq('4AAA038765003')
89
89
  assert.isArray(response.body.subscriptions)
90
90
  })
91
91
  })
@@ -11,8 +11,8 @@ Cypress.Commands.add('mockConsent', () => {
11
11
 
12
12
  const userMap = {
13
13
  default: {
14
- username: 'temp.account@tempaccount.com',
15
- password: 'asdasd1A',
14
+ username: 'render.e2e.default@yopmail.com',
15
+ password: 'Ad45p0-swq151@',
16
16
  },
17
17
  noSub: {
18
18
  username: 'render.e2e.no-sub@yopmail.com',
@@ -25,7 +25,11 @@ const userMap = {
25
25
  withSub: {
26
26
  username: 'render.e2e.sub@yopmail.com',
27
27
  password: 'Ad45p0-swq151@',
28
- }
28
+ },
29
+ paypalSub: {
30
+ username: 'render-paypal-payment@yopmail.com',
31
+ password: 'testing123',
32
+ },
29
33
  }
30
34
 
31
35
  Cypress.Commands.add('GetAcsSession', (user = 'default') => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newskit-render/core",
3
- "version": "1.42.3",
3
+ "version": "1.45.0",
4
4
  "description": "Newskit Render - Core package",
5
5
  "author": "",
6
6
  "license": "UNLICENSED",
@@ -33,13 +33,14 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@apollo/client": "3.4.16",
36
- "@newskit-render/api": "^0.18.0",
37
- "@newskit-render/auth": "^0.31.2",
38
- "@newskit-render/checkout": "^0.26.1",
36
+ "@newskit-render/api": "^0.18.1",
37
+ "@newskit-render/auth": "^0.31.3",
38
+ "@newskit-render/checkout": "^0.26.4",
39
39
  "@newskit-render/feature-flags": "^0.13.0",
40
- "@newskit-render/feed": "^0.5.1",
41
- "@newskit-render/my-account": "^0.151.1",
42
- "@newskit-render/shared-components": "^0.43.1",
40
+ "@newskit-render/feed": "^0.5.3",
41
+ "@newskit-render/my-account": "^0.152.4",
42
+ "@newskit-render/shared-components": "^0.45.1",
43
+ "@newskit-render/standalone-components": "^0.2.1",
43
44
  "@newskit-render/validation": "^0.39.1",
44
45
  "cross-fetch": "3.1.5",
45
46
  "graphql": "15.6.0",
@@ -4,11 +4,15 @@ import {
4
4
  createApolloClient,
5
5
  ClientTypes,
6
6
  getAcsCookie,
7
+ Publisher,
7
8
  } from '@newskit-render/api'
8
9
  import { UserData } from '@newskit-render/my-account'
10
+ import {
11
+ recommendationsProvider,
12
+ Article,
13
+ } from '@newskit-render/standalone-components'
9
14
  import { GET_UNIVERSAL_ARTICLE } from '../../../queries'
10
15
  import ArticlePage, { UniversalArticle } from '../../../components/article'
11
- import { highlights, relatedArticles } from '../../../helpers/mocks/articleMock'
12
16
  import { fetchUser } from '../../../helpers/getUser'
13
17
  import { ACCOUNT_QUERY_URL } from '../../../constants'
14
18
  import { addCacheHeaders } from '../../../helpers/addCacheHeaders'
@@ -20,6 +24,7 @@ export type ArticleSlug = {
20
24
  siteHost: string
21
25
  gscId?: string
22
26
  user?: UserData
27
+ recommendations: Article[]
23
28
  }
24
29
  const Article: React.FC<ArticleSlug> = ({
25
30
  universalArticle,
@@ -28,7 +33,11 @@ const Article: React.FC<ArticleSlug> = ({
28
33
  siteHost,
29
34
  gscId,
30
35
  user,
36
+ recommendations,
31
37
  }) => {
38
+ const highlitedArticles = recommendations.slice(0, 4)
39
+ const relatedArticles = recommendations.slice(4, 12)
40
+
32
41
  return (
33
42
  <ArticlePage
34
43
  articleURL={articleURL}
@@ -36,7 +45,7 @@ const Article: React.FC<ArticleSlug> = ({
36
45
  siteHost={siteHost}
37
46
  gscId={gscId}
38
47
  twitterUsername={twitterUsername}
39
- highlights={highlights}
48
+ highlights={highlitedArticles}
40
49
  relatedArticles={relatedArticles}
41
50
  user={user}
42
51
  />
@@ -57,11 +66,12 @@ export async function getServerSideProps(context) {
57
66
  `Article: /${section}/${articleId}/${articleSlug}`
58
67
  )
59
68
 
60
- const [{ data }, user] = await Promise.all([
69
+ const [{ data }, recommendations, user] = await Promise.all([
61
70
  apolloClient.query({
62
71
  query: GET_UNIVERSAL_ARTICLE,
63
72
  variables: { publisher: 'DEMO', id: articleId },
64
73
  }),
74
+ await recommendationsProvider({ articleId, publisher: Publisher.SUN_UK }),
65
75
  await fetchUser(acsCookie, ACCOUNT_QUERY_URL),
66
76
  ])
67
77
 
@@ -74,6 +84,7 @@ export async function getServerSideProps(context) {
74
84
  siteHost: process.env.SITE_HOST || '',
75
85
  gscId: process.env.GSC_ID || '',
76
86
  showAds: true,
87
+ recommendations,
77
88
  user,
78
89
  },
79
90
  }
@@ -1,10 +1,18 @@
1
1
  import { NextApiRequest, NextApiResponse } from 'next'
2
- import { newsSitemap, PublisherGroup } from '@newskit-render/feed'
2
+ import { newsSitemap } from '@newskit-render/feed'
3
+ import { Publisher } from '@newskit-render/api'
4
+
5
+ /* We do not have sitemap date for Demo so using Virgin,
6
+ * This can be removed and replace with just - publisher: process.env.PUBLISHER as PublisherGroup, in created projects
7
+ */
3
8
 
4
9
  const handler = async (req: NextApiRequest, res: NextApiResponse) =>
5
10
  newsSitemap({
6
11
  res,
7
- publisher: process.env.PUBLISHER as PublisherGroup,
12
+ publisher:
13
+ process.env.PUBLISHER === 'DEMO'
14
+ ? Publisher.VIRGIN
15
+ : (process.env.PUBLISHER as Publisher),
8
16
  domain: new URL(process.env.SITE_HOST as string).host,
9
17
  publicationName: process.env.SITEMAP_PUBLICATION_NAME as string,
10
18
  })
@@ -1,9 +1,10 @@
1
1
  import { NextApiRequest, NextApiResponse } from 'next'
2
- import {
3
- genericSitemap,
4
- PublisherGroup,
5
- CustomStaticPage,
6
- } from '@newskit-render/feed'
2
+ import { genericSitemap, CustomStaticPage } from '@newskit-render/feed'
3
+ import { Publisher } from '@newskit-render/api'
4
+
5
+ /* We do not have sitemap date for Demo so using Virgin,
6
+ * This can be removed and replace with just - publisher: process.env.PUBLISHER as PublisherGroup, in created projects
7
+ */
7
8
 
8
9
  const defaultCustomStaticPagesCollection: CustomStaticPage[] = [
9
10
  {
@@ -14,7 +15,10 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) =>
14
15
  genericSitemap({
15
16
  res,
16
17
  query: req.query,
17
- publisher: process.env.PUBLISHER as PublisherGroup,
18
+ publisher:
19
+ process.env.PUBLISHER === 'DEMO'
20
+ ? Publisher.VIRGIN
21
+ : (process.env.PUBLISHER as Publisher),
18
22
  domain: new URL(process.env.SITE_HOST as string).host,
19
23
  firstArticleDate: process.env.SITEMAP_FIRST_PUBLICATION_DATE as string,
20
24
  publicationName: process.env.SITEMAP_PUBLICATION_NAME as string,