From 34af5f492d9e1e2489fa25ee9321bbd591ae5bc5 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sat, 16 Nov 2024 16:52:57 +0500 Subject: [PATCH 01/13] featureUrl removed --- task/script.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/task/script.js b/task/script.js index 7101fca9..f0faf817 100644 --- a/task/script.js +++ b/task/script.js @@ -1,6 +1,25 @@ const API_BASE_URL = window.API_BASE_URL; const suggestedUsers = []; const allUser = []; + +const params = new URLSearchParams(window.location.search); +const isDev = params.get('dev') === 'true'; + +const featureUrlField = document + .getElementById('featureUrl') + .closest('.inputBox'); + +if (isDev && featureUrlField) { + featureUrlField.style.display = 'none'; +} +const featureRadio = document + .getElementById('feature') + ?.closest('.radioButtons'); + +if (isDev && featureRadio) { + featureRadio.style.display = 'none'; +} + const category = document.getElementById('category'); category.addEventListener('change', async () => { @@ -136,7 +155,6 @@ taskForm.onsubmit = async (e) => { const { title, purpose, - featureUrl, type, links, endsOn, @@ -154,7 +172,9 @@ taskForm.onsubmit = async (e) => { lossRateNeelam, isNoteworthy, } = getObjectOfFormData(taskForm); - + if (!isDev) { + const featureUrl = getObjectOfFormData(taskForm); + } if (status === 'ASSIGNED' && !assignee.trim()) { alert('Assignee can not be empty'); showSubmitLoader(false); From dd9f56b935316dd2e974af8348064af59a86adab Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sat, 16 Nov 2024 18:18:58 +0500 Subject: [PATCH 02/13] removed feature/group --- task/script.js | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/task/script.js b/task/script.js index f0faf817..c52ba386 100644 --- a/task/script.js +++ b/task/script.js @@ -155,7 +155,6 @@ taskForm.onsubmit = async (e) => { const { title, purpose, - type, links, endsOn, status, @@ -163,7 +162,6 @@ taskForm.onsubmit = async (e) => { level, dependsOn, assignee, - participants, priority, percentCompleted, completionAwardDinero, @@ -173,8 +171,9 @@ taskForm.onsubmit = async (e) => { isNoteworthy, } = getObjectOfFormData(taskForm); if (!isDev) { - const featureUrl = getObjectOfFormData(taskForm); + const { featureUrl, type, participants } = getObjectOfFormData(taskForm); } + if (status === 'ASSIGNED' && !assignee.trim()) { alert('Assignee can not be empty'); showSubmitLoader(false); @@ -215,25 +214,29 @@ taskForm.onsubmit = async (e) => { if (status === 'AVIALABLE') { delete dataToBeSent.endsOn; } - - if (dataToBeSent.type == 'feature') { + if (isDev) { + delete dataToBeSent.featureUrl; + delete dataToBeSent.type; + delete dataToBeSent.participants; dataToBeSent.assignee = assignee.trim() ? assignee : ' '; - } - - if (dataToBeSent.type == 'group') { - dataToBeSent.participants = participants.trim() - ? participants.split(',') - : []; + } else { + if (dataToBeSent.featureUrl.trim() === '') { + delete dataToBeSent.featureUrl; + } + if (dataToBeSent.type == 'feature') { + dataToBeSent.assignee = assignee.trim() ? assignee : ' '; + } + if (dataToBeSent.type == 'group') { + dataToBeSent.participants = participants.trim() + ? participants.split(',') + : []; + } } if (dataToBeSent.purpose.trim() === '') { delete dataToBeSent.purpose; } - if (dataToBeSent.featureUrl.trim() === '') { - delete dataToBeSent.featureUrl; - } - dataToBeSent.links = dataToBeSent.links.filter((link) => link); if (dataToBeSent.links.length !== 0) { @@ -328,6 +331,7 @@ let stateHandle = () => { }; let hideUnusedField = (radio) => { + if (isDev) return; const assigneeInput = document.getElementById('assigneeInput'); const participantsInput = document.getElementById('participantsInput'); if ( From 42a43840db838b8364421cc80aa237c005138ecc Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sat, 16 Nov 2024 19:53:26 +0500 Subject: [PATCH 03/13] change class inputBox instead radioButton --- task/script.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/task/script.js b/task/script.js index c52ba386..d52310dc 100644 --- a/task/script.js +++ b/task/script.js @@ -12,9 +12,7 @@ const featureUrlField = document if (isDev && featureUrlField) { featureUrlField.style.display = 'none'; } -const featureRadio = document - .getElementById('feature') - ?.closest('.radioButtons'); +const featureRadio = document.getElementById('feature')?.closest('.inputBox'); if (isDev && featureRadio) { featureRadio.style.display = 'none'; From b53f5d94cf04aaac2ed871479cdb430af8f2305f Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sun, 17 Nov 2024 11:56:01 +0500 Subject: [PATCH 04/13] task level section removed --- task/script.js | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/task/script.js b/task/script.js index d52310dc..c471ebed 100644 --- a/task/script.js +++ b/task/script.js @@ -17,10 +17,18 @@ const featureRadio = document.getElementById('feature')?.closest('.inputBox'); if (isDev && featureRadio) { featureRadio.style.display = 'none'; } +const taskLevelDiv = document + .querySelector('.inputBox label[for="taskLevel"]') + .closest('.inputBox'); + +if (isDev && taskLevelDiv) { + taskLevelDiv.style.display = 'none'; +} const category = document.getElementById('category'); category.addEventListener('change', async () => { + if (isDev) return; try { showSubmitLoader(); const categoryValue = category.value; @@ -156,8 +164,6 @@ taskForm.onsubmit = async (e) => { links, endsOn, status, - category, - level, dependsOn, assignee, priority, @@ -169,7 +175,8 @@ taskForm.onsubmit = async (e) => { isNoteworthy, } = getObjectOfFormData(taskForm); if (!isDev) { - const { featureUrl, type, participants } = getObjectOfFormData(taskForm); + const { featureUrl, type, participants, category, level } = + getObjectOfFormData(taskForm); } if (status === 'ASSIGNED' && !assignee.trim()) { @@ -269,19 +276,21 @@ taskForm.onsubmit = async (e) => { const result = await response.json(); if (response.ok) { - const body = { - itemId: result.id, - itemType: 'task', - tagPayload: [{ tagId: category, levelId: level }], - }; - await fetch(`${API_BASE_URL}/items`, { - method: 'POST', - credentials: 'include', - body: JSON.stringify(body), - headers: { - 'Content-type': 'application/json', - }, - }); + if (!isDev) { + const body = { + itemId: result.id, + itemType: 'task', + tagPayload: [{ tagId: category, levelId: level }], + }; + await fetch(`${API_BASE_URL}/items`, { + method: 'POST', + credentials: 'include', + body: JSON.stringify(body), + headers: { + 'Content-type': 'application/json', + }, + }); + } alert(result.message); window.location.reload(true); } @@ -426,6 +435,7 @@ function debounce(func, delay) { } async function fetchTags() { + if (isDev) return; const response = await fetch(`${API_BASE_URL}/tags`); const data = await response.json(); const { tags } = data; @@ -441,6 +451,7 @@ async function fetchTags() { } async function fetchLevel() { + if (isDev) return; const response = await fetch(`${API_BASE_URL}/levels`); const data = await response.json(); const { levels } = data; From 5c0086258e1f288e26e2b787293ccb605f34d8c9 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sun, 17 Nov 2024 12:14:28 +0500 Subject: [PATCH 05/13] unncessary object destruction under featureflag removed --- task/script.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/task/script.js b/task/script.js index c471ebed..b932c650 100644 --- a/task/script.js +++ b/task/script.js @@ -24,7 +24,7 @@ const taskLevelDiv = document if (isDev && taskLevelDiv) { taskLevelDiv.style.display = 'none'; } - +console.log('hehehe'); const category = document.getElementById('category'); category.addEventListener('change', async () => { @@ -161,11 +161,16 @@ taskForm.onsubmit = async (e) => { const { title, purpose, + featureUrl, + type, links, endsOn, status, + category, + level, dependsOn, assignee, + participants, priority, percentCompleted, completionAwardDinero, @@ -174,10 +179,6 @@ taskForm.onsubmit = async (e) => { lossRateNeelam, isNoteworthy, } = getObjectOfFormData(taskForm); - if (!isDev) { - const { featureUrl, type, participants, category, level } = - getObjectOfFormData(taskForm); - } if (status === 'ASSIGNED' && !assignee.trim()) { alert('Assignee can not be empty'); @@ -264,6 +265,7 @@ taskForm.onsubmit = async (e) => { } try { + console.log(dataToBeSent); const response = await fetch(`${API_BASE_URL}/tasks?userStatusFlag=true`, { method: 'POST', credentials: 'include', From c838796c250a87979c6eb5a70cfc24fe2a18e7e1 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sun, 17 Nov 2024 13:19:31 +0500 Subject: [PATCH 06/13] status=available typo fixed --- task/script.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/task/script.js b/task/script.js index b932c650..99565e69 100644 --- a/task/script.js +++ b/task/script.js @@ -24,7 +24,6 @@ const taskLevelDiv = document if (isDev && taskLevelDiv) { taskLevelDiv.style.display = 'none'; } -console.log('hehehe'); const category = document.getElementById('category'); category.addEventListener('change', async () => { @@ -217,7 +216,7 @@ taskForm.onsubmit = async (e) => { delete dataToBeSent.endsOn; } - if (status === 'AVIALABLE') { + if (status === 'AVAILABLE') { delete dataToBeSent.endsOn; } if (isDev) { @@ -265,7 +264,6 @@ taskForm.onsubmit = async (e) => { } try { - console.log(dataToBeSent); const response = await fetch(`${API_BASE_URL}/tasks?userStatusFlag=true`, { method: 'POST', credentials: 'include', From ab328c61ab045cef21e563dea5930ffcb7c571a6 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sun, 17 Nov 2024 16:16:32 +0500 Subject: [PATCH 07/13] tests added for updated changes --- __tests__/tasks/task-dev-dependency.test.js | 106 ++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 __tests__/tasks/task-dev-dependency.test.js diff --git a/__tests__/tasks/task-dev-dependency.test.js b/__tests__/tasks/task-dev-dependency.test.js new file mode 100644 index 00000000..a50f0839 --- /dev/null +++ b/__tests__/tasks/task-dev-dependency.test.js @@ -0,0 +1,106 @@ +const API_BASE_URL = 'https://api.realdevsquad.com'; +const puppeteer = require('puppeteer'); +const { users } = require('../../mock-data/users'); + +describe('Task Form - Dev Mode', () => { + let browser; + let page; + jest.setTimeout(60000); + + beforeAll(async () => { + browser = await puppeteer.launch({ + headless: 'new', + ignoreHTTPSErrors: true, + args: ['--incognito', '--disable-web-security'], + devtools: false, + }); + page = await browser.newPage(); + + // Setup request interception + await page.setRequestInterception(true); + page.on('request', (interceptedRequest) => { + const url = interceptedRequest.url(); + + if (url === `${API_BASE_URL}/users`) { + 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(users), + }); + } else { + interceptedRequest.continue(); + } + }); + + await page.goto('http://localhost:8000/task?dev=true'); + await page.waitForNetworkIdle(); + }); + + afterAll(async () => { + await browser.close(); + }); + + describe('Hidden Fields', () => { + it('should hide feature URL field', async () => { + const featureUrlField = await page.$('#featureUrl'); + const isHidden = await featureUrlField.evaluate( + (el) => + window.getComputedStyle(el.closest('.inputBox')).display === 'none', + ); + expect(isHidden).toBe(true); + }); + + it('should hide feature radio options', async () => { + const featureRadio = await page.$('#feature'); + const isHidden = await featureRadio.evaluate( + (el) => + window.getComputedStyle(el.closest('.inputBox')).display === 'none', + ); + expect(isHidden).toBe(true); + }); + + it('should hide task level field', async () => { + const taskLevelField = await page.$('[for="taskLevel"]'); + const isHidden = await taskLevelField.evaluate( + (el) => + window.getComputedStyle(el.closest('.inputBox')).display === 'none', + ); + expect(isHidden).toBe(true); + }); + }); + + describe('API Calls', () => { + it('should not make API calls for tags and levels', async () => { + const apiCalls = []; + page.on('request', (request) => { + apiCalls.push(request.url()); + }); + + await page.reload(); + await page.waitForNetworkIdle(); + + expect(apiCalls).not.toContain(`${API_BASE_URL}/tags`); + expect(apiCalls).not.toContain(`${API_BASE_URL}/levels`); + }); + + it('should not make API calls for suggested users when category changes', async () => { + const apiCalls = []; + page.on('request', (request) => { + apiCalls.push(request.url()); + }); + + await page.select('#category', '1'); + await page.waitForNetworkIdle(); + + const suggestedUsersCall = apiCalls.find((url) => + url.includes(`${API_BASE_URL}/users/suggestedUsers`), + ); + expect(suggestedUsersCall).toBeUndefined(); + }); + }); +}); From 5bd1614ea96a5dc79e431ac77dbb2030c0cf0569 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Wed, 20 Nov 2024 17:26:47 +0500 Subject: [PATCH 08/13] Tests fixed --- __tests__/tasks/task-dev-dependency.test.js | 118 ++++++++++++-------- 1 file changed, 73 insertions(+), 45 deletions(-) diff --git a/__tests__/tasks/task-dev-dependency.test.js b/__tests__/tasks/task-dev-dependency.test.js index a50f0839..3ca23947 100644 --- a/__tests__/tasks/task-dev-dependency.test.js +++ b/__tests__/tasks/task-dev-dependency.test.js @@ -1,10 +1,13 @@ const API_BASE_URL = 'https://api.realdevsquad.com'; const puppeteer = require('puppeteer'); +const { tags } = require('../../mock-data/tags'); +const { levels } = require('../../mock-data/levels'); const { users } = require('../../mock-data/users'); -describe('Task Form - Dev Mode', () => { +describe('Dev Feature Flag Tests', () => { let browser; let page; + jest.setTimeout(60000); beforeAll(async () => { @@ -14,14 +17,28 @@ describe('Task Form - Dev Mode', () => { args: ['--incognito', '--disable-web-security'], devtools: false, }); - page = await browser.newPage(); + }); - // Setup request interception + beforeEach(async () => { + page = await browser.newPage(); await page.setRequestInterception(true); + + // Mock API responses page.on('request', (interceptedRequest) => { const url = interceptedRequest.url(); - if (url === `${API_BASE_URL}/users`) { + if (url === `${API_BASE_URL}/levels`) { + 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(levels), + }); + } else if (url === `${API_BASE_URL}/users`) { interceptedRequest.respond({ status: 200, contentType: 'application/json', @@ -32,75 +49,86 @@ describe('Task Form - Dev Mode', () => { }, body: JSON.stringify(users), }); + } else if (url === `${API_BASE_URL}/tags`) { + 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(tags), + }); } else { interceptedRequest.continue(); } }); - - await page.goto('http://localhost:8000/task?dev=true'); - await page.waitForNetworkIdle(); }); afterAll(async () => { await browser.close(); }); - describe('Hidden Fields', () => { + describe('With dev=true', () => { + beforeEach(async () => { + await page.goto('http://localhost:8000/task?dev=true'); + await page.waitForNetworkIdle(); + }); + it('should hide feature URL field', async () => { - const featureUrlField = await page.$('#featureUrl'); - const isHidden = await featureUrlField.evaluate( - (el) => - window.getComputedStyle(el.closest('.inputBox')).display === 'none', + const featureUrlField = await page.$eval( + '#featureUrl', + (el) => window.getComputedStyle(el.closest('.inputBox')).display, ); - expect(isHidden).toBe(true); + expect(featureUrlField).toBe('none'); }); - it('should hide feature radio options', async () => { - const featureRadio = await page.$('#feature'); - const isHidden = await featureRadio.evaluate( - (el) => - window.getComputedStyle(el.closest('.inputBox')).display === 'none', + it('should hide feature/group radio buttons', async () => { + const featureRadio = await page.$eval( + '.feature', + (el) => window.getComputedStyle(el.closest('.inputBox')).display, ); - expect(isHidden).toBe(true); + expect(featureRadio).toBe('none'); }); it('should hide task level field', async () => { - const taskLevelField = await page.$('[for="taskLevel"]'); - const isHidden = await taskLevelField.evaluate( - (el) => - window.getComputedStyle(el.closest('.inputBox')).display === 'none', + const taskLevelDiv = await page.$eval( + 'label[for="taskLevel"]', + (el) => window.getComputedStyle(el.closest('.inputBox')).display, ); - expect(isHidden).toBe(true); + expect(taskLevelDiv).toBe('none'); }); }); - describe('API Calls', () => { - it('should not make API calls for tags and levels', async () => { - const apiCalls = []; - page.on('request', (request) => { - apiCalls.push(request.url()); - }); - - await page.reload(); + describe('With dev=false (default)', () => { + beforeEach(async () => { + await page.goto('http://localhost:8000/task'); await page.waitForNetworkIdle(); - - expect(apiCalls).not.toContain(`${API_BASE_URL}/tags`); - expect(apiCalls).not.toContain(`${API_BASE_URL}/levels`); }); - it('should not make API calls for suggested users when category changes', async () => { - const apiCalls = []; - page.on('request', (request) => { - apiCalls.push(request.url()); - }); + it('should show feature URL field', async () => { + const featureUrlField = await page.$eval( + '#featureUrl', + (el) => window.getComputedStyle(el.closest('.inputBox')).display, + ); + expect(featureUrlField).not.toBe('none'); + }); - await page.select('#category', '1'); - await page.waitForNetworkIdle(); + it('should show feature/group radio buttons', async () => { + const featureRadio = await page.$eval( + '.feature', + (el) => window.getComputedStyle(el.closest('.inputBox')).display, + ); + expect(featureRadio).not.toBe('none'); + }); - const suggestedUsersCall = apiCalls.find((url) => - url.includes(`${API_BASE_URL}/users/suggestedUsers`), + it('should show task level field', async () => { + const taskLevelDiv = await page.$eval( + 'label[for="taskLevel"]', + (el) => window.getComputedStyle(el.closest('.inputBox')).display, ); - expect(suggestedUsersCall).toBeUndefined(); + expect(taskLevelDiv).not.toBe('none'); }); }); }); From 93a52212ba0b05bdb8bbea3505853e1e6e72162d Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Mon, 25 Nov 2024 21:22:00 +0500 Subject: [PATCH 09/13] Added data-testid for testing,also added new tests --- __tests__/tasks/task-dependency.test.js | 209 ++++++++++++++------ __tests__/tasks/task-dev-dependency.test.js | 134 ------------- task/index.html | 56 +++--- 3 files changed, 172 insertions(+), 227 deletions(-) delete mode 100644 __tests__/tasks/task-dev-dependency.test.js diff --git a/__tests__/tasks/task-dependency.test.js b/__tests__/tasks/task-dependency.test.js index 26e2035e..dfd64f1f 100644 --- a/__tests__/tasks/task-dependency.test.js +++ b/__tests__/tasks/task-dependency.test.js @@ -14,51 +14,37 @@ describe('Input box', () => { headless: 'new', ignoreHTTPSErrors: true, args: ['--incognito', '--disable-web-security'], - devtools: false, }); - page = await browser.newPage(); - await page.setRequestInterception(true); - - page.on('request', (interceptedRequest) => { - const url = interceptedRequest.url(); - if (url === `${STAGING_API_URL}/levels`) { - 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(levels), - }); - } else if (url === `${STAGING_API_URL}/users`) { - 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(users), - }); - } else if (url === `${STAGING_API_URL}/tags`) { - 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(tags), - }); - } else { - interceptedRequest.continue(); - } - }); + // Mock API response setup + const interceptAPI = async (page) => { + await page.setRequestInterception(true); + page.on('request', (interceptedRequest) => { + const url = interceptedRequest.url(); + const mockResponses = { + [`${API_BASE_URL}/levels`]: levels, + [`${API_BASE_URL}/users`]: users, + [`${API_BASE_URL}/tags`]: tags, + }; + + if (mockResponses[url]) { + interceptedRequest.respond({ + status: 200, + contentType: 'application/json', + headers: { + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify(mockResponses[url]), + }); + } else { + interceptedRequest.continue(); + } + }); + }; + + // Open a shared page instance and intercept API for all tests + page = await browser.newPage(); + await interceptAPI(page); await page.goto('http://localhost:8000/task'); await page.waitForNetworkIdle(); }); @@ -66,29 +52,122 @@ describe('Input box', () => { afterAll(async () => { await browser.close(); }); - it('DependsOn input box should exist', async () => { - const inputBox = await page.evaluate(() => - document.querySelector('.inputBox'), - ); - const linksDisplay = await page.evaluate(() => - document.querySelector('#linksDisplay'), - ); + + // Form Presence Tests + describe('Form Field Presence', () => { + it('should display the title field', async () => { + const titleField = await page.$('[data-testid="title"]'); + expect(titleField).toBeTruthy(); + }); + + it('should display the status field', async () => { + const statusField = await page.$('[data-testid="status"]'); + expect(statusField).toBeTruthy(); + }); + + it('should display the priority field', async () => { + const priorityField = await page.$('[data-testid="priority"]'); + expect(priorityField).toBeTruthy(); + }); + + it('should display the isNoteworthy checkbox', async () => { + const noteworthyField = await page.$('[data-testid="isNoteworthy"]'); + expect(noteworthyField).toBeTruthy(); + }); + + it('should display the purpose field', async () => { + const purposeField = await page.$('[data-testid="purpose"]'); + expect(purposeField).toBeTruthy(); + }); + + it('should display the dependsOn field', async () => { + const dependsOnField = await page.$('[data-testid="dependsOn"]'); + expect(dependsOnField).toBeTruthy(); + }); }); - it('DependsOn input should have correct attributes', async () => { - const input = await page.$('#dependsOn'); - const type = await input.evaluate((el) => el.getAttribute('type')); - const name = await input.evaluate((el) => el.getAttribute('name')); - const id = await input.evaluate((el) => el.getAttribute('id')); - const placeholder = await input.evaluate((el) => - el.getAttribute('placeholder'), - ); - const classList = await input.evaluate((el) => Array.from(el.classList)); - - expect(type).toBe('text'); - expect(name).toBe('dependsOn'); - expect(id).toBe('dependsOn'); - expect(placeholder).toBe('Task ID separated with comma '); - expect(classList.includes('notEditing')).toBeTruthy(); + // Status Field Behavior Tests + describe('Status Field Behavior', () => { + beforeEach(async () => { + await page.goto('http://localhost:8000/task'); + await page.waitForNetworkIdle(); + }); + + it('should have default status as "available"', async () => { + const defaultStatus = await page.$eval( + '[data-testid="status"] select', + (el) => el.value, + ); + expect(defaultStatus).toBe('AVAILABLE'); + }); + + it('should show/hide fields based on "status" selection', async () => { + // Change status to "assigned" + await page.select('[data-testid="status"] select', 'ASSIGNED'); + + const assigneeVisible = await page.$eval( + '[data-testid="assignee"]', + (el) => window.getComputedStyle(el).display !== 'none', + ); + const endsOnVisible = await page.$eval( + '[data-testid="endsOn"]', + (el) => window.getComputedStyle(el).display !== 'none', + ); + expect(assigneeVisible).toBeTruthy(); + expect(endsOnVisible).toBeTruthy(); + + // Change status back to "available" + await page.select('[data-testid="status"] select', 'available'); + + const assigneeHidden = await page.$eval( + '[data-testid="assignee"]', + (el) => window.getComputedStyle(el).display === 'none', + ); + const endsOnHidden = await page.$eval( + '[data-testid="endsOn"]', + (el) => window.getComputedStyle(el).display === 'none', + ); + expect(assigneeHidden).toBeTruthy(); + expect(endsOnHidden).toBeTruthy(); + }); + }); + + // Dev Mode Tests + describe('Dev Mode Behavior', () => { + beforeAll(async () => { + await page.goto('http://localhost:8000/task?dev=true'); + await page.waitForNetworkIdle(); + }); + + it('should hide feature URL field in dev mode', async () => { + const featureUrlField = await page.$('[data-testid="featureUrl"]'); + const display = await page.$eval( + '[data-testid="featureUrl"]', + (el) => window.getComputedStyle(el).display, + ); + expect(display).toBe('none'); + }); + + it('should hide task level field in dev mode', async () => { + const taskLevelField = await page.$('[data-testid="taskLevel"]'); + const display = await page.$eval( + '[data-testid="taskLevel"]', + (el) => window.getComputedStyle(el).display, + ); + expect(display).toBe('none'); + }); + + it('should hide feature/group radio buttons in dev mode', async () => { + const radioButtons = await page.$('[data-testid="radioButtons"]'); + const display = await page.$eval( + '[data-testid="radioButtons"]', + (el) => window.getComputedStyle(el).display, + ); + expect(display).toBe('none'); + }); + it('should display the dependsOn field in dev mode', async () => { + const dependsOnField = await page.$('[data-testid="dependsOn"]'); + expect(dependsOnField).toBeTruthy(); + }); }); }); diff --git a/__tests__/tasks/task-dev-dependency.test.js b/__tests__/tasks/task-dev-dependency.test.js deleted file mode 100644 index 3ca23947..00000000 --- a/__tests__/tasks/task-dev-dependency.test.js +++ /dev/null @@ -1,134 +0,0 @@ -const API_BASE_URL = 'https://api.realdevsquad.com'; -const puppeteer = require('puppeteer'); -const { tags } = require('../../mock-data/tags'); -const { levels } = require('../../mock-data/levels'); -const { users } = require('../../mock-data/users'); - -describe('Dev Feature Flag Tests', () => { - let browser; - let page; - - jest.setTimeout(60000); - - beforeAll(async () => { - browser = await puppeteer.launch({ - headless: 'new', - ignoreHTTPSErrors: true, - args: ['--incognito', '--disable-web-security'], - devtools: false, - }); - }); - - beforeEach(async () => { - page = await browser.newPage(); - await page.setRequestInterception(true); - - // Mock API responses - page.on('request', (interceptedRequest) => { - const url = interceptedRequest.url(); - - if (url === `${API_BASE_URL}/levels`) { - 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(levels), - }); - } else if (url === `${API_BASE_URL}/users`) { - 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(users), - }); - } else if (url === `${API_BASE_URL}/tags`) { - 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(tags), - }); - } else { - interceptedRequest.continue(); - } - }); - }); - - afterAll(async () => { - await browser.close(); - }); - - describe('With dev=true', () => { - beforeEach(async () => { - await page.goto('http://localhost:8000/task?dev=true'); - await page.waitForNetworkIdle(); - }); - - it('should hide feature URL field', async () => { - const featureUrlField = await page.$eval( - '#featureUrl', - (el) => window.getComputedStyle(el.closest('.inputBox')).display, - ); - expect(featureUrlField).toBe('none'); - }); - - it('should hide feature/group radio buttons', async () => { - const featureRadio = await page.$eval( - '.feature', - (el) => window.getComputedStyle(el.closest('.inputBox')).display, - ); - expect(featureRadio).toBe('none'); - }); - - it('should hide task level field', async () => { - const taskLevelDiv = await page.$eval( - 'label[for="taskLevel"]', - (el) => window.getComputedStyle(el.closest('.inputBox')).display, - ); - expect(taskLevelDiv).toBe('none'); - }); - }); - - describe('With dev=false (default)', () => { - beforeEach(async () => { - await page.goto('http://localhost:8000/task'); - await page.waitForNetworkIdle(); - }); - - it('should show feature URL field', async () => { - const featureUrlField = await page.$eval( - '#featureUrl', - (el) => window.getComputedStyle(el.closest('.inputBox')).display, - ); - expect(featureUrlField).not.toBe('none'); - }); - - it('should show feature/group radio buttons', async () => { - const featureRadio = await page.$eval( - '.feature', - (el) => window.getComputedStyle(el.closest('.inputBox')).display, - ); - expect(featureRadio).not.toBe('none'); - }); - - it('should show task level field', async () => { - const taskLevelDiv = await page.$eval( - 'label[for="taskLevel"]', - (el) => window.getComputedStyle(el.closest('.inputBox')).display, - ); - expect(taskLevelDiv).not.toBe('none'); - }); - }); -}); diff --git a/task/index.html b/task/index.html index d086ac56..8c8cf6e4 100644 --- a/task/index.html +++ b/task/index.html @@ -16,7 +16,7 @@
-
+
-
+
-
+
-
+
-
+
@@ -86,7 +86,7 @@ *
-
+
-
+
@@ -112,11 +112,11 @@
-
+

-
-
- - - -
-
+
+ + + +
+
@@ -167,7 +167,7 @@

Suggested users

-
+
Suggested users class="notEditing" />
-
+
-
+
@@ -207,7 +207,7 @@

Suggested users

-
+
@@ -221,7 +221,7 @@

Suggested users

class="notEditing" />
-
+

@@ -249,7 +249,7 @@

Suggested users

/>
-
+

@@ -278,7 +278,7 @@

Suggested users

-
+
Date: Tue, 26 Nov 2024 22:23:45 +0500 Subject: [PATCH 10/13] Test api updated to staging --- __tests__/tasks/task-dependency.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/__tests__/tasks/task-dependency.test.js b/__tests__/tasks/task-dependency.test.js index dfd64f1f..49d74d13 100644 --- a/__tests__/tasks/task-dependency.test.js +++ b/__tests__/tasks/task-dependency.test.js @@ -14,6 +14,7 @@ describe('Input box', () => { headless: 'new', ignoreHTTPSErrors: true, args: ['--incognito', '--disable-web-security'], + devtools: false, }); // Mock API response setup From aa0f2dca6c0c1b0a018bdec60bb12d2b161c84d6 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Fri, 29 Nov 2024 13:05:53 +0500 Subject: [PATCH 11/13] refactored for readability --- __tests__/tasks/task-dependency.test.js | 2 ++ task/index.html | 12 ++++--- task/script.js | 42 +++++++++++++++---------- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/__tests__/tasks/task-dependency.test.js b/__tests__/tasks/task-dependency.test.js index 49d74d13..2266f8f0 100644 --- a/__tests__/tasks/task-dependency.test.js +++ b/__tests__/tasks/task-dependency.test.js @@ -22,6 +22,7 @@ describe('Input box', () => { await page.setRequestInterception(true); page.on('request', (interceptedRequest) => { const url = interceptedRequest.url(); + const mockResponses = { [`${API_BASE_URL}/levels`]: levels, [`${API_BASE_URL}/users`]: users, @@ -166,6 +167,7 @@ describe('Input box', () => { ); expect(display).toBe('none'); }); + it('should display the dependsOn field in dev mode', async () => { const dependsOnField = await page.$('[data-testid="dependsOn"]'); expect(dependsOnField).toBeTruthy(); diff --git a/task/index.html b/task/index.html index 8c8cf6e4..a5fba571 100644 --- a/task/index.html +++ b/task/index.html @@ -47,7 +47,7 @@ >
-
+
-
+
@@ -112,7 +116,7 @@
-
+

@@ -137,7 +141,7 @@
-
+
{ + const element = document.getElementById(id); + if (element) { + element.style.display = 'none'; + } + }); + } } -const taskLevelDiv = document - .querySelector('.inputBox label[for="taskLevel"]') - .closest('.inputBox'); +// hide fields if dev=true +hideElements(isDev, containers); -if (isDev && taskLevelDiv) { - taskLevelDiv.style.display = 'none'; -} const category = document.getElementById('category'); category.addEventListener('change', async () => { if (isDev) return; + try { showSubmitLoader(); const categoryValue = category.value; @@ -219,10 +221,12 @@ taskForm.onsubmit = async (e) => { if (status === 'AVAILABLE') { delete dataToBeSent.endsOn; } + if (isDev) { delete dataToBeSent.featureUrl; delete dataToBeSent.type; delete dataToBeSent.participants; + dataToBeSent.assignee = assignee.trim() ? assignee : ' '; } else { if (dataToBeSent.featureUrl.trim() === '') { @@ -282,6 +286,7 @@ taskForm.onsubmit = async (e) => { itemType: 'task', tagPayload: [{ tagId: category, levelId: level }], }; + await fetch(`${API_BASE_URL}/items`, { method: 'POST', credentials: 'include', @@ -339,6 +344,7 @@ let stateHandle = () => { let hideUnusedField = (radio) => { if (isDev) return; + const assigneeInput = document.getElementById('assigneeInput'); const participantsInput = document.getElementById('participantsInput'); if ( @@ -436,6 +442,7 @@ function debounce(func, delay) { async function fetchTags() { if (isDev) return; + const response = await fetch(`${API_BASE_URL}/tags`); const data = await response.json(); const { tags } = data; @@ -452,6 +459,7 @@ async function fetchTags() { async function fetchLevel() { if (isDev) return; + const response = await fetch(`${API_BASE_URL}/levels`); const data = await response.json(); const { levels } = data; From 130fd769e6d95b599fb0b4e0ad9a51c2dc3971ef Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Sat, 30 Nov 2024 15:15:07 +0500 Subject: [PATCH 12/13] created a constants file --- task/constants.js | 4 ++++ task/index.html | 1 + task/script.js | 20 +++++++++++--------- 3 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 task/constants.js diff --git a/task/constants.js b/task/constants.js new file mode 100644 index 00000000..b27eb797 --- /dev/null +++ b/task/constants.js @@ -0,0 +1,4 @@ +const StatusType = { + AVAILABLE: 'AVAILABLE', + ASSIGNED: 'ASSIGNED', +}; diff --git a/task/index.html b/task/index.html index a5fba571..b0dc59df 100644 --- a/task/index.html +++ b/task/index.html @@ -307,6 +307,7 @@

Suggested users

+
diff --git a/task/script.js b/task/script.js index 68a483cd..a231a7f5 100644 --- a/task/script.js +++ b/task/script.js @@ -80,7 +80,7 @@ const getDaysInEpoch = (remainingDays) => { }; const setDefaultDates = () => { - if (document.getElementById('status').value === 'ASSIGNED') { + if (document.getElementById('status').value === StatusType.ASSIGNED) { const endsOn = document.getElementById('endsOn'); endsOn.value = getFutureDateString(14); endsOn.min = getFutureDateString(1); @@ -97,7 +97,7 @@ function getObjectOfFormData(formId) { const object = {}; const data = new FormData(formId); const isStatusAssigned = - document.getElementById('status').value === 'ASSIGNED'; + document.getElementById('status').value === StatusType.ASSIGNED; data.forEach((value, key) => { if (!Reflect.has(object, key)) { @@ -181,7 +181,7 @@ taskForm.onsubmit = async (e) => { isNoteworthy, } = getObjectOfFormData(taskForm); - if (status === 'ASSIGNED' && !assignee.trim()) { + if (status === StatusType.ASSIGNED && !assignee.trim()) { alert('Assignee can not be empty'); showSubmitLoader(false); document.getElementById('assignee').focus(); @@ -210,7 +210,7 @@ taskForm.onsubmit = async (e) => { isNoteworthy: isNoteworthy == 'on', }; - if (status === 'ASSIGNED') { + if (status === StatusType.ASSIGNED) { dataToBeSent.startedOn = new Date() / 1000; } @@ -218,7 +218,7 @@ taskForm.onsubmit = async (e) => { delete dataToBeSent.endsOn; } - if (status === 'AVAILABLE') { + if (status === StatusType.AVAILABLE) { delete dataToBeSent.endsOn; } @@ -324,7 +324,7 @@ let stateHandle = () => { ) { return true; } else if ( - item.value === 'ASSIGNED' && + item.value === StatusType.ASSIGNED && (wasAssigneeSet === false || assigneeEl.value === '') ) { return true; @@ -401,12 +401,14 @@ const handleDateChange = (event) => { previewDate.innerHTML = !!input.value ? getRemainingDays(input.value) : 14; }; -function handleStatusChange(event = { target: { value: 'AVAILABLE' } }) { +function handleStatusChange( + event = { target: { value: StatusType.AVAILABLE } }, +) { const assignee = document.getElementById('assigneeInput'); const assigneeEl = document.getElementById('assignee'); const endsOnWrapper = document.getElementById('endsOnWrapper'); const featureRadio = document.getElementById('feature'); - if (event.target.value === 'ASSIGNED') { + if (event.target.value === StatusType.ASSIGNED) { setDefaultDates(); assignee.classList.add('show-assignee-field'); assignee.style.display = 'none'; @@ -418,7 +420,7 @@ function handleStatusChange(event = { target: { value: 'AVAILABLE' } }) { document.getElementById('endsOn').value = ''; assigneeEl.value = ''; } - if (event.target.value === 'ASSIGNED' && featureRadio.checked) { + if (event.target.value === StatusType.ASSIGNED && featureRadio.checked) { assignee.style.display = 'flex'; } } From 14374bd6f12b42d871d5c640584cf1900df0d487 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Tue, 3 Dec 2024 00:44:42 +0500 Subject: [PATCH 13/13] API_BASE_URL changed to stating for testing --- __tests__/tasks/task-dependency.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/__tests__/tasks/task-dependency.test.js b/__tests__/tasks/task-dependency.test.js index 2266f8f0..3043e26d 100644 --- a/__tests__/tasks/task-dependency.test.js +++ b/__tests__/tasks/task-dependency.test.js @@ -24,9 +24,9 @@ describe('Input box', () => { const url = interceptedRequest.url(); const mockResponses = { - [`${API_BASE_URL}/levels`]: levels, - [`${API_BASE_URL}/users`]: users, - [`${API_BASE_URL}/tags`]: tags, + [`${STAGING_API_URL}/levels`]: levels, + [`${STAGING_API_URL}/users`]: users, + [`${STAGING_API_URL}/tags`]: tags, }; if (mockResponses[url]) {