Skip to content

Commit 40d1450

Browse files
authored
Merge pull request #734 from Real-Dev-Squad/develop
dev to main sync
2 parents d46f0bb + 99a6405 commit 40d1450

File tree

5 files changed

+262
-4
lines changed

5 files changed

+262
-4
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
const puppeteer = require('puppeteer');
2+
const {
3+
pendingRequest,
4+
requestActionResponse,
5+
approvedRequest,
6+
} = require('../../mock-data/requests');
7+
const { allUsersData } = require('../../mock-data/users');
8+
9+
const API_BASE_URL = 'https://api.realdevsquad.com';
10+
const SITE_URL = 'http://localhost:8000';
11+
12+
describe('Tests the request card', () => {
13+
let browser;
14+
let page;
15+
jest.setTimeout(60000);
16+
17+
beforeAll(async () => {
18+
browser = await puppeteer.launch({
19+
headless: 'new',
20+
ignoreHTTPSErrors: true,
21+
args: ['--incognito', '--disable-web-security'],
22+
devtools: false,
23+
});
24+
page = await browser.newPage();
25+
26+
await page.setRequestInterception(true);
27+
28+
page.on('request', (interceptedRequest) => {
29+
const url = interceptedRequest.url();
30+
31+
if (url === `${API_BASE_URL}/users/search?role=in_discord`) {
32+
interceptedRequest.respond({
33+
status: 200,
34+
contentType: 'application/json',
35+
headers: {
36+
'Access-Control-Allow-Origin': '*',
37+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
38+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
39+
},
40+
body: JSON.stringify(allUsersData),
41+
});
42+
} else if (url === `${API_BASE_URL}/requests?dev=true&type=OOO&size=12`) {
43+
interceptedRequest.respond({
44+
status: 200,
45+
contentType: 'application/json',
46+
headers: {
47+
'Access-Control-Allow-Origin': '*',
48+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
49+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
50+
},
51+
body: JSON.stringify(pendingRequest),
52+
});
53+
} else if (
54+
url === `${API_BASE_URL}/requests/Wl4TTbpSrQDIjs6KLJwD?dev=true`
55+
) {
56+
interceptedRequest.respond({
57+
status: 200,
58+
contentType: 'application/json',
59+
headers: {
60+
'Access-Control-Allow-Origin': '*',
61+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
62+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
63+
},
64+
body: JSON.stringify(requestActionResponse),
65+
});
66+
} else if (
67+
url === `${API_BASE_URL}/requests?dev=true&id=Wl4TTbpSrQDIjs6KLJwD`
68+
) {
69+
interceptedRequest.respond({
70+
status: 200,
71+
contentType: 'application/json',
72+
headers: {
73+
'Access-Control-Allow-Origin': '*',
74+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
75+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
76+
},
77+
body: JSON.stringify(approvedRequest),
78+
});
79+
} else {
80+
interceptedRequest.continue();
81+
}
82+
});
83+
await page.goto(`${SITE_URL}/requests`);
84+
await page.waitForNetworkIdle();
85+
});
86+
87+
afterAll(async () => {
88+
await browser.close();
89+
});
90+
91+
it('should update the card when the accept or reject button is clicked', async () => {
92+
await page.waitForSelector('.request__status');
93+
const statusButtonText = await page.$eval(
94+
'.request__status',
95+
(el) => el.textContent,
96+
);
97+
expect(statusButtonText).toBe('Pending');
98+
99+
await page.click('.request__action__btn.accept__btn');
100+
101+
await page.waitForSelector('.request__status');
102+
const updatedStatusButtonText = await page.$eval(
103+
'.request__status',
104+
(el) => el.textContent,
105+
);
106+
expect(updatedStatusButtonText).toBe('Approved');
107+
});
108+
});

mock-data/requests/index.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const pendingRequest = {
2+
message: 'Request fetched successfully',
3+
data: [
4+
{
5+
id: 'Wl4TTbpSrQDIjs6KLJwD',
6+
createdAt: 1711439903761,
7+
requestedBy: 'V4rqL1aDecNGoa1IxiCu',
8+
from: 1712275200000,
9+
until: 1712448000000,
10+
type: 'OOO',
11+
message: 'Testing purpose',
12+
lastModifiedBy: 'V4rqL1aDecNGoa1IxiCu',
13+
state: 'PENDING',
14+
updatedAt: 1711482912686,
15+
},
16+
],
17+
next: null,
18+
prev: null,
19+
};
20+
21+
const approvedRequest = {
22+
message: 'Request fetched successfully',
23+
data: [
24+
{
25+
id: 'Wl4TTbpSrQDIjs6KLJwD',
26+
createdAt: 1711439903761,
27+
requestedBy: 'V4rqL1aDecNGoa1IxiCu',
28+
from: 1712275200000,
29+
until: 1712448000000,
30+
type: 'OOO',
31+
message: 'Testing purpose',
32+
lastModifiedBy: 'V4rqL1aDecNGoa1IxiCu',
33+
state: 'APPROVED',
34+
updatedAt: 1711482912686,
35+
},
36+
],
37+
next: null,
38+
prev: null,
39+
};
40+
41+
const requestActionResponse = {
42+
message: 'Request approved successfully',
43+
data: {
44+
id: 'Wl4TTbpSrQDIjs6KLJwD',
45+
updatedAt: 1711490085808,
46+
lastModifiedBy: 'V4rqL1aDecNGoa1IxiCu',
47+
type: 'OOO',
48+
state: 'APPROVED',
49+
},
50+
};
51+
52+
module.exports = { pendingRequest, approvedRequest, requestActionResponse };

requests/script.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,12 +478,35 @@ async function performAcceptRejectAction(isAccepted, e) {
478478
state: isAccepted ? 'APPROVED' : 'REJECTED',
479479
});
480480
}
481-
changeFilter();
482-
startLoading();
481+
const parentDiv = e.target.closest('.ooo_request__card');
482+
parentDiv.classList.add('disabled');
483+
const removeSpinner = addSpinner(parentDiv);
484+
483485
const response = await acceptRejectRequest(requestId, body);
484-
stopLoading();
486+
removeSpinner();
487+
parentDiv.classList.remove('disabled');
488+
485489
if (response) {
486-
await renderOooRequestCards({ state: statusValue, sort: sortByValue });
490+
try {
491+
const updatedRequestDetails = (await getRequestDetailsById(requestId))
492+
.data[0];
493+
const superUserDetails = await getUserDetails(
494+
updatedRequestDetails.lastModifiedBy,
495+
);
496+
const requesterUserDetails = await getUserDetails(
497+
updatedRequestDetails.requestedBy,
498+
);
499+
500+
const updatedCard = createOooRequestCard(
501+
updatedRequestDetails,
502+
superUserDetails,
503+
requesterUserDetails,
504+
);
505+
parentDiv.replaceWith(updatedCard);
506+
} catch (error) {
507+
console.log(error);
508+
showMessage('ERROR', ErrorMessages.SERVER_ERROR);
509+
}
487510
}
488511
}
489512

requests/style.css

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
--base-transition: all 0.3s ease-in-out;
2525
--base-light-grey-border: 1px solid var(--light-gray-color);
2626
--color-red-light: #ff7979;
27+
--white-gray: #f2f2f3;
28+
--dark-blue: #1b1378;
2729
}
2830

2931
body {
@@ -115,6 +117,7 @@ p {
115117

116118
/* swapnil code */
117119
.ooo_request__card {
120+
position: relative;
118121
display: flex;
119122
flex-direction: column;
120123
background-color: var(--white);
@@ -372,6 +375,44 @@ nav a:hover {
372375
color: var(--black-color);
373376
}
374377

378+
.disabled {
379+
opacity: 0.5;
380+
pointer-events: none;
381+
}
382+
383+
.spinner {
384+
border: 8px solid var(--white-gray);
385+
border-radius: 50%;
386+
border-top: 8px solid var(--dark-blue);
387+
width: 1.5rem;
388+
height: 1.5rem;
389+
-webkit-animation: spin 2s linear infinite;
390+
animation: spin 2s linear infinite;
391+
position: absolute;
392+
inset: 0;
393+
margin: auto;
394+
}
395+
396+
@-webkit-keyframes spin {
397+
0% {
398+
-webkit-transform: rotate(0deg);
399+
}
400+
401+
100% {
402+
-webkit-transform: rotate(360deg);
403+
}
404+
}
405+
406+
@keyframes spin {
407+
0% {
408+
transform: rotate(0deg);
409+
}
410+
411+
100% {
412+
transform: rotate(360deg);
413+
}
414+
}
415+
375416
/* tooltip css */
376417

377418
.tooltip-container {

requests/util.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,37 @@ async function getInDiscordUserList() {
102102
console.log(error);
103103
}
104104
}
105+
106+
const addSpinner = (container) => {
107+
const spinner = createElement({
108+
type: 'div',
109+
attributes: { class: 'spinner' },
110+
});
111+
112+
container.append(spinner);
113+
114+
function removeSpinner() {
115+
spinner.remove();
116+
}
117+
118+
return removeSpinner;
119+
};
120+
121+
async function getRequestDetailsById(requestId) {
122+
try {
123+
const res = await fetch(
124+
`${API_BASE_URL}/requests?dev=true&id=${requestId}`,
125+
{
126+
credentials: 'include',
127+
method: 'GET',
128+
headers: {
129+
'Content-type': 'application/json',
130+
},
131+
},
132+
);
133+
const data = await res.json();
134+
return data;
135+
} catch (error) {
136+
console.log(error);
137+
}
138+
}

0 commit comments

Comments
 (0)