From 1964abb007350fc72ffe12590e6e66c85a0cf0e5 Mon Sep 17 00:00:00 2001 From: jhuerta Date: Fri, 8 Aug 2025 15:13:17 -0700 Subject: [PATCH] Added Framework Publishing DIV --- frameworkPublishFrameworkDIVResults.xlsx | Bin 0 -> 93736 bytes index.js | 3 + tests/ExACT_frameworkPublishFrameworkDIV.js | 3084 +++++++++++++++++++ 3 files changed, 3087 insertions(+) create mode 100644 frameworkPublishFrameworkDIVResults.xlsx create mode 100644 tests/ExACT_frameworkPublishFrameworkDIV.js diff --git a/frameworkPublishFrameworkDIVResults.xlsx b/frameworkPublishFrameworkDIVResults.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e0affcd990b331b7af165e59935ada7beeab086c GIT binary patch literal 93736 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 {
+

`); @@ -72,6 +74,7 @@ app.get('/ExACT_contentPage', ExACT_contentPage); //Framework app.get('/ExACT_frameworkManagementPage', ExACT_frameworkManagementPage); app.get('/ExACT_frameworkPublishingPage', ExACT_frameworkPublishingPage); + app.get('/ExACT_frameworkPublishFrameworkDIV', ExACT_frameworkPublishFrameworkDIV); app.listen(8000, () => { console.log('Server is running on port 8000'); }); \ No newline at end of file diff --git a/tests/ExACT_frameworkPublishFrameworkDIV.js b/tests/ExACT_frameworkPublishFrameworkDIV.js new file mode 100644 index 0000000..c399ff3 --- /dev/null +++ b/tests/ExACT_frameworkPublishFrameworkDIV.js @@ -0,0 +1,3084 @@ +import { Builder, By, Key, until } from 'selenium-webdriver'; +import fs from 'fs'; +import XLSX from 'xlsx'; +import path from 'path'; + +const ExACT_frameworkPublishFrameworkDIV = (req, res) => { + res.send('

ExACT Automated Test Script: Publish Framework DIV(ExACT_frameworkPublishFrameworkDIV); Initiated

'); + (async function example() { + let driver = await new Builder().forBrowser('chrome').build(); + let testStatus = 'Failed'; + let workbook; + let worksheet; + const startTime = new Date().toISOString(); + +const steps = [ + { description: 'Navigate to ExACT Landing Page', action: async () => await driver.navigate().to('https://stage.edgate.com/exact/login.php') }, //PROD - https://correlation.edgate.com/exact/login.php + { description: 'Expand browser', action: async () => await driver.manage().window().maximize() }, + + //LOGIN + { description: 'Enter username', action: async () => await driver.findElement(By.css('.form-control:nth-child(2)')).sendKeys('exact_juan') }, + { description: 'Enter password', action: async () => await driver.findElement(By.css('.passfield')).sendKeys('Edgate1!') }, + { description: 'Click Login button', action: async () => await driver.findElement(By.css('.login')).click() }, + { description: 'Wait for login process to complete', action: async () => await driver.sleep(10000) }, + + //Wait for dashboard to load - Correlation Coverages View Details button + { + description: 'Wait for dashboard load to completely', + action: async () => { + return await driver.wait(until.elementLocated(By.linkText('View Details')), 10000).catch(() => false); + } + }, + + //Dashboard title + { + description: 'Validate dashboard title', + action: async () => { + const elementText = await driver.findElement(By.css('.e-heading')).getText(); + if (elementText === 'Correlation Dashboard') { + console.log(`Passed: "${elementText}" title matched as expected`); + } else { + throw new Error(`Expected: "Correlation Dashboard"; Actual: "${elementText}"`); + } + } + }, + + //Align icon color -gray + { + description: 'Validate Align icon color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.fb-align')).getCssValue('color'); + if (elementStyle === 'rgba(99, 99, 99, 1)') { + console.log('Passed: Align icon color matched as expected'); + } else { + throw new Error(`Align icon color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //NEXT ACTION - Navigate to Framework Management page + { description: 'Click Frameworks navigation link', action: async () => await driver.findElement(By.linkText('Frameworks')).click() }, + + //Wait for page to load - Correlation Coverages View Details button + { + description: 'Wait for page to load', + action: async () => { + return await driver.wait(until.elementLocated(By.css('h2')), 10000).catch(() => false); + } + }, + + //Framework Management page title + { + description: 'Validate Framework Management page title', + action: async () => { + const elementText = await driver.findElement(By.css('h2')).getText(); + if (elementText === 'Framework Management') { + console.log('Passed: Framework Management page title matched as expected'); + } else { + throw new Error(`Expected: "Framework Management" page title; Actual: "${elementText}"`); + } + + } + }, + + //Framework Management page title text color -dark blue + { + description: 'Validate Framework Management page title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('h2')).getCssValue('color'); + if (elementStyle === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Align icon color matched as expected'); + } else { + throw new Error(`Align icon color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Framework Management page title text font + { + description: 'Validate Framework Management page title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('h2')).getCssValue('font-size'); + if (elementStyle === '32px') { + console.log('Passed: Framework Management page title text font-size matched as expected'); + } else { + throw new Error(`Framework Management page title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Publishing button icon + { + description: 'Verify Publishing buttion icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.btn > .fa-cloud-upload')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Publishing button icon not found'); + } + console.log('Passed: Publishing button icon present'); + } + }, + + //Publishing button text + { + description: 'Validate Publishing button text', + action: async () => { + const elementText = await driver.findElement(By.linkText('Publishing')).getText(); + if (elementText === 'Publishing') { + console.log('Passed: Publishing button text matched as expected'); + } else { + throw new Error(`Expected: "Publishing" button text; Actual: "${elementText}"`); + } + } + }, + + //Publishing button color -green + { + description: 'Validate Publishing button color', + action: async () => { + const elementStyle = await driver.findElement(By.linkText('Publishing')).getCssValue('background-color'); + if (elementStyle === 'rgba(48, 200, 172, 1)') { + console.log('Passed: Align icon color matched as expected'); + } else { + throw new Error(`Align icon color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //NEXT ACTION - Click Publishing button + { description: 'Click Publishing button', action: async () => await driver.findElement(By.linkText('Publishing')).click() }, + + //Publishing Page + { + description: 'Wait for Publishing page to load', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('h2')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Publishing page did not load'); + } + console.log('Passed: Publishing page loaded'); + } + }, + + //Framework Publishing page title + { + description: 'Validate Framework Publishing page title', + action: async () => { + const elementText = await driver.findElement(By.css('h2')).getText(); + if (elementText === 'Framework Publishing') { + console.log('Passed: Framework Publishing page title text matched as expected'); + } else { + throw new Error(`Expected: "Framework Publishing" page title text; Actual: "${elementText}"`); + } + } + }, + + //Framework Publishing page title text color -dark blue + { + description: 'Validate Framework Publishing page title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('h2')).getCssValue('color'); + if (elementStyle === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Framework Publishing page title text color matched as expected'); + } else { + throw new Error(`Framework Publishing page title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Framework Publishing page title text font + { + description: 'Validate Framework Publishing page title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('h2')).getCssValue('font-size'); + if (elementStyle === '32px') { + console.log('Passed: Framework Publishing page title text font-size matched as expected'); + } else { + throw new Error(`Framework Publishing page title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Publish Framework button icon + { + description: 'Verify Publish Framework buttion icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-cloud-upload')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Publish Framework button icon not found'); + } + console.log('Passed: Publish Framework button icon present'); + } + }, + + //Publish Framework button text + { + description: 'Validate Publish Framework button text', + action: async () => { + const elementText = await driver.findElement(By.linkText('Publish Framework')).getText(); + if (elementText === 'Publish Framework') { + console.log('Passed: Publish Framework button text matched as expected'); + } else { + throw new Error(`Expected: "Publish Framework" button text; Actual: "${elementText}"`); + } + } + }, + + //Publish Framework button color -green + { + description: 'Validate Publish Framework button color', + action: async () => { + const elementStyle = await driver.findElement(By.linkText('Publish Framework')).getCssValue('background-color'); + if (elementStyle === 'rgba(48, 200, 172, 1)') { + console.log('Passed: Publish Framework button color matched as expected'); + } else { + throw new Error(`Publish Framework button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Groups button icon + { + description: 'Verify Groups buttion icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-th-list')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Groups button icon not found'); + } + console.log('Passed: Groups button icon present'); + } + }, + + //Groups button text + { + description: 'Validate Groups button text', + action: async () => { + const elementText = await driver.findElement(By.linkText('Groups')).getText(); + if (elementText === 'Groups') { + console.log('Passed: Groups button text matched as expected'); + } else { + throw new Error(`Expected: "Groups" button text; Actual: "${elementText}"`); + } + } + }, + + //Groups button color -navy blue + { + description: 'Validate Groups button color', + action: async () => { + const elementStyle = await driver.findElement(By.linkText('Groups')).getCssValue('background-color'); + if (elementStyle === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Groups button color matched as expected'); + } else { + throw new Error(`Groups button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Settings button icon + { + description: 'Verify Settings buttion icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-cog')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Settings button icon not found'); + } + console.log('Passed: Settings button icon present'); + } + }, + + //Settings button text + { + description: 'Validate Settings button text', + action: async () => { + const elementText = await driver.findElement(By.linkText('Settings')).getText(); + if (elementText === 'Settings') { + console.log('Passed: Settings button text matched as expected'); + } else { + throw new Error(`Expected: "Settings" button text; Actual: "${elementText}"`); + } + } + }, + + //Settings button color -green + { + description: 'Validate Settings button color', + action: async () => { + const elementStyle = await driver.findElement(By.linkText('Settings')).getCssValue('background-color'); + if (elementStyle === 'rgba(48, 200, 172, 1)') { + console.log('Passed: Settings button color matched as expected'); + } else { + throw new Error(`Settings button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Publishing History sub title + { + description: 'Validate Publishing History sub title', + action: async () => { + const elementText = await driver.findElement(By.css('h4')).getText(); + if (elementText === 'Publishing History http://qaclient.esp.edgate.com') { + console.log('Passed: Publishing History sub title text matched as expected'); + } else { + throw new Error(`Expected: "Publishing History" sub title text; Actual: "${elementText}"`); + } + } + }, + + //Publishing History sub title text color -navy blue + { + description: 'Validate Publishing History sub title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('h4')).getCssValue('color'); + if (elementStyle === 'rgba(40, 39, 90, 1)') { + console.log('Passed: Publishing History sub title text color matched as expected'); + } else { + throw new Error(`Publishing History sub title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Publishing History Sub title text font + { + description: 'Validate Publishing History sub title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('h4')).getCssValue('font-size'); + if (elementStyle === '24px') { + console.log('Passed: Publishing History sub title text font-size matched as expected'); + } else { + throw new Error(`Publishing History sub title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Publishing History button text + { + description: 'Validate Publish History button text', + action: async () => { + const elementText = await driver.findElement(By.css('body > div.container.body > div > div.right_col > div > h4 > a')).getText(); + if (elementText === 'http://qaclient.esp.edgate.com') { + console.log('Passed: http://qaclient.esp.edgate.com button text matched as expected'); + } else { + throw new Error(`Expected: "http://qaclient.esp.edgate.com" button text; Actual: "${elementText}"`); + } + } + }, + + //Publishing History button color -green + { + description: 'Validate Publishing History button color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.btn-sm')).getCssValue('background-color'); + if (elementStyle === 'rgba(48, 200, 172, 1)') { + console.log('Passed: Publishing History button color matched as expected'); + } else { + throw new Error(`Publishing History button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Publishing History button icon + { + description: 'Verify Publishing History buttion icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.btn-sm > .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Publishing History button icon not found'); + } + console.log('Passed: Publishing History button icon present'); + } + }, + + //Framework column title + { + description: 'Validate Framework column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(1)')).getText(); + if (elementText === 'Framework') { + console.log('Passed: Framework column title text matched as expected'); + } else { + throw new Error(`Expected: "Framework" column title text; Actual: "${elementText}"`); + } + } + }, + + //Framework column title text color -dark blue + { + description: 'Validate Framework column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(1)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Framework column title text color matched as expected'); + } else { + throw new Error(`Framework column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Framework column title text font + { + description: 'Validate Framework column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(1)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Framework column title text font-size matched as expected'); + } else { + throw new Error(`Framework column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Version column title + { + description: 'Validate Version column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(2)')).getText(); + if (elementText === 'Version') { + console.log('Passed: Version column title text matched as expected'); + } else { + throw new Error(`Expected: "Version" column title text; Actual: "${elementText}"`); + } + } + }, + + //Version column title text color -dark blue + { + description: 'Validate Version column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(2)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Version column title text color matched as expected'); + } else { + throw new Error(`Version column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Version column title text font + { + description: 'Validate Version column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(2)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Version column title text font-size matched as expected'); + } else { + throw new Error(`Version column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Revision column title + { + description: 'Validate Revision column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(3)')).getText(); + if (elementText === 'Revision') { + console.log('Passed: Revision column title text matched as expected'); + } else { + throw new Error(`Expected: "Revision" column title text; Actual: "${elementText}"`); + } + } + }, + + //Revision column title text color -dark blue + { + description: 'Validate Revision column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(3)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Revision column title text color matched as expected'); + } else { + throw new Error(`Revision column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Revision column title text font + { + description: 'Validate Revision column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(3)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Revision column title text font-size matched as expected'); + } else { + throw new Error(`Revision column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Status column title + { + description: 'Validate Status column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(4)')).getText(); + if (elementText === 'Status') { + console.log('Passed: Status column title text matched as expected'); + } else { + throw new Error(`Expected: "Status" column title text; Actual: "${elementText}"`); + } + } + }, + + //Status column title text color -dark blue + { + description: 'Validate Status column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(4)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Status column title text color matched as expected'); + } else { + throw new Error(`Status column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Status column title text font + { + description: 'Validate Status column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(4)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Status column title text font-size matched as expected'); + } else { + throw new Error(`Status column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Visibility column title + { + description: 'Validate Visibility column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(5)')).getText(); + if (elementText === 'Visibility') { + console.log('Passed: Visibility column title text matched as expected'); + } else { + throw new Error(`Expected: "Visibility" column title text; Actual: "${elementText}"`); + } + } + }, + + //Visibility column title text color -dark blue + { + description: 'Validate Visibility column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(5)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Visibility column title text color matched as expected'); + } else { + throw new Error(`Visibility column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Visibility column title text font + { + description: 'Validate Visibility column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(5)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Visibility column title text font-size matched as expected'); + } else { + throw new Error(`Visibility column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Group column title + { + description: 'Validate Group column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(6)')).getText(); + if (elementText === 'Group') { + console.log('Passed: Group column title text matched as expected'); + } else { + throw new Error(`Expected: "Group" column title text; Actual: "${elementText}"`); + } + } + }, + + //Group column title text color -dark blue + { + description: 'Validate Group column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(6)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Group column title text color matched as expected'); + } else { + throw new Error(`Group column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Group column title text font + { + description: 'Validate Group column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(6)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Group column title text font-size matched as expected'); + } else { + throw new Error(`Group column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published At column title + { + description: 'Validate Published At column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(7)')).getText(); + if (elementText === 'Published At') { + console.log('Passed: Published At column title text matched as expected'); + } else { + throw new Error(`Expected: "Published At" column title text; Actual: "${elementText}"`); + } + } + }, + + //Published At column title text color -dark blue + { + description: 'Validate Published At column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(7)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Published At column title text color matched as expected'); + } else { + throw new Error(`Published At column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published At column title text font + { + description: 'Validate Published At column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(7)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Published At column title text font-size matched as expected'); + } else { + throw new Error(`Published At column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //By column title + { + description: 'Validate By column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(8)')).getText(); + if (elementText === 'By') { + console.log('Passed: By column title text matched as expected'); + } else { + throw new Error(`Expected: "By" column title text; Actual: "${elementText}"`); + } + } + }, + + //By column title text color -dark blue + { + description: 'Validate By column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(8)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: By column title text color matched as expected'); + } else { + throw new Error(`By column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //By column title text font + { + description: 'Validate By column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(8)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: By column title text font-size matched as expected'); + } else { + throw new Error(`By column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Comments column title + { + description: 'Validate Comments column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(9)')).getText(); + if (elementText === 'Comments') { + console.log('Passed: Comments column title text matched as expected'); + } else { + throw new Error(`Expected: "Comments" column title text; Actual: "${elementText}"`); + } + } + }, + + //Comments column title text color -dark blue + { + description: 'Validate Comments column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(9)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Comments column title text color matched as expected'); + } else { + throw new Error(`Comments column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Comments column title text font + { + description: 'Validate Comments column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(9)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Comments column title text font-size matched as expected'); + } else { + throw new Error(`Comments column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Action column title + { + description: 'Validate Action column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(10)')).getText(); + if (elementText === 'Action') { + console.log('Passed: Action column title text matched as expected'); + } else { + throw new Error(`Expected: "Action" column title text; Actual: "${elementText}"`); + } + } + }, + + //Action column title text color -dark blue + { + description: 'Validate Action column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(10)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Action column title text color matched as expected'); + } else { + throw new Error(`Action column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Action column title text font + { + description: 'Validate Action column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(10)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Action column title text font-size matched as expected'); + } else { + throw new Error(`Action column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published Framework 1 display title + { + description: 'Validate Published Framework 1 display title', + action: async () => { + try { + const element = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Painting Done Today'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Framework title row 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Framework title row 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //Published Framework 1 Notes icon + { + description: 'Verify Published Framework 1 notes icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-sticky-note-o')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework 1 Notes icon not found'); + } + console.log('Passed: Published Framework 1 Notes icon present'); + } + }, + + //Published Framework 1 title + { + description: 'Validate Published Framework 1 title', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) em')).getText(); + if (elementText === 'Juan Testing Again & Again') { + console.log('Passed: Juan Testing Again & Again row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Juan Testing Again & Again" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Version + { + description: 'Validate Published Framework 1 version', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(2)')).getText(); + if (elementText === '1.1') { + console.log('Passed: Version 1.1 row 1 title text matched as expected'); + } else { + throw new Error(`Expected: Version "1.1" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Revision + { + description: 'Validate Published Framework 1 revision', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(3)')).getText(); + if (elementText === '5') { + console.log('Passed: Revision 5 row 1 title text matched as expected'); + } else { + throw new Error(`Expected: Revision "5" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Status button text + { + description: 'Validate Published Framework 1 status button text', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td > .badge')).getText(); + if (elementText === 'Implemented') { + console.log('Passed: Implemented row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Implemented" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Status button color -green + { + description: 'Validate Action column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('tr:nth-child(2) > td > .badge')).getCssValue('background-color'); + if (elementStyle === 'rgba(40, 167, 69, 1)') { + console.log('Passed: Published Framework row 1 Status button color matched as expected'); + } else { + throw new Error(`Published Framework row 1 Status button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published Framework 1 Visibility + { + description: 'Validate Published Framework 1 visibility', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(5)')).getText(); + if (elementText === 'Public') { + console.log('Passed: Public row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Public" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Group + { + description: 'Validate Published Framework 1 group', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(6)')).getText(); + if (elementText === 'Initial Framework Group for Testing') { + console.log('Passed: Initial Framework Group for Testing row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Initial Framework Group for Testing" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Published At + { + description: 'Validate Published Framework 1 published at', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(7) > small')).getText(); + if (elementText === 'Apr 15, 2025 10:29pm PDT') { + console.log('Passed: Apr 15, 2025 10:29pm PDT row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Apr 15, 2025 10:29pm PDT" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 By + { + description: 'Validate Published Framework 1 by', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(8)')).getText(); + if (elementText === 'exact_juan') { + console.log('Passed: exact_juan row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "exact_juan" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Comments icon + { + description: 'Verify Published Framework 1 comments icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('tr:nth-child(2) .fa-check-circle')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 1 comments icon not found'); + } + console.log('Passed: Published Framework row 1 comments icon present'); + } + }, + + //Published Framework 1 Comments Count icon + { + description: 'Validate Published Framework 1 comments count icon', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) a > .badge')).getText(); + if (elementText === '3') { + console.log('Passed: Comments count 3 row 1 title text matched as expected'); + } else { + throw new Error(`Expected: Comments count "3" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 ellipsis icon + { + description: 'Verify Published Framework 1 ellipsis icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#dropdownMenu17 > .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 1 ellipsis icon not found'); + } + console.log('Passed: Published Framework row 1 ellipsis icon present'); + } + }, + + //Published Framework 2 display title + { + description: 'Validate Published Framework 2 display title', + action: async () => { + try { + const element = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'KathleenTest DontBringBack Comments'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Framework title row 2 "${expectedText}" text found in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Framework title row 2 "${expectedText}" text found within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //Published Framework 2 title + { + description: 'Validate Published Framework 2 title', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) em')).getText(); + if (elementText === 'Kathleen Test') { + console.log('Passed: Kathleen Test row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Kathleen Test" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Version + { + description: 'Validate Published Framework 2 version', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(2)')).getText(); + if (elementText === '10.1') { + console.log('Passed: Version 10.1 row 2 title text matched as expected'); + } else { + throw new Error(`Expected: Version "10.1" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Revision + { + description: 'Validate Published Framework 2 revision', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(3)')).getText(); + if (elementText === '2') { + console.log('Passed: Revision 2 row 2 title text matched as expected'); + } else { + throw new Error(`Expected: Revision "2" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Status button text + { + description: 'Validate Published Framework 2 status button text', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td > .badge')).getText(); + if (elementText === 'Adopted') { + console.log('Passed: Adopted row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Adopted" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Status button color -teal + { + description: 'Validate Action column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('tr:nth-child(3) > td > .badge')).getCssValue('background-color'); + if (elementStyle === 'rgba(23, 162, 184, 1)') { + console.log('Passed: Published Framework row 2 Status button color matched as expected'); + } else { + throw new Error(`Published Framework row 2 Status button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published Framework 2 Visibility + { + description: 'Validate Published Framework 2 visibility', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(5)')).getText(); + if (elementText === 'Hidden') { + console.log('Passed: Hidden row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Hidden" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Group + { + description: 'Validate Published Framework 2 group', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(6)')).getText(); + if (elementText === 'Another Group To Use') { + console.log('Passed: Another Group To Use row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Another Group To Use" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Published At + { + description: 'Validate Published Framework 2 published at', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(7) > small')).getText(); + if (elementText === 'Mar 01, 2025 09:56pm PST') { + console.log('Passed: Apr 15, 2025 10:29pm PDT row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Apr 15, 2025 10:29pm PDT" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 By + { + description: 'Validate Published Framework 2 by', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(8)')).getText(); + if (elementText === 'exact_juan') { + console.log('Passed: exact_juan row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "exact_juan" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Comments icon + { + description: 'Verify Published Framework 2 comments icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('tr:nth-child(3) > td > .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 2 comments icon not found'); + } + console.log('Passed: Published Framework row 2 comments icon present'); + } + }, + + //Published Framework 2 Comments Count icon + { + description: 'Validate Published Framework 2 comments count icon', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) a > .badge')).getText(); + if (elementText === '4') { + console.log('Passed: Comments count 4 row 2 title text matched as expected'); + } else { + throw new Error(`Expected: Comments count "4" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 ellipsis icon + { + description: 'Verify Published Framework 2 ellipsis icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#dropdownMenu14 > .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 2 ellipsis icon not found'); + } + console.log('Passed: Published Framework row 2 ellipsis icon present'); + } + }, + + //NEXT ACTION - Click Publish Framework button + { description: 'Click Publish Framework button', action: async () => await driver.findElement(By.linkText('Publish Framework')).click() }, + + //Wait for DIV to open + { + description: 'Wait for DIV to open', + action: async () => { + return await driver.wait(until.elementLocated(By.css('.modal-title')), 10000).catch(() => false); + } + }, + + //DIV title text + { + description: 'Validate title', + action: async () => { + const elementText = await driver.findElement(By.css('.modal-title')).getText(); + if (elementText === 'Publish Framework') { + console.log('Passed: Edit Publish Framework title text matched as expected'); + } else { + throw new Error(`Expected: "Publish Framework" title text; Actual: "${elementText}"`); + } + } + }, + + //DIV X icon color -red + { + description: 'Validate X icon color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.close > span')).getCssValue('color'); + if (elementStyle === 'rgba(246, 60, 40, 1)') { + console.log('Passed: Align icon color matched as expected'); + } else { + throw new Error(`Align icon color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Framework label + { + description: 'Validate Framework label', + action: async () => { + const elementText = await driver.findElement(By.css('#divtype > .form-label')).getText(); + if (elementText === 'Framework') { + console.log('Passed: Framework title text matched as expected'); + } else { + throw new Error(`Expected: "Framework" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Framework data + { + description: 'Validate Framework dropdown option', + action: async () => { + const dropdown = await driver.findElement(By.css('#divtype')); + const options = await dropdown.findElements(By.css('option')); + + for (const option of options) { + const elementText = await option.getText(); + if (elementText === 'Select a framework') { + await option.click(); + console.log(`Passed: Dropdown option: "${elementText}", matched as expected`); + return; + } + throw new Error(`Expected dropdown option: "${elementText}", value not found`); + } + } + }, + + //DIV Display Title label + { + description: 'Validate Display Title label', + action: async () => { + const elementText = await driver.findElement(By.css('#divname > .form-label')).getText(); + if (elementText === 'Display Title') { + console.log('Passed: Display Title label text matched as expected'); + } else { + throw new Error(`Expected: "Display Title" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Display Title - info icon + { + description: 'Verify Display Title info icon', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#divname .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Display Title info icon not found'); + } + console.log('Passed: Display Title info icon present'); + } + }, + + //DIV Display Title - value + { + description: 'Validate Display Title value', + action: async () => { + const elementValue = await driver.findElement(By.css('#title')).getAttribute('value'); + if (elementValue === '') { + console.log('Passed: Display Title empty value text, matched as expected'); + } else { + throw new Error(`Expected: "empty" value text; Actual: "${elementValue}"`); + } + } + }, + + //DIV Version label + { + description: 'Validate Version label', + action: async () => { + const elementText = await driver.findElement(By.css('#divsource > .form-label')).getText(); + if (elementText === 'Version') { + console.log('Passed: Version label text matched as expected'); + } else { + throw new Error(`Expected: "Version" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Version - info icon + { + description: 'Verify Version info icon', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#divsource .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Version info icon not found'); + } + console.log('Passed: Version info icon present'); + } + }, + + //DIV Version - value + { + description: 'Validate Version value', + action: async () => { + const elementValue = await driver.findElement(By.css('#version')).getAttribute('value'); + if (elementValue === '') { + console.log('Passed: empty value text, matched as expected'); + } else { + throw new Error(`Expected: "empty" value text; Actual: "${elementValue}"`); + } + } + }, + + //DIV Display Status label + { + description: 'Validate Display Status label', + action: async () => { + const elementText = await driver.findElement(By.css('#divpublisher > .form-label')).getText(); + if (elementText === 'Display Status') { + console.log('Passed: Display Status label text matched as expected'); + } else { + throw new Error(`Expected: "Display Status" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Display Status - info icon + { + description: 'Verify Display Status info icon', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#divpublisher .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Display Status info icon not found'); + } + console.log('Passed: Display Status info icon present'); + } + }, + + //DIV Display Status - value + { + description: 'Validate Display dropdown selection', + action: async () => { + const elementOption = await driver.findElement(By.css('#status')).getAttribute('value'); + if (elementOption === 'Implemented') { + console.log('Passed: Implemented dropdown option matched as expected'); + } else { + throw new Error(`Expected: "Implemented" dropdown selection; Actual: "${elementOption}"`); + } + } + }, + + //DIV Group label + { + description: 'Validate Group label', + action: async () => { + const elementText = await driver.findElement(By.css('#divparent > .form-label')).getText(); + if (elementText === 'Group') { + console.log('Passed: Group label text matched as expected'); + } else { + throw new Error(`Expected: "Group" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Group - info icon + { + description: 'Verify Group info icon', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#divparent .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Group info icon not found'); + } + console.log('Passed: Group info icon present'); + } + }, + + //DIV Group - value {7=Initial Framwork Group for Testing} + { + description: 'Validate Group dropdown selection', + action: async () => { + const elementOption = await driver.findElement(By.css('#group')).getAttribute('value'); + if (elementOption === '7') { + console.log('Passed: Initial Framwork Group for Testing dropdown option matched as expected'); + } else { + throw new Error(`Expected: "Initial Framwork Group for Testing" dropdown selection; Actual: "${elementOption}"`); + } + } + }, + + //DIV Download Formats label + { + description: 'Validate Download Formats label', + action: async () => { + const elementText = await driver.findElement(By.css('#divcreator > .form-label')).getText(); + if (elementText === 'Download Formats') { + console.log('Passed: Download Formats label text matched as expected'); + } else { + throw new Error(`Expected: "Download Formats" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Download Formats - info icon + { + description: 'Verify Download Formats info icon', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#divcreator .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Download Formats info icon not found'); + } + console.log('Passed: Download Formats info icon present'); + } + }, + + //DIV Download Formats: CSV checkbox -active + { + description: 'Validate CSV checkbox option enabled', + action: async () => { + const elementStyle = await driver.findElement(By.css('#formatcsv')).getAttribute('checked'); + if (elementStyle === 'true') { + console.log('Passed: CSV checkbox option value matched as expected'); + } else { + throw new Error(`CSV checkbox option value checked did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Download Formats: CSV handle + { + description: 'Validate CSV label', + action: async () => { + const elementText = await driver.findElement(By.css('#divcreator > .form-check:nth-child(4) > .form-check-label')).getText(); + if (elementText === 'CSV') { + console.log('Passed: CSV label text matched as expected'); + } else { + throw new Error(`Expected: "CSV" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Download Formats: PDF checkbox -active + { + description: 'Validate PDF checkbox option enabled', + action: async () => { + const elementStyle = await driver.findElement(By.css('#formatpdf')).getAttribute('checked'); + if (elementStyle === 'true') { + console.log('Passed: PDF checkbox option value matched as expected'); + } else { + throw new Error(`PDF checkbox option value checked did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Download Formats: PDF handle + { + description: 'Validate PDF label', + action: async () => { + const elementText = await driver.findElement(By.css('.form-check:nth-child(5) > .form-check-label')).getText(); + if (elementText === 'PDF') { + console.log('Passed: PDF label text matched as expected'); + } else { + throw new Error(`Expected: "PDF" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Download Formats: JSON checkbox -active + { + description: 'Validate JSON checkbox option enabled', + action: async () => { + const elementStyle = await driver.findElement(By.css('#formatcase')).getAttribute('checked'); + if (elementStyle === 'true') { + console.log('Passed: JSON checkbox option value matched as expected'); + } else { + throw new Error(`JSON checkbox option value checked did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Download Formats: JSON handle + { + description: 'Validate JSON label', + action: async () => { + const elementText = await driver.findElement(By.css('.form-check:nth-child(6) > .form-check-label')).getText(); + if (elementText === 'CASE JSON/API*') { + console.log('Passed: CASE JSON/API* label text matched as expected'); + } else { + throw new Error(`Expected: "CASE JSON/API*" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Download Formats: Required text + { + description: 'Validate Required text', + action: async () => { + const elementText = await driver.findElement(By.css('em > small')).getText(); + if (elementText === 'This option also allows access to this framework via CASE compliant API') { + console.log('Passed: This option also allows access to this framework via CASE compliant API text matched as expected'); + } else { + throw new Error(`Expected: "This option also allows access to this framework via CASE compliant API" text; Actual: "${elementText}"`); + } + } + }, + + //DIV Comment Settings text + { + description: 'Validate Comment Settings text', + action: async () => { + const elementText = await driver.findElement(By.css('#divstatus > .form-label')).getText(); + if (elementText === 'Comment Settings') { + console.log('Passed: Comment Settings text matched as expected'); + } else { + throw new Error(`Expected: "Comment Settings" text; Actual: "${elementText}"`); + } + } + }, + + //DIV Comment Settings: Allow Comments checkbox -active + { + description: 'Validate Allow Comments checkbox option enabled', + action: async () => { + const elementStyle = await driver.findElement(By.css('#comments')).getAttribute('checked'); + if (elementStyle === 'true') { + console.log('Passed: Allow Comments checkbox option value matched as expected'); + } else { + throw new Error(`Allow Comments checkbox option value checked did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Comment Settings: Allow Comments handle + { + description: 'Validate Allow Comments label', + action: async () => { + const elementText = await driver.findElement(By.css('.form-check:nth-child(3) > .form-check-label')).getText(); + if (elementText === 'Allow Comments') { + console.log('Passed: Allow Comments label text matched as expected'); + } else { + throw new Error(`Expected: "Allow Comments" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Comment Settings: Comments are private checkbox + { + description: 'Validate Comments are private checkbox', + action: async () => { + const elementStyle = await driver.findElement(By.css('#private')).getAttribute('type'); + if (elementStyle === 'checkbox') { + console.log('Passed: Comments are private checkbox type matched as expected'); + } else { + throw new Error(`Comments are private checkbox type does not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Comment Settings: Comments are private handle + { + description: 'Validate Comments are private label', + action: async () => { + const elementText = await driver.findElement(By.css('#divstatus > .form-check:nth-child(4) > .form-check-label')).getText(); + if (elementText === 'Comments are private') { + console.log('Passed: Comments are private label text matched as expected'); + } else { + throw new Error(`Expected: "Comments are private" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Publishers Notes label + { + description: 'Validate Publishers Notes label', + action: async () => { + const elementText = await driver.findElement(By.css('#divpubnotes > .form-label')).getText(); + if (elementText === `Publisher's Notes`) { + console.log(`Passed: Publisher's Notese label text matched as expected`); + } else { + throw new Error(`Expected: "Publisher's Notes" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Publishers Notes textbox placeholder + { + description: 'Validate Publishers Notes textbox placeholder', + action: async () => { + const elementValue = await driver.findElement(By.css('#pubnotes')).getAttribute('placeholder'); + if (elementValue === '') { + console.log('Passed: "blank" placeholder text, matched as expected'); + } else { + throw new Error(`Expected: "blank" placeholder text; Actual: "${elementValue}"`); + } + } + }, + + //DIV Publish button text + { + description: 'Validate Publish button text', + action: async () => { + const elementText = await driver.findElement(By.css('#modalop')).getAttribute('value'); + if (elementText === 'Publish') { + console.log('Passed: Publish button text matched as expected'); + } else { + throw new Error(`Expected: "Publish" button text; Actual: "${elementText}"`); + } + } + }, + + //DIV Publish button color -white + { + description: 'Validate Publish button color', + action: async () => { + const elementStyle = await driver.findElement(By.css('#modalop')).getCssValue('background-color'); + if (elementStyle === 'rgba(48, 200, 172, 1)') { + console.log('Passed: Publish button color matched as expected'); + } else { + throw new Error(`Publish button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Close button text + { + description: 'Validate Close button text', + action: async () => { + const elementText = await driver.findElement(By.css('#modalclose')).getText(); + if (elementText === 'Close') { + console.log('Passed: Close button text matched as expected'); + } else { + throw new Error(`Expected: "Close" button text; Actual: "${elementText}"`); + } + } + }, + + //DIV Close button color -white + { + description: 'Validate Close button color', + action: async () => { + const elementStyle = await driver.findElement(By.css('#modalclose')).getCssValue('background-color'); + if (elementStyle === 'rgba(0, 0, 0, 0)') { + console.log('Passed: Close button color matched as expected'); + } else { + throw new Error(`Close button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //NEXT ACTION - Publish button (validation) + { description: 'Click Publish button', action: async () => await driver.findElement(By.css('#modalop')).click() }, + + //Wait for validation to appear + { + description: 'Wait for validation text', + action: async () => { + return await driver.wait(until.elementLocated(By.css('.invalid-feedback:nth-child(3)')), 10000).catch(() => false); + } + }, + + //Framework validation text + { + description: 'Validate Framework validation text', + action: async () => { + const elementText = await driver.findElement(By.css('.invalid-feedback:nth-child(3)')).getText(); + if (elementText === 'You must select a framework to publish.') { + console.log('Passed: Framework validation text matched as expected'); + } else { + throw new Error(`Expected: "You must select a framework to publish." validation text; Actual: "${elementText}"`); + } + } + }, + + //Framework validation text color -red + { + description: 'Validate Framework validation text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.invalid-feedback:nth-child(3)')).getCssValue('color'); + if (elementStyle === 'rgba(220, 53, 69, 1)') { + console.log('Passed: Framework validation text color matched as expected'); + } else { + throw new Error(`Framework validation text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Display Title validation text + { + description: 'Validate Display Title validation text', + action: async () => { + const elementText = await driver.findElement(By.css('#divname > .invalid-feedback')).getText(); + if (elementText === 'You must enter a framework title') { + console.log('Passed: Display Title validation text matched as expected'); + } else { + throw new Error(`Expected: "You must enter a framework title" validation text; Actual: "${elementText}"`); + } + } + }, + + //Display Title validation text color -red + { + description: 'Validate Display Title validation text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('#divname > .invalid-feedback')).getCssValue('color'); + if (elementStyle === 'rgba(220, 53, 69, 1)') { + console.log('Passed: Display Title validation text color matched as expected'); + } else { + throw new Error(`Display Title validation text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Version validation text + { + description: 'Validate Version validation text', + action: async () => { + const elementText = await driver.findElement(By.css('#divsource > .invalid-feedback')).getText(); + if (elementText === 'You must enter a version for the published framework') { + console.log('Passed: Version validation text matched as expected'); + } else { + throw new Error(`Expected: "You must enter a version for the published framework" validation text; Actual: "${elementText}"`); + } + } + }, + + //Version validation text color -red + { + description: 'Validate Version validation text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('#divsource > .invalid-feedback')).getCssValue('color'); + if (elementStyle === 'rgba(220, 53, 69, 1)') { + console.log('Passed: Version validation text color matched as expected'); + } else { + throw new Error(`Version validation text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV validation text + { + description: 'Validate DIV validation text', + action: async () => { + const elementText = await driver.findElement(By.css('b')).getText(); + if (elementText === 'Please enter a value for all highlighted fields') { + console.log('Passed: DIV validation text matched as expected'); + } else { + throw new Error(`Expected: "Please enter a value for all highlighted fields" validation text; Actual: "${elementText}"`); + } + } + }, + + //DIV validation text color -red + { + description: 'Validate DIV validation text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('b')).getCssValue('color'); + if (elementStyle === 'rgba(220, 53, 69, 1)') { + console.log('Passed: DIV validation text color matched as expected'); + } else { + throw new Error(`DIV validation text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //PUBLISH FRAMEWORK + //NEXT ACTION - Publish Framework (to be deleted) + { description: 'Click Framework dropdown', action: async () => await driver.findElement(By.css('#divtype > .form-label')).click() }, + { description: 'Select framework - Make Sure To Delete', action: async () => await driver.findElement(By.css('optgroup:nth-child(8) > option')).click() }, + { description: 'Enter Display Title', action: async () => await driver.findElement(By.css('#title')).sendKeys('I will automatically delete you') }, + { description: 'Enter Version', action: async () => await driver.findElement(By.css('#version')).sendKeys('1.19') }, + { description: 'Click Publish button', action: async () => await driver.findElement(By.css('#modalop')).click() }, + { description: 'Wait for action to complete', action: async () => await driver.sleep(5000) }, + + //Alert banner + { + description: 'Validate alert banner text', + action: async () => { + try { + const element = await driver.findElement(By.css('.alert')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Make Sure To Delete'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text found as expected`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text found as expected`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //Alert banner background color -green + { + description: 'Validate alert banner background text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.alert')).getCssValue('background-color'); + if (elementStyle === 'rgba(40, 167, 69, 1)') { + console.log('Passed: Alert banner background text color matched as expected'); + } else { + throw new Error(`Alert banner text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //NEXT ACTION - Close alert banner + { description: 'Click X icon on alert banner', action: async () => await driver.findElement(By.css('.close > span')).click() }, + { description: 'Wait for action to complete', action: async () => await driver.sleep(2000) }, + + //Framework column title + { + description: 'Validate Framework column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(1)')).getText(); + if (elementText === 'Framework') { + console.log('Passed: Framework column title text matched as expected'); + } else { + throw new Error(`Expected: "Framework" column title text; Actual: "${elementText}"`); + } + } + }, + + //Framework column title text color -dark blue + { + description: 'Validate Framework column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(1)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Framework column title text color matched as expected'); + } else { + throw new Error(`Framework column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Framework column title text font + { + description: 'Validate Framework column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(1)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Framework column title text font-size matched as expected'); + } else { + throw new Error(`Framework column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Version column title + { + description: 'Validate Version column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(2)')).getText(); + if (elementText === 'Version') { + console.log('Passed: Version column title text matched as expected'); + } else { + throw new Error(`Expected: "Version" column title text; Actual: "${elementText}"`); + } + } + }, + + //Version column title text color -dark blue + { + description: 'Validate Version column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(2)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Version column title text color matched as expected'); + } else { + throw new Error(`Version column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Version column title text font + { + description: 'Validate Version column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(2)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Version column title text font-size matched as expected'); + } else { + throw new Error(`Version column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Revision column title + { + description: 'Validate Revision column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(3)')).getText(); + if (elementText === 'Revision') { + console.log('Passed: Revision column title text matched as expected'); + } else { + throw new Error(`Expected: "Revision" column title text; Actual: "${elementText}"`); + } + } + }, + + //Revision column title text color -dark blue + { + description: 'Validate Revision column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(3)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Revision column title text color matched as expected'); + } else { + throw new Error(`Revision column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Revision column title text font + { + description: 'Validate Revision column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(3)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Revision column title text font-size matched as expected'); + } else { + throw new Error(`Revision column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Status column title + { + description: 'Validate Status column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(4)')).getText(); + if (elementText === 'Status') { + console.log('Passed: Status column title text matched as expected'); + } else { + throw new Error(`Expected: "Status" column title text; Actual: "${elementText}"`); + } + } + }, + + //Status column title text color -dark blue + { + description: 'Validate Status column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(4)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Status column title text color matched as expected'); + } else { + throw new Error(`Status column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Status column title text font + { + description: 'Validate Status column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(4)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Status column title text font-size matched as expected'); + } else { + throw new Error(`Status column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Visibility column title + { + description: 'Validate Visibility column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(5)')).getText(); + if (elementText === 'Visibility') { + console.log('Passed: Visibility column title text matched as expected'); + } else { + throw new Error(`Expected: "Visibility" column title text; Actual: "${elementText}"`); + } + } + }, + + //Visibility column title text color -dark blue + { + description: 'Validate Visibility column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(5)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Visibility column title text color matched as expected'); + } else { + throw new Error(`Visibility column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Visibility column title text font + { + description: 'Validate Visibility column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(5)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Visibility column title text font-size matched as expected'); + } else { + throw new Error(`Visibility column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Group column title + { + description: 'Validate Group column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(6)')).getText(); + if (elementText === 'Group') { + console.log('Passed: Group column title text matched as expected'); + } else { + throw new Error(`Expected: "Group" column title text; Actual: "${elementText}"`); + } + } + }, + + //Group column title text color -dark blue + { + description: 'Validate Group column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(6)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Group column title text color matched as expected'); + } else { + throw new Error(`Group column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Group column title text font + { + description: 'Validate Group column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(6)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Group column title text font-size matched as expected'); + } else { + throw new Error(`Group column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published At column title + { + description: 'Validate Published At column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(7)')).getText(); + if (elementText === 'Published At') { + console.log('Passed: Published At column title text matched as expected'); + } else { + throw new Error(`Expected: "Published At" column title text; Actual: "${elementText}"`); + } + } + }, + + //Published At column title text color -dark blue + { + description: 'Validate Published At column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(7)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Published At column title text color matched as expected'); + } else { + throw new Error(`Published At column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published At column title text font + { + description: 'Validate Published At column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(7)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Published At column title text font-size matched as expected'); + } else { + throw new Error(`Published At column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //By column title + { + description: 'Validate By column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(8)')).getText(); + if (elementText === 'By') { + console.log('Passed: By column title text matched as expected'); + } else { + throw new Error(`Expected: "By" column title text; Actual: "${elementText}"`); + } + } + }, + + //By column title text color -dark blue + { + description: 'Validate By column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(8)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: By column title text color matched as expected'); + } else { + throw new Error(`By column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //By column title text font + { + description: 'Validate By column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(8)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: By column title text font-size matched as expected'); + } else { + throw new Error(`By column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Comments column title + { + description: 'Validate Comments column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(9)')).getText(); + if (elementText === 'Comments') { + console.log('Passed: Comments column title text matched as expected'); + } else { + throw new Error(`Expected: "Comments" column title text; Actual: "${elementText}"`); + } + } + }, + + //Comments column title text color -dark blue + { + description: 'Validate Comments column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(9)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Comments column title text color matched as expected'); + } else { + throw new Error(`Comments column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Comments column title text font + { + description: 'Validate Comments column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(9)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Comments column title text font-size matched as expected'); + } else { + throw new Error(`Comments column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Action column title + { + description: 'Validate Action column title', + action: async () => { + const elementText = await driver.findElement(By.css('th:nth-child(10)')).getText(); + if (elementText === 'Action') { + console.log('Passed: Action column title text matched as expected'); + } else { + throw new Error(`Expected: "Action" column title text; Actual: "${elementText}"`); + } + } + }, + + //Action column title text color -dark blue + { + description: 'Validate Action column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(10)')).getCssValue('color'); + if (elementStyle === 'rgba(33, 37, 41, 1)') { + console.log('Passed: Action column title text color matched as expected'); + } else { + throw new Error(`Action column title text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Action column title text font + { + description: 'Validate Action column title text font size', + action: async () => { + const elementStyle = await driver.findElement(By.css('th:nth-child(10)')).getCssValue('font-size'); + if (elementStyle === '14.3px') { + console.log('Passed: Action column title text font-size matched as expected'); + } else { + throw new Error(`Action column title text font-size did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published Framework 1 display title + { + description: 'Validate Published Framework 1 display title', + action: async () => { + try { + const element = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'I will automatically delete you'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Framework title row 1 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Framework title row 1 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //Published Framework 1 API icon + { + description: 'Verify Published Framework 1 API icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('tr:nth-child(2) .fa-code')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework 1 API icon not found'); + } + console.log('Passed: Published Framework 1 API icon present'); + } + }, + + //Published Framework 1 title + { + description: 'Validate Published Framework 1 title', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) em')).getText(); + if (elementText === 'Make Sure To Delete') { + console.log('Passed: Make Sure To Delete row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Make Sure To Delete" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Version + { + description: 'Validate Published Framework 1 version', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(2)')).getText(); + if (elementText === '1.19') { + console.log('Passed: Version 1.19 row 1 title text matched as expected'); + } else { + throw new Error(`Expected: Version "1.19" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + /*Published Framework 1 Revision {revision number increases at every publish} + { + description: 'Validate Published Framework 1 revision', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(3)')).getText(); + if (elementText === '1') { + console.log('Passed: Revision 1 row 1 title text matched as expected'); + } else { + throw new Error(`Expected: Revision "1" row 1 title text; Actual: "${elementText}"`); + } + } + },*/ + + //Published Framework 1 Status button text + { + description: 'Validate Published Framework 1 status button text', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td > .badge')).getText(); + if (elementText === 'Implemented') { + console.log('Passed: Implemented row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Implemented" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Status button color -gray + { + description: 'Validate Action column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('tr:nth-child(2) > td > .badge')).getCssValue('background-color'); + if (elementStyle === 'rgba(40, 167, 69, 1)') { + console.log('Passed: Published Framework row 1 Status button color matched as expected'); + } else { + throw new Error(`Published Framework row 1 Status button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published Framework 1 Visibility + { + description: 'Validate Published Framework 1 visibility', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(5)')).getText(); + if (elementText === 'Public') { + console.log('Passed: Public row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Public" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Group + { + description: 'Validate Published Framework 1 group', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(6)')).getText(); + if (elementText === 'Initial Framework Group for Testing') { + console.log('Passed: Initial Framework Group for Testing row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Initial Framework Group for Testing" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + /*Published Framework 1 Published At + { + description: 'Validate Published Framework 1 published at', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(7) > small')).getText(); + if (elementText === 'Apr 15, 2025 10:29pm PDT') { + console.log('Passed: Apr 15, 2025 10:29pm PDT row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "Apr 15, 2025 10:29pm PDT" row 1 title text; Actual: "${elementText}"`); + } + } + },*/ + + //Published Framework 1 By + { + description: 'Validate Published Framework 1 by', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) > td:nth-child(8)')).getText(); + if (elementText === 'exact_juan') { + console.log('Passed: exact_juan row 1 title text matched as expected'); + } else { + throw new Error(`Expected: "exact_juan" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 Comments icon + { + description: 'Verify Published Framework 1 comments icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('tr:nth-child(2) .fa-check-circle')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 1 comments icon not found'); + } + console.log('Passed: Published Framework row 1 comments icon present'); + } + }, + + //Published Framework 1 Comments Count icon + { + description: 'Validate Published Framework 1 comments count icon', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(2) .badge-primary')).getText(); + if (elementText === '0') { + console.log('Passed: Comments count 0 row 1 title text matched as expected'); + } else { + throw new Error(`Expected: Comments count "0" row 1 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 1 ellipsis icon + { + description: 'Verify Published Framework 1 ellipsis icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.xpath('//td[11]/div/a/i')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 1 ellipsis icon not found'); + } + console.log('Passed: Published Framework row 1 ellipsis icon present'); + } + }, + + //Published Framework 2 display title + { + description: 'Validate Published Framework 2 display title', + action: async () => { + try { + const element = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(1)')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Painting Done Today'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: Framework title row 2 "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: Framework title row 2 "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //Published Framework 2 Notes icon + { + description: 'Verify Published Framework 2 notes icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-sticky-note-o')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework 2 Notes icon not found'); + } + console.log('Passed: Published Framework 2 Notes icon present'); + } + }, + + //Published Framework 2 title + { + description: 'Validate Published Framework 2 title', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) em')).getText(); + if (elementText === 'Juan Testing Again & Again') { + console.log('Passed: Juan Testing Again & Again row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Juan Testing Again & Again" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Version + { + description: 'Validate Published Framework 2 version', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(2)')).getText(); + if (elementText === '1.1') { + console.log('Passed: Version 1.1 row 2 title text matched as expected'); + } else { + throw new Error(`Expected: Version "1.1" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Revision + { + description: 'Validate Published Framework 2 revision', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(3)')).getText(); + if (elementText === '5') { + console.log('Passed: Revision 5 row 2 title text matched as expected'); + } else { + throw new Error(`Expected: Revision "5" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Status button text + { + description: 'Validate Published Framework 2 status button text', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td > .badge')).getText(); + if (elementText === 'Implemented') { + console.log('Passed: Implemented row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Implemented" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Status button color -green + { + description: 'Validate Action column title text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('tr:nth-child(3) > td > .badge')).getCssValue('background-color'); + if (elementStyle === 'rgba(40, 167, 69, 1)') { + console.log('Passed: Published Framework row 2 Status button color matched as expected'); + } else { + throw new Error(`Published Framework row 2 Status button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //Published Framework 2 Visibility + { + description: 'Validate Published Framework 2 visibility', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(5)')).getText(); + if (elementText === 'Public') { + console.log('Passed: Public row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Public" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Group + { + description: 'Validate Published Framework 2 group', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(6)')).getText(); + if (elementText === 'Initial Framework Group for Testing') { + console.log('Passed: Initial Framework Group for Testing row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Initial Framework Group for Testing" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Published At + { + description: 'Validate Published Framework 2 published at', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(7) > small')).getText(); + if (elementText === 'Apr 15, 2025 10:29pm PDT') { + console.log('Passed: Apr 15, 2025 10:29pm PDT row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "Apr 15, 2025 10:29pm PDT" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 By + { + description: 'Validate Published Framework 2 by', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) > td:nth-child(8)')).getText(); + if (elementText === 'exact_juan') { + console.log('Passed: exact_juan row 2 title text matched as expected'); + } else { + throw new Error(`Expected: "exact_juan" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 Comments icon + { + description: 'Verify Published Framework 2 comments icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('tr:nth-child(3) .fa-check-circle')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 2 comments icon not found'); + } + console.log('Passed: Published Framework row 2 comments icon present'); + } + }, + + //Published Framework 2 Comments Count icon + { + description: 'Validate Published Framework 2 comments count icon', + action: async () => { + const elementText = await driver.findElement(By.css('tr:nth-child(3) a > .badge')).getText(); + if (elementText === '3') { + console.log('Passed: Comments count 3 row 2 title text matched as expected'); + } else { + throw new Error(`Expected: Comments count "3" row 2 title text; Actual: "${elementText}"`); + } + } + }, + + //Published Framework 2 ellipsis icon + { + description: 'Verify Published Framework 2 ellipsis icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('#dropdownMenu17 > .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Published Framework row 2 ellipsis icon not found'); + } + console.log('Passed: Published Framework row 2 ellipsis icon present'); + } + }, + + //RESET PUBLISHING HISTORY + //NEXT ACTION - Delete published Framework + { description: 'Click published framework ellipsis icon', action: async () => await driver.findElement(By.xpath('//td[11]/div/a/i')).click() }, + { description: 'Wait for action to complete', action: async () => await driver.sleep(2000) }, + + //Ellipsis menu - View text + { + description: 'Validate ellipsis menu option View text label', + action: async () => { + const elementText = await driver.findElement(By.linkText('View')).getText(); + if (elementText === 'View') { + console.log('Passed: Ellipsis menu option View label text matched as expected'); + } else { + throw new Error(`Expected: Ellisis menu option "View" label text; Actual: "${elementText}"`); + } + } + }, + + //Ellipsis menu - View icon + { + description: 'Verify ellipsis menu option View icon', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.show > .dropdown-item > .fa')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Ellipsis view icon not found'); + } + console.log('Passed: Ellipsis view icon present'); + } + }, + + //Ellipsis menu - Edit text + { + description: 'Validate ellipsis menu option Edit text label', + action: async () => { + const elementText = await driver.findElement(By.linkText('Edit')).getText(); + if (elementText === 'Edit') { + console.log('Passed: Ellipsis menu option Edit label text matched as expected'); + } else { + throw new Error(`Expected: Ellisis menu option "Edit" label text; Actual: "${elementText}"`); + } + } + }, + + //Ellipsis menu - Archive text + { + description: 'Validate ellipsis menu option Archive text label', + action: async () => { + const elementText = await driver.findElement(By.linkText('Archive')).getText(); + if (elementText === 'Archive') { + console.log('Passed: Ellipsis menu option Archive label text matched as expected'); + } else { + throw new Error(`Expected: Ellisis menu option "Archive" label text; Actual: "${elementText}"`); + } + } + }, + + //Ellipsis menu - Delete text + { + description: 'Validate ellipsis menu option Delete text label', + action: async () => { + const elementText = await driver.findElement(By.linkText('Delete')).getText(); + if (elementText === 'Delete') { + console.log('Passed: Ellipsis menu option Delete label text matched as expected'); + } else { + throw new Error(`Expected: Ellisis menu option "Delete" label text; Actual: "${elementText}"`); + } + } + }, + + //Ellipsis menu - Delete text color -red + { + description: 'Validate ellipsis Delete text color', + action: async () => { + const elementStyle = await driver.findElement(By.linkText('Delete')).getCssValue('color'); + if (elementStyle === 'rgba(220, 53, 69, 1)') { + console.log('Passed: Delete text color matched as expected'); + } else { + throw new Error(`Delete text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //NEXT ACTION - Delete published Framework + { description: 'Click Delete link', action: async () => await driver.findElement(By.linkText('Delete')).click() }, + + //Wait for DIV to load - Delete + { + description: 'Wait for DIV to load', + action: async () => { + return await driver.wait(until.elementLocated(By.css('.modal-title')), 10000).catch(() => false); + } + }, + + //DIV Delete Published Framework title text + { + description: 'Validate Delete Published Framework title text', + action: async () => { + const elementText = await driver.findElement(By.css('.modal-title')).getText(); + if (elementText === 'Delete Published Framework') { + console.log('Passed: Delete Published Framework title text matched as expected'); + } else { + throw new Error(`Expected: "Delete Published Framework" title text; Actual: "${elementText}"`); + } + } + }, + + //DIV X icon color -red + { + description: 'Validate X icon color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.close > span')).getCssValue('color'); + if (elementStyle === 'rgba(246, 60, 40, 1)') { + console.log('Passed: DIV X icon color matched as expected'); + } else { + throw new Error(`DIV X icon color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV info icon + { + description: 'Verify Delete Info icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-info-circle')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Info icon not found'); + } + console.log('Passed: Info button icon present'); + } + }, + + //DIV Delete description text + { + description: 'Validate Delete description text', + action: async () => { + const elementText = await driver.findElement(By.css('.alert')).getText(); + if (elementText === 'You are about to delete this framework revision from the system. Its data will no longer be accesible and this action is not recoverable.') { + console.log('Passed: Deleting descriptive text matched as expected'); + } else { + throw new Error(`Expected: "Deleting descriptive" text; Actual: "${elementText}"`); + } + } + }, + + //DIV Delete description text background color -red + { + description: 'Validate Delete description background text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.alert')).getCssValue('background-color'); + if (elementStyle === 'rgba(231, 76, 60, 0.88)') { + console.log('Passed: Delete background text color matched as expected'); + } else { + throw new Error(`Delete background text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Framework label + { + description: 'Validate Framework label', + action: async () => { + const elementText = await driver.findElement(By.css('#divtype > .form-label')).getText(); + if (elementText === 'Framework') { + console.log('Passed: Framework label text matched as expected'); + } else { + throw new Error(`Expected: "Framework" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Framework value text + { + description: 'Validate Framework value text', + action: async () => { + try { + const element = await driver.findElement(By.css('#divtype')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'I will automatically delete you'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text in first line`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text within full text`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //DIV Retain comments checkbox -null + { + description: 'Validate Retain comments checkbox option enabled', + action: async () => { + const elementStyle = await driver.findElement(By.css('#retain')).getAttribute('type'); + if (elementStyle === 'checkbox') { + console.log('Passed: Retain comments checkbox type matched as expected'); + } else { + throw new Error(`Retain comments checkbox type does not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Retain comments label + { + description: 'Validate Retain comments label', + action: async () => { + const elementText = await driver.findElement(By.css('.form-check-label')).getText(); + if (elementText === 'Retain comments') { + console.log('Passed: Retain comments label text matched as expected'); + } else { + throw new Error(`Expected: "Retain comments" label text; Actual: "${elementText}"`); + } + } + }, + + //DIV Delete button text + { + description: 'Validate Delete button text', + action: async () => { + const elementText = await driver.findElement(By.css('#modalop')).getAttribute('value'); + if (elementText === 'Delete') { + console.log('Passed: Delete button text matched as expected'); + } else { + throw new Error(`Expected: "Delete" button text; Actual: "${elementText}"`); + } + } + }, + + //DIV Delete button color -red + { + description: 'Validate Delete button color', + action: async () => { + const elementStyle = await driver.findElement(By.css('#modalop')).getCssValue('background-color'); + if (elementStyle === 'rgba(220, 53, 69, 1)') { + console.log('Passed: Delete button color matched as expected'); + } else { + throw new Error(`Delete button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //DIV Close button text + { + description: 'Validate Close button text', + action: async () => { + const elementText = await driver.findElement(By.css('#modalclose')).getText(); + if (elementText === 'Close') { + console.log('Passed: Close button text matched as expected'); + } else { + throw new Error(`Expected: "Close" button text; Actual: "${elementText}"`); + } + } + }, + + //DIV Close button color -white + { + description: 'Validate Close button color', + action: async () => { + const elementStyle = await driver.findElement(By.css('#modalclose')).getCssValue('background-color'); + if (elementStyle === 'rgba(0, 0, 0, 0)') { + console.log('Passed: Close button color matched as expected'); + } else { + throw new Error(`Close button color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //NEXT ACTION - Click Delete + { description: 'Click Delete button', action: async () => await driver.findElement(By.css('#modalop')).click() }, + { description: 'Wait for action to complete', action: async () => await driver.sleep(2000) }, + + //Alert banner + { + description: 'Validate alert banner text', + action: async () => { + try { + const element = await driver.findElement(By.css('.alert')); + + //Get different versions of the text for debugging + const fullText = await element.getText(); + + //Check for the expected text in different ways + const expectedText = 'Framework deleted!'; + const trimmedFullText = fullText.trim(); + const firstLine = trimmedFullText.split('\n')[0].trim(); + + //Try multiple matching strategies + if (firstLine.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text found as expected`); + } else if (trimmedFullText.includes(expectedText)) { + console.log(`Passed: "${expectedText}" text found as expected`); + } else { + throw new Error( + `Text validation failed.\nExpected: "${expectedText}"\n` + + `Full text: "${fullText}"\n` + + `First line: "${firstLine}"\n` + ); + } + + } catch (error) { + console.error('Detailed error during validation:', error); + throw error; //Re-throw after logging + } + } + }, + + //Alert banner background color -green + { + description: 'Validate alert banner background text color', + action: async () => { + const elementStyle = await driver.findElement(By.css('.alert')).getCssValue('background-color'); + if (elementStyle === 'rgba(40, 167, 69, 1)') { + console.log('Passed: Alert banner background text color matched as expected'); + } else { + throw new Error(`Alert banner text color did not match; Actual: "${elementStyle}"`); + } + } + }, + + //LOG OUT + //NEXT ACTION - Log out + { description: 'Click Username dropdown', action: async () => await driver.findElement(By.css('#navbarDropdown > span')).click() }, + { description: 'Wait for action to complete', action: async () => await driver.sleep(2000) }, + + //Log Out icon + { + description: 'Verify Log Out icon is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.fa-sign-out')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Log Out icon not found'); + } + console.log('Passed: Log Out icon present'); + } + }, + + { description: 'Click Log Out link', action: async () => await driver.findElement(By.linkText('Log Out')).click() }, + + //Wait for login screen to load + { + description: 'Wait for log out process to complete', + action: async () => { + return await driver.wait(until.elementLocated(By.css('.login')), 10000).catch(() => false); + } + }, + + //Log Out button + { + description: 'Verify Log Out button is present', + action: async () => + { const expectedIcon = await driver.wait(until.elementLocated(By.css('.login')), 5000).catch(() => false); + if (!expectedIcon) { + throw new Error('Log Out button not found'); + } + console.log('Passed: Log Out button present; Script completed'); + } + }, +]; + +const logStep = (worksheet, stepDescription, status, stepIndex, timestamp, screenshotPath) => { + const json_data = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); + json_data.push([stepIndex, stepDescription, status, timestamp, screenshotPath]); + return XLSX.utils.aoa_to_sheet(json_data); +}; + +const takeScreenshot = async (driver, stepIndex, stepDescription) => { + const screenshot = await driver.takeScreenshot(); + + const dir = path.join('screenshots', 'frameworkPublishFrameworkDIV'); + + const screenshotFileName = `step_${stepIndex}_${stepDescription.replace(/\s+/g, '_')}.png`; + const screenshotPath = path.join(dir, screenshotFileName); + fs.writeFileSync(screenshotPath, screenshot, 'base64'); + return screenshotPath; +}; + +const clearOldResults = () => { + // Remove old screenshots + const screenshotDir = path.join('screenshots', 'frameworkPublishFrameworkDIV'); + if (fs.existsSync(screenshotDir)) { + fs.rmSync(screenshotDir, { recursive: true, force: true }); + } + fs.mkdirSync(screenshotDir, { recursive: true }); + + // Remove old Excel file + if (fs.existsSync('frameworkPublishFrameworkDIVResults.xlsx')) { + fs.unlinkSync('frameworkPublishFrameworkDIVResults.xlsx'); + } +}; + +try { + // Initialize workbook and worksheet + clearOldResults(); + + // Initialize workbook and worksheet + workbook = XLSX.utils.book_new(); + worksheet = XLSX.utils.aoa_to_sheet([ + ['Step Number', 'Step Description', 'Status', 'Timestamp', 'Screenshot'] + ]); + XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); + + // Log test start time + worksheet = logStep(worksheet, 'Test Start', 'Started', '', startTime, ''); + + let allStepsPassed = true; + + for (const step of steps) { + const stepIndex = steps.indexOf(step) + 1; + const timestamp = new Date().toISOString(); + + try { + await step.action(); + const screenshotPath = await takeScreenshot(driver, stepIndex, step.description); + worksheet = logStep(worksheet, step.description, 'Passed', stepIndex, timestamp, screenshotPath); + } catch (error) { + const screenshotPath = await takeScreenshot(driver, stepIndex, `${step.description}_Failed`); + worksheet = logStep(worksheet, step.description, 'Failed', stepIndex, timestamp, screenshotPath); + console.error(`Step ${stepIndex} FAILED: ${error.message}`); + testStatus = 'Failed'; + allStepsPassed = false; + } + } + + //Check if log out was successful + const loginButton = await driver.wait(until.elementLocated(By.css('.login')), 5000).catch(() => false); + + if (loginButton && allStepsPassed) { + console.log('PASSED: Framework Publish Frameowrk DIV(ExACT_frameworkPublishFrameworkDIV); All test steps completed successfully'); + testStatus = 'Passed'; + } else { + console.log('FAILED: Framework Publish Frameowrk DIV(ExACT_frameworkPublishFrameworkDIV); One or more test steps failed'); + testStatus = 'Failed'; + } + + // Log test end time + const endTime = new Date().toISOString(); + worksheet = logStep(worksheet, 'Test End', testStatus, '', endTime, ''); + + // Write the updated worksheet back to the workbook and save it + workbook.Sheets['Sheet1'] = worksheet; + XLSX.writeFile(workbook, 'frameworkPublishFrameworkDIVResults.xlsx'); +} finally { + await driver.quit(); +} +})(); +} + +export default ExACT_frameworkPublishFrameworkDIV;