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

Merge pull request #5697 from weseek/imprv/vrt-for-home

support: improve home.spec.ts
Yuki Takei 4 лет назад
Родитель
Сommit
e12b578438

+ 1 - 1
.github/workflows/reusable-app-prod.yml

@@ -185,7 +185,7 @@ jobs:
       fail-fast: false
       matrix:
         # List string expressions that is comma separated ids of tests in "test/cypress/integration"
-        spec-group: ['1', '2', '3', '4']
+        spec-group: ['1', '2', '3', '4', '6']
 
     services:
       mongodb:

+ 7 - 3
packages/app/src/components/Me/ApiSettings.jsx

@@ -1,13 +1,14 @@
 
 import React from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
-import { withUnstatedContainers } from '../UnstatedUtils';
-
 import AppContainer from '~/client/services/AppContainer';
 import PersonalContainer from '~/client/services/PersonalContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
+
+import { withUnstatedContainers } from '../UnstatedUtils';
 
 
 class ApiSettings extends React.Component {
@@ -46,6 +47,8 @@ class ApiSettings extends React.Component {
             {personalContainer.state.apiToken != null
               ? (
                 <input
+                  data-testid="grw-api-settings-input"
+                  data-hide-in-vrt
                   className="form-control"
                   type="text"
                   name="apiToken"
@@ -76,6 +79,7 @@ class ApiSettings extends React.Component {
         <div className="row my-3">
           <div className="offset-4 col-5">
             <button
+              data-testid="grw-api-settings-update-button"
               type="button"
               className="btn btn-primary text-nowrap"
               onClick={this.onClickSubmit}

+ 5 - 4
packages/app/src/components/Me/AssociateModal.jsx

@@ -1,21 +1,22 @@
 
 import React from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
-
 import {
   Modal,
   ModalHeader,
   ModalBody,
   ModalFooter,
 } from 'reactstrap';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
-import { withUnstatedContainers } from '../UnstatedUtils';
+
 
 import AppContainer from '~/client/services/AppContainer';
 import PersonalContainer from '~/client/services/PersonalContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
 import LdapAuthTest from '../Admin/Security/LdapAuthTest';
+import { withUnstatedContainers } from '../UnstatedUtils';
 
 class AssociateModal extends React.Component {
 
@@ -70,7 +71,7 @@ class AssociateModal extends React.Component {
     const { t } = this.props;
 
     return (
-      <Modal isOpen={this.props.isOpen} toggle={this.props.onClose} size="lg">
+      <Modal isOpen={this.props.isOpen} toggle={this.props.onClose} size="lg" data-testid="grw-associate-modal">
         <ModalHeader className="bg-primary text-light" toggle={this.props.onClose}>
           { t('admin:user_management.create_external_account') }
         </ModalHeader>

+ 10 - 3
packages/app/src/components/Me/BasicInfoSettings.jsx

@@ -1,14 +1,15 @@
 
 import React, { Fragment } from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
+import PersonalContainer from '~/client/services/PersonalContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { localeMetadatas } from '~/client/util/i18n';
 
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { withUnstatedContainers } from '../UnstatedUtils';
 
-import PersonalContainer from '~/client/services/PersonalContainer';
 
 class BasicInfoSettings extends React.Component {
 
@@ -144,7 +145,13 @@ class BasicInfoSettings extends React.Component {
 
         <div className="row my-3">
           <div className="offset-4 col-5">
-            <button type="button" className="btn btn-primary" onClick={this.onClickSubmit} disabled={personalContainer.state.retrieveError != null}>
+            <button
+              data-testid="grw-besic-info-settings-update-button"
+              type="button"
+              className="btn btn-primary"
+              onClick={this.onClickSubmit}
+              disabled={personalContainer.state.retrieveError != null}
+            >
               {t('Update')}
             </button>
           </div>

+ 11 - 4
packages/app/src/components/Me/EditorSettings.tsx

@@ -2,13 +2,15 @@ import React, {
   Dispatch,
   FC, SetStateAction, useCallback, useEffect, useState,
 } from 'react';
-import { useTranslation } from 'react-i18next';
+
 import PropTypes from 'prop-types';
+import { useTranslation } from 'react-i18next';
+
 import AppContainer from '~/client/services/AppContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
 import { withUnstatedContainers } from '../UnstatedUtils';
 
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
 type EditorSettingsBodyProps = {
   appContainer: AppContainer
@@ -249,8 +251,12 @@ const EditorSettingsBody: FC<EditorSettingsBodyProps> = (props) => {
     }
   };
 
+  if (textlintRules == null) {
+    return <></>;
+  }
+
   return (
-    <>
+    <div data-testid="grw-editor-settings">
       <RuleListGroup
         title="editor_settings.common_settings.common_settings"
         ruleList={commonRulesMenuItems}
@@ -267,6 +273,7 @@ const EditorSettingsBody: FC<EditorSettingsBodyProps> = (props) => {
       <div className="row my-3">
         <div className="offset-4 col-5">
           <button
+            data-testid="grw-editor-settings-update-button"
             type="button"
             className="btn btn-primary"
             onClick={updateRulesHandler}
@@ -275,7 +282,7 @@ const EditorSettingsBody: FC<EditorSettingsBodyProps> = (props) => {
           </button>
         </div>
       </div>
-    </>
+    </div>
   );
 };
 

+ 12 - 4
packages/app/src/components/Me/ExternalAccountLinkedMe.jsx

@@ -1,16 +1,19 @@
 
 import React, { Fragment } from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-import { toastError } from '~/client/util/apiNotification';
 
 import AppContainer from '~/client/services/AppContainer';
 import PersonalContainer from '~/client/services/PersonalContainer';
-import ExternalAccountRow from './ExternalAccountRow';
+import { toastError } from '~/client/util/apiNotification';
+
+import { withUnstatedContainers } from '../UnstatedUtils';
+
 import AssociateModal from './AssociateModal';
 import DisassociateModal from './DisassociateModal';
+import ExternalAccountRow from './ExternalAccountRow';
 
 class ExternalAccountLinkedMe extends React.Component {
 
@@ -68,7 +71,12 @@ class ExternalAccountLinkedMe extends React.Component {
     return (
       <Fragment>
         <h2 className="border-bottom my-4">
-          <button type="button" className="btn btn-outline-secondary btn-sm pull-right" onClick={this.openAssociateModal}>
+          <button
+            type="button"
+            data-testid="grw-external-account-add-button"
+            className="btn btn-outline-secondary btn-sm pull-right"
+            onClick={this.openAssociateModal}
+          >
             <i className="icon-plus" aria-hidden="true" />
             Add
           </button>

+ 4 - 2
packages/app/src/components/Me/InAppNotificationSettings.tsx

@@ -2,10 +2,11 @@ import React, {
   FC, useState, useEffect, useCallback,
 } from 'react';
 
-import { useTranslation } from 'react-i18next';
 import { pullAllBy } from 'lodash';
-import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';
+import { useTranslation } from 'react-i18next';
+
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
+import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';
 import { subscribeRuleNames, SubscribeRuleDescriptions } from '~/interfaces/in-app-notification';
 
 type SubscribeRule = {
@@ -96,6 +97,7 @@ const InAppNotificationSettings: FC = () => {
       <div className="row my-3">
         <div className="offset-4 col-5">
           <button
+            data-testid="grw-in-app-notification-settings-update-button"
             type="button"
             className="btn btn-primary"
             onClick={updateSettingsHandler}

+ 5 - 3
packages/app/src/components/Me/PasswordSettings.jsx

@@ -1,13 +1,14 @@
 
 import React from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
-import { withUnstatedContainers } from '../UnstatedUtils';
-
 import AppContainer from '~/client/services/AppContainer';
 import PersonalContainer from '~/client/services/PersonalContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
+
+import { withUnstatedContainers } from '../UnstatedUtils';
 
 
 class PasswordSettings extends React.Component {
@@ -138,6 +139,7 @@ class PasswordSettings extends React.Component {
         <div className="row my-3">
           <div className="offset-5">
             <button
+              data-testid="grw-password-settings-update-button"
               type="button"
               className="btn btn-primary"
               onClick={this.onClickSubmit}

+ 8 - 4
packages/app/src/components/Me/PersonalSettings.jsx

@@ -1,15 +1,17 @@
 
 import React, { useMemo } from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
 import CustomNavAndContents from '../CustomNavigation/CustomNavAndContents';
-import UserSettings from './UserSettings';
-import PasswordSettings from './PasswordSettings';
-import ExternalAccountLinkedMe from './ExternalAccountLinkedMe';
+
 import ApiSettings from './ApiSettings';
 import { EditorSettings } from './EditorSettings';
+import ExternalAccountLinkedMe from './ExternalAccountLinkedMe';
 import InAppNotificationSettings from './InAppNotificationSettings';
+import PasswordSettings from './PasswordSettings';
+import UserSettings from './UserSettings';
 
 const PersonalSettings = (props) => {
 
@@ -58,7 +60,9 @@ const PersonalSettings = (props) => {
 
 
   return (
-    <CustomNavAndContents navTabMapping={navTabMapping} navigationMode="both" tabContentClasses={['px-0']} />
+    <div data-testid="grw-personal-settings">
+      <CustomNavAndContents navTabMapping={navTabMapping} navigationMode="both" tabContentClasses={['px-0']} />
+    </div>
   );
 
 };

+ 4 - 3
packages/app/src/components/Me/UserSettings.jsx

@@ -1,5 +1,6 @@
 
-import React, { Fragment } from 'react';
+import React from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
@@ -12,7 +13,7 @@ class UserSettings extends React.Component {
     const { t } = this.props;
 
     return (
-      <Fragment>
+      <div data-testid="grw-user-settings">
         <div className="mb-5">
           <h2 className="border-bottom my-4">{t('Basic Info')}</h2>
           <BasicInfoSettings />
@@ -21,7 +22,7 @@ class UserSettings extends React.Component {
           <h2 className="border-bottom my-4">{t('Set Profile Image')}</h2>
           <ProfileImageSettings />
         </div>
-      </Fragment>
+      </div>
     );
   }
 

+ 7 - 8
packages/app/src/components/Navbar/GrowiNavbar.tsx

@@ -1,22 +1,21 @@
 import React, { FC, memo } from 'react';
-import PropTypes from 'prop-types';
 
+import PropTypes from 'prop-types';
 import { useTranslation } from 'react-i18next';
-
 import { UncontrolledTooltip } from 'reactstrap';
 
 import AppContainer from '~/client/services/AppContainer';
 import { IUser } from '~/interfaces/user';
-import { useIsDeviceSmallerThanMd } from '~/stores/ui';
-import { usePageCreateModal } from '~/stores/modal';
 import { useIsSearchPage, useCurrentPagePath } from '~/stores/context';
+import { usePageCreateModal } from '~/stores/modal';
+import { useIsDeviceSmallerThanMd } from '~/stores/ui';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
 import GrowiLogo from '../Icons/GrowiLogo';
+import InAppNotificationDropdown from '../InAppNotification/InAppNotificationDropdown';
+import { withUnstatedContainers } from '../UnstatedUtils';
 
-import PersonalDropdown from './PersonalDropdown';
 import GlobalSearch from './GlobalSearch';
-import InAppNotificationDropdown from '../InAppNotification/InAppNotificationDropdown';
+import PersonalDropdown from './PersonalDropdown';
 
 
 type NavbarRightProps = {
@@ -52,7 +51,7 @@ const NavbarRight: FC<NavbarRightProps> = memo((props: NavbarRightProps) => {
         </button>
       </li>
 
-      <li className="grw-personal-dropdown nav-item dropdown dropdown-toggle dropdown-toggle-no-caret">
+      <li className="grw-personal-dropdown nav-item dropdown dropdown-toggle dropdown-toggle-no-caret" data-testid="grw-personal-dropdown">
         <PersonalDropdown />
       </li>
     </>

+ 7 - 10
packages/app/src/components/Navbar/PersonalDropdown.jsx

@@ -1,18 +1,13 @@
 import React, { useState, useCallback } from 'react';
-import PropTypes from 'prop-types';
 
+import { UserPicture } from '@growi/ui';
+import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
-
 import { UncontrolledTooltip } from 'reactstrap';
 
-import { UserPicture } from '@growi/ui';
 
-import { useUserUISettings } from '~/client/services/user-ui-settings';
 import AppContainer from '~/client/services/AppContainer';
-
-import { withUnstatedContainers } from '../UnstatedUtils';
-import { usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser } from '~/stores/ui';
-
+import { useUserUISettings } from '~/client/services/user-ui-settings';
 import {
   isUserPreferenceExists,
   isDarkMode as isDarkModeByUtil,
@@ -21,12 +16,14 @@ import {
   updateUserPreference,
   updateUserPreferenceWithOsSettings,
 } from '~/client/util/color-scheme';
+import { usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser } from '~/stores/ui';
 
 
-import SidebarDrawerIcon from '../Icons/SidebarDrawerIcon';
-import SidebarDockIcon from '../Icons/SidebarDockIcon';
 import MoonIcon from '../Icons/MoonIcon';
+import SidebarDockIcon from '../Icons/SidebarDockIcon';
+import SidebarDrawerIcon from '../Icons/SidebarDrawerIcon';
 import SunIcon from '../Icons/SunIcon';
+import { withUnstatedContainers } from '../UnstatedUtils';
 
 
 const PersonalDropdown = (props) => {

+ 1 - 1
packages/app/src/server/views/layout-growi/user_page.html

@@ -1,7 +1,7 @@
 {% extends 'page.html' %}
 
 {% block content_main %}
-  <div class="grw-container-convertible user-page">
+  <div class="grw-container-convertible user-page" data-testid="grw-user-page">
 
     {% include '../widget/page_content.html' %}
 

+ 1 - 1
packages/app/src/server/views/layout/layout.html

@@ -96,7 +96,7 @@
 </div><!-- /#wrapper -->
 
 {% block fixed-controls %}
-<div id="grw-fab-container"></div>
+<div id="grw-fab-container" data-testid="grw-fab-container"></div>
 {% endblock %}
 
 <div id="grw-hotkeys-manager"></div>

+ 2 - 4
packages/app/test/cypress/integration/2-basic-features/access-to-page.spec.ts

@@ -19,10 +19,8 @@ context('Access to page', () => {
   it('/Sandbox with anchor hash is successfully loaded', () => {
     cy.visit('/Sandbox#Headers');
 
-    // wait until opacity is 1.
-    cy.getByTestid('grw-fab')
-      .invoke('show')
-      .should('have.css', 'opacity', '1');
+    // hide fab
+    cy.getByTestid('grw-fab-container').invoke('attr', 'style', 'display: none');
 
     cy.screenshot(`${ssPrefix}-sandbox-headers`);
   });

+ 0 - 32
packages/app/test/cypress/integration/6-home-settings/access-home.spec.ts

@@ -1,32 +0,0 @@
-/* eslint-disable cypress/no-unnecessary-waiting */
-context('Access Home', () => {
-  const ssPrefix = 'access-home-';
-
-  let connectSid: string | undefined;
-
-  before(() => {
-    // login
-    cy.fixture("user-admin.json").then(user => {
-      cy.login(user.username, user.password);
-    });
-    cy.getCookie('connect.sid').then(cookie => {
-      connectSid = cookie?.value;
-    });
-  });
-
-  beforeEach(() => {
-    if (connectSid != null) {
-      cy.setCookie('connect.sid', connectSid);
-    }
-  });
-
-  it('Visit home', () => {
-    cy.visit('/');
-    cy.get('.grw-personal-dropdown').click();
-    cy.get('.grw-personal-dropdown .dropdown-menu .btn-group > .btn-outline-secondary:eq(0)').click();
-
-    cy.wait(1500);
-    cy.screenshot(`${ssPrefix}-visit-home`, { capture: 'viewport' });
-  });
-
-});

+ 0 - 85
packages/app/test/cypress/integration/6-home-settings/access-user-settings.spec.ts

@@ -1,85 +0,0 @@
-/* eslint-disable cypress/no-unnecessary-waiting */
-context('Access User settings', () => {
-  const ssPrefix = 'access-user-settings-';
-
-  let connectSid: string | undefined;
-
-  before(() => {
-    // login
-    cy.fixture("user-admin.json").then(user => {
-      cy.login(user.username, user.password);
-    });
-    cy.getCookie('connect.sid').then(cookie => {
-      connectSid = cookie?.value;
-    });
-
-    cy.visit('/');
-    cy.get('.grw-personal-dropdown').click();
-    cy.get('[href="/me"]').click();
-
-    cy.wait(1500);
-  });
-
-  beforeEach(() => {
-    if (connectSid != null) {
-      cy.setCookie('connect.sid', connectSid);
-    }
-  });
-
-  it('Update settings', () => {
-    // Access User information
-    cy.get('#personal-setting .tab-pane.active > div:first button').click(); // Click basic info update button
-
-    cy.wait(500);
-
-    cy.screenshot(`${ssPrefix}-user-information`, { capture: 'viewport' });
-    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
-
-    // Access External account
-    cy.get('#personal-setting .nav-title.nav li:eq(1) a').click(); // click
-    cy.get('#personal-setting .tab-pane.active h2 button').click(); // click add button
-    cy.get('.modal-footer button').click(); // click add button in modal form
-    cy.get('.close[aria-label="Close"]').click(); // close modal form
-
-    cy.wait(500);
-
-    cy.screenshot(`${ssPrefix}-external-account`, { capture: 'viewport' });
-    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
-
-    // Access Password setting
-    cy.get('#personal-setting .nav-title.nav li:eq(2) a').click();
-    cy.get('#personal-setting .tab-pane.active button').click(); // click update button
-
-    cy.wait(500);
-
-    cy.screenshot(`${ssPrefix}-password-setting`, { capture: 'viewport' });
-    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
-
-    // Access API setting
-    cy.get('#personal-setting .nav-title.nav li:eq(2) a').click();
-    cy.get('#personal-setting .tab-pane.active button').click(); // click update API token button
-
-    cy.wait(500);
-
-    cy.screenshot(`${ssPrefix}-api-setting`, { capture: 'viewport' });
-    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
-
-    // Access Editor setting
-    cy.get('#personal-setting .nav-title.nav li:eq(3) a').click();
-    cy.get('#personal-setting .tab-pane.active button').click(); // click update button
-
-    cy.wait(500);
-
-    cy.screenshot(`${ssPrefix}-editor-setting`, { capture: 'viewport' });
-    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
-
-    // Access In-app notification setting
-    cy.get('#personal-setting .nav-title.nav li:eq(4) a').click();
-    cy.get('#personal-setting .tab-pane.active button').click(); // click update button
-
-    cy.wait(500);
-
-    cy.screenshot(`${ssPrefix}-in-app-notification-setting`, { capture: 'viewport' });
-  });
-
-});

+ 101 - 0
packages/app/test/cypress/integration/6-home/home.spec.ts

@@ -0,0 +1,101 @@
+context('Access Home', () => {
+  const ssPrefix = 'home-';
+
+  beforeEach(() => {
+    // login
+    cy.fixture("user-admin.json").then(user => {
+      cy.login(user.username, user.password);
+    });
+  });
+
+  it('Visit home', () => {
+    cy.visit('/dummy');
+    cy.getByTestid('grw-personal-dropdown').click();
+    cy.getByTestid('grw-personal-dropdown').find('.dropdown-menu .btn-group > .btn-outline-secondary:eq(0)').click();
+
+    cy.getByTestid('grw-user-page').should('be.visible');
+
+    cy.screenshot(`${ssPrefix}-visit-home`);
+  });
+
+});
+
+
+context('Access User settings', () => {
+  const ssPrefix = 'access-user-settings-';
+
+  beforeEach(() => {
+    // login
+    cy.fixture("user-admin.json").then(user => {
+      cy.login(user.username, user.password);
+    });
+  });
+
+  it('Update settings', () => {
+    cy.visit('/me');
+
+    // hide fab
+    cy.getByTestid('grw-fab-container').invoke('attr', 'style', 'display: none');
+
+    // User information
+    cy.getByTestid('grw-user-settings').should('be.visible');
+    cy.screenshot(`${ssPrefix}-user-information-1`);
+    cy.getByTestid('grw-besic-info-settings-update-button').click();
+    cy.get('.toast').should('be.visible');
+    cy.screenshot(`${ssPrefix}-user-information-2`);
+    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
+
+    // Access External account
+    cy.getByTestid('grw-personal-settings').find('.nav-title.nav li:eq(1) a').click();
+    cy.scrollTo('top');
+    cy.screenshot(`${ssPrefix}-external-account-1`);
+    cy.getByTestid('grw-external-account-add-button').click();
+    cy.getByTestid('grw-associate-modal').should('be.visible');
+    cy.screenshot(`${ssPrefix}-external-account-2`);
+    cy.getByTestid('grw-associate-modal').find('.modal-footer button').click(); // click add button in modal form
+    cy.screenshot(`${ssPrefix}-external-account-3`);
+    cy.getByTestid('grw-associate-modal').find('.close').click();
+    cy.get('.toast').should('be.visible');
+    cy.screenshot(`${ssPrefix}-external-account-4`);
+    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
+
+    // Access Password setting
+    cy.getByTestid('grw-personal-settings').find('.nav-title.nav li:eq(2) a').click();
+    cy.scrollTo('top');
+    cy.screenshot(`${ssPrefix}-password-settings-1`);
+    cy.getByTestid('grw-password-settings-update-button').click();
+    cy.get('.toast').should('be.visible');
+    cy.screenshot(`${ssPrefix}-password-settings-2`);
+    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
+
+    // Access API setting
+    cy.getByTestid('grw-personal-settings').find('.nav-title.nav li:eq(3) a').click();
+    cy.scrollTo('top');
+    cy.screenshot(`${ssPrefix}-api-setting-1`);
+    cy.getByTestid('grw-api-settings-update-button').click();
+    cy.getByTestid('grw-api-settings-input').should('be.visible');
+    cy.get('.toast').should('be.visible');
+    cy.screenshot(`${ssPrefix}-api-setting-2`);
+    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
+
+    // Access Editor setting
+    cy.getByTestid('grw-personal-settings').find('.nav-title.nav li:eq(4) a').click();
+    cy.scrollTo('top');
+    cy.getByTestid('grw-editor-settings').should('be.visible');
+    cy.screenshot(`${ssPrefix}-editor-setting-1`);
+    cy.getByTestid('grw-editor-settings-update-button').click();
+    cy.get('.toast').should('be.visible');
+    cy.screenshot(`${ssPrefix}-editor-setting-2`);
+    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
+
+    // Access In-app notification setting
+    cy.getByTestid('grw-personal-settings').find('.nav-title.nav li:eq(5) a').click();
+    cy.scrollTo('top');
+    cy.screenshot(`${ssPrefix}-in-app-notification-setting-1`);
+    cy.getByTestid('grw-in-app-notification-settings-update-button').click();
+    cy.get('.toast').should('be.visible');
+    cy.screenshot(`${ssPrefix}-in-app-notification-setting-2`);
+    cy.get('.toast-close-button').click({ multiple: true }); // close toast alert
+  });
+
+});