-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#122: Add JavaScript functional test harness #129
Changes from 1 commit
999762b
43e4a30
e01f13f
938234e
8c4d931
0b326d9
210644c
68b791b
8d87435
c8f2ee2
ed8e087
9e2ab8e
b04d519
a3fa717
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,86 +2,54 @@ | |
<html lang="en" dir="ltr"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<link rel="shortcut icon" href=""> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's this for, anyway? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Firefox seems to, by default, make a GET request to get the page's favicon for display in the tab. If I don't have a favicon, my HTTP server throws an error. This is an empty favicon to prevent that error. I can make a comment saying as much. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gtk! A comment would be great for Future Me. |
||
<link rel="icon" href="data:,"> | ||
<title>isVisible functional test</title> | ||
<style type="text/css"> | ||
:root { | ||
--size: 100px; | ||
} | ||
#not-visible-1 { | ||
width: 0px; | ||
overflow: hidden; | ||
} | ||
#not-visible-2 { | ||
height: 0px; | ||
overflow: hidden; | ||
} | ||
#not-visible-3 { | ||
display: none; | ||
} | ||
#not-visible-4-ancestor { | ||
display: none; | ||
} | ||
#not-visible-5 { | ||
opacity: 0; | ||
} | ||
#not-visible-6-ancestor { | ||
opacity: 0; | ||
} | ||
#not-visible-7-ancestor { | ||
width: 0; | ||
} | ||
#not-visible-7 { | ||
overflow: hidden; | ||
} | ||
#not-visible-8-ancestor { | ||
height: 0; | ||
} | ||
#not-visible-8 { | ||
overflow: hidden; | ||
} | ||
.off-screen { | ||
width: var(--size); | ||
height: var(--size); | ||
border: 1px solid black; | ||
position: absolute; | ||
} | ||
#not-visible-9 { | ||
left: calc(-2 * var(--size)); | ||
} | ||
#not-visible-10 { | ||
top: calc(-2 * var(--size)); | ||
} | ||
#not-visible-11 { | ||
right: calc(100vw + 2 * var(--size)); | ||
} | ||
#not-visible-12 { | ||
bottom: calc(100vh + 2 * var(--size)); | ||
} | ||
|
||
</style> | ||
</head> | ||
<body> | ||
<h1>isVisible functional test</h1> | ||
<div id="not-visible-1"></div> | ||
<div id="not-visible-2"></div> | ||
<div id="not-visible-3"></div> | ||
<div id="not-visible-4-ancestor"> | ||
<div id="not-visible-1" style="width: 0px; overflow: hidden;"></div> | ||
<div id="not-visible-2" style="height: 0px; overflow: hidden;"></div> | ||
<div id="not-visible-3" style="display: none;"></div> | ||
<!-- ``display: none`` ancestor --> | ||
<div id="ancestor-not-visible-4" style="display: none;"> | ||
<div id="not-visible-4"></div> | ||
</div> | ||
<div id="not-visible-5"></div> | ||
<div id="not-visible-6-ancestor"> | ||
<div id="not-visible-5" style="opacity: 0;"></div> | ||
<!-- ``opacity: 0`` ancestor --> | ||
<div id="ancestor-not-visible-6" style="opacity: 0;"> | ||
<div id="not-visible-6"></div> | ||
</div> | ||
<div id="not-visible-7-ancestor"> | ||
<div id="not-visible-7"></div> | ||
<!-- ``overflow: hidden`` with zero width ancestor --> | ||
<div id="ancestor-not-visible-7" style="width: 0;"> | ||
<div id="not-visible-7" style="overflow: hidden;"></div> | ||
</div> | ||
<!-- ``overflow: hidden`` with zero height ancestor --> | ||
<div id="ancestor-not-visible-8" style="height: 0;"> | ||
<div id="not-visible-8" style="overflow: hidden;"></div> | ||
</div> | ||
<div id="not-visible-8-ancestor"> | ||
<div id="not-visible-8"></div> | ||
<!-- off-screen to the left of viewport --> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love how you've commented and inlined these! |
||
<div id="not-visible-9" class="off-screen" style="left: calc(-2 * var(--size));"></div> | ||
<!-- off-screen above viewport --> | ||
<div id="not-visible-10" class="off-screen" style="top: calc(-2 * var(--size));"></div> | ||
<!-- off-screen to the right of viewport --> | ||
<div id="not-visible-11" class="off-screen" style="right: calc(100vw + 2 * var(--size));"></div> | ||
<!-- off-screen below viewport --> | ||
<div id="not-visible-12" class="off-screen" style="bottom: calc(100vh + 2 * var(--size));"></div> | ||
<div id="not-visible-13" style="display: contents"></div> | ||
<!-- ``display: contents`` ancestor --> | ||
<div id="ancestor-visible-1" style="display: contents"> | ||
<div id="visible-1"></div> | ||
</div> | ||
<div id="not-visible-9" class="off-screen"></div> | ||
<div id="not-visible-10" class="off-screen"></div> | ||
<div id="not-visible-11" class="off-screen"></div> | ||
<div id="not-visible-12" class="off-screen"></div> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
const { assert } = require('chai'); | ||
const {assert} = require('chai'); | ||
const firefox = require('selenium-webdriver/firefox'); | ||
const webdriver = require('selenium-webdriver'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You never actually use |
||
const { ancestors, isDomElement, isVisible, toDomElement } = require('../../utilsForFrontend'); | ||
const {ancestors, isDomElement, isVisible, toDomElement} = require('../../utilsForFrontend'); | ||
|
||
const { until, By } = webdriver; | ||
const {Builder, until, By} = webdriver; | ||
|
||
const WAIT_MS = 10000; | ||
const TEST_PAGE_URL = 'http://localhost:8000/isVisible.html'; | ||
|
@@ -12,45 +12,46 @@ describe('isVisible', () => { | |
const options = new firefox.Options(); | ||
options.headless(); | ||
|
||
const driver = new webdriver.Builder() | ||
const driver = new Builder() | ||
.forBrowser('firefox') | ||
.setFirefoxOptions(options) | ||
.build(); | ||
|
||
it('Should return false when an element is hidden', async () => { | ||
const hiddenElementIds = [ | ||
'not-visible-1', | ||
'not-visible-2', | ||
'not-visible-3', | ||
'not-visible-4', | ||
'not-visible-5', | ||
'not-visible-6', | ||
'not-visible-7', | ||
'not-visible-8', | ||
'not-visible-9', | ||
'not-visible-10', | ||
'not-visible-11', | ||
'not-visible-12', | ||
]; | ||
async function checkVisibility(id, expected) { | ||
await driver.wait(until.elementLocated(By.id(id)), WAIT_MS); | ||
const isElementVisible = await driver.executeScript(` | ||
${ancestors} | ||
${isDomElement} | ||
${toDomElement} | ||
return ${isVisible}(document.getElementById('${id}')); | ||
`); | ||
assert.equal( | ||
isElementVisible, | ||
expected, | ||
`isVisible should return false for element with id '${id}'.` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am going to guess what you are saying here, since you have chosen not to use words... heh. This assertion is not executing inside the page like the Also, the first and second arguments into If I'm missing something, please let me know. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I failed to make myself clear! What I meant was that the error message assert.equal takes is assuming that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh; yes the error message if the check fails. Thanks for the catch. |
||
); | ||
} | ||
|
||
it('should return false when an element is hidden', async () => { | ||
const hiddenElementIds = await driver.executeScript(` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that's a nice piece of DRY. :-) The knowledge of how many hidden elements there is lives in only one place: the markup. |
||
return [].slice.call(document.querySelectorAll('[id^="not-visible-"]')).map((element) => element.id); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the Shorter still, you could do |
||
`); | ||
|
||
await driver.get(TEST_PAGE_URL); | ||
// await driver.wait(async () => { | ||
// const readyState = await driver.executeScript('return document.readyState'); | ||
// return readyState === 'complete'; | ||
// }, WAIT_MS, `Page did not finish loading after ${WAIT_MS} ms`); | ||
|
||
for (const id of hiddenElementIds) { | ||
await driver.wait(until.elementLocated(By.id(id)), WAIT_MS); | ||
const isElementVisible = await driver.executeScript(` | ||
${ancestors} | ||
${isDomElement} | ||
${toDomElement} | ||
return ${isVisible}(document.getElementById('${id}')); | ||
`); | ||
assert.equal( | ||
isElementVisible, | ||
false, | ||
`isVisible should return false for element with id '${id}'.` | ||
); | ||
await checkVisibility(id, false); | ||
} | ||
}).timeout(60000); | ||
|
||
it('should return true when an element is visible', async () => { | ||
const visibleElementIds = await driver.executeScript(` | ||
return [].slice.call(document.querySelectorAll('[id^="visible-"]')).map((element) => element.id); | ||
`); | ||
await driver.get(TEST_PAGE_URL); | ||
|
||
for (const id of visibleElementIds) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should even factor all this stuff up (the Array.prototype.... call, the for loop, and everything). It's nontrivial. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... not sure I'm following. Can you clarify? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I think I see what you are saying -- make a new function that each I couldn't factor out |
||
await checkVisibility(id, true); | ||
} | ||
}).timeout(60000); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Btw, I like that you gave isVisible.html and isVisible.js the same root names. That'll make it easier for Future People to untangle that they go together. |
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about calling these "browser" instead of "functional"? I could see us doing unit-style testing of routines that happen to need to run in the browser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the directory rename, the
isVisible
test now runs first in themocha --recursive
command. Not a problem, just an observation.