From bf289bce9f93e81b5919ad00b9ec694185d49e15 Mon Sep 17 00:00:00 2001 From: Bobbykumar706584 Date: Wed, 11 Oct 2023 10:30:06 +0530 Subject: [PATCH 1/7] export and archive test --- e2e-tests/base.test.ts | 160 +++++++++++++++-- e2e-tests/common.js | 161 ++++++++++++------ e2e-tests/myFixtures.ts | 50 +++--- jsconfig.json | 1 + .../src/components/Projects/ProjectList.js | 2 +- .../src/components/Projects/ProjectRow.js | 4 +- renderer/src/components/SnackBar/SnackBar.js | 2 +- renderer/src/layouts/projects/Layout.js | 4 +- renderer/src/modules/projects/Profile.js | 1 + 9 files changed, 295 insertions(+), 90 deletions(-) diff --git a/e2e-tests/base.test.ts b/e2e-tests/base.test.ts index 8afbb2507..2268a4a95 100644 --- a/e2e-tests/base.test.ts +++ b/e2e-tests/base.test.ts @@ -2,7 +2,7 @@ import { test, expect } from './myFixtures'; import packageInfo from '../package.json'; -import { showLoginPage, checkLogInOrNot, userFile, userFolder, userJson, createProjectValidation, createProjects, unstarProject, starProject, userValidation, signOut, showActiveUsers, searchProject, checkProjectName, checkNotification, goToProjectPage } from './common'; +import { showLoginPage, checkLogInOrNot, userFile, userFolder, userJson, createProjectValidation, createProjects, unstarProject, starProject, userValidation, signOut, showActiveUsers, searchProject, checkProjectName, checkNotification, goToProjectPage, exportProjects, archivedProjects, unarchivedProjects, goToEditProject, changeAppLanguage } from './common'; const fs = require('fs'); const path = require('path'); @@ -63,8 +63,8 @@ test('Create a new user and login', async ({ userName }) => { await window.locator('//input[@placeholder="Username"]').fill(userName) await expect(window.locator('//button[@type="submit"]')).toBeVisible() await window.click('[type=submit]'); - const title = await window.locator('//h1[@aria-label="projects"]', { timeout: 10000 }).textContent(); - expect(title).toBe('Projects'); + const title = await window.locator('//*[@aria-label="projects"]').textContent(); + await expect(title).toBe('Projects'); }) @@ -87,8 +87,8 @@ test('Click New and Fill project page details to create a new project for text t await window.locator('//*[@aria-label="nt-Matthew"]').click() await window.locator('//*[@id="save-canon"]').click() await window.locator('//button[@aria-label="create"]').click() - const notifyMe = await window.textContent('//*[@id="__next"]/div/div[2]/div[2]/div/div') - await expect(notifyMe).toBe('New project created') + // const notifyMe = await window.textContent('//*[@id="__next"]/div/div[2]/div[2]/div/div') + // await expect(notifyMe).toBe('New project created') const projectName = await window.innerText(`//div[@id="${textProject}"]`) await expect(projectName).toBe(textProject); }) @@ -226,13 +226,149 @@ test('Return to the projects from audio editor page', async () => { /* about the scribe */ test("About scribe Application and License", async () => { await window.locator('//*[@aria-label="about-button"]').click() - const developedby = await window.innerText('[aria-label=developed-by]'); + const developedby = await window.locator('[aria-label=developed-by]').textContent(); expect(developedby).toBe('Developed by Bridge Connectivity Solutions'); await window.click('[aria-label=license-button]'); await window.locator('//*[@aria-label="about-description"]').click() await window.click('[aria-label=close-about]'); - const title = await window.locator('//h1[@aria-label="projects"]', { timeout: 10000 }).textContent(); - expect(title).toBe('Projects'); + const title = await window.locator('//*[@aria-label="projects"]').textContent(); + await expect(title).toBe('Projects'); +}) + +/* exports project */ +test("Export text translation project in the Downloads folder", async ({ textProject }) => { + await exportProjects(window, expect, textProject) +}) + +test("Export the obs project in the Downloads folder", async ({ obsProject }) => { + await exportProjects(window, expect, obsProject) +}) + +test("Export the audio project in the Downloads folder", async ({ audioProject }) => { + await exportProjects(window, expect, audioProject) +}) + +/*archive and unarchive project */ +test("Archive text translation project", async ({ textProject }) => { + await archivedProjects(window, expect, textProject) +}) + +test("Restore text translation project from archived page", async ({ textProject }) => { + await unarchivedProjects(window, expect, textProject) +}) + +test("Archive obs project", async ({ obsProject }) => { + await archivedProjects(window, expect, obsProject) +}) + +test("Restore the obs project from archived page", async ({ obsProject }) => { + await unarchivedProjects(window, expect, obsProject) +}) + +test("Archive audio project", async ({ audioProject }) => { + await archivedProjects(window, expect, audioProject) +}) + +test("Restore the audio project from the archived page", async ({ audioProject }) => { + await unarchivedProjects(window, expect, audioProject) +}) + +/*Update/Edit the text translation project */ +test("Update/Edit text translation project of description and abbreviation", async ({ textProject }) => { + await goToEditProject(window, expect, textProject) + const description = await window.textContent('//textarea[@id="project_description"]') + await expect(description).toBe('test description') + await window.locator('//textarea[@id="project_description"]').fill('edit test version') + const editDescription = await window.textContent('//textarea[@id="project_description"]') + await expect(editDescription).toBe('edit test version') + await window.locator('input[name="version_abbreviated"]').fill('tvs') + await expect(window.locator('//button[@aria-label="save-edit-project"]')).toBeVisible() + await window.locator('//button[@aria-label="save-edit-project"]').click() + await window.waitForTimeout(3000) + const title = await window.textContent('[aria-label=projects]'); + expect(await title).toBe('Projects') +}) + +test("Update/Edit text translation project scope mark and luke", async ({ textProject }) => { + await goToEditProject(window, expect, textProject) + await expect(window.locator('//button[@id="open-advancesettings"]')).toBeVisible() + await window.locator('//button[@id="open-advancesettings"]').click() + await expect(window.locator('//div[@aria-label="custom-book"]')).toBeVisible() + await window.locator('//div[@aria-label="custom-book"]').click() + await window.locator('//*[@aria-label="nt-Mark"]').click() + await window.locator('//*[@aria-label="nt-Luke"]').click() + await window.locator('//*[@id="save-canon"]').click() + await expect(window.locator('//button[@aria-label="save-edit-project"]')).toBeVisible() + await window.locator('//button[@aria-label="save-edit-project"]').click() + await window.waitForTimeout(2500) + const title = await window.textContent('[aria-label=projects]'); + expect(await title).toBe('Projects') +}) + +test("Update/Edit text translation project scope custom book into NT", async ({ textProject }) => { + await goToEditProject(window, expect, textProject) + await expect(window.locator('//button[@id="open-advancesettings"]')).toBeVisible() + await window.locator('//button[@id="open-advancesettings"]').click() + await expect(window.locator('//div[@aria-label="new-testament"]')).toBeVisible() + await window.locator('//div[@aria-label="new-testament"]').click() + await window.locator('//button[contains(text(),"Ok")]').click() + await expect(window.locator('//button[@aria-label="save-edit-project"]')).toBeVisible() + await window.locator('//button[@aria-label="save-edit-project"]').click() + await window.waitForTimeout(3000) + const title = await window.textContent('[aria-label=projects]'); + expect(await title).toBe('Projects') +}) + +test("Update/Edit text transaltion project scope custom book genesis and exodus from OT", async ({ textProject }) => { + await goToEditProject(window, expect, textProject) + await expect(window.locator('//button[@id="open-advancesettings"]')).toBeVisible() + await window.locator('//button[@id="open-advancesettings"]').click() + await expect(window.locator('//div[@aria-label="custom-book"]')).toBeVisible() + await window.locator('//div[@aria-label="custom-book"]').click() + await window.locator('//*[@aria-label="ot-Genesis"]').click() + await window.locator('//*[@aria-label="ot-Exodus"]').click() + await window.locator('//*[@id="save-canon"]').click() + await expect(window.locator('//button[@aria-label="save-edit-project"]')).toBeVisible() + await window.locator('//button[@aria-label="save-edit-project"]').click() + await window.waitForTimeout(3000) + const title = await window.textContent('[aria-label=projects]'); + expect(await title).toBe('Projects') +}) + +test("Update/Edit text translation project license", async ({ textProject }) => { + await goToEditProject(window, expect, textProject) + await expect(window.locator('//button[@id="open-advancesettings"]')).toBeVisible() + await window.locator('//button[@id="open-advancesettings"]').click() + await window.getByRole('button', { name: 'CC BY-SA' }).click() + await window.getByRole('option', { name: 'CC BY', exact: true }).click() + await expect(window.locator('//button[@aria-label="save-edit-project"]')).toBeVisible() + await window.locator('//button[@aria-label="save-edit-project"]').click() + await window.waitForTimeout(3000) + const title = await window.textContent('[aria-label=projects]'); + expect(await title).toBe('Projects') +}) + + +/*changing app language */ +test("App language change English to hindi", async () => { + await changeAppLanguage(window, expect, "English", "Hindi") + const snackbar = await window.locator('//*[@id="__next"]/div[2]/div/div').isVisible() + expect(await snackbar === true) + const textHindi = await window.locator('//*[@aria-label="projects"]').allTextContents() + expect(await textHindi[0]).toBe("प्रोफ़ाइल") +}) + +test("App language change Hindi to English", async () => { + expect(await window.locator('//*[@aria-label="projectList"]')).toBeVisible() + await window.locator('//*[@aria-label="projectList"]').click() + await window.waitForTimeout(2000) + const title = await window.textContent('[aria-label=projects]', { timeout: 10000 }); + expect(await title).toBe('प्रोजेक्ट्स') + await changeAppLanguage(window, expect, "Hindi", "English") + const snackbar = await window.locator('//*[@id="__next"]/div[2]/div/div').isVisible() + const profile = await window.locator('//*[@aria-label="projects"]').allTextContents() + expect(await profile[0]).toBe("Profile") + expect(await snackbar === true) }) /*signing out */ @@ -249,8 +385,8 @@ test("Click the view users button, log in with playwright user, and sign out", a if (await div.nth(i).textContent() === userName.toLowerCase()) { await div.nth(i).click() await window.waitForTimeout(1000) - const title = await window.locator('//h1[@aria-label="projects"]', { timeout: 10000 }).textContent(); - expect(title).toBe('Projects') + const title = await window.locator('//*[@aria-label="projects"]').textContent(); + await expect(title).toBe('Projects') await signOut(window, expect) break } @@ -281,8 +417,8 @@ test("Delete the user from the active tab and check in the archived tab", async break } } - const title = await window.locator('//h1[@aria-label="projects"]', { timeout: 10000 }).textContent(); - expect(title).toBe('Projects') + const title = await window.locator('//*[@aria-label="projects"]').textContent(); + await expect(title).toBe('Projects') }) /* logout and delete the playwright user */ diff --git a/e2e-tests/common.js b/e2e-tests/common.js index f225f96a7..a5742f079 100644 --- a/e2e-tests/common.js +++ b/e2e-tests/common.js @@ -1,10 +1,13 @@ export const checkLogInOrNot = async (window, expect) => { await window.waitForSelector('//*[@id="__next"]/div', '//*[@id="__next"]/div[1]', { timeout: 5000 }) - const textVisble = await window.locator('//h1[@aria-label="projects"]', { timeout: 5000 }).isVisible() + const textVisble = await window.locator('//*[@aria-label="projects"]', { timeout: 5000 }).isVisible() if (textVisble) { - const title = await window.locator('//h1[@aria-label="projects"]').textContent() - await expect(title).toBe('Projects') - + const title = await window.locator('//*[@aria-label="projects"]').textContent() + if(await title === "Projects"){ + await expect(title).toBe("Projects") + }else{ + await expect(title).not.toBe('Projects') + } } else { const welcome = await window.locator('//h2[@aria-label="welcome"]', {timeout:5000}).textContent() await expect(welcome).toBe("Welcome!") @@ -55,16 +58,15 @@ export const userValidation = async (window, expect) => { await expect(window.locator('//button[@type="submit"]')).toBeVisible() await window.click('[type=submit]'); const lengthError = await window.locator('//*[@id="show-error"]') - expect(await lengthError === true) expect(await lengthError.textContent()).toBe('The input has to be between 3 and 15 characters long') } // project creation validation export const createProjectValidation = async (window, expect) => { await window.locator('//button[@aria-label="create"]').click() - const snackbar = await window.textContent('//*[@id="__next"]/div/div[2]/div[2]/div/div') - expect(await snackbar).toBe('Fill all the fields') - const title = await window.locator('//h1[@aria-label="projects"]').textContent(); + const snackbar = await window.locator('//*[@aria-label="snack-text"]').textContent() + await expect(snackbar).toBe('Fill all the fields') + const title = await window.locator('//*[@aria-label="projects"]').textContent(); await expect(title).toBe('New Project'); await window.waitForTimeout(3000) } @@ -91,48 +93,32 @@ export const createProjects = async (window, expect, projectname, type, descript await expect(projectName).toBe(projectname); } -// star the project -export const starProject = async (window, expect, projectname) => { - await expect(window.locator('//*[@id="projects-list"]')).toBeVisible() - const table = window.locator('//*[@id="projects-list"]') - const body = table.locator('//*[@id="projects-list-unstar"]') - const starBody = table.locator('//*[@id="projects-list-star"]') +// Star and Unstar +export const commonUtilExport = async (window, expect, name, clickStar) => { + await expect(window.locator('//table[@id="projects-list"]')).toBeVisible() + const table = window.locator('//table[@id="projects-list"]') + const body = table.locator('//*[@id="projects-list-body"]') const rows = await body.locator('tr') for (let i = 0; i < await rows.count(); i++) { const row = await rows.nth(i); const tds = await row.locator('td'); - if (await tds.nth(1).textContent() === projectname) { - expect(await tds.first().locator('[aria-label=unstar-project]')).toBeVisible() - await tds.first().locator('[aria-label=unstar-project]').click() - expect(await rows.count()).toBe(2) - const starRows = await starBody.locator('tr') - const starProjectName = await starRows.locator("td").nth(1).innerText() - expect(await starProjectName).toBe(projectname) - expect(await starRows.count()).toBe(1) + if (await tds.nth(1).textContent() === name) { + expect(await tds.first().locator(`[aria-label=${clickStar}]`)).toBeVisible() + await tds.first().locator(`[aria-label=${clickStar}]`).click() + await window.waitForTimeout(500) break } } } +// star the project +export const starProject = async (window, expect, projectname) => { + await commonUtilExport(window, expect, projectname, "star-project") +} + // unstar the project export const unstarProject = async (window, expect, projectname) => { - await expect(window.locator('//*[@id="projects-list"]')).toBeVisible() - const table = window.locator('//*[@id="projects-list"]') - const body = table.locator('//*[@id="projects-list-star"]') - const rows = await body.locator('tr') - for (let i = 0; i < await rows.count(); i++) { - const row = await rows.nth(i); - const tds = await row.locator('td'); - if (await tds.nth(1).textContent() === projectname) { - expect(await tds.first().locator('[aria-label=star-project]')).toBeVisible() - await tds.first().locator('[aria-label=star-project]').click() - const unstarBody = table.locator('//*[@id="projects-list-unstar"]') - const unstarRows = await unstarBody.locator('tr') - expect(await rows.count()).toBe(0) - expect(await unstarRows.count()).toBe(3) - break; - } - } + await commonUtilExport(window, expect, projectname, "unstar-project") } // search projects @@ -140,7 +126,7 @@ export const searchProject = async (window, expect, projectName, searchtext) => await window.waitForTimeout(500) await expect(window.locator('//input[@id="search_box"]')).toBeVisible() await window.locator('//input[@id="search_box"]').fill(searchtext) - const projectname = await window.innerText(`//*[@id="${projectName}"]`); + const projectname = await window.locator(`//*[@id="${projectName}"]`).textContent() await expect(projectname).toBe(projectName); } @@ -148,7 +134,7 @@ export const searchProject = async (window, expect, projectName, searchtext) => export const checkProjectName = async (window, expect, name) => { await expect(window.locator('//*[@id="projects-list"]')).toBeVisible() const table = window.locator('//*[@id="projects-list"]') - const body = table.locator('//*[@id="projects-list-unstar"]') + const body = table.locator('//*[@id="projects-list-body"]') const rows = await body.locator('tr') for (let i = 0; i < await rows.count(); i++) { const row = await rows.nth(i); @@ -159,15 +145,16 @@ export const checkProjectName = async (window, expect, name) => { } } await window.waitForTimeout(1000) - const projectname = await window.locator('[aria-label=editor-project-name]', { timeout: 10000 }).textContent() - expect(projectname).toBe(name); + const projectname = await window.locator('[aria-label=editor-project-name]').textContent({ timeout: 30000 }) + await expect(projectname).toBe(name); } // check notification export const checkNotification = async (window, expect) => { await window.locator('//*[@aria-label="notification-button"]').click() - const title = await window.innerText('[aria-label=notification-title]'); - await expect(title).toBe('NOTIFICATIONS'); + await window.waitForTimeout(1000) + const title = await window.locator('[aria-label=notification-title]').textContent(); + await expect(title).toBe('Notifications'); await window.locator('//*[@aria-label="close-notification"]').click() } @@ -175,12 +162,90 @@ export const checkNotification = async (window, expect) => { export const goToProjectPage = async (window, expect) => { await expect(window.locator('//*[@id="back-button"]')).toBeVisible() await window.locator('//*[@id="back-button"]').click(); - const title = await window.locator('//h1[@aria-label="projects"]', { timeout: 10000 }).textContent(); - expect(title).toBe('Projects'); + const title = await window.locator('//*[@aria-label="projects"]').textContent(); + await expect(title).toBe('Projects'); await window.waitForTimeout(1000) } -// sing out +// common function for looping the table +export const commonUtilArchive = async (window, expect, projectName, clickItem) => { + await expect(window.locator('//*[@id="projects-list"]')).toBeVisible() + const table = window.locator('//*[@id="projects-list"]') + const body = table.locator('//*[@id="projects-list-body"]') + const rows = await body.locator('tr') + for (let i = 0; i < await rows.count(); i++) { + const row = await rows.nth(i); + const tds = await row.locator('td'); + if (await tds.nth(1).textContent() === projectName) { + expect(await tds.last().locator('[aria-label="expand-project"]')).toBeVisible() + await tds.last().locator('[aria-label="expand-project"]').click() + await window.waitForTimeout(1000) + await window.locator('//*[@aria-label="menu-project"]').click() + await window.locator(`//*[@aria-label="${clickItem}"]`).click() + break + } + } +} + +// export projects +export const exportProjects = async (window, expect, projectname) => { + const newpath = await window.evaluate(() => Object.assign({}, window.localStorage)) + const userpath = newpath.userPath.split(".")[0] + await commonUtilArchive(window, expect, projectname, "export-project") + await expect(window.locator('input[name="location"]')).toBeVisible() + await window.locator('input[name="location"]').fill(`${userpath}/Downloads`) + await window.locator('//*[@aria-label="export-projects"]').click() + await window.waitForTimeout(2000) + const snackText = await window.locator('//*[@aria-label="snack-text"]').textContent() + await expect(snackText).toBe("Exported Successfully") + await window.locator('[aria-label=arrow-up]').click() +} + + +// archived projects +export const archivedProjects = async (window, expect, projectname) => { + await commonUtilArchive(window, expect, projectname, "archive-restore-project") + await window.locator('//*[@aria-label="archived-projects"]').click() + const archiveTitle = await window.locator('//*[@aria-label="projects"]').textContent() + await expect(archiveTitle).toBe("Archived projects") + const projectName = await window.innerText(`//div[@id="${projectname}"]`) + await expect(projectName).toBe(projectname); + await window.locator('//*[@aria-label="active-projects"]').click() + const projectTitle = await window.locator('//*[@aria-label="projects"]').textContent() + await expect(projectTitle).toBe('Projects'); +} + +// unarchived projects +export const unarchivedProjects = async (window, expect, projectname) => { + await window.locator('//*[@aria-label="archived-projects"]').click() + await commonUtilArchive(window, expect, projectname, "archive-restore-project") + const archiveTitle = await window.locator('//*[@aria-label="projects"]').textContent() + await expect(archiveTitle).toBe("Archived projects") + await window.locator('//*[@aria-label="active-projects"]').click() + const projectName = await window.innerText(`//div[@id="${projectname}"]`) + await expect(projectName).toBe(projectname); + const projectTitle = await window.locator('//*[@aria-label="projects"]').textContent() + await expect(projectTitle).toBe('Projects'); +} + +export const goToEditProject = async (window, expect, projectName) => { + await commonUtilArchive(window, expect, projectName, "edit-project") + const editTitle = await window.locator('//*[@aria-label="projects"]').textContent() + await expect(editTitle).toBe('Edit Project'); +} + +export const changeAppLanguage = async (window, expect, fromLanguage, toLanguage) => { + expect(await window.locator('//*[@id="user-profile"]')).toBeVisible() + await window.locator('//*[@id="user-profile"]').click() + expect(await window.locator('//*[@aria-label="user-profile"]')).toBeVisible() + await window.locator('//*[@aria-label="user-profile"]').click() + await window.getByRole('button', { name: fromLanguage }).click() + await window.getByRole('option', { name: toLanguage }).click() + expect(await window.locator('//*[@id="save-profile"]')).toBeVisible() + await window.locator('//*[@id="save-profile"]').click() +} + +// sign out export const signOut = async (window, expect) => { await expect(window.locator('//*[@id="user-profile"]')).toBeVisible() await window.locator('//*[@id="user-profile"]').click() diff --git a/e2e-tests/myFixtures.ts b/e2e-tests/myFixtures.ts index 7c0318327..884385686 100644 --- a/e2e-tests/myFixtures.ts +++ b/e2e-tests/myFixtures.ts @@ -1,32 +1,32 @@ -import {test as myTest} from "@playwright/test" +import { test as myTest } from "@playwright/test" type myFixture = { - userName: string - textProject: string, - obsProject: string, - audioProject: string, - syncName:string, - doorUser:string, - doorPassword:string, - flavorText:string, - flavorObs:string - textUnderscore:string, - obsUnderscore:string, - obsUrduProject:string, + userName: string + textProject: string, + obsProject: string, + audioProject: string, + syncName: string, + doorUser: string, + doorPassword: string, + flavorText: string, + flavorObs: string + textUnderscore: string, + obsUnderscore: string, + obsUrduProject: string, } const myFixtureTest = myTest.extend({ - userName : "Playwright user", - textProject: "Translation test project", - obsProject: "Obs test project", - textUnderscore: "Translation_test_project", - obsUnderscore: "Obs_test_project", - audioProject: "Audio test project", - syncName:"Sync_Collab_Test", - doorUser:"bobby", - doorPassword:"Bobby@123", - flavorText: "textTranslation", - flavorObs: "textStories", - obsUrduProject: "Obs urdu project", + userName: "Playwright user", + textProject: "Translation test project", + obsProject: "Obs test project", + textUnderscore: "Translation_test_project", + obsUnderscore: "Obs_test_project", + audioProject: "Audio test project", + syncName: "Sync_Collab_Test", + doorUser: "bobby", + doorPassword: "Bobby@123", + flavorText: "textTranslation", + flavorObs: "textStories", + obsUrduProject: "Obs urdu project", }) export const test = myFixtureTest; diff --git a/jsconfig.json b/jsconfig.json index f94e0cddc..4138fa416 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "resolveJsonModule": true, "baseUrl": ".", "paths": { "@/icons/*": [ diff --git a/renderer/src/components/Projects/ProjectList.js b/renderer/src/components/Projects/ProjectList.js index 8c58286f4..4c8f691e3 100644 --- a/renderer/src/components/Projects/ProjectList.js +++ b/renderer/src/components/Projects/ProjectList.js @@ -82,7 +82,7 @@ export default function ProjectList() {
- +
+ {projects && (stableSort( projects, getComparator(order, orderBy), @@ -167,6 +167,7 @@ const ProjectRow = ({ {({ active }) => ( -

+

{snackText}

diff --git a/renderer/src/layouts/projects/Layout.js b/renderer/src/layouts/projects/Layout.js index 9c4898ab2..7c4b023f5 100644 --- a/renderer/src/layouts/projects/Layout.js +++ b/renderer/src/layouts/projects/Layout.js @@ -103,12 +103,12 @@ export default function ProjectsLayout(props) { {showArchived ? ( <> - {t('label-active')} + {t('label-active')} ) : ( <> - {t('label-archived')} + {t('label-archived')} )} diff --git a/renderer/src/modules/projects/Profile.js b/renderer/src/modules/projects/Profile.js index 91e20f22e..6b25f923c 100644 --- a/renderer/src/modules/projects/Profile.js +++ b/renderer/src/modules/projects/Profile.js @@ -326,6 +326,7 @@ export default function UserProfile() {