From 8b4fdc706e29caeeceef5631f5f3879dba6cfcea Mon Sep 17 00:00:00 2001 From: jhuerta Date: Mon, 19 Oct 2026 17:00:36 -0700 Subject: [PATCH] Initial Alignment Content Page update --- alignContentPageResults.xlsx | Bin 75770 -> 20818 bytes tests/alignContentPage.js | 1159 +++++++++++++++++++++++++++++++++- 2 files changed, 1148 insertions(+), 11 deletions(-) diff --git a/alignContentPageResults.xlsx b/alignContentPageResults.xlsx index d10f06591fcaef6a75acbd3db466c633ace19377..0b1de35b241e981a8e0cb4af7707674fce24e959 100644 GIT binary patch delta 1551 zcmb7E-)j_C6rOQSN~DNUH?t{?xlxl%b!RenX723Ht{9I1hsgVj?1n1SJn5K1tqN^`U)gX`v{66SWU5g?eYBt?o<<&eOm>=R4o| zzH`o>->rVUAl^RHyXK_(L?4X{!f1TyLT{_MN+U}Peb>c}ri@h?TVH6pZD=-0D+F6` zuzxuoe$b3*=&?Is@sm@{ua-iHHVuyo65QG*x9p{*vIkGM?TU!YsMCO{1UI(J-D6Je zt2}k8Ma0Ui;v(iAV<}WCA9qv8@rv*>iNlNS#ycpwts07{=__2Wr3_F{wLnShhL@?R z$V_@A@}{ilyQs%pk0IvdBPteXg;pDdQQj%cl&ZA;nnRlsLN*l(b3MK}C&5ESCOO9W z@gpj-hkM=kFyTrKyQ9j*Rw}YYdKRyTcSnU|;)k0`}-?B3G!=N(C{B z@{}=p1kuB2)+xDgNsmf3%oX-E1NUZ&bB5SUcYe-|yK9zZ0{Wu%(#zwPwpEhVFfv)`f~3`b`2Q-E1YsN?PYu-g%aQztbvD z?d+1#MAa#}h|BKswj<>JGSf_!<76~#+IL#S1bl2YfV$rR6{~c%NRN7G&Z*ShU~#w( zT>8USvwi`Lg#-O211cOLSI>X#7TEug0Xu?>mEkVTk4Uh8Fwmn@l;QH{Qro|^7Y0MM zHAOXoiQ!puLyfF{88znmNU)Q9gIJwA_#djo;qg$jF<4Wu%G(Jb{o!aLzYa$b!K6Wd za{cb&gu`4kPAPM%h@UMAt9L{sXoRek`C$kCfQO-}I)g1cBO-O2X+(ZVHjfMyP<427 zRwM8z*#({1wf@z0q6D91%?)o~SKY>jVp(u8i{PhZn?KMle#-Cj-P7&j{f%!OZhxXr zJP`ZC7W^xHq8(ct5&R#6pRS#P|4~vjW9LT&KbI5-W6#F~|6EcWik%o2{D(<#YwLr3 H0{>nCU>nce literal 75770 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 Y>DzziXGNxu!~eeyN|F8|I1zjQ3$rv2X#fBK diff --git a/tests/alignContentPage.js b/tests/alignContentPage.js index 6917082..88f3fc5 100644 --- a/tests/alignContentPage.js +++ b/tests/alignContentPage.js @@ -22,10 +22,6 @@ const alignContentPage = (req, res) => { let worksheet; const startTime = new Date().toISOString(); -//CONSTANTS -//My Content Widget -const myContentItemTotals = '5038 items'; - const steps = [ { description: 'Navigate to ExACT Landing Page', action: async () => await driver.navigate().to('https://correlation.edgate.com/exact/login.php') }, { description: 'Expand browser', action: async () => await driver.manage().window().maximize() }, @@ -164,13 +160,13 @@ const steps = [ } } }, -/* + //NEXT ACTION { - description: 'Click Frameworks navigation link', + description: 'Click Align navigation link', action: async () => { - await driver.findElement(By.linkText('Frameworks')).click(); - console.log('----->| NEXT ACTION: Clicked Frameworks navigation link'); + await driver.findElement(By.linkText('Align')).click(); + console.log('----->| NEXT ACTION: Clicked Align navigation link'); //Wait for page readyState await driver.wait(async () => { @@ -179,19 +175,1158 @@ const steps = [ }, 30000, 'ExACT Dashboard did not fully load within 30 seconds'); //Wait until the element exists in the DOM - const pageTitle = await driver.wait( - until.elementLocated(By.css('h2')), + const contentTab = await driver.wait( + until.elementLocated(By.css('#content-tab')), 30000 ); //Wait until it becomes visible await driver.wait( - until.elementIsVisible(pageTitle), + until.elementIsVisible(contentTab), 30000 ); } }, + //Content tab + { + description: 'Content tab title text, size, color, and background color', + action: async () => { + const multipleChecks = 'Content tab title'; + + const element = await driver.findElement(By.linkText('Content')); + + //Get text, font, size, color, and background color + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + const elementBgColor = await element.getCssValue('background-color'); + + //Tool-tip lives on the parent
  • ; Bootstrap moves "title" into "data-original-title" and blanks "title" + const tooltipHost = await element.findElement(By.xpath('./parent::li')); + const elementTitle = (await tooltipHost.getAttribute('data-original-title')) || (await tooltipHost.getAttribute('title')); + const elementTitleFont = await element.getCssValue('font-family'); + const elementTitleSize = await element.getCssValue('font-size'); + const elementTitleColor = await element.getCssValue('color'); + const elementTitleBgColor = await element.getCssValue('background-color'); + + //Track all errors + const errors = []; + + //element text + if (elementText === 'Content') { + console.log('Passed: Content tab title text matched as expected'); + } else { + errors.push(`Expected: "Content"; Actual: "${elementText}"`); + } + + //element font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Content tab title font-family matched as expected'); + } else { + errors.push(`Expected: Content tab title font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //element size + if (elementSize === '15px') { + console.log('Passed: Content tab title text font-size matched as expected'); + } else { + errors.push(`Expected: Content tab title text font-size "15px"; Actual: "${elementSize}"`); + } + + //element color + if (elementColor === 'rgba(255, 255, 255, 1)') { + console.log('Passed: Content tab title text color matched as expected'); + } else { + errors.push(`Expected: Content tab title text color: "rgba(255, 255, 255, 1)"; Actual: "${elementColor}"`); + } + + //element background color + if (elementBgColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Content tab title active background color matched as expected'); + } else { + errors.push(`Expected: Content tab title active background color: "rgba(40, 39, 90, 1)"; Actual: "${elementBgColor}"`); + } + + //element tool-tip text + if (elementTitle === 'Browse content and align by tagging concepts') { + console.log('Passed: Content tab tool-tip text matched as expected'); + } else { + errors.push(`Expected: Content tab tool-tip "Browse content and align by tagging concepts"; Actual: "${elementTitle}"`); + } + + //element tool-tip font + if (elementTitleFont === 'Poppins, sans-serif') { + console.log('Passed: Content tab tool-tip font-family matched as expected'); + } else { + errors.push(`Expected: Content tab tool-tip font-family "Poppins, sans-serif"; Actual: ${elementTitleFont}`); + } + + //element tool-tip size + if (elementTitleSize === '15px') { + console.log('Passed: Content tab tool-tip text font-size matched as expected'); + } else { + errors.push(`Expected: Content tab tool-tip text font-size "15px"; Actual: "${elementTitleSize}"`); + } + + //element tool-tip color + if (elementTitleColor === 'rgba(255, 255, 255, 1)') { + console.log('Passed: Content tab tool-tip text color matched as expected'); + } else { + errors.push(`Expected: Content tab tool-tip text color: "rgba(255, 255, 255, 1)"; Actual: "${elementTitleColor}"`); + } + + //element tool-tip background color + if (elementTitleBgColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Content tab tool-tip active background color matched as expected'); + } else { + errors.push(`Expected: Content tab tool-tip active background color: "rgba(40, 39, 90, 1)"; Actual: "${elementTitleBgColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Standards tab + { + description: 'Standards tab title text, size, color, and background color', + action: async () => { + const multipleChecks = 'Standards tab title'; + + const element = await driver.findElement(By.linkText('Standards')); + + //Get text, font, size, color, and background color + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + const elementBgColor = await element.getCssValue('background-color'); + + //Tool-tip lives on the parent
  • ; Bootstrap moves "title" into "data-original-title" and blanks "title" + const tooltipHost = await element.findElement(By.xpath('./parent::li')); + const elementTitle = (await tooltipHost.getAttribute('data-original-title')) || (await tooltipHost.getAttribute('title')); + const elementTitleFont = await element.getCssValue('font-family'); + const elementTitleSize = await element.getCssValue('font-size'); + const elementTitleColor = await element.getCssValue('color'); + const elementTitleBgColor = await element.getCssValue('background-color'); + + //Track all errors + const errors = []; + + //element text + if (elementText === 'Standards') { + console.log('Passed: Standards tab title text matched as expected'); + } else { + errors.push(`Expected: "Standards"; Actual: "${elementText}"`); + } + + //element font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Standards tab title font-family matched as expected'); + } else { + errors.push(`Expected: Standards tab title font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //element size + if (elementSize === '15px') { + console.log('Passed: Standards tab title text font-size matched as expected'); + } else { + errors.push(`Expected: Standards tab title text font-size "15px"; Actual: "${elementSize}"`); + } + + //element color + if (elementColor === 'rgba(182, 186, 181, 1)') { + console.log('Passed: Standards tab title text color matched as expected'); + } else { + errors.push(`Expected: Standards tab title text color: "rgba(182, 186, 181, 1)"; Actual: "${elementColor}"`); + } + + //element background color + if (elementBgColor === 'rgba(0, 0, 0, 0)') { + console.log('Passed: Standards tab title dimmed background color matched as expected'); + } else { + errors.push(`Expected: Standards tab title dimmed background color: "rgba(0, 0, 0, 0)"; Actual: "${elementBgColor}"`); + } + + //element tool-tip text + if (elementTitle === 'Browse standards and align content using specific standards') { + console.log('Passed: Standards tab tool-tip text matched as expected'); + } else { + errors.push(`Expected: Standards tab tool-tip "Browse standards and align content using specific standards"; Actual: "${elementTitle}"`); + } + + //element tool-tip font + if (elementTitleFont === 'Poppins, sans-serif') { + console.log('Passed: Standards tab tool-tip font-family matched as expected'); + } else { + errors.push(`Expected: Standards tab tool-tip font-family "Poppins, sans-serif"; Actual: ${elementTitleFont}`); + } + + //element tool-tip size + if (elementTitleSize === '15px') { + console.log('Passed: Standards tab tool-tip text font-size matched as expected'); + } else { + errors.push(`Expected: Standards tab tool-tip text font-size "15px"; Actual: "${elementTitleSize}"`); + } + + //element tool-tip color + if (elementTitleColor === 'rgba(182, 186, 181, 1)') { + console.log('Passed: Standards tab tool-tip text color matched as expected'); + } else { + errors.push(`Expected: Standards tab tool-tip text color: "rgba(182, 186, 181, 1)"; Actual: "${elementTitleColor}"`); + } + + //element tool-tip background color + if (elementTitleBgColor === 'rgba(0, 0, 0, 0)') { + console.log('Passed: Standards tab tool-tip active background color matched as expected'); + } else { + errors.push(`Expected: Standards tab tool-tip active background color: "rgba(0, 0, 0, 0)"; Actual: "${elementTitleBgColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //AutoAlign tab + { + description: 'AutoAlign tab title text, size, color, and background color', + action: async () => { + const multipleChecks = 'AutoAlign tab title'; + + const element = await driver.findElement(By.linkText('AutoAlign')); + + //Get text, font, size, color, and background color + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + const elementBgColor = await element.getCssValue('background-color'); + + //Tool-tip lives on the parent
  • ; Bootstrap moves "title" into "data-original-title" and blanks "title" + const tooltipHost = await element.findElement(By.xpath('./parent::li')); + const elementTitle = (await tooltipHost.getAttribute('data-original-title')) || (await tooltipHost.getAttribute('title')); + const elementTitleFont = await element.getCssValue('font-family'); + const elementTitleSize = await element.getCssValue('font-size'); + const elementTitleColor = await element.getCssValue('color'); + const elementTitleBgColor = await element.getCssValue('background-color'); + + //Track all errors + const errors = []; + + //element text + if (elementText === 'AutoAlign') { + console.log('Passed: AutoAlign tab title text matched as expected'); + } else { + errors.push(`Expected: "AutoAlign"; Actual: "${elementText}"`); + } + + //element font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: AutoAlign tab title font-family matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab title font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //element size + if (elementSize === '15px') { + console.log('Passed: AutoAlign tab title text font-size matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab title text font-size "15px"; Actual: "${elementSize}"`); + } + + //element color + if (elementColor === 'rgba(182, 186, 181, 1)') { + console.log('Passed: AutoAlign tab title text color matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab title text color: "rgba(182, 186, 181, 1)"; Actual: "${elementColor}"`); + } + + //element background color + if (elementBgColor === 'rgba(0, 0, 0, 0)') { + console.log('Passed: AutoAlign tab title dimmed background color matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab title dimmed background color: "rgba(0, 0, 0, 0)"; Actual: "${elementBgColor}"`); + } + + //element tool-tip text + if (elementTitle === 'AutoAlign a Content Set') { + console.log('Passed: AutoAlign tab tool-tip text matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab tool-tip "AutoAlign a Content Set"; Actual: "${elementTitle}"`); + } + + //element tool-tip font + if (elementTitleFont === 'Poppins, sans-serif') { + console.log('Passed: AutoAlign tab tool-tip font-family matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab tool-tip font-family "Poppins, sans-serif"; Actual: ${elementTitleFont}`); + } + + //element tool-tip size + if (elementTitleSize === '15px') { + console.log('Passed: AutoAlign tab tool-tip text font-size matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab tool-tip text font-size "15px"; Actual: "${elementTitleSize}"`); + } + + //element tool-tip color + if (elementTitleColor === 'rgba(182, 186, 181, 1)') { + console.log('Passed: AutoAlign tab tool-tip text color matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab tool-tip text color: "rgba(182, 186, 181, 1)"; Actual: "${elementTitleColor}"`); + } + + //element tool-tip background color + if (elementTitleBgColor === 'rgba(0, 0, 0, 0)') { + console.log('Passed: AutoAlign tab tool-tip active background color matched as expected'); + } else { + errors.push(`Expected: AutoAlign tab tool-tip active background color: "rgba(0, 0, 0, 0)"; Actual: "${elementTitleBgColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Available Content header + { + description: 'Available Content text, size, and color', + action: async () => { + const multipleChecks = 'Available Content header'; + + const element = await driver.findElement(By.css('#content .fom-title')); + + //Get text, font, size, and color + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Track all errors + const errors = []; + + //text + if (elementText === 'Available Content') { + console.log('Passed: Available Content header text matched as expected'); + } else { + errors.push(`Expected: "Available Content"; Actual: "${elementText}"`); + } + + //font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Available Content header font-family matched as expected'); + } else { + errors.push(`Expected: Available Content header font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //size + if (elementSize === '13px') { + console.log('Passed: Available Content header text font-size matched as expected'); + } else { + errors.push(`Expected: Available Content header text font-size "13px"; Actual: "${elementSize}"`); + } + + //color + if (elementColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Available Content header text color matched as expected'); + } else { + errors.push(`Expected: Available Content header text color: "rgba(40, 39, 90, 1)"; Actual: "${elementColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Available Content List + { + description: 'Available Content - List', + action: async () => { + const multipleChecks = 'Available Content - List'; + + const errors = []; + + const rows = await driver.executeScript(` + const results = []; + //List sits in the
    right after the "Available Content"

    + const items = document.querySelectorAll('#content .fom-title + div .list-group-item > a'); + items.forEach((link, index) => { + const name = link.textContent.trim(); + results.push({ position: index + 1, name }); + }); + return results; + `); + + const expected = [ + { position: 1, name: 'US History III' }, + { position: 2, name: 'English I' }, + { position: 3, name: 'Algebra' }, + { position: 4, name: 'Biology' }, + { position: 5, name: 'Copy Move Delete Test 1' }, + { position: 6, name: 'Copy Move Delete Test 2' }, + { position: 7, name: 'Import Align - Concept Based 1' }, + { position: 8, name: 'Import Align - Concept Based 2' }, + { position: 9, name: 'Import Align - Direct Align 1' }, + { position: 10, name: 'Import Align - Direct Align 2' }, + { position: 11, name: 'Math Alignment Import Test' }, + { position: 12, name: 'create me' }, + { position: 13, name: 'Illustrative Math Test 1' }, + { position: 14, name: 'Illustrative Math Test 2' }, + { position: 15, name: 'Khan URL test' }, + { position: 16, name: 'seesaw test' }, + { position: 17, name: 'ECS-3037 On Prod TC2' }, + { position: 18, name: 'ECS-3037 On Prod TC1' }, + { position: 19, name: 'webinar test' }, + { position: 20, name: 'Review Screen Open' }, + { position: 21, name: 'New One For Agust Post Night' }, + { position: 22, name: 'Post NIght July26' }, + { position: 23, name: 'create import test' } + ]; + + //Entire list - item count must match + if (rows.length === expected.length) { + console.log(`Passed: Available Content list count (${rows.length}) matched as expected`); + } else { + errors.push(`Available Content list count - Expected: ${expected.length}; Actual: ${rows.length}`); + } + + for (const exp of expected) { + const actual = rows[exp.position - 1]; + if (!actual) { + errors.push(`Available Content ${exp.position}: row not found`); + continue; + } + + if (actual.name === exp.name) { + console.log(`Passed: Available Content ${exp.position} - ${exp.name} matched as expected`); + } else { + errors.push(`Available Content ${exp.position} name - Expected: "${exp.name}"; Actual: "${actual.name}"`); + } + } + + //Unexpected extra items on the page + rows.slice(expected.length).forEach(r => { + errors.push(`Available Content ${r.position}: unexpected item "${r.name}"`); + }); + + //On any mismatch, print the actual list in "expected" format so it can be pasted above + if (errors.length > 0) { + console.log('Actual Available Content list:\n' + rows.map(r => + ` { position: ${r.position}, name: '${r.name.replace(/'/g, "\\'")}' },` + ).join('\n')); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + throw new Error(errors.join('\n')); + } + } + }, + + //ADVANCED OPTIONS + //Scroll to bottom of page + { + description: 'Scroll to bottom of page', + action: async () => { + await driver.executeScript('window.scrollTo(0, document.body.scrollHeight);'); + await driver.sleep(2000); + } + }, + + //Advanced Options link + { + description: 'Advanced Options link text, size, and color', + action: async () => { + const multipleChecks = 'Advanced Options link'; + + const element = await driver.findElement(By.css('#link-button-ads')); + + //Get text, font, size, and color + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Track all errors + const errors = []; + + //text + if (elementText === 'Advanced Options') { + console.log('Passed: Advanced Options link text matched as expected'); + } else { + errors.push(`Expected: "Advanced Options"; Actual: "${elementText}"`); + } + + //font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Advanced Options link font-family matched as expected'); + } else { + errors.push(`Expected: Advanced Options link font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //size + if (elementSize === '13px') { + console.log('Passed: Advanced Options link text font-size matched as expected'); + } else { + errors.push(`Expected: Advanced Options link text font-size "13px"; Actual: "${elementSize}"`); + } + + //color + if (elementColor === 'rgba(48, 200, 172, 1)') { + console.log('Passed: Advanced Options link text color matched as expected'); + } else { + errors.push(`Expected: Advanced Options link text color: "rgba(48, 200, 172, 1)"; Actual: "${elementColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //NEXT ACTION + { + description: 'Click Advanced Options link', + action: async () => { + await driver.findElement(By.css('#link-button-ads')).click(); + console.log('----->| NEXT ACTION: Clicked Advanced Options link'); + + //Wait for page readyState + await driver.wait(async () => { + const readyState = await driver.executeScript('return document.readyState'); + return readyState === 'complete'; + }, 30000, 'ExACT Dashboard did not fully load within 30 seconds'); + + //Wait until the element exists in the DOM + const element = await driver.wait( + until.elementLocated(By.css('#searchbox-content > p')), + 30000 + ); + + //Wait until it becomes visible + await driver.wait( + until.elementIsVisible(element), + 30000 + ); + + await driver.executeScript('window.scrollTo(0, document.body.scrollHeight);'); + await driver.sleep(2000); + } + }, + + //Apply filters to results label + { + description: 'Apply filters to results label text, size, and color', + action: async () => { + const multipleChecks = 'Apply filters to results label'; + + const element = await driver.findElement(By.css('#searchbox-content > p')); + + //Get text, font, size, and color + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Track all errors + const errors = []; + + //text + if (elementText === 'Apply filters to results:') { + console.log('Passed: Apply filters to results label text matched as expected'); + } else { + errors.push(`Expected: "Apply filters to results:"; Actual: "${elementText}"`); + } + + //font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Apply filters to results label font-family matched as expected'); + } else { + errors.push(`Expected: Apply filters to results label font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //size + if (elementSize === '13px') { + console.log('Passed: Apply filters to results label text font-size matched as expected'); + } else { + errors.push(`Expected: Apply filters to results label text font-size "13px"; Actual: "${elementSize}"`); + } + + //color + if (elementColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Apply filters to results label text color matched as expected'); + } else { + errors.push(`Expected: Apply filters to results label text color: "rgba(40, 39, 90, 1)"; Actual: "${elementColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Apply filters to results- Grade label + { + description: 'Apply filters to results - Grade label text, size, and color', + action: async () => { + const multipleChecks = 'Apply filters to results - Grade label'; + + //"Grade:" is a bare text node inside the

  • (no wrapping tag); styles are inherited from the
  • + const element = await driver.findElement(By.css('#searchbox-content > ul > li:nth-child(1)')); + + //Get label text (direct text nodes only, excludes the dropdown), font, size, and color + const elementText = await driver.executeScript(` + return Array.from(arguments[0].childNodes) + .filter(n => n.nodeType === Node.TEXT_NODE) + .map(n => n.textContent.trim()) + .join(''); + `, element); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Track all errors + const errors = []; + + //text + if (elementText === 'Grade:') { + console.log('Passed: Apply filters to results - Grade label text matched as expected'); + } else { + errors.push(`Expected: "Grade:"; Actual: "${elementText}"`); + } + + //font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Apply filters to results - Grade label font-family matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Grade label font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //size + if (elementSize === '14.3px') { + console.log('Passed: Apply filters to results - Grade label text font-size matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Grade label text font-size "14.3px"; Actual: "${elementSize}"`); + } + + //color + if (elementColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Apply filters to results - Grade label text color matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Grade label text color: "rgba(40, 39, 90, 1)"; Actual: "${elementColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Apply filters to results- Grade dropdown value and list + { + description: 'Apply filters to results - Grade dropdown value and list', + action: async () => { + const multipleChecks = 'Grade dropdown list'; + + const element = await driver.findElement(By.css('.list-group-item:nth-child(1) .multiselect-selected-text')); + + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Dropdown items are
  • (no wrapping tag); styles are inherited from the
  • + const element = await driver.findElement(By.css('#searchbox-content > ul > li:nth-child(2)')); + + //Get label text (direct text nodes only, excludes the dropdown), font, size, and color + const elementText = await driver.executeScript(` + return Array.from(arguments[0].childNodes) + .filter(n => n.nodeType === Node.TEXT_NODE) + .map(n => n.textContent.trim()) + .join(''); + `, element); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Track all errors + const errors = []; + + //text + if (elementText === 'Subject:') { + console.log('Passed: Apply filters to results - Subject label text matched as expected'); + } else { + errors.push(`Expected: "Subject:"; Actual: "${elementText}"`); + } + + //font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Apply filters to results - Subject label font-family matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Subject label font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //size + if (elementSize === '14.3px') { + console.log('Passed: Apply filters to results - Subject label text font-size matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Subject label text font-size "14.3px"; Actual: "${elementSize}"`); + } + + //color + if (elementColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Apply filters to results - Subject label text color matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Subject label text color: "rgba(40, 39, 90, 1)"; Actual: "${elementColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Apply filters to results- Subject dropdown value and list + { + description: 'Apply filters to results - Subject dropdown value and list', + action: async () => { + const multipleChecks = 'Subject dropdown list'; + + const element = await driver.findElement(By.css('.list-group-item:nth-child(2) .multiselect-selected-text')); + + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Dropdown items are
  • (no wrapping tag); styles are inherited from the
  • + const element = await driver.findElement(By.css('#searchbox-content > ul > li:nth-child(3)')); + + //Get label text (direct text nodes only, excludes the dropdown), font, size, and color + const elementText = await driver.executeScript(` + return Array.from(arguments[0].childNodes) + .filter(n => n.nodeType === Node.TEXT_NODE) + .map(n => n.textContent.trim()) + .join(''); + `, element); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Track all errors + const errors = []; + + //text + if (elementText === 'Alignment Status:') { + console.log('Passed: Apply filters to results - Alignment Status label text matched as expected'); + } else { + errors.push(`Expected: "Alignment Status:"; Actual: "${elementText}"`); + } + + //font + if (elementFont === 'Poppins, sans-serif') { + console.log('Passed: Apply filters to results - Alignment Status label font-family matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Alignment Status label font-family "Poppins, sans-serif"; Actual: ${elementFont}`); + } + + //size + if (elementSize === '14.3px') { + console.log('Passed: Apply filters to results - Alignment Status label text font-size matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Alignment Status label text font-size "14.3px"; Actual: "${elementSize}"`); + } + + //color + if (elementColor === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Apply filters to results - Alignment Status label text color matched as expected'); + } else { + errors.push(`Expected: Apply filters to results - Alignment Status label text color: "rgba(40, 39, 90, 1)"; Actual: "${elementColor}"`); + } + + //Throw summary if any validation failed + if (errors.length > 0) { + //Add summary line only when multiple checks failed + if (errors.length > 1) { + errors.unshift(`${multipleChecks} - Multiple validation checks did not pass`); + } + + //Throw collected messages — catch() will prefix with "FAILED:" + throw new Error(errors.join('\n')); + } + } + }, + + //Apply filters to results- Subject dropdown value and list + { + description: 'Apply filters to results - Subject dropdown value and list', + action: async () => { + const multipleChecks = 'Subject dropdown list'; + + const element = await driver.findElement(By.css('.list-group-item:nth-child(3) .multiselect-selected-text')); + + const elementText = await element.getText(); + const elementFont = await element.getCssValue('font-family'); + const elementSize = await element.getCssValue('font-size'); + const elementColor = await element.getCssValue('color'); + + //Dropdown items are