Skip to content

Commit e809740

Browse files
Merge pull request #668 from Real-Dev-Squad/develop
Dev to Main sync
2 parents 863d57e + 8fa2e86 commit e809740

File tree

29 files changed

+1989
-163
lines changed

29 files changed

+1989
-163
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
const puppeteer = require('puppeteer');
2+
3+
const {
4+
fetchedApplications,
5+
acceptedApplications,
6+
} = require('../../mock-data/applications');
7+
const { superUserForAudiLogs } = require('../../mock-data/users');
8+
9+
const SITE_URL = 'http://localhost:8000';
10+
// helper/loadEnv.js file causes API_BASE_URL to be stagin-api on local env url in taskRequest/index.html
11+
const API_BASE_URL = 'https://staging-api.realdevsquad.com';
12+
13+
describe('Applications page', () => {
14+
let browser;
15+
let page;
16+
17+
jest.setTimeout(60000);
18+
19+
beforeEach(async () => {
20+
browser = await puppeteer.launch({
21+
headless: 'new',
22+
ignoreHTTPSErrors: true,
23+
args: ['--incognito', '--disable-web-security'],
24+
});
25+
});
26+
beforeEach(async () => {
27+
page = await browser.newPage();
28+
29+
await page.setRequestInterception(true);
30+
31+
page.on('request', (request) => {
32+
if (
33+
request.url() === `${API_BASE_URL}/applications?size=5` ||
34+
request.url() ===
35+
`${API_BASE_URL}/applications?next=YwTi6zFNI3GlDsZVjD8C&size=5`
36+
) {
37+
request.respond({
38+
status: 200,
39+
contentType: 'application/json',
40+
body: JSON.stringify({
41+
applications: fetchedApplications,
42+
next: '/applications?next=YwTi6zFNI3GlDsZVjD8C&size=5',
43+
}),
44+
headers: {
45+
'Access-Control-Allow-Origin': '*',
46+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
47+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
48+
},
49+
});
50+
} else if (
51+
request.url() === `${API_BASE_URL}/applications?size=5&status=accepted`
52+
) {
53+
request.respond({
54+
status: 200,
55+
contentType: 'application/json',
56+
body: JSON.stringify({ applications: acceptedApplications }),
57+
headers: {
58+
'Access-Control-Allow-Origin': '*',
59+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
60+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
61+
},
62+
});
63+
} else if (request.url() === `${API_BASE_URL}/users/self`) {
64+
request.respond({
65+
status: 200,
66+
contentType: 'application/json',
67+
headers: {
68+
'Access-Control-Allow-Origin': '*',
69+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
70+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
71+
},
72+
body: JSON.stringify(superUserForAudiLogs),
73+
});
74+
} else if (
75+
request.url() === `${API_BASE_URL}/applications/lavEduxsb2C5Bl4s289P`
76+
) {
77+
request.respond({
78+
status: 200,
79+
contentType: 'application/json',
80+
body: JSON.stringify({
81+
message: 'application updated successfully!',
82+
}),
83+
headers: {
84+
'Access-Control-Allow-Origin': '*',
85+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
86+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
87+
},
88+
});
89+
} else {
90+
request.continue();
91+
}
92+
});
93+
await page.goto(`${SITE_URL}/applications`);
94+
await page.waitForNetworkIdle();
95+
});
96+
97+
afterEach(async () => {
98+
await page.close();
99+
});
100+
101+
afterAll(async () => {
102+
await browser.close();
103+
});
104+
105+
it('should render the initial UI elements', async function () {
106+
const title = await page.$('.header h1');
107+
const filterButton = await page.$('.filter-button');
108+
const applicationCards = await page.$$('.application-card');
109+
expect(title).toBeTruthy();
110+
expect(filterButton).toBeTruthy();
111+
expect(applicationCards).toBeTruthy();
112+
expect(applicationCards.length).toBe(5);
113+
});
114+
115+
it('should load and render the accepted application requests when accept is selected from filter, and after clearing the filter it should again show all the applications', async function () {
116+
await page.click('.filter-button');
117+
118+
await page.$eval('input[name="status"][value="accepted"]', (radio) =>
119+
radio.click(),
120+
);
121+
await page.click('.apply-filter-button');
122+
await page.waitForNetworkIdle();
123+
let applicationCards = await page.$$('.application-card');
124+
expect(applicationCards.length).toBe(4);
125+
126+
await page.click('.filter-button');
127+
await page.click('.clear-btn');
128+
129+
await page.waitForNetworkIdle();
130+
applicationCards = await page.$$('.application-card');
131+
expect(applicationCards.length).toBe(5);
132+
});
133+
134+
it('should load more applications on going to the bottom of the page', async function () {
135+
let applicationCards = await page.$$('.application-card');
136+
expect(applicationCards.length).toBe(5);
137+
await page.evaluate(() => {
138+
const element = document.querySelector('#page_bottom_element');
139+
if (element) {
140+
element.scrollIntoView({ behavior: 'auto' });
141+
}
142+
});
143+
await page.waitForNetworkIdle();
144+
applicationCards = await page.$$('.application-card');
145+
expect(applicationCards.length).toBe(10);
146+
});
147+
148+
it('should open application details modal for application, when user click on view details on any card', async function () {
149+
const applicationDetailsModal = await page.$('.application-details');
150+
expect(
151+
await applicationDetailsModal.evaluate((el) =>
152+
el.classList.contains('hidden'),
153+
),
154+
).toBe(true);
155+
await page.click('.view-details-button');
156+
expect(
157+
await applicationDetailsModal.evaluate((el) =>
158+
el.classList.contains('hidden'),
159+
),
160+
).toBe(false);
161+
});
162+
163+
it('should show toast message with application updated successfully', async function () {
164+
await page.click('.view-details-button');
165+
await page.click('.application-details-accept');
166+
const toast = await page.$('#toast');
167+
expect(await toast.evaluate((el) => el.classList.contains('hidden'))).toBe(
168+
false,
169+
);
170+
expect(await toast.evaluate((el) => el.innerText)).toBe(
171+
'application updated successfully!',
172+
);
173+
await page.waitForNetworkIdle();
174+
});
175+
});

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

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const {
2121
} = require('../../mock-data/users');
2222
const { usersStatus } = require('../../mock-data/users-status');
2323
const { taskDone, auditLogTasks } = require('../../mock-data/tasks/index');
24-
24+
const baseUrl = 'http://localhost:8000/extension-requests';
2525
describe('Tests the Extension Requests Screen', () => {
2626
let browser;
2727
let page;
@@ -46,7 +46,9 @@ describe('Tests the Extension Requests Screen', () => {
4646
const url = interceptedRequest.url();
4747
if (
4848
url ===
49-
'https://api.realdevsquad.com/extension-requests?order=asc&size=5&q=status%3APENDING'
49+
'https://api.realdevsquad.com/extension-requests?order=asc&size=5&q=status%3APENDING' ||
50+
url ===
51+
'https://api.realdevsquad.com/extension-requests?dev=true&order=asc'
5052
) {
5153
interceptedRequest.respond({
5254
status: 200,
@@ -109,6 +111,19 @@ describe('Tests the Extension Requests Screen', () => {
109111
},
110112
body: JSON.stringify(userSunny),
111113
});
114+
} else if (
115+
url === 'https://api.realdevsquad.com/users?search=randhir&size=1'
116+
) {
117+
interceptedRequest.respond({
118+
status: 200,
119+
contentType: 'application/json',
120+
headers: {
121+
'Access-Control-Allow-Origin': '*',
122+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
123+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
124+
},
125+
body: JSON.stringify(userRandhir),
126+
});
112127
} else if (
113128
url ===
114129
'https://api.realdevsquad.com/tasks/PYj79ki2agB0q5JN3kUf/details'
@@ -263,7 +278,9 @@ describe('Tests the Extension Requests Screen', () => {
263278
});
264279
} else if (
265280
url ===
266-
'https://api.realdevsquad.com/extension-requests?order=asc&size=5&q=status%3AAPPROVED%2BPENDING%2BDENIED'
281+
'https://api.realdevsquad.com/extension-requests?order=asc&size=5&q=status%3AAPPROVED%2BPENDING%2BDENIED' ||
282+
url ===
283+
'https://api.realdevsquad.com/extension-requests?dev=true&order=asc&q=status%3AAPPROVED%2BDENIED'
267284
) {
268285
interceptedRequest.respond({
269286
status: 200,
@@ -327,12 +344,26 @@ describe('Tests the Extension Requests Screen', () => {
327344
},
328345
body: JSON.stringify(extensionRequestLogs['lw7dRB0I3a6ivsFR5Izs']),
329346
});
347+
} else if (
348+
url ===
349+
'https://api.realdevsquad.com/extension-requests?order=asc&size=5&q=status%3AAPPROVED%2Cassignee%3AiODXB6gfsjaZB9p0XlBw%2B7yzVDl8s1ORNCtH9Ps7K'
350+
) {
351+
interceptedRequest.respond({
352+
status: 200,
353+
contentType: 'application/json',
354+
headers: {
355+
'Access-Control-Allow-Origin': '*',
356+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
357+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
358+
},
359+
body: JSON.stringify(extensionRequestsListUserSearch),
360+
});
330361
} else {
331362
interceptedRequest.continue();
332363
}
333364
});
334365

335-
await page.goto('http://localhost:8000/extension-requests');
366+
await page.goto(baseUrl);
336367

337368
await page.waitForNetworkIdle();
338369

@@ -361,6 +392,31 @@ describe('Tests the Extension Requests Screen', () => {
361392
expect(extensionCardsList.length).toBe(4);
362393
expect(extensionRequestsElement).toBeTruthy();
363394
});
395+
it('Should contain all dates elements', async () => {
396+
const checkContainer = async (containerId) => {
397+
const textExists = await page.$eval(
398+
`${containerId} .card-row-text`,
399+
(el) => !!el,
400+
);
401+
const valueExists = await page.$eval(
402+
`${containerId} .tooltip-container`,
403+
(el) => !!el,
404+
);
405+
const tooltipExists = await page.$eval(
406+
`${containerId} .tooltip`,
407+
(el) => !!el,
408+
);
409+
410+
expect(textExists).toBeTruthy();
411+
expect(valueExists).toBeTruthy();
412+
expect(tooltipExists).toBeTruthy();
413+
};
414+
415+
await checkContainer('#deadline-container');
416+
await checkContainer('#requested-time-container');
417+
await checkContainer('#new-deadline-container');
418+
await checkContainer('#extension-container');
419+
});
364420

365421
it('checks the search functionality', async () => {
366422
await page.type('#assignee-search', 'sunny');
@@ -511,14 +567,14 @@ describe('Tests the Extension Requests Screen', () => {
511567
'.extension-card:first-child .panel',
512568
);
513569
const firstAccordionIsVisible = await firstAccordionContent.evaluate(
514-
(el) => el.style.display === 'block',
570+
(el) => el.style.maxHeight !== '',
515571
);
516572
expect(firstAccordionIsVisible).toBe(true);
517573

518574
await firstAccordionButton.click();
519575

520576
const firstAccordionIsHidden = await firstAccordionContent.evaluate(
521-
(el) => el.style.display !== 'block',
577+
(el) => el.style.maxHeight === '',
522578
);
523579
expect(firstAccordionIsHidden).toBe(true);
524580
});
@@ -630,7 +686,7 @@ describe('Tests the Extension Requests Screen', () => {
630686
await page.$eval('.title-text-input', (el) => (el.value = ''));
631687
await page.type('.title-text-input', newTitle);
632688

633-
const newDate = '2023-09-19T22:20';
689+
const newDate = '2023-09-19';
634690
await page.evaluate((newDate) => {
635691
document.querySelector('.date-input').value = newDate;
636692
}, newDate);
@@ -668,7 +724,7 @@ describe('Tests the Extension Requests Screen', () => {
668724
const newTitle = 'New Title Text';
669725
await page.type('.title-text-input', newTitle);
670726

671-
const newDate = '2023-09-19T22:20';
727+
const newDate = '2023-09-19';
672728
await page.evaluate((newDate) => {
673729
document.querySelector('.date-input').value = newDate;
674730
}, newDate);
@@ -774,7 +830,7 @@ describe('Tests the Extension Requests Screen', () => {
774830
const cardNumber1Value = await extensionRequestNumberContainer[1].evaluate(
775831
(node) => node.textContent,
776832
);
777-
expect(cardNumber1Value).toBe('5');
833+
expect(cardNumber1Value).toBe('#5');
778834
});
779835

780836
test('Default Request Number to 1 if requestNumber field is missing in API Response', async () => {
@@ -791,7 +847,7 @@ describe('Tests the Extension Requests Screen', () => {
791847
const cardNumber2Value = await extensionRequestNumberContainer[3].evaluate(
792848
(node) => node.textContent,
793849
);
794-
expect(cardNumber2Value).toBe('1');
850+
expect(cardNumber2Value).toBe('#1');
795851
});
796852

797853
it('Validating if audit logs are being generated in realtime', async () => {
@@ -823,7 +879,7 @@ describe('Tests the Extension Requests Screen', () => {
823879
// Click the first element with class '.edit-button'
824880
await page.$$eval('.edit-button', (buttons) => buttons[0].click());
825881
const newTitle = 'This is a new title test case';
826-
const newDate = '2024-09-19T22:20';
882+
const newDate = '2024-09-19';
827883
const newReason = 'This is the new reason';
828884

829885
// Updating all the input fields
@@ -849,4 +905,41 @@ describe('Tests the Extension Requests Screen', () => {
849905
logs = await extensionLogsForFirstER.$$('.log-div');
850906
expect(Array.from(logs).length).toBe(9);
851907
});
908+
909+
it('Should update page url when filters and usernames are changed', async () => {
910+
await page.click('#filter-button');
911+
await page.click('input[value="PENDING"]');
912+
await page.click('input[value="APPROVED"]');
913+
await page.click('#apply-filter-button');
914+
await page.type('#assignee-search', 'sunny,randhir');
915+
await page.keyboard.press('Enter');
916+
await page.waitForNetworkIdle();
917+
const url = page.url();
918+
expect(url).toBe(
919+
`${baseUrl}?order=asc&size=5&q=status%3AAPPROVED%2Cassignee%3Asunny%2Brandhir`,
920+
);
921+
});
922+
it('Should have UI elements in sync with url', async () => {
923+
await page.goto(
924+
`${baseUrl}/?order=asc&size=5&q=status%3AAPPROVED%2Cassignee%3Asunny%2Brandhir`,
925+
);
926+
const filterButton = await page.$('#filter-button');
927+
await filterButton.click();
928+
await page.waitForSelector('.filter-modal');
929+
const approvedFilter = await page.$('input[value="APPROVED"]');
930+
const currentState = await approvedFilter.getProperty('checked');
931+
const isApprovedChecked = await currentState.jsonValue();
932+
expect(isApprovedChecked).toBe(true);
933+
const searchText = await page.$eval(
934+
'#assignee-search',
935+
(input) => input.value,
936+
);
937+
expect(searchText).toBe('sunny,randhir');
938+
await page.waitForSelector('.sort-button');
939+
const ascSortIconDisplayStyle = await page.$eval(
940+
'#asc-sort-icon',
941+
(icon) => window.getComputedStyle(icon).display,
942+
);
943+
expect(ascSortIconDisplayStyle).toBe('block');
944+
});
852945
});

0 commit comments

Comments
 (0)