Просмотр исходного кода

Merge pull request #7779 from overleaf/ta-settings-fixes-3

[SettingsPage] Small Fixes 3

GitOrigin-RevId: 98accb3c53c802e83f2939e5c25d13fcf3b5e054
Miguel Serrano 4 лет назад
Родитель
Сommit
14a22de754

+ 13 - 5
services/web/frontend/js/features/settings/components/linking-section.tsx

@@ -1,17 +1,25 @@
+import { useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
 import { useSSOContext, SSOSubscription } from '../context/sso-context'
 import { SSOLinkingWidget } from './linking/sso-widget'
-
-const integrationLinkingWidgets = importOverleafModules(
-  'integrationLinkingWidgets'
-)
-const referenceLinkingWidgets = importOverleafModules('referenceLinkingWidgets')
+import getMeta from '../../../utils/meta'
 
 function LinkingSection() {
   const { t } = useTranslation()
   const { subscriptions } = useSSOContext()
 
+  const [integrationLinkingWidgets] = useState(
+    () =>
+      getMeta('integrationLinkingWidgets') ||
+      importOverleafModules('integrationLinkingWidgets')
+  )
+  const [referenceLinkingWidgets] = useState(
+    () =>
+      getMeta('referenceLinkingWidgets') ||
+      importOverleafModules('referenceLinkingWidgets')
+  )
+
   const hasIntegrationLinkingSection = integrationLinkingWidgets.length
   const hasReferencesLinkingSection = referenceLinkingWidgets.length
   const hasSSOLinkingSection = Object.keys(subscriptions).length > 0

+ 7 - 3
services/web/frontend/js/features/settings/components/root.tsx

@@ -64,12 +64,16 @@ function SettingsPageContent() {
           <SSOProvider>
             <LinkingSection />
           </SSOProvider>
-          {isOverleaf ? <BetaProgramSection /> : null}
-          <hr />
+          {isOverleaf ? (
+            <>
+              <BetaProgramSection />
+              <hr />
+            </>
+          ) : null}
           <SessionsSection />
-          <hr />
           {isOverleaf ? (
             <>
+              <hr />
               <NewsletterSection />
               <hr />
               <LeaveSection />

+ 1 - 1
services/web/frontend/js/features/settings/context/sso-context.tsx

@@ -35,7 +35,7 @@ type SSOProviderProps = {
 
 export function SSOProvider({ children }: SSOProviderProps) {
   const isMountedRef = useIsMounted()
-  const oauthProviders = getMeta('ol-oauthProviders') as OAuthProviders
+  const oauthProviders = getMeta('ol-oauthProviders', {}) as OAuthProviders
   const thirdPartyIds = getMeta('ol-thirdPartyIds') as ThirdPartyIds
 
   const [subscriptions, setSubscriptions] = useState<

+ 2 - 0
services/web/frontend/stories/settings/helpers/account-info.js

@@ -9,11 +9,13 @@ export function defaultSetupMocks(fetchMock) {
 export function setDefaultMeta() {
   window.metaAttributesCache = window.metaAttributesCache || new Map()
   window.metaAttributesCache.set('ol-user', {
+    ...window.metaAttributesCache.get('ol-user'),
     email: 'sherlock@holmes.co.uk',
     first_name: 'Sherlock',
     last_name: 'Holmes',
   })
   window.metaAttributesCache.set('ol-ExposedSettings', {
+    ...window.metaAttributesCache.get('ol-ExposedSettings'),
     hasAffiliationsFeature: false,
   })
   window.metaAttributesCache.set('ol-isExternalAuthenticationSystemUsed', false)

+ 1 - 0
services/web/frontend/stories/settings/helpers/emails.js

@@ -72,6 +72,7 @@ export function errorsMocks(fetchMock) {
 export function setDefaultMeta() {
   window.metaAttributesCache = window.metaAttributesCache || new Map()
   window.metaAttributesCache.set('ol-ExposedSettings', {
+    ...window.metaAttributesCache.get('ol-ExposedSettings'),
     hasAffiliationsFeature: true,
     hasSamlFeature: true,
     samlInitPath: 'saml/init',

+ 4 - 1
services/web/frontend/stories/settings/helpers/leave.js

@@ -9,6 +9,9 @@ export function defaultSetupMocks(fetchMock) {
 export function setDefaultMeta() {
   window.metaAttributesCache = window.metaAttributesCache || new Map()
   window.metaAttributesCache.set('ol-usersEmail', 'user@primary.com')
-  window.metaAttributesCache.set('ol-ExposedSettings', { isOverleaf: true })
+  window.metaAttributesCache.set('ol-ExposedSettings', {
+    ...window.metaAttributesCache.get('ol-ExposedSettings'),
+    isOverleaf: true,
+  })
   window.metaAttributesCache.set('ol-hasPassword', true)
 }

+ 3 - 0
services/web/frontend/stories/settings/helpers/linking.js

@@ -12,6 +12,7 @@ export function defaultSetupMocks(fetchMock) {
 
 export function setDefaultMeta() {
   window.metaAttributesCache.set('ol-user', {
+    ...window.metaAttributesCache.get('ol-user'),
     features: { github: true, dropbox: true, mendeley: false, zotero: false },
     refProviders: {
       mendeley: true,
@@ -55,4 +56,6 @@ export function setDefaultMeta() {
       linkPath: '/auth/twitter',
     },
   })
+  window.metaAttributesCache.delete('integrationLinkingWidgets')
+  window.metaAttributesCache.delete('referenceLinkingWidgets')
 }

+ 1 - 0
services/web/frontend/stories/settings/helpers/password.js

@@ -22,6 +22,7 @@ export function defaultSetupMocks(fetchMock) {
 export function setDefaultMeta() {
   window.metaAttributesCache = window.metaAttributesCache || new Map()
   window.metaAttributesCache.set('ol-ExposedSettings', {
+    ...window.metaAttributesCache.get('ol-ExposedSettings'),
     isOverleaf: true,
   })
   window.metaAttributesCache.set('ol-isExternalAuthenticationSystemUsed', false)

+ 25 - 1
services/web/frontend/stories/settings/page.stories.js

@@ -22,7 +22,7 @@ import {
 } from './helpers/linking'
 import { UserProvider } from '../../js/shared/context/user-context'
 
-export const Root = args => {
+export const Overleaf = args => {
   setDefaultLeaveMeta()
   setDefaultAccountInfoMeta()
   setDefaultPasswordMeta()
@@ -43,6 +43,30 @@ export const Root = args => {
   )
 }
 
+export const ServerPro = args => {
+  setDefaultAccountInfoMeta()
+  setDefaultPasswordMeta()
+  useFetchMock(fetchMock => {
+    defaultSetupAccountInfoMocks(fetchMock)
+    defaultSetupPasswordMocks(fetchMock)
+  })
+
+  window.metaAttributesCache.set('ol-ExposedSettings', {
+    ...window.metaAttributesCache.get('ol-ExposedSettings'),
+    hasAffiliationsFeature: false,
+    isOverleaf: false,
+  })
+  window.metaAttributesCache.set('integrationLinkingWidgets', [])
+  window.metaAttributesCache.set('referenceLinkingWidgets', [])
+  window.metaAttributesCache.delete('ol-oauthProviders')
+
+  return (
+    <UserProvider>
+      <SettingsPageRoot {...args} />
+    </UserProvider>
+  )
+}
+
 export default {
   title: 'Account Settings / Full Page',
   component: SettingsPageRoot,

+ 98 - 0
services/web/test/frontend/features/settings/components/linking-section.test.tsx

@@ -0,0 +1,98 @@
+import { expect } from 'chai'
+import { screen, render } from '@testing-library/react'
+import fetchMock from 'fetch-mock'
+import LinkingSection from '../../../../../frontend/js/features/settings/components/linking-section'
+import { UserProvider } from '../../../../../frontend/js/shared/context/user-context'
+import { SSOProvider } from '../../../../../frontend/js/features/settings/context/sso-context'
+
+function renderSectionWithProviders() {
+  render(<LinkingSection />, {
+    wrapper: ({ children }) => (
+      <UserProvider>
+        <SSOProvider>{children}</SSOProvider>
+      </UserProvider>
+    ),
+  })
+}
+
+const mockOauthProviders = {
+  google: {
+    descriptionKey: 'login_with_service',
+    descriptionOptions: { service: 'Google' },
+    name: 'Google',
+    linkPath: '/auth/google',
+  },
+  orcid: {
+    descriptionKey: 'oauth_orcid_description',
+    descriptionOptions: {
+      link: '/blog/434',
+      appName: 'Overleaf',
+    },
+    name: 'Orcid',
+    linkPath: '/auth/orcid',
+  },
+  twitter: {
+    hideWhenNotLinked: true,
+    name: 'Twitter',
+    linkPath: '/auth/twitter',
+  },
+}
+
+describe('<LinkingSection />', function () {
+  beforeEach(function () {
+    window.metaAttributesCache = window.metaAttributesCache || new Map()
+    window.metaAttributesCache.set('ol-user', {})
+
+    // suppress integrations and references widgets as they cannot be tested in
+    // all environments
+    window.metaAttributesCache.set('integrationLinkingWidgets', [])
+    window.metaAttributesCache.set('referenceLinkingWidgets', [])
+
+    window.metaAttributesCache.set('ol-thirdPartyIds', {
+      google: 'google-id',
+    })
+
+    window.metaAttributesCache.set('ol-oauthProviders', mockOauthProviders)
+  })
+
+  afterEach(function () {
+    window.metaAttributesCache = new Map()
+    fetchMock.reset()
+  })
+
+  it('shows header', async function () {
+    renderSectionWithProviders()
+
+    screen.getByText('Integrations')
+    screen.getByText(
+      'You can link your Overleaf account with other services to enable the features described below'
+    )
+  })
+
+  it('lists SSO providers', async function () {
+    renderSectionWithProviders()
+    screen.getByText('linked accounts')
+
+    screen.getByText('Google')
+    screen.getByText('Log in with Google')
+    screen.getByRole('button', { name: 'Unlink' })
+
+    screen.getByText('Orcid')
+    screen.getByText(
+      /Securely establish your identity by linking your ORCID iD/
+    )
+    const helpLink = screen.getByRole('link', { name: 'Learn more' })
+    expect(helpLink.getAttribute('href')).to.equal('/blog/434')
+    const linkButton = screen.getByRole('link', { name: 'Link' })
+    expect(linkButton.getAttribute('href')).to.equal('/auth/orcid?intent=link')
+
+    expect(screen.queryByText('Twitter')).to.not.exist
+  })
+
+  it('does not show providers section when empty', async function () {
+    window.metaAttributesCache.delete('ol-oauthProviders')
+    renderSectionWithProviders()
+
+    expect(screen.queryByText('linked accounts')).to.not.exist
+  })
+})