Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 13 additions & 37 deletions __tests__/extension-requests/extension-requests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,32 +643,6 @@ describe('Tests the Extension Requests Screen', () => {
const cardCount = extensionCardsAfter.length;
expect(cardCount === 3 || cardCount === 7).toBe(true);
});
it('checks whether the shimmer effect is visible under dev flag only for the assignee image element', async () => {
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
const assignImageSelector = await page.$$(
'[data-testid="assignee-image skeleton"]',
);
expect(assignImageSelector).toBeTruthy();

await page.waitForTimeout(5000);
const hasSkeletonClassAfter = await page.$eval('.assignee-image', (el) =>
el.classList.contains('skeleton'),
);
expect(hasSkeletonClassAfter).toBe(false);
});

it('checks whether the shimmer effect is visible under dev flag only for the assignee name element', async () => {
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
const assignNameSelector = await page.$$(
'[data-testid="assignee-name skeleton-text"]',
);
expect(assignNameSelector).toBeTruthy();
await page.waitForTimeout(5000);
const hasSkeletonClassAfter = await page.$eval('.assignee-name', (el) =>
el.classList.contains('skeleton-text'),
);
expect(hasSkeletonClassAfter).toBe(false);
});

it('shows error messages for empty title and reason inputs on update under dev feature flag', async () => {
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
Expand Down Expand Up @@ -720,8 +694,8 @@ describe('Tests the Extension Requests Screen', () => {

await page.click(editButtonSelector);

const extensionInputSelector = '[data-testid="extension-input"]';
const extensionErrorSelector = '[data-testid="extension-input-error"]';
const extensionInputSelector = '[data-testid="request-input"]';
const extensionErrorSelector = '[data-testid="request-input-error"]';
await page.$eval(extensionInputSelector, (input) => {
input.value = '2020-01-01';
});
Expand Down Expand Up @@ -750,7 +724,7 @@ describe('Tests the Extension Requests Screen', () => {

await page.type('[data-testid="title-text-input"]', 'Valid Title');
await page.type('[data-testid="reason-input-text-area"]', 'Valid Reason');
await page.type('[data-testid="extension-input"]', '2050-01-01');
await page.type('[data-testid="request-input"]', '2050-01-01');

await page.click(updateButtonSelector);

Expand All @@ -772,7 +746,7 @@ describe('Tests the Extension Requests Screen', () => {
const titleInputSelector = '[data-testid="title-text-input"]';
const reasonInputSelector = '[data-testid="reason-input-text-area"]';
const titleDisplaySelector = '.title-text';
const reasonDisplaySelector = '.reason-text';
const reasonDisplaySelector = '[data-testid="request-reason"]';

const longTitle = 'A'.repeat(300);
const longReason = 'This is a very long reason '.repeat(50);
Expand Down Expand Up @@ -811,8 +785,8 @@ describe('Tests the Extension Requests Screen', () => {

await page.click(editButtonSelector);

const extensionInputSelector = '[data-testid="extension-input"]';
const extensionErrorSelector = '[data-testid="extension-input-error"]';
const extensionInputSelector = '[data-testid="request-input"]';
const extensionErrorSelector = '[data-testid="request-input-error"]';

await page.$eval(extensionInputSelector, (input) => {
input.value = 'invalid-date';
Expand Down Expand Up @@ -1206,7 +1180,7 @@ describe('Tests the Extension Requests Screen', () => {
).toBe(false);
const toastMessage = await page.$('[data-testid="toast-message"]');
expect(await toastMessage.evaluate((el) => el.textContent)).toBe(
'Extension request successfully updated.',
'Request updated successfully',
);
});

Expand All @@ -1222,13 +1196,15 @@ describe('Tests the Extension Requests Screen', () => {
await page.click(`input[type="checkbox"][id="DENIED"]`);
await page.click(applyFilterButton);
await page.waitForNetworkIdle();
const extensionRequestCards = await page.$$('.extension-card');
const extensionRequestCards = await page.$$(
'[data-testid="extension-request-card"]',
);
expect(extensionRequestCards.length).toBe(
extensionRequestListForAuditLogs.allExtensionRequests.length,
);
});

it.skip('should display all the required field in the extension request card under feature flag', async () => {
it('should display all the required field in the extension request card under feature flag', async () => {
await page.goto(
`${LOCAL_TEST_PAGE_URL}/extension-requests?order=desc&dev=true&size=1&q=status%3APENDING`,
);
Expand Down Expand Up @@ -1258,7 +1234,7 @@ describe('Tests the Extension Requests Screen', () => {
expect(taskTitle).toContain(taskDone.taskData.title);
});

it.skip('should remove the card from display after approving the request under feature flag', async () => {
it('should remove the card from display after approving the request under feature flag', async () => {
await page.goto(
`${LOCAL_TEST_PAGE_URL}/extension-requests?order=desc&dev=true&size=1&q=status%3APENDING`,
);
Expand All @@ -1280,7 +1256,7 @@ describe('Tests the Extension Requests Screen', () => {
expect(extensionCardsAfter.length).toBe(0);
});

it.skip('should remove the card from display after rejecting the request under feature flag', async () => {
it('should remove the card from display after rejecting the request under feature flag', async () => {
await page.goto(
`${LOCAL_TEST_PAGE_URL}/extension-requests?order=desc&dev=true&size=1&q=status%3APENDING`,
);
Expand Down
21 changes: 8 additions & 13 deletions __tests__/requests/requests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ describe('Tests the request cards', () => {
body: JSON.stringify(requestActionResponse),
});
} else if (
url === `${STAGING_API_URL}/requests?dev=true&id=Wl4TTbpSrQDIjs6KLJwD`
url ===
`${STAGING_API_URL}/requests?dev=true&id=Wl4TTbpSrQDIjs6KLJwD` ||
url === `${STAGING_API_URL}/requests/Wl4TTbpSrQDIjs6KLJwD`
) {
interceptedRequest.respond({
status: 200,
Expand Down Expand Up @@ -568,15 +570,8 @@ describe('Tests the request cards', () => {
await page.goto(`${LOCAL_TEST_PAGE_URL}/requests?dev=true`);
await page.waitForNetworkIdle();
await page.click('#ooo_tab_link');
await page.waitForSelector('.request__status');

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

await page.click('.request__action__btn.accept__btn');
await page.waitForNetworkIdle();
await page.click('.approve-button');
await page.waitForSelector('[data-testid="toast-component"].show');
const toastComponent = await page.$('[data-testid="toast-component"]');
expect(
Expand Down Expand Up @@ -615,13 +610,13 @@ describe('Tests the request cards', () => {
expect(requestCards.length).toBe(approvedRequestsData.data.length);

const statusText = await requestCards[0].$eval(
'[data-testid="request-status"]',
'[data-testid="request-card-status"]',
(el) => el.textContent,
);
expect(statusText).toContain('Approved');
expect(statusText).toContain('APPROVED');
});

describe.skip('Test Request Card (Dev Mode Enabled)', () => {
describe('Test Request Card (Dev Mode Enabled)', () => {
beforeEach(async () => {
await page.goto(`${LOCAL_TEST_PAGE_URL}/requests?dev=true`);
await page.waitForNetworkIdle();
Expand Down
39 changes: 39 additions & 0 deletions components/request-card/constant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const CARD_REMOVAL_INITIAL_DELAY_MS = 800;
const CARD_REMOVAL_ANIMATION_DURATION_MS = 800;
const CARD_REMOVAL_ANIMATION_EASING = 'ease-out';
const DEADLINE_WARNING_THRESHOLD_DAYS = 3;
const HOVER_CARD_HIDE_DELAY = 300;
const ICONS = Object.freeze({
DEFAULT_USER_AVATAR: '/images/avatar.png',
EDIT: '/images/edit-icon.svg',
CANCEL: '/images/x-icon.svg',
CANCEL_WHITE: '/images/x-icon-white.svg',
CHECK: '/images/check-icon.svg',
CHECK_WHITE: '/images/check-icon-white.svg',
ARROW_DOWN: '/images/chevron-down-black.svg',
});

const REQUEST_STATUS = Object.freeze({
APPROVED: 'APPROVED',
PENDING: 'PENDING',
DENIED: 'DENIED',
REJECTED: 'REJECTED',
});

const REQUEST_TYPE = Object.freeze({
EXTENSION: 'EXTENSION',
OOO: 'OOO',
ONBOARDING: 'ONBOARDING',
});

const ERROR_MESSAGE = Object.freeze({
UPDATE: 'Error updating request',
DATE_INPUT_ERROR: 'Invalid date format. Please provide a valid date.',
DEADLINE_PASSED: "Past date can't be the new deadline.",
});

const SUCCESS_MESSAGE = Object.freeze({
APPROVED: 'Request approved successfully',
REJECTED: 'Request rejected successfully',
UPDATED: 'Request updated successfully',
});
90 changes: 70 additions & 20 deletions components/request-card/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async function createRequestCardComponent({
isDeadLineCrossed: requestDetails.isDeadlineCrossed,
deadlineDays: requestDetails.deadlineDays,
data,
oldEndsOn: requestDetails.oldEndsOnInMillisecond,
oldEndsOnValue: requestDetails.oldEndsOnInMillisecond,
isStatusPending: requestDetails.statusPending,
});
const {
Expand Down Expand Up @@ -126,7 +126,13 @@ async function createRequestCardComponent({
titleInputWrapper,
},
uiHandlers: { toggleInputs, appendLogs },
domRefs: { panel, accordionButton, rootElement, parentContainer },
domRefs: {
panel,
accordionButton,
rootElement,
parentContainer,
requestDetails,
},
});

titleInputWrapper.append(titleInput, titleInputError);
Expand All @@ -153,12 +159,12 @@ async function createRequestCardComponent({
taskStatusContainer.append(taskStatusTextLabel, taskStatusElement);
summaryContainer.append(datesContainer);
newDeadlineValue.append(newEndsOnTooltip);
requestForValue.append(requestCreatedAtTooltip);
requestForValue.append(newEndsOnTooltip.cloneNode(true));

const requestNumberContainer = createElement({ type: 'div' });
if (isExtensionRequest) {
datesContainer.append(requestNumberContainer);
} else if (data.type !== RequestType.OOO) {
} else if (data.type !== REQUEST_TYPE.OOO) {
taskDetailsContainer.append(requestNumberContainer);
}

Expand All @@ -177,7 +183,7 @@ async function createRequestCardComponent({

if (isExtensionRequest) {
panel.append(logContainer);
} else if (data?.state !== RequestStatus.PENDING) {
} else if (data?.state !== REQUEST_STATUS.PENDING) {
panel.append(commentContainer);
}

Expand Down Expand Up @@ -243,7 +249,12 @@ async function createRequestCardComponent({
data.title = formData.title;
data.newEndsOn = formData.newEndsOn;
showSuccessHighlight(rootElement);
showToast(SUCCESS_MESSAGE, 'success');
showToastMessage({
isDev: true,
oldToastFunction: showToast,
type: 'success',
message: SUCCESS_MESSAGE.UPDATED,
});

appendLogs(payloadForLog, data.id);
})
Expand All @@ -252,8 +263,15 @@ async function createRequestCardComponent({
showErrorHighlight(rootElement);

const errorMessage =
error?.response?.data?.message || error?.message || ERROR_MESSAGE;
showToast(errorMessage, 'error');
error?.response?.data?.message ||
error?.message ||
ERROR_MESSAGE.UPDATE;
showToastMessage({
isDev: true,
oldToastFunction: showToast,
type: 'error',
message: errorMessage,
});
})
.finally(() => {
rootElement.classList.remove('disabled');
Expand Down Expand Up @@ -306,16 +324,49 @@ async function createRequestCardComponent({
function toggleInputs() {
titleInputWrapper.classList.toggle('hidden');
titleInput.classList.toggle('hidden');
titleInputError.classList.toggle('hidden');
titleText.classList.toggle('hidden');
reasonInput.classList.toggle('hidden');
reasonParagraph.classList.toggle('hidden');
reasonInputError.classList.toggle('hidden');
newDeadlineValue.classList.toggle('hidden');
requestInput.classList.toggle('hidden');
}

const userImage = requestUser?.picture?.url ?? DEFAULT_USER_AVATAR;
async function renderLogs(extensionRequestId) {
const logContainer = document.getElementById(
`log-container-${extensionRequestId}`,
);
if (logContainer.querySelector('.server-log')?.innerHTML) {
return;
}
try {
const extensionLogs = await getExtensionRequestLogs({
extensionRequestId,
});
const innerHTML = generateSentence(
extensionLogs.logs,
'server-log',
extensionRequestId,
);
if (innerHTML) {
const isLocalLogPresent = logContainer.querySelectorAll('.local-log');
if (isLocalLogPresent) {
const tempDiv = document.createElement('div');
tempDiv.classList.add('invisible-div');
tempDiv.innerHTML = innerHTML;

const localLogElement = logContainer.querySelector('.local-log');
logContainer.insertBefore(tempDiv, localLogElement);
} else {
logContainer.innerHTML += innerHTML;
}
updateAccordionHeight(panel);
}
} catch (error) {
console.error('Failed to fetch extension request logs:', error);
}
}

const userImage = requestUser?.picture?.url ?? ICONS.DEFAULT_USER_AVATAR;
let userFirstName = requestUser?.first_name ?? data.assignee;
const userId = requestUser?.id;
const userStatus = userStatusMap?.get(userId);
Expand Down Expand Up @@ -376,10 +427,11 @@ async function createRequestCardComponent({

function prepareRequestCardData({ data, isExtensionRequest }) {
const currentTimestamp = Date.now();
let oldEndsOn = data.oldEndsOn;
let newEndsOn = data.newEndsOn;

if (data.type === RequestType.OOO) {
let oldEndsOn = data?.oldEndsOn;
let newEndsOn = data?.newEndsOn;

if (data.type === REQUEST_TYPE.OOO) {
oldEndsOn = data.from;
newEndsOn = data.until;
}
Expand All @@ -399,11 +451,9 @@ function prepareRequestCardData({ data, isExtensionRequest }) {

const isDeadlineCrossed = currentTimestamp > oldEndsOnInMillisecond;
const isNewDeadlineCrossed = currentTimestamp > newEndsOnInMillisecond;

const statusPending = isExtensionRequest
? data.status === RequestStatus.PENDING
: data.state === RequestStatus.PENDING;

? data.status === REQUEST_STATUS.PENDING
: data.state === REQUEST_STATUS.PENDING;
const deadlineDays = dateDiff(
currentTimestamp,
oldEndsOnInMillisecond,
Expand All @@ -416,7 +466,7 @@ function prepareRequestCardData({ data, isExtensionRequest }) {
newEndsOnInMillisecond,
(d) => d + (isNewDeadlineCrossed ? ' ago' : ''),
)
: getTwoDigitDate(newEndsOn);
: getTwoDigitDate(newEndsOnInMillisecond, true);

return {
oldEndsOnInMillisecond,
Expand Down Expand Up @@ -585,7 +635,7 @@ function createAccordionContainer() {
const downArrowIcon = createElement({
type: 'img',
attributes: {
src: ICON_ARROW_DOWN,
src: ICONS.ARROW_DOWN,
alt: 'down-arrow',
},
});
Expand Down
Loading
Loading