-
-
Notifications
You must be signed in to change notification settings - Fork 247
[tests] Selenium test for Preview configuration with keyboard #868 #955
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
[tests] Selenium test for Preview configuration with keyboard #868 #955
Conversation
Added a Selenium test case to replicate the process by creating a device, clicking its anchor tag, pressing ALT+P to open the preview, and pressing ESC to close it. Fixes openwisp#868
nemesifier
left a comment
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.
So far it's pretty good but I found some issues during testing.
I will push some changes shortly to address the shortcomings and show you how to better write these tests.
| lambda driver: driver.find_element( | ||
| By.CSS_SELECTOR, '.djnjc-overlay' | ||
| ).value_of_css_property('display') | ||
| == 'none' |
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.
This assertion is ineffective and passes always, even if the closePreview JS function is broken on purpose.
Lesson: always break the tested code on purpose to verify the test catches the failure.
| try: | ||
| WebDriverWait(self.web_driver, 2).until( | ||
| lambda driver: driver.find_element( | ||
| By.CSS_SELECTOR, '.djnjc-overlay' |
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.
Watch out! There's two .djnjc-overlay in the HTML page and in this code you were executing tests without ensuring you're running assertions on the right element!
| By.CSS_SELECTOR, '.djnjc-overlay' | |
| By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)' |
- Improved naming of test - Removed useless lines of code - Fail test explicitly with clear error message on Timeout exception instead of using assertTrue - Introduced subTest to separate phases for better readability
nemesifier
left a comment
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.
| self._create_config(device=self._create_device(name='Test')) | ||
| self.login() | ||
| self.open(reverse('admin:config_device_changelist')) | ||
|
|
||
| # open first device in the list | ||
| self.web_driver.find_element( | ||
| by=By.CSS_SELECTOR, value='tbody tr:nth-child(1) th a' | ||
| ).click() |
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.
This can be shortened by directly opening the device page.
| self._create_config(device=self._create_device(name='Test')) | |
| self.login() | |
| self.open(reverse('admin:config_device_changelist')) | |
| # open first device in the list | |
| self.web_driver.find_element( | |
| by=By.CSS_SELECTOR, value='tbody tr:nth-child(1) th a' | |
| ).click() | |
| device = self._create_config(device=self._create_device(name='Test')).device | |
| self.login() | |
| self.open(reverse('admin:config_device_change', args=[device.id])) |
pandafy
left a comment
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.
We can further improve the test to make it robust and efficient.
| try: | ||
| WebDriverWait(self.web_driver, 2).until( | ||
| EC.presence_of_element_located((By.CSS_SELECTOR, '#content-main')) | ||
| ) | ||
| except TimeoutException: | ||
| self.fail('Device detail page did not load in time') |
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.
The open method already uses WebDriverWait. We can just wrap it in a try-except block.
| WebDriverWait(self.web_driver, 2).until( | ||
| lambda driver: driver.find_element( | ||
| By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)' | ||
| ).value_of_css_property('display') | ||
| == 'none' | ||
| ) |
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.
Similarly, this can be changed to use EC.invisibility_of_element_located
| WebDriverWait(self.web_driver, 2).until( | |
| lambda driver: driver.find_element( | |
| By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)' | |
| ).value_of_css_property('display') | |
| == 'none' | |
| ) | |
| WebDriverWait(self.web_driver, 2).until( | |
| EC.invisibility_of_element_located( | |
| (By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)') | |
| ) | |
| ) |
| WebDriverWait(self.web_driver, 2).until( | ||
| lambda driver: driver.find_element( | ||
| By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)' | ||
| ).value_of_css_property('display') | ||
| != 'none' | ||
| ) |
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.
Let's use EC.visibility_of_element_located
| WebDriverWait(self.web_driver, 2).until( | |
| lambda driver: driver.find_element( | |
| By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)' | |
| ).value_of_css_property('display') | |
| != 'none' | |
| ) | |
| WebDriverWait(self.web_driver, 2).until( | |
| EC.visibility_of_element_located( | |
| (By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)') | |
| ) | |
| ) |
Refactored WebDriverWait usage to use built-in expected conditions. Fixes openwisp#868
| actions.key_down(Keys.ALT).send_keys('p').key_up(Keys.ALT).perform() | ||
| try: | ||
| WebDriverWait(self.web_driver, 2).until( | ||
| EC.invisibility_of_element_located( |
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.
Shouldn't this be as follows?
| EC.invisibility_of_element_located( | |
| EC.visibility_of_element_located( |
| actions = ActionChains(self.web_driver) | ||
| actions.key_down(Keys.ALT).send_keys('p').key_up(Keys.ALT).perform() | ||
| try: | ||
| WebDriverWait(self.web_driver, 2).until( |
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.
I guess we can change this to 1 as it's a fast operation.
| WebDriverWait(self.web_driver, 2).until( | |
| WebDriverWait(self.web_driver, 1).until( |
| actions = ActionChains(self.web_driver) | ||
| actions.send_keys(Keys.ESCAPE).perform() | ||
| try: | ||
| WebDriverWait(self.web_driver, 2).until( |
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.
| WebDriverWait(self.web_driver, 2).until( | |
| WebDriverWait(self.web_driver, 1).until( |
Manually removed ALT+P logic to ensure test fails with correct message. Fixes openwisp#868
nemesifier
left a comment
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.
LGTM 👍, thanks! 🙏
Added a Selenium test case to replicate the process by creating a device, clicking its anchor tag, pressing ALT+P to open the preview, and pressing ESC to close it.
Fixes #868
Checklist
Reference to Existing Issue
Closes #868
Description of Changes:
Alt + Pto open the preview configuration overlay.Escapeto close the overlay.