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, 'Align page 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