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