From 19471d86589d920a851970b73f272314e9a0f04e Mon Sep 17 00:00:00 2001 From: Anish Pawaskar Date: Tue, 1 Aug 2023 01:36:35 +0530 Subject: [PATCH 1/8] refactor: change button positioning --- index.html | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 88d48cf3..bcb1a5a4 100644 --- a/index.html +++ b/index.html @@ -19,12 +19,13 @@
+
- -
+
@@ -36,12 +37,13 @@
- -
+
+
From 84d3d0a321d8479d740662a5649a6aecd9e4f3ad Mon Sep 17 00:00:00 2001 From: Anish Pawaskar Date: Tue, 1 Aug 2023 01:49:51 +0530 Subject: [PATCH 2/8] refactor: making two api calls based on button id --- script.js | 102 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 23 deletions(-) diff --git a/script.js b/script.js index f030e81a..914522b1 100644 --- a/script.js +++ b/script.js @@ -23,7 +23,7 @@ function getCurrentTimestamp() { export async function showSuperUserOptions(...privateBtns) { try { const isSuperUser = await checkUserIsSuperUser(); - if (isSuperUser) { + if (true) { privateBtns.forEach((btn) => btn.classList.remove('element-display-remove'), ); @@ -83,47 +83,103 @@ async function handleSync( const wrapper = button.parentElement; const spinner = wrapper.querySelector('.spinner'); const status = wrapper.querySelector('.status'); - + //console.log('button', button.id); button.disabled = true; button.classList.add(DISABLED); spinner.style.display = 'inline-block'; status.textContent = SYNC_IN_PROGRESS; - try { - const response = await fetch(`${API_BASE_URL}${endpoint}`, { - method: method, - credentials: 'include', - }); - if (response.ok) { - status.textContent = SYNC_SUCCESSFUL; - const lastSyncTimestamp = getCurrentTimestamp(); + if(button.id === "sync-users-status") { + try { + const response = await fetch(`${API_BASE_URL}${endpoint.userStatusUpdate}`, { + method: method.userStatusMethod, + credentials: 'include', + }); + + const idleData = await fetch(`${API_BASE_URL}${endpoint.idle}`, { + method: method.idleMethod, + credentials: 'include', + }) + .then((res) => res.json()) + .then((data) => data.data.users) + console.log('idleData', idleData); - localStorage.setItem(localStorageKey, lastSyncTimestamp); + const batchResponse = await fetch(`${API_BASE_URL}${endpoint.batchIdle}`, { + headers: { + 'Content-Type': 'application/json' + }, + method: method.batchIdleMethod, + body: JSON.stringify({ users: idleData }), + credentials: 'include' + }) - if (lastSyncElement) { - lastSyncElement.textContent = `Last Sync: ${lastSyncTimestamp}`; + if (response.ok && batchResponse.ok) { + status.textContent = SYNC_SUCCESSFUL; + const lastSyncTimestamp = getCurrentTimestamp(); + + localStorage.setItem(localStorageKey, lastSyncTimestamp); + + if (lastSyncElement) { + lastSyncElement.textContent = `Last Sync: ${lastSyncTimestamp}`; + } + } else { + status.textContent = SYNC_FAILED; } - } else { + } catch (err) { + console.error(err); status.textContent = SYNC_FAILED; + } finally { + spinner.style.display = 'none'; + button.classList.remove(DISABLED); + button.disabled = false; + } + + } else { + try { + const response = await fetch(`${API_BASE_URL}${endpoint}`, { + method: method, + credentials: 'include', + }); + + if (response.ok) { + status.textContent = SYNC_SUCCESSFUL; + const lastSyncTimestamp = getCurrentTimestamp(); + + localStorage.setItem(localStorageKey, lastSyncTimestamp); + + if (lastSyncElement) { + lastSyncElement.textContent = `Last Sync: ${lastSyncTimestamp}`; + } + } else { + status.textContent = SYNC_FAILED; + } + } catch (err) { + console.error(err); + status.textContent = SYNC_FAILED; + } finally { + spinner.style.display = 'none'; + button.classList.remove(DISABLED); + button.disabled = false; } - } catch (err) { - console.error(err); - status.textContent = SYNC_FAILED; - } finally { - spinner.style.display = 'none'; - button.classList.remove(DISABLED); - button.disabled = false; } } // Attach (button,API,cookie name,div element of status,HTTP method of API addClickEventListener( syncUsersStatusButton, - '/users/status/update', + { + idle: '/users/status?aggregate=true', + batchIdle: '/users/status/batch', + userStatusUpdate: '/users/status/update' + }, 'lastSyncUsersStatus', syncUsersStatusUpdate, - 'PATCH', + { + idleMethod: 'GET', + batchIdleMethod: 'PATCH', + userStatusMethod: 'PATCH' + }, ); addClickEventListener( syncExternalAccountsButton, From 213bf9041e1ecbc5e49cc5b3e787923fa6a5f6e6 Mon Sep 17 00:00:00 2001 From: Anish Pawaskar Date: Tue, 1 Aug 2023 14:54:35 +0530 Subject: [PATCH 3/8] refactor: running non-dependent api's concurrently Add Promise.all( ) to run non-dependent promises at same time --- script.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/script.js b/script.js index 914522b1..58fd75c5 100644 --- a/script.js +++ b/script.js @@ -83,38 +83,38 @@ async function handleSync( const wrapper = button.parentElement; const spinner = wrapper.querySelector('.spinner'); const status = wrapper.querySelector('.status'); - //console.log('button', button.id); + button.disabled = true; button.classList.add(DISABLED); spinner.style.display = 'inline-block'; status.textContent = SYNC_IN_PROGRESS; - if(button.id === "sync-users-status") { try { - const response = await fetch(`${API_BASE_URL}${endpoint.userStatusUpdate}`, { + const userStatus = fetch(`${API_BASE_URL}${endpoint.userStatusUpdate}`, { method: method.userStatusMethod, credentials: 'include', }); - const idleData = await fetch(`${API_BASE_URL}${endpoint.idle}`, { + const idleUsers = fetch(`${API_BASE_URL}${endpoint.idle}`, { method: method.idleMethod, credentials: 'include', }) .then((res) => res.json()) .then((data) => data.data.users) - console.log('idleData', idleData); + + const [ userStatusResponse, idleUsersData ] = await Promise.all([ userStatus, idleUsers ]); const batchResponse = await fetch(`${API_BASE_URL}${endpoint.batchIdle}`, { headers: { 'Content-Type': 'application/json' }, method: method.batchIdleMethod, - body: JSON.stringify({ users: idleData }), + body: JSON.stringify({ users: idleUsersData }), credentials: 'include' }) - if (response.ok && batchResponse.ok) { + if (userStatusResponse.ok && batchResponse.ok) { status.textContent = SYNC_SUCCESSFUL; const lastSyncTimestamp = getCurrentTimestamp(); From 699e70e1f9efca3fbca1d3cc2d5d935012b89651 Mon Sep 17 00:00:00 2001 From: Anish Pawaskar Date: Tue, 1 Aug 2023 15:42:43 +0530 Subject: [PATCH 4/8] refactor: revert super user access --- script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.js b/script.js index 58fd75c5..142fce6e 100644 --- a/script.js +++ b/script.js @@ -23,7 +23,7 @@ function getCurrentTimestamp() { export async function showSuperUserOptions(...privateBtns) { try { const isSuperUser = await checkUserIsSuperUser(); - if (true) { + if (isSuperUser) { privateBtns.forEach((btn) => btn.classList.remove('element-display-remove'), ); From d699865ced7526d31736af937305f4461b32cd01 Mon Sep 17 00:00:00 2001 From: Sriza Sen Date: Thu, 3 Aug 2023 19:35:40 +0530 Subject: [PATCH 5/8] FEAT: added repo sync button and handlers (#427) * added repo sync button and handlers * minor fix * FIX: fix prettier and add spinner * fix rsponse not being read * REFACTOR: toast style * updated button to allow for dev=true and not restricted to superusers * added toast fix * prettier fix * added discord users button * added tests * added constant * minor fixes * change headless true to "new" * FIX(PRETTIER): fix formating * TEST(FIX): fix test cases * updated style to standard formatting * updated to use px instead of rem for <=10px * updated rem to px for smaller values --------- Co-authored-by: sahsisunny Co-authored-by: ritikjaiswal75 --- __tests__/home/home.test.js | 159 ++++++++++++++++++++++++++++++++++++ constants.js | 3 + index.html | 18 ++++ script.js | 78 +++++++++++++++++- style.css | 146 +++++++++++++++++++++++---------- 5 files changed, 358 insertions(+), 46 deletions(-) create mode 100644 __tests__/home/home.test.js diff --git a/__tests__/home/home.test.js b/__tests__/home/home.test.js new file mode 100644 index 00000000..9a512a51 --- /dev/null +++ b/__tests__/home/home.test.js @@ -0,0 +1,159 @@ +const puppeteer = require('puppeteer'); + +describe('Home Page', () => { + let browser; + let page; + jest.setTimeout(60000); + + beforeAll(async () => { + browser = await puppeteer.launch({ + headless: 'new', + ignoreHTTPSErrors: true, + args: ['--incognito', '--disable-web-security'], + devtools: false, + }); + page = await browser.newPage(); + + await page.goto('http://localhost:8000/'); + await page.waitForNetworkIdle(); + }); + + afterAll(async () => { + await browser.close(); + }); + + it('should display the Sync Users Status button', async () => { + const syncUsersStatusButton = await page.$('#sync-users-status'); + expect(syncUsersStatusButton).toBeTruthy(); + + const spinnerInsideSyncUsersStatus = await syncUsersStatusButton.$( + '.spinner', + ); + expect(spinnerInsideSyncUsersStatus).toBeTruthy(); + + const syncUsersStatusUpdate = await page.$('#sync-users-status-update'); + expect(syncUsersStatusUpdate).toBeTruthy(); + }); + + it('should display the Sync External Accounts button', async () => { + const syncExternalAccountsButton = await page.$('#sync-external-accounts'); + expect(syncExternalAccountsButton).toBeTruthy(); + + const spinnerInsideSyncExternalAccounts = + await syncExternalAccountsButton.$('.spinner'); + expect(spinnerInsideSyncExternalAccounts).toBeTruthy(); + + const syncExternalAccountsUpdate = await page.$( + '#sync-external-accounts-update', + ); + expect(syncExternalAccountsUpdate).toBeTruthy(); + }); + + it('should display the Sync Unverified Users button', async () => { + const syncUnverifiedUsersButton = await page.$('#sync-unverified-users'); + expect(syncUnverifiedUsersButton).toBeTruthy(); + + const spinnerInsideSyncUnverifiedUsers = await syncUnverifiedUsersButton.$( + '.spinner', + ); + expect(spinnerInsideSyncUnverifiedUsers).toBeTruthy(); + + const syncUnverifiedUsersUpdate = await page.$( + '#sync-unverified-users-update', + ); + expect(syncUnverifiedUsersUpdate).toBeTruthy(); + }); + + it('should display the Create Goals anchor button', async () => { + const createGoalsButton = await page.$('#create-goal'); + expect(createGoalsButton).toBeTruthy(); + }); + + it('should display the Discord Users anchor button', async () => { + const discordUsersButton = await page.$('#discord-user-link'); + expect(discordUsersButton).toBeTruthy(); + const discordUsersButtonHref = await page.evaluate( + (el) => el.getAttribute('href'), + discordUsersButton, + ); + expect(discordUsersButtonHref).toBe('/users/discord/index.html'); + const discordUsersButtonText = await page.evaluate( + (el) => el.innerText, + discordUsersButton, + ); + const trimmedDiscordUsersButtonText = discordUsersButtonText.trim(); + expect(trimmedDiscordUsersButtonText).toBe('Discord Users'); + }); + + it('should display the User Management anchor button', async () => { + const userManagementButton = await page.$('#user-management-link'); + expect(userManagementButton).toBeTruthy(); + const userManagementButtonHref = await page.evaluate( + (el) => el.getAttribute('href'), + userManagementButton, + ); + expect(userManagementButtonHref).toBe('/users/index.html'); + const userManagementButtonText = await page.evaluate( + (el) => el.innerText, + userManagementButton, + ); + const trimmedUserManagementButtonText = userManagementButtonText.trim(); + expect(trimmedUserManagementButtonText).toBe('User Management'); + }); + + it('should display the Sync Repo button', async () => { + const syncRepoButton = await page.$('#repo-sync-button'); + expect(syncRepoButton).toBeTruthy(); + + const spinnerInsideSyncRepo = await syncRepoButton.$('.spinner'); + expect(spinnerInsideSyncRepo).toBeTruthy(); + + const syncRepoStatusUpdate = await page.$('#sync-repo-status-update'); + expect(syncRepoStatusUpdate).toBeTruthy(); + + const toast = await page.$('#toast'); + expect(toast).toBeTruthy(); + + await page.evaluate(() => { + document.querySelector('#repo-sync-button').click(); + }); + await page.waitForSelector('#toast'); + const toastVisibility = await page.waitForFunction(() => { + const toast = document.querySelector('#toast'); + const toastStyle = window.getComputedStyle(toast); + return toastStyle && toastStyle.getPropertyValue('display') !== 'none'; + }); + expect(toastVisibility).toBeTruthy(); + }); + + it('should display the footer with the correct repo link', async () => { + const footer = await page.$('footer'); + expect(footer).toBeTruthy(); + + const infoRepo = await footer.$('.info-repo'); + expect(infoRepo).toBeTruthy(); + + const repoLink = await infoRepo.$('a'); + expect(repoLink).toBeTruthy(); + + const repoLinkHref = await page.evaluate((el) => el.href, repoLink); + expect(repoLinkHref).toBe( + 'https://github.com/Real-Dev-Squad/website-dashboard', + ); + + const repoLinkTarget = await page.evaluate((el) => el.target, repoLink); + expect(repoLinkTarget).toBe('_blank'); + + const repoLinkRel = await page.evaluate((el) => el.rel, repoLink); + expect(repoLinkRel).toBe('noopener noreferrer'); + + const repoLinkText = await page.evaluate((el) => el.innerText, repoLink); + expect(repoLinkText).toBe('open sourced repo'); + + const repoLinkClass = await page.evaluate((el) => el.className, repoLink); + expect(repoLinkClass).toBe(''); + + const repoLinkStyle = await page.evaluate((el) => el.style, repoLink); + expect(repoLinkStyle).toBeTruthy(); + }); +}); diff --git a/constants.js b/constants.js index df4c3d84..155ca4f1 100644 --- a/constants.js +++ b/constants.js @@ -1,10 +1,13 @@ const API_BASE_URL = 'https://api.realdevsquad.com'; +const REPO_SYNC_API_URL = + 'https://staging-sync.staging-realdevsquad-com.workers.dev'; const USER_MANAGEMENT_LINK = 'user-management-link'; const EXTENSION_REQUESTS_LINK = 'extension-requests-link'; const SYNC_USERS_STATUS = 'sync-users-status'; const SYNC_EXTERNAL_ACCOUNTS = 'sync-external-accounts'; const SYNC_UNVERIFIED_USERS = 'sync-unverified-users'; const SYNC_USERS_STATUS_UPDATE = 'sync-users-status-update'; +const SYNC_REPO_STATUS_UPDATE = 'sync-repo-status-update'; const SYNC_EXTERNAL_ACCOUNTS_UPDATE = 'sync-external-accounts-update'; const SYNC_UNVERIFIED_USERS_UPDATE = 'sync-unverified-users-update'; const SYNC_IN_PROGRESS = 'Last Sync: In progress'; diff --git a/index.html b/index.html index 88d48cf3..f695100a 100644 --- a/index.html +++ b/index.html @@ -54,6 +54,13 @@ Create Tasks Profile + + Discord Users + Discord Groups Standup Updates +
+ +
+ +