Skip to content

Commit

Permalink
feat: onboarding extension tab
Browse files Browse the repository at this point in the history
  • Loading branch information
AnujChhikara committed Feb 21, 2025
1 parent c74e1f4 commit 87e445e
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 142 deletions.
132 changes: 130 additions & 2 deletions __tests__/requests/requests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const {
requestActionResponse,
approvedRequest,
extensionRequest,
onboardingExtensionRequest,
} = require('../../mock-data/requests');
const { allUsersData } = require('../../mock-data/users');
const {
Expand Down Expand Up @@ -66,6 +67,19 @@ describe('Tests the request cards', () => {
},
body: JSON.stringify(extensionRequest),
});
} else if (
url === `${STAGING_API_URL}/requests?dev=true&type=ONBOARDING&size=12`
) {
interceptedRequest.respond({
status: 200,
contentType: 'application/json',
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
body: JSON.stringify(onboardingExtensionRequest),
});
} else if (
url === `${STAGING_API_URL}/requests/Wl4TTbpSrQDIjs6KLJwD?dev=true`
) {
Expand Down Expand Up @@ -114,6 +128,11 @@ describe('Tests the request cards', () => {

await page.click('.request__action__btn.accept__btn');

await page.waitForFunction(
() =>
document.querySelector('.request__status')?.textContent === 'Approved',
);

await page.waitForSelector('.request__status');
const updatedStatusButtonText = await page.$eval(
'.request__status',
Expand All @@ -124,18 +143,127 @@ describe('Tests the request cards', () => {

it('should load the extension request when the extension tab is clicked', async () => {
await page.click('#extension_tab_link');
await page.waitForSelector('.ooo_request__card');
await page.waitForSelector('.request__card');

const cardTitle = await page.$eval(
'.request__content p',
(el) => el.textContent,
);
expect(cardTitle).toBe('request message');
expect(cardTitle).toBe('Reason: request message');

const statusButtonText = await page.$eval(
'.request__status',
(el) => el.textContent,
);
expect(statusButtonText).toBe('Approved');
});

it('should hide the onboarding extension tab when dev is not true', async () => {
const onboardingTabLink = await page.$('[data-testid="onboarding-tab"]');
expect(await onboardingTabLink.isVisible()).toBe(false);
});

describe('Onboarding Requests UI (Dev Mode Enabled)', () => {
beforeAll(async () => {
await page.goto(`${LOCAL_TEST_PAGE_URL}/requests?dev=true`);
await page.waitForNetworkIdle();
});

it('should display the onboarding extension tab ', async () => {
await page.waitForNetworkIdle();
const onboardingTabLink = await page.$('[data-testid="onboarding-tab"]');
expect(await onboardingTabLink.isVisible()).toBe(true);
});

it('should display onboarding extension requests after clicking the onboarding tab', async () => {
await page.click('#onboarding_extension_tab_link');

await page.waitForSelector('[data-testid="onboarding-request-card"]', {
state: 'visible',
});

const onboardingExtensionRequestCards = await page.$$(
'[data-testid="onboarding-request-card"]',
);

expect(onboardingExtensionRequestCards.length).toEqual(
onboardingExtensionRequest.data.length,
);

const statusButtonText = await page.$eval(
'[data-testid="request-status"]',
(el) => el.textContent,
);
expect(statusButtonText.toLowerCase()).toBe(
onboardingExtensionRequest.data[0].state.toLowerCase(),
);
});

it('should show action buttons and input field only for pending requests', async () => {
const onboardingTabLink = await page.$('[data-testid="onboarding-tab"]');
await onboardingTabLink.click();
await page.waitForSelector('[data-testid="onboarding-request-card"]');

const requestCards = await page.$$(
'[data-testid="onboarding-request-card"]',
);
expect(requestCards.length).toBeGreaterThan(0);

for (const card of requestCards) {
const statusText = await card.$eval(
'[data-testid="request-status"]',
(el) => el.textContent.trim(),
);

const actionContainer = await card.$(
'[data-testid="action-container"]',
);
const approveButton = await card.$('[data-testid="approve-button"]');
const rejectButton = await card.$('[data-testid="reject-button"]');
const remarkInput = await card.$(
'[data-testid="request-remark-input"]',
);

if (statusText === 'Pending') {
expect(await actionContainer.isVisible()).toBe(true);
expect(await approveButton.isVisible()).toBe(true);
expect(await rejectButton.isVisible()).toBe(true);
expect(await remarkInput.isVisible()).toBe(true);
} else {
expect(await actionContainer.isVisible()).toBe(false);
expect(await approveButton.isVisible()).toBe(false);
expect(await rejectButton.isVisible()).toBe(false);
expect(await remarkInput.isVisible()).toBe(false);
}
}
});

it('should display superuser details only for non-pending requests', async () => {
const onboardingTabLink = await page.$('[data-testid="onboarding-tab"]');
await onboardingTabLink.click();
await page.waitForSelector('[data-testid="onboarding-request-card"]');

const requestCards = await page.$$(
'[data-testid="onboarding-request-card"]',
);
expect(requestCards.length).toBeGreaterThan(0);

for (const card of requestCards) {
const statusText = await card.$eval(
'[data-testid="request-status"]',
(el) => el.textContent.trim(),
);

const superuserSection = await card.$(
'[data-testid="admin-info-and-status"]',
);

if (statusText === 'Pending') {
expect(await superuserSection.isVisible()).toBe(false);
} else {
expect(await superuserSection.isVisible()).toBe(true);
}
}
});
});
});
119 changes: 63 additions & 56 deletions feed/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let nextLink = '';
let isDataLoading = false;
let category = CATEGORY.ALL;
let activeIndex = -1;
let debounceTimeout = null;

const tabsData = [
{ name: 'All', 'data-type': CATEGORY.ALL, class: 'active' },
Expand Down Expand Up @@ -308,29 +309,29 @@ async function populateActivityFeed(query = {}, newLink) {

try {
isDataLoading = true;
addLoader(container);
addLoader(activityFeedContainer);

const activityFeedData = await getActivityFeedData(combinedQuery, newLink);

if (!activityFeedData) return;

activityFeedContainer.innerHTML = '';

if (activityFeedData) {
nextLink = activityFeedData.next;
const allActivityFeedData = activityFeedData.data;
nextLink = activityFeedData.next;
const allActivityFeedData = activityFeedData.data;

if (currentVersion !== activityFeedPage) {
return;
}
if (currentVersion !== activityFeedPage) {
return;
}

if (allActivityFeedData.length === 0) {
addEmptyPageMessage(activityFeedContainer);
return;
}
if (allActivityFeedData.length === 0) {
addEmptyPageMessage(activityFeedContainer);
return;
}

for (const data of allActivityFeedData) {
const renderedItem = renderActivityItem(data);
activityFeedContainer.appendChild(renderedItem);
}
for (const data of allActivityFeedData) {
const renderedItem = renderActivityItem(data);
activityFeedContainer.appendChild(renderedItem);
}
} catch (error) {
showMessage(activityFeedContainer, error);
Expand All @@ -346,38 +347,32 @@ async function getActivityFeedData(query = {}, nextLink) {
validateQuery(query);
let finalUrl =
API_BASE_URL + (nextLink || '/logs' + generateActivityFeedParams(query));
const res = await fetch(finalUrl, {
credentials: 'include',
method: 'GET',
headers: {
'Content-type': 'application/json',
},
});

try {
const res = await fetch(finalUrl, {
credentials: 'include',
method: 'GET',
headers: {
'Content-type': 'application/json',
},
});

const data = await res.json();
if (res.ok) {
return data;
} else {
switch (res.status) {
case 401:
return showMessage(
activityFeedContainer,
ERROR_MESSAGE.UNAUTHENTICATED,
);
showMessage(activityFeedContainer, ERROR_MESSAGE.UNAUTHENTICATED);
return null;
case 403:
return showMessage(activityFeedContainer, ERROR_MESSAGE.UNAUTHORIZED);
showMessage(activityFeedContainer, ERROR_MESSAGE.UNAUTHORIZED);
return null;
case 404:
return showMessage(
activityFeedContainer,
ERROR_MESSAGE.LOGS_NOT_FOUND,
);
showMessage(activityFeedContainer, ERROR_MESSAGE.LOGS_NOT_FOUND);
return null;
case 400:
showMessage(activityFeedContainer, data.message);
return;
return null;
default:
break;
}
Expand Down Expand Up @@ -454,37 +449,49 @@ async function fetchSuggestions() {
const query = input.value.trim();
const suggestionBox = document.getElementById('suggestion-box');

if (!query) {
if (query === '') {
suggestionBox.style.display = 'none';
return;
}

try {
const response = await fetch(`${API_BASE_URL}/users?search=${query}`, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
});
if (/^\d/.test(query)) {
suggestionBox.innerHTML =
'<div class="suggestion-item">Please enter a valid username</div>';
suggestionBox.style.display = 'block';
return;
}

if (response.ok) {
const data = await response.json();
const users = data.users || [];
if (users.length > 0) {
renderSuggestions(users);
suggestionBox.style.display = 'block';
clearTimeout(debounceTimeout);

debounceTimeout = setTimeout(async () => {
try {
const response = await fetch(`${API_BASE_URL}/users?search=${query}`, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
});

if (response.ok) {
const data = await response.json();
const users = data.users || [];

if (users.length > 0) {
renderSuggestions(users);
suggestionBox.style.display = 'block';
} else {
suggestionBox.innerHTML =
'<div class="suggestion-item">No users found</div>';
suggestionBox.style.display = 'block';
}
} else {
suggestionBox.innerHTML =
'<div class="suggestion-item">No users found</div>';
suggestionBox.style.display = 'block';
console.error('Error fetching suggestions:', response.statusText);
}
} else {
console.error('Error fetching suggestions:', response.statusText);
} catch (error) {
console.error('Error:', error);
}
} catch (error) {
console.error('Error:', error);
}
}, 1500);
}

function renderSuggestions(users) {
Expand Down
6 changes: 6 additions & 0 deletions feed/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ body {
display: none;
border-radius: 0.5rem;
margin-top: 0.4rem;
min-height: 3rem;
}

.suggestion-item {
Expand All @@ -246,6 +247,7 @@ body {
transition: background-color 0.2s;
border-radius: 0.5rem;
height: 2rem;
margin-top: 0.2rem;
}

.suggestion-item:hover {
Expand All @@ -269,6 +271,10 @@ body {
border-radius: 50%;
}

.error-message {
text-align: center;
}

@media (max-width: 480px) {
.filters,
.filter-row {
Expand Down
3 changes: 3 additions & 0 deletions feed/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ function addEmptyPageMessage(container) {
}

function showMessage(container, errorMsg) {
container.innerHTML = '';

if (errorMsg) {
const errorHeading = createElement({
type: 'h4',
attributes: { class: 'error-message' },
innerText: errorMsg,
});

Expand Down
1 change: 0 additions & 1 deletion global.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ body {
display: flex;
margin: 0;
justify-content: start;
width: 100%;
}

#pageTitle {
Expand Down
Loading

0 comments on commit 87e445e

Please sign in to comment.