Skip to content

Commit 1ecffc5

Browse files
tanu-chahalrishirishhhAnujChhikara
authored
Feature: edit extension request before approval or rejection (#910)
* Added input validation and toast based on api response - behind dev flag. * Added tests for input validation and edit button under dev flag. * Added dev flag in ER update api request. * Resolved failing test cases. * Updated failing tests based on new changes. * Added missing tests. * Changed the confusing dev feature flag name. * Added Error Handling for Unavailable user details. * Changes style values to 8/4 metric and made toast timing a constant. * Changed the getSelfUser endpoint to new one. * Updated the getSelfUser() url for tests. * Fix: Prevent Code Format Overflow in Task Request Page (#927) added code css property * Added input validation and toast based on api response - behind dev flag. * Took latest pull from develop and merged it. * Added missing tests. * Changes style values to 8/4 metric and made toast timing a constant. * Made shouldDisplayEditButton() a pure function. * Added tests for input validation and edit button under dev flag. * Updated failing tests based on new changes. * Added missing tests. * Made shouldDisplayEditButton() a pure function. * Rebased and removed duplicate tests. --------- Co-authored-by: Rishi <[email protected]> Co-authored-by: Anuj Chhikara <[email protected]>
1 parent 8ce0841 commit 1ecffc5

File tree

5 files changed

+376
-15
lines changed

5 files changed

+376
-15
lines changed

__tests__/extension-requests/extension-requests.test.js

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ describe('Tests the Extension Requests Screen', () => {
281281
},
282282
body: JSON.stringify(extensionRequestListForAuditLogs),
283283
});
284-
} else if (url === `${STAGING_API_URL}/users/self`) {
284+
} else if (url === `${STAGING_API_URL}/users?profile=true`) {
285285
interceptedRequest.respond({
286286
status: 200,
287287
contentType: 'application/json',
@@ -654,6 +654,165 @@ describe('Tests the Extension Requests Screen', () => {
654654
expect(hasSkeletonClassAfter).toBe(false);
655655
});
656656

657+
it('shows error messages for empty title and reason inputs on update under dev feature flag', async () => {
658+
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
659+
const editButtonSelector = '[data-testid="edit-button"]';
660+
const editButton = await page.$(editButtonSelector);
661+
if (!editButton) {
662+
return;
663+
}
664+
await page.click(editButtonSelector);
665+
const updateButtonSelector = '[data-testid="update-button"]';
666+
const titleInputSelector = '[data-testid="title-text-input"]';
667+
const reasonInputSelector = '[data-testid="reason-input-text-area"]';
668+
const titleErrorSelector = '[data-testid="title-input-error"]';
669+
const reasonErrorSelector = '[data-testid="reason-input-error"]';
670+
671+
await page.evaluate((selector) => {
672+
const element = document.querySelector(selector);
673+
if (element) element.value = '';
674+
}, titleInputSelector);
675+
676+
await page.evaluate((selector) => {
677+
const element = document.querySelector(selector);
678+
if (element) element.value = '';
679+
}, reasonInputSelector);
680+
681+
await page.click(updateButtonSelector);
682+
683+
const isTitleErrorVisible = await page
684+
.$eval(titleErrorSelector, (el) => el && !el.classList.contains('hidden'))
685+
.catch(() => false);
686+
687+
const isReasonErrorVisible = await page
688+
.$eval(
689+
reasonErrorSelector,
690+
(el) => el && !el.classList.contains('hidden'),
691+
)
692+
.catch(() => false);
693+
expect(isTitleErrorVisible).toBe(true);
694+
expect(isReasonErrorVisible).toBe(true);
695+
});
696+
697+
it('shows error message if deadline is set to past date under dev feature flag', async () => {
698+
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
699+
const editButtonSelector = '[data-testid="edit-button"]';
700+
const editButton = await page.$(editButtonSelector);
701+
if (!editButton) {
702+
return;
703+
}
704+
705+
await page.click(editButtonSelector);
706+
707+
const extensionInputSelector = '[data-testid="extension-input"]';
708+
const extensionErrorSelector = '[data-testid="extension-input-error"]';
709+
await page.$eval(extensionInputSelector, (input) => {
710+
input.value = '2020-01-01';
711+
});
712+
await page.click('[data-testid="update-button"]');
713+
const isExtensionErrorVisible = await page.$eval(
714+
extensionErrorSelector,
715+
(el) =>
716+
!el.classList.contains('hidden') &&
717+
el.innerText.includes("Past date can't be the new deadline"),
718+
);
719+
expect(isExtensionErrorVisible).toBe(true);
720+
});
721+
722+
it('hides edit button and displays update wrapper on successful update under dev feature flag', async () => {
723+
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
724+
const editButtonSelector = '[data-testid="edit-button"]';
725+
const editButton = await page.$(editButtonSelector);
726+
if (!editButton) {
727+
return;
728+
}
729+
730+
await page.click(editButtonSelector);
731+
732+
const updateButtonSelector = '[data-testid="update-button"]';
733+
const updateWrapperSelector = '[data-testid="update-wrapper"]';
734+
735+
await page.type('[data-testid="title-text-input"]', 'Valid Title');
736+
await page.type('[data-testid="reason-input-text-area"]', 'Valid Reason');
737+
await page.type('[data-testid="extension-input"]', '2050-01-01');
738+
739+
await page.click(updateButtonSelector);
740+
741+
const isEditButtonHidden = await page.$eval(editButtonSelector, (el) =>
742+
el.classList.contains('hidden'),
743+
);
744+
const isUpdateWrapperVisible = await page.$eval(
745+
updateWrapperSelector,
746+
(el) => !el.classList.contains('hidden'),
747+
);
748+
expect(isEditButtonHidden).toBe(true);
749+
expect(isUpdateWrapperVisible).toBe(true);
750+
});
751+
752+
it('handles long title and long reason properly under dev feature flag', async () => {
753+
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
754+
755+
const editButtonSelector = '[data-testid="edit-button"]';
756+
const titleInputSelector = '[data-testid="title-text-input"]';
757+
const reasonInputSelector = '[data-testid="reason-input-text-area"]';
758+
const titleDisplaySelector = '.title-text';
759+
const reasonDisplaySelector = '.reason-text';
760+
761+
const longTitle = 'A'.repeat(300);
762+
const longReason = 'This is a very long reason '.repeat(50);
763+
764+
const editButton = await page.$(editButtonSelector);
765+
if (!editButton) {
766+
return;
767+
}
768+
await page.click(editButtonSelector);
769+
770+
await page.type(titleInputSelector, longTitle);
771+
await page.type(reasonInputSelector, longReason);
772+
773+
const isTitleTruncated = await page.$eval(
774+
titleDisplaySelector,
775+
(el) => window.getComputedStyle(el).textOverflow === 'ellipsis',
776+
);
777+
778+
const isReasonWrapped = await page.$eval(
779+
reasonDisplaySelector,
780+
(el) => window.getComputedStyle(el).whiteSpace === 'normal',
781+
);
782+
783+
expect(isTitleTruncated).toBe(true);
784+
expect(isReasonWrapped).toBe(true);
785+
});
786+
787+
it('displays an error message for invalid date format under dev feature flag', async () => {
788+
await page.goto(`${LOCAL_TEST_PAGE_URL}/extension-requests/?dev=true`);
789+
790+
const editButtonSelector = '[data-testid="edit-button"]';
791+
const editButton = await page.$(editButtonSelector);
792+
if (!editButton) {
793+
return;
794+
}
795+
796+
await page.click(editButtonSelector);
797+
798+
const extensionInputSelector = '[data-testid="extension-input"]';
799+
const extensionErrorSelector = '[data-testid="extension-input-error"]';
800+
801+
await page.$eval(extensionInputSelector, (input) => {
802+
input.value = 'invalid-date';
803+
});
804+
await page.click('[data-testid="update-button"]');
805+
806+
const isExtensionErrorVisible = await page.$eval(
807+
extensionErrorSelector,
808+
(el) =>
809+
!el.classList.contains('hidden') &&
810+
el.innerText.includes('Invalid date format.'),
811+
);
812+
813+
expect(isExtensionErrorVisible).toBe(true);
814+
});
815+
657816
it('Checks whether the card is not removed from display when api call is unsuccessful', async () => {
658817
const extensionCards = await page.$$('.extension-card');
659818

extension-requests/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ const SORT_ASC_ICON = 'asc-sort-icon';
4141
const SORT_DESC_ICON = 'desc-sort-icon';
4242
const OLDEST_FIRST = 'Oldest first';
4343
const NEWEST_FIRST = 'Newest first';
44+
45+
const UPDATE_TOAST_TIMING = 3000;

extension-requests/local-utils.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const Order = {
1010
};
1111
async function getSelfUser() {
1212
try {
13-
const res = await fetch(`${API_BASE_URL}/users/self`, {
13+
const res = await fetch(`${API_BASE_URL}/users?profile=true`, {
1414
method: 'GET',
1515
credentials: 'include',
1616
headers: {
@@ -103,8 +103,10 @@ const parseExtensionRequestParams = (uri, nextPageParamsObject) => {
103103
return nextPageParamsObject;
104104
};
105105

106-
async function updateExtensionRequest({ id, body }) {
107-
const url = `${API_BASE_URL}/extension-requests/${id}`;
106+
async function updateExtensionRequest({ id, body, underDevFeatureFlag }) {
107+
const url = underDevFeatureFlag
108+
? `${API_BASE_URL}/extension-requests/${id}?dev=true`
109+
: `${API_BASE_URL}/extension-requests/${id}`;
108110
const res = await fetch(url, {
109111
credentials: 'include',
110112
method: 'PATCH',

0 commit comments

Comments
 (0)