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

Merge branch 'master' into imprv/143964-144048-truncate-pagepath-and-title-in-view

reiji-h 2 лет назад
Родитель
Сommit
f2d958c710

+ 7 - 7
.github/workflows/ci-app-prod.yml

@@ -48,13 +48,13 @@ concurrency:
 
 jobs:
 
-  test-prod-node18:
-    uses: weseek/growi/.github/workflows/reusable-app-prod.yml@master
-    with:
-      node-version: 18.x
-      skip-cypress: true
-    secrets:
-      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+  # test-prod-node18:
+  #   uses: weseek/growi/.github/workflows/reusable-app-prod.yml@master
+  #   with:
+  #     node-version: 18.x
+  #     skip-cypress: true
+  #   secrets:
+  #     SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
 
 
   test-prod-node20:

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

@@ -214,7 +214,8 @@ jobs:
       fail-fast: false
       matrix:
         # List string expressions that is comma separated ids of tests in "test/cypress/integration"
-        spec-group: ['10', '20', '21', '22', '23', '30', '40', '50', '60']
+        # spec-group: ['10', '20', '21', '22', '23', '30', '40', '50', '60']
+        spec-group: ['50']
 
     services:
       mongodb:

+ 1 - 0
apps/app/src/client/services/upload-attachments/index.ts

@@ -0,0 +1 @@
+export * from './upload-attachments';

+ 39 - 0
apps/app/src/client/services/upload-attachments/upload-attachments.ts

@@ -0,0 +1,39 @@
+import type { IAttachment } from '@growi/core';
+
+import { apiv3Get, apiv3PostForm } from '~/client/util/apiv3-client';
+import type { IApiv3GetAttachmentLimitParams, IApiv3GetAttachmentLimitResponse, IApiv3PostAttachmentResponse } from '~/interfaces/apiv3/attachment';
+import loggerFactory from '~/utils/logger';
+
+
+const logger = loggerFactory('growi:client:services:upload-attachment');
+
+
+type UploadOpts = {
+  onUploaded?: (attachment: IAttachment) => void,
+  onError?: (error: Error, file: File) => void,
+}
+
+export const uploadAttachments = async(pageId: string, files: File[], opts?: UploadOpts): Promise<void> => {
+  files.forEach(async(file) => {
+    try {
+      const params: IApiv3GetAttachmentLimitParams = { fileSize: file.size };
+      const { data: resLimit } = await apiv3Get<IApiv3GetAttachmentLimitResponse>('/attachment/limit', params);
+
+      if (!resLimit.isUploadable) {
+        throw new Error(resLimit.errorMessage);
+      }
+
+      const formData = new FormData();
+      formData.append('file', file);
+      formData.append('page_id', pageId);
+
+      const { data: resAdd } = await apiv3PostForm<IApiv3PostAttachmentResponse>('/attachment', formData);
+
+      opts?.onUploaded?.(resAdd.attachment);
+    }
+    catch (e) {
+      logger.error('failed to upload', e);
+      opts?.onError?.(e, file);
+    }
+  });
+};

+ 11 - 30
apps/app/src/components/PageComment/CommentEditor.tsx

@@ -13,7 +13,7 @@ import {
   TabContent, TabPane,
 } from 'reactstrap';
 
-import { apiv3Get, apiv3PostForm } from '~/client/util/apiv3-client';
+import { uploadAttachments } from '~/client/services/upload-attachments';
 import { toastError } from '~/client/util/toastr';
 import type { IEditorMethods } from '~/interfaces/editor-methods';
 import { useSWRxPageComment, useSWRxEditingCommentsNum } from '~/stores/comment';
@@ -201,40 +201,21 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
 
   // the upload event handler
   const uploadHandler = useCallback((files: File[]) => {
-    files.forEach(async(file) => {
-      try {
-        const { data: resLimit } = await apiv3Get('/attachment/limit', { fileSize: file.size });
-
-        if (!resLimit.isUploadable) {
-          throw new Error(resLimit.errorMessage);
-        }
-
-        const formData = new FormData();
-        formData.append('file', file);
-        if (pageId != null) {
-          formData.append('page_id', pageId);
-        }
-
-        const { data: resAdd } = await apiv3PostForm('/attachment', formData);
-
-        const attachment = resAdd.attachment;
+    uploadAttachments(pageId, files, {
+      onUploaded: (attachment) => {
         const fileName = attachment.originalName;
 
-        let insertText = `[${fileName}](${attachment.filePathProxied})\n`;
-        // when image
-        if (attachment.fileFormat.startsWith('image/')) {
-          // modify to "![fileName](url)" syntax
-          insertText = `!${insertText}`;
-        }
+        const prefix = attachment.fileFormat.startsWith('image/')
+          ? '!' // use "![fileName](url)" syntax when image
+          : '';
+        const insertText = `${prefix}[${fileName}](${attachment.filePathProxied})\n`;
 
         codeMirrorEditor?.insertText(insertText);
-      }
-      catch (e) {
-        logger.error('failed to upload', e);
-        toastError(e);
-      }
+      },
+      onError: (error) => {
+        toastError(error);
+      },
     });
-
   }, [codeMirrorEditor, pageId]);
 
   const getCommentHtml = useCallback(() => {

+ 3 - 3
apps/app/src/components/PageEditor/EditorNavbarBottom.tsx

@@ -10,11 +10,11 @@ const OptionsSelector = dynamic(() => import('~/components/PageEditor/OptionsSel
 const EditorNavbarBottom = (): JSX.Element => {
   return (
     <div className="border-top" data-testid="grw-editor-navbar-bottom">
-      <div className={`flex-expand-horiz align-items-center px-2 py-1 py-md-2 px-md-3 ${moduleClass}`}>
-        <form className="m-2 me-auto">
+      <div className={`flex-expand-horiz align-items-center p-2 ps-md-3 pe-md-4 ${moduleClass}`}>
+        <form className="me-auto">
           <OptionsSelector />
         </form>
-        <form className="m-2">
+        <form>
           <SavePageControls />
         </form>
       </div>

+ 17 - 29
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -21,7 +21,7 @@ import { throttle, debounce } from 'throttle-debounce';
 import { useShouldExpandContent } from '~/client/services/layout';
 import { useUpdateStateAfterSave } from '~/client/services/page-operation';
 import { updatePage, extractRemoteRevisionDataFromErrorObj } from '~/client/services/update-page';
-import { apiv3Get, apiv3PostForm } from '~/client/util/apiv3-client';
+import { uploadAttachments } from '~/client/services/upload-attachments';
 import { toastError, toastSuccess, toastWarning } from '~/client/util/toastr';
 import {
   useDefaultIndentSize, useCurrentUser,
@@ -237,40 +237,28 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
 
   // the upload event handler
   const uploadHandler = useCallback((files: File[]) => {
-    files.forEach(async(file) => {
-      try {
-        const { data: resLimit } = await apiv3Get('/attachment/limit', { fileSize: file.size });
-
-        if (!resLimit.isUploadable) {
-          throw new Error(resLimit.errorMessage);
-        }
-
-        const formData = new FormData();
-        formData.append('file', file);
-        if (pageId != null) {
-          formData.append('page_id', pageId);
-        }
-
-        const { data: resAdd } = await apiv3PostForm('/attachment', formData);
+    if (pageId == null) {
+      logger.error('pageId is invalid', {
+        pageId,
+      });
+      throw new Error('pageId is invalid');
+    }
 
-        const attachment = resAdd.attachment;
+    uploadAttachments(pageId, files, {
+      onUploaded: (attachment) => {
         const fileName = attachment.originalName;
 
-        let insertText = `[${fileName}](${attachment.filePathProxied})\n`;
-        // when image
-        if (attachment.fileFormat.startsWith('image/')) {
-          // modify to "![fileName](url)" syntax
-          insertText = `!${insertText}`;
-        }
+        const prefix = attachment.fileFormat.startsWith('image/')
+          ? '!' // use "![fileName](url)" syntax when image
+          : '';
+        const insertText = `${prefix}[${fileName}](${attachment.filePathProxied})\n`;
 
         codeMirrorEditor?.insertText(insertText);
-      }
-      catch (e) {
-        logger.error('failed to upload', e);
-        toastError(e);
-      }
+      },
+      onError: (error) => {
+        toastError(error);
+      },
     });
-
   }, [codeMirrorEditor, pageId]);
 
   // set handler to save and return to View

+ 22 - 8
apps/app/src/components/PageEditor/ScrollSyncHelper.tsx

@@ -19,12 +19,12 @@ const getDataLine = (element: Element | null): number => {
 
 const getEditorElements = (editorRootElement: HTMLElement): Array<Element> => {
   return Array.from(editorRootElement.getElementsByClassName('cm-line'))
-    .filter((element) => { return !Number.isNaN(element.getAttribute('data-line')) });
+    .filter((element) => { return !Number.isNaN(element.getAttribute('data-line') ?? Number.NaN) });
 };
 
 const getPreviewElements = (previewRootElement: HTMLElement): Array<Element> => {
   return Array.from(previewRootElement.getElementsByClassName('has-data-line'))
-    .filter((element) => { return !Number.isNaN(element.getAttribute('data-line')) });
+    .filter((element) => { return !Number.isNaN(element.getAttribute('data-line') ?? Number.NaN) });
 };
 
 // Ref: https://github.com/mikolalysenko/binary-search-bounds/blob/f436a2a8af11bf3208434e18bbac17e18e7a3a30/search-bounds.js
@@ -63,14 +63,14 @@ const findElementIndexFromDataLine = (previewElements: Array<Element>, dataline:
 
 
 type SourceElement = {
-  start: DOMRect,
-  top: DOMRect,
-  next: DOMRect | undefined,
+  start?: DOMRect,
+  top?: DOMRect,
+  next?: DOMRect,
 }
 
 type TargetElement = {
-  start: DOMRect,
-  next: DOMRect | undefined,
+  start?: DOMRect,
+  next?: DOMRect,
 }
 
 const calcScrollElementToTop = (element: Element): number => {
@@ -78,7 +78,13 @@ const calcScrollElementToTop = (element: Element): number => {
 };
 
 const calcScorllElementByRatio = (sourceElement: SourceElement, targetElement: TargetElement): number => {
-  if (sourceElement.start === sourceElement.next || sourceElement.next == null || targetElement.next == null) {
+  if (sourceElement.start === sourceElement.next) {
+    return 0;
+  }
+  if (sourceElement.start == null || sourceElement.top == null || sourceElement.next == null) {
+    return 0;
+  }
+  if (targetElement.start == null || targetElement.next == null) {
     return 0;
   }
   const sourceAllHeight = sourceElement.next.top - sourceElement.start.top;
@@ -107,6 +113,10 @@ const scrollEditor = (editorRootElement: HTMLElement, previewRootElement: HTMLEl
 
   let newScrollTop = previewRootElement.scrollTop;
 
+  if (previewElements[topPreviewElementIndex] == null) {
+    return;
+  }
+
   newScrollTop += calcScrollElementToTop(previewElements[topPreviewElementIndex]);
   newScrollTop += calcScorllElementByRatio(
     {
@@ -136,6 +146,10 @@ const scrollPreview = (editorRootElement: HTMLElement, previewRootElement: HTMLE
   const startEditorElementIndex = findElementIndexFromDataLine(editorElements, getDataLine(previewElements[topPreviewElementIndex]));
   const nextEditorElementIndex = findElementIndexFromDataLine(editorElements, getDataLine(previewElements[topPreviewElementIndex + 1]));
 
+  if (editorElements[startEditorElementIndex] == null) {
+    return;
+  }
+
   let newScrollTop = editorRootElement.scrollTop;
 
   newScrollTop += calcScrollElementToTop(editorElements[startEditorElementIndex]);

+ 0 - 1
apps/app/src/components/Sidebar/PageCreateButton/CreateButton.tsx

@@ -15,7 +15,6 @@ export const CreateButton = (props: Props): JSX.Element => {
       type="button"
       {...props}
       className={`${moduleClass} btn btn-primary ${props.className ?? ''}`}
-      data-testid="grw-sidebar-nav-page-create-button"
     >
       <Hexagon />
       <span className="icon material-symbols-outlined position-absolute">edit</span>

+ 1 - 0
apps/app/src/components/Sidebar/PageCreateButton/DropendMenu.tsx

@@ -26,6 +26,7 @@ export const DropendMenu = React.memo((props: DropendMenuProps): JSX.Element =>
   return (
     <DropdownMenu
       container="body"
+      data-testid="grw-page-create-button-dropend-menu"
     >
       <DropdownItem
         onClick={onClickCreateNewPage}

+ 1 - 0
apps/app/src/components/Sidebar/PageCreateButton/DropendToggle.tsx

@@ -14,6 +14,7 @@ export const DropendToggle = (): JSX.Element => {
       color="primary"
       className={`position-absolute z-1 ${moduleClass}`}
       aria-expanded={false}
+      data-testid="grw-page-create-button-dropend-toggle"
     >
       <Hexagon />
       <div className="hitarea position-absolute" />

+ 1 - 0
apps/app/src/components/Sidebar/PageCreateButton/PageCreateButton.tsx

@@ -45,6 +45,7 @@ export const PageCreateButton = React.memo((): JSX.Element => {
       className="d-flex flex-row mt-2"
       onMouseEnter={onMouseEnterHandler}
       onMouseLeave={onMouseLeaveHandler}
+      data-testid="grw-page-create-button"
     >
       <div className="btn-group flex-grow-1">
         <CreateButton

+ 6 - 7
apps/app/src/components/Sidebar/Tag.tsx

@@ -2,7 +2,7 @@ import type { FC } from 'react';
 import React, { useState, useCallback } from 'react';
 
 import { useTranslation } from 'next-i18next';
-import { useRouter } from 'next/router';
+import Link from 'next/link';
 
 import type { IDataTagCount } from '~/interfaces/tag';
 import { useSWRxTagsList } from '~/stores/tag';
@@ -19,8 +19,6 @@ const TAG_CLOUD_LIMIT = 20;
 
 const Tag: FC = () => {
 
-  const router = useRouter();
-
   const [activePage, setActivePage] = useState<number>(1);
   const [offset, setOffset] = useState<number>(0);
 
@@ -71,13 +69,14 @@ const Tag: FC = () => {
       }
 
       <div className="d-flex justify-content-center my-5">
-        <button
+        <Link
+          href="/tags"
           className="btn btn-primary rounded px-4"
-          type="button"
-          onClick={() => router.push('/tags')}
+          role="button"
+          prefetch={false}
         >
           {t('Check All tags')}
-        </button>
+        </Link>
       </div>
 
       <h6 className="my-3 pb-1 border-bottom">{t('popular_tags')}</h6>

+ 15 - 0
apps/app/src/interfaces/apiv3/attachment.ts

@@ -0,0 +1,15 @@
+import type { IAttachment, IPage, IRevision } from '@growi/core';
+
+import type { ICheckLimitResult } from '../attachment';
+
+export type IApiv3GetAttachmentLimitParams = {
+  fileSize: number,
+};
+
+export type IApiv3GetAttachmentLimitResponse = ICheckLimitResult;
+
+export type IApiv3PostAttachmentResponse = {
+  page: IPage,
+  revision: IRevision,
+  attachment: IAttachment,
+}

+ 5 - 0
apps/app/src/interfaces/attachment.ts

@@ -6,3 +6,8 @@ import type { PaginateResult } from './mongoose-utils';
 export type IResAttachmentList = {
   paginateResult: PaginateResult<IAttachmentHasId>
 };
+
+export type ICheckLimitResult = {
+  isUploadable: boolean,
+  errorMessage?: string,
+}

+ 4 - 4
apps/app/src/server/crowi/index.js

@@ -176,8 +176,6 @@ Crowi.prototype.init = async function() {
     this.setupExternalUserGroupSyncService(),
   ]);
 
-  await this.autoInstall();
-
   await normalizeData();
 };
 
@@ -414,7 +412,7 @@ Crowi.prototype.setupMailer = async function() {
   }
 };
 
-Crowi.prototype.autoInstall = function() {
+Crowi.prototype.autoInstall = async function() {
   const isInstalled = this.configManager.getConfig('crowi', 'app:installed');
   const username = this.configManager.getConfig('crowi', 'autoInstall:adminUsername');
 
@@ -438,7 +436,7 @@ Crowi.prototype.autoInstall = function() {
   const installerService = new InstallerService(this);
 
   try {
-    installerService.install(firstAdminUserToSave, globalLang ?? 'en_US', {
+    await installerService.install(firstAdminUserToSave, globalLang ?? 'en_US', {
       allowGuestMode,
       serverDate,
     });
@@ -485,6 +483,8 @@ Crowi.prototype.start = async function() {
   instantiateYjsConnectionManager(this.socketIoService.io);
   this.socketIoService.setupYjsConnection();
 
+  await this.autoInstall();
+
   // listen
   const serverListening = httpServer.listen(this.port, () => {
     logger.info(`[${this.node_env}] Express server is listening on port ${this.port}`);

+ 3 - 7
apps/app/src/server/service/file-uploader/file-uploader.ts

@@ -2,6 +2,7 @@ import { randomUUID } from 'crypto';
 
 import type { Response } from 'express';
 
+import type { ICheckLimitResult } from '~/interfaces/attachment';
 import { type RespondOptions, ResponseMode } from '~/server/interfaces/attachment';
 import { Attachment, type IAttachmentDocument } from '~/server/models';
 import loggerFactory from '~/utils/logger';
@@ -17,11 +18,6 @@ export type SaveFileParam = {
   data,
 }
 
-export type CheckLimitResult = {
-  isUploadable: boolean,
-  errorMessage?: string,
-}
-
 export type TemporaryUrl = {
   url: string,
   lifetimeSec: number,
@@ -38,7 +34,7 @@ export interface FileUploader {
   deleteFiles(): void,
   getFileUploadTotalLimit(): number,
   getTotalFileSize(): Promise<number>,
-  doCheckLimit(uploadFileSize: number, maxFileSize: number, totalLimit: number): Promise<CheckLimitResult>,
+  doCheckLimit(uploadFileSize: number, maxFileSize: number, totalLimit: number): Promise<ICheckLimitResult>,
   determineResponseMode(): ResponseMode,
   respond(res: Response, attachment: IAttachmentDocument, opts?: RespondOptions): void,
   findDeliveryFile(attachment: IAttachmentDocument): Promise<NodeJS.ReadableStream>,
@@ -135,7 +131,7 @@ export abstract class AbstractFileUploader implements FileUploader {
    * Check files size limits for all uploaders
    *
    */
-  async doCheckLimit(uploadFileSize: number, maxFileSize: number, totalLimit: number): Promise<CheckLimitResult> {
+  async doCheckLimit(uploadFileSize: number, maxFileSize: number, totalLimit: number): Promise<ICheckLimitResult> {
     if (uploadFileSize > maxFileSize) {
       return { isUploadable: false, errorMessage: 'File size exceeds the size limit per file' };
     }

+ 9 - 3
apps/app/src/services/renderer/rehype-plugins/add-line-number-attribute.ts

@@ -1,11 +1,11 @@
-import { Schema as SanitizeOption } from 'hast-util-sanitize';
+import type { Schema as SanitizeOption } from 'hast-util-sanitize';
 import type { Element } from 'hast-util-select/lib/types';
 import type { Plugin } from 'unified';
-import { visit } from 'unist-util-visit';
+import { visit, EXIT, CONTINUE } from 'unist-util-visit';
 
 import { addClassToProperties } from './add-class';
 
-const REGEXP_TARGET_TAGNAMES = new RegExp(/^(h1|h2|h3|h4|h5|h6|p|img|pre|blockquote|hr|ol|ul|table|tr)$/);
+const REGEXP_TARGET_TAGNAMES = new RegExp(/^(h1|h2|h3|h4|h5|h6|p|img|pre|blockquote|hr|ol|ul|table)$/);
 
 export const rehypePlugin: Plugin = () => {
   return (tree) => {
@@ -13,6 +13,11 @@ export const rehypePlugin: Plugin = () => {
       if (REGEXP_TARGET_TAGNAMES.test(node.tagName as string)) {
         const properties = node.properties ?? {};
 
+        // skip footnotes node
+        if (properties?.id === 'footnote-label') {
+          return EXIT;
+        }
+
         // add class
         addClassToProperties(properties, 'has-data-line');
         // add attribute
@@ -20,6 +25,7 @@ export const rehypePlugin: Plugin = () => {
 
         node.properties = properties;
       }
+      return CONTINUE;
     });
   };
 };

+ 1 - 8
apps/app/src/styles/organisms/_wiki.scss

@@ -177,14 +177,7 @@
     border-top: 1px solid bs.$border-color;
     /* Hide the section label for visual users. */
     #footnote-label {
-      position: absolute;
-      width: 1px;
-      height: 1px;
-      padding: 0;
-      overflow: hidden;
-      clip: rect(0, 0, 0, 0);
-      word-wrap: normal;
-      border: 0;
+      display: none;
     }
   }
   /* Place `[` and `]` around footnote references. */

+ 16 - 20
apps/app/test/cypress/e2e/23-editor/23-editor--saving.cy.ts

@@ -1,4 +1,4 @@
-context('PageCreateModal', () => {
+context('PageCreateButton', () => {
 
   const ssPrefix = 'page-create-modal-';
 
@@ -9,41 +9,37 @@ context('PageCreateModal', () => {
     });
   });
 
-  it("PageCreateModal is shown and closed successfully", () => {
+  it("DropendMenu is shown successfully", () => {
     cy.visit('/');
     cy.collapseSidebar(true, true);
 
+    cy.getByTestid('grw-page-create-button').trigger('mouseover');
+
     cy.waitUntil(() => {
       // do
-      cy.getByTestid('newPageBtn').click({force: true});
+      cy.getByTestid('grw-page-create-button-dropend-toggle').click({force: true});
       // wait until
-      return cy.getByTestid('page-create-modal').then($elem => $elem.is(':visible'));
-    });
-
-    cy.getByTestid('page-create-modal').should('be.visible').within(() => {
-      cy.screenshot(`${ssPrefix}new-page-modal-opened`);
-      cy.get('button.close').click();
+      return cy.getByTestid('grw-page-create-button-dropend-menu').then($elem => $elem.is(':visible'));
     });
 
-    cy.screenshot(`${ssPrefix}page-create-modal-closed`);
+    cy.screenshot(`${ssPrefix}page-create-button-dropend-menu-shown`);
   });
 
   it("Successfully Create Today's page", () => {
-    const pageName = "Today's page";
     cy.visit('/');
     cy.collapseSidebar(true);
 
+    cy.getByTestid('grw-page-create-button').trigger('mouseover');
+
     cy.waitUntil(() => {
       // do
-      cy.getByTestid('newPageBtn').click({force: true});
+      cy.getByTestid('grw-page-create-button-dropend-toggle').click({force: true});
       // wait until
-      return cy.getByTestid('page-create-modal').then($elem => $elem.is(':visible'));
+      return cy.getByTestid('grw-page-create-button-dropend-menu').then($elem => $elem.is(':visible'));
     });
 
-    cy.getByTestid('page-create-modal').should('be.visible').within(() => {
-      cy.get('.page-today-input2').type(pageName);
-      cy.screenshot(`${ssPrefix}today-add-page-name`);
-      cy.getByTestid('btn-create-memo').click();
+    cy.getByTestid('grw-page-create-button-dropend-menu').should('be.visible').within(() => {
+      cy.get('button').eq(1).click();
     });
 
     cy.getByTestid('page-editor').should('be.visible');
@@ -60,7 +56,7 @@ context('PageCreateModal', () => {
     cy.screenshot(`${ssPrefix}create-today-page`);
   });
 
-  it('Successfully create page under specific path', () => {
+  it.skip('Successfully create page under specific path', () => {
     const pageName = 'child';
 
     cy.visit('/foo/bar');
@@ -98,7 +94,7 @@ context('PageCreateModal', () => {
     cy.screenshot(`${ssPrefix}create-page-under-specific-page`);
   });
 
-  it('Trying to create template page under the root page fail', () => {
+  it.skip('Trying to create template page under the root page fail', () => {
     cy.visit('/');
     cy.collapseSidebar(true);
 
@@ -137,7 +133,7 @@ context('PageCreateModal', () => {
 });
 
 
-context('Shortcuts', () => {
+context.skip('Shortcuts', () => {
   const ssPrefix = 'shortcuts';
 
   beforeEach(() => {

+ 3 - 3
apps/app/test/cypress/e2e/50-sidebar/50-sidebar--access-to-side-bar.cy.ts

@@ -22,7 +22,7 @@ describe('Access to sidebar', () => {
         cy.visit('/');
 
         // Since this is a sidebar test, call collapseSidebar in beforeEach.
-        cy.collapseSidebar(false);
+        cy.collapseSidebar(false, true);
       });
 
       describe('Test show/collapse button', () => {
@@ -197,7 +197,7 @@ describe('Access to sidebar', () => {
 
         it('Successfully access to custom sidebar', () => {
           cy.getByTestid('grw-sidebar-contents').within(() => {
-            cy.get('.grw-sidebar-content-header > h3').find('a');
+            cy.get('.grw-sidebar-content-header > h4').find('a');
 
             cy.waitUntilSkeletonDisappear();
             cy.screenshot(`${ssPrefix}custom-sidebar-1-access-to-custom-sidebar`, { blackout: blackoutOverride });
@@ -270,7 +270,7 @@ describe('Access to sidebar', () => {
 
         it('Succesfully click all tags button', () => {
           cy.getByTestid('grw-sidebar-content-tags').within(() => {
-            cy.get('.btn-primary').click({force: true});
+            cy.get('.btn-primary').click();
           });
           cy.collapseSidebar(true);
           cy.getByTestid('grw-tags-list').should('be.visible');