Skip to content

Conversation

@dee077
Copy link
Member

@dee077 dee077 commented Dec 24, 2024

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

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.

Reference to Existing Issue

Closes #868

Description of Changes:

  • Creates and saves a device configuration.
  • Navigate to the device detail page.
  • Simulates pressing Alt + P to open the preview configuration overlay.
  • Verifies that the overlay becomes visible.
  • Simulates pressing Escape to close the overlay.
  • Confirms that the overlay disappears.

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
@coveralls
Copy link

coveralls commented Dec 24, 2024

Coverage Status

coverage: 98.261%. remained the same
when pulling 28eee54 on dee077:issues/868-preview-keyboard-keys-selenium-test
into 98fd7b1 on openwisp:master.

Copy link
Member

@nemesifier nemesifier left a 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'
Copy link
Member

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'
Copy link
Member

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!

Suggested change
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
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dee077 please check my changes and read the commit description for an overview on the reasons of the changes: 937f2f2.

Comment on lines 136 to 143
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()
Copy link
Member

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.

Suggested change
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]))

Copy link
Member

@pandafy pandafy left a 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.

Comment on lines 144 to 149
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')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 168 to 173
WebDriverWait(self.web_driver, 2).until(
lambda driver: driver.find_element(
By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)'
).value_of_css_property('display')
== 'none'
)
Copy link
Member

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

Suggested change
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)')
)
)

Comment on lines 155 to 160
WebDriverWait(self.web_driver, 2).until(
lambda driver: driver.find_element(
By.CSS_SELECTOR, '.djnjc-overlay:not(.loading)'
).value_of_css_property('display')
!= 'none'
)
Copy link
Member

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

Suggested change
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(
Copy link
Member

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?

Suggested change
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(
Copy link
Member

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.

Suggested change
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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍, thanks! 🙏

@nemesifier nemesifier merged commit 211bebc into openwisp:master Jan 22, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug:ui] Preview keyboard keys do not work anymore

4 participants