-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
Fixed datepicker positioning calculation #2337
base: main
Are you sure you want to change the base?
Conversation
See jquery#2057. This still needs merging.
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.
Thanks for the PR. We'll need tests for this change, though, as I indicated in the other PR. Have a look at existing test in https://github.com/jquery/jquery-ui/tree/main/tests/unit/datepicker to see how to write one.
@mgol these are unit tests. Can you please explain what about this change needs to be added or updated with unit tests? As for integration tests, which is actually the only way to add tests around this - does this lib even have those? And if so, can you please direct me to one as an example where you can test the visibility of the datepicker's location within a browser window? |
We only have unit tests. While I agree some tests would better work as integration ones, most of the changes can be tested via unit tests. I'd start with constructing a runnable example on a platform like JS Bin where the issue is obvious - this would be useful for people looking at the reasons for this patch in the future as well. Then we can think about a possible test case that would represent what we saw. If you don't have any idea for how the unit test would look like, start with a runnable example and maybe I'll be able to propose something. |
@mgol How are you going to write a unit test for something that's dynamically calculated based on a browser window's scroll position? |
Tests are run on real browsers, the HTML files used for tests are also defined by us. You can scroll programmatically as long as you make sure there’s enough content to have something to scroll even on large screens. |
The existing spinner.html template probably doesn't have too much to scroll, but you can always dynamically attach a div with a large size to If more invasive changes are needed, I added infrastructure for isolated iframe tests in #2342, but it might not be necessary here. |
Okay, I've added a test for the positioning with the more lazily calculated top position. The issue occurs in more complex positioning scenarios. I've added a test that creates a more complex positioning scenario to verify positioning. |
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.
Thanks for the updates. I added some comments. Please make sure lint & tests are passing for you locally before pushing changes. Right now, neither the lint nor the test you added is passing.
$container.css({ | ||
position: "static", | ||
top: 0, | ||
left: 0, | ||
height: "5000px", | ||
}); |
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 not change these; this is so that the fixture is not obscuring the test report view if not necessary. Also, I'm not sure if these styles are reset between runs.
If for some reason this has to be visible on the screen, please append another container to #qunit-fixture
and style it.
assert.expect( 4 ); | ||
|
||
var $container = $( "#qunit-fixture" ), | ||
$modal = $container.children('div'), |
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.
Make sure lint passes. Because it fails at the lint stage, it doesn't even run tests in half of the cases.
}); | ||
|
||
// Add an internal wrapper around all the children nodes | ||
$modal.wrapInner(`<div id="relative-wrapper" style="position: relative"></div>`) |
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.
ES6+ is not currently allowed; ESLint also catches that.
assert.expect( 4 ); | ||
|
||
var $container = $( "#qunit-fixture" ), | ||
$modal = $container.children('div'), |
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.
That's a bit fragile to depend on it always being a single div. If you need a reference to this element, can you maybe start from the inp
input and go to the parent?
// Wrap inputs with a container | ||
$inputOne.wrap(`<div id="input-one-container" style="height: 200px;"></div>`); | ||
$inputTwo.wrap(`<div id="input-two-container" style="height: 200px;"></div>`); |
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 is doing the wrapping after the widget is already initialized. I think we'd rather want to prepare the intended HTML structure before initializing the widget. If you modify the structure of an already running widget, various things may not work correctly and I don't think this issue requires any of that, does it?
Also, are all those modifications really needed? If it gets too heavy, it might be easier to write a separate iframe test where you can put all the style info in a style tag. But let's first verify why all those modifications are needed. Can you explain them all?
Plus, you're wrapping two different inputs with divs with the same ID; that's not compliant.
|
||
// Set the page scroll position way down the page | ||
var done = assert.async(); | ||
$(document).ready(function() { |
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.
It shouldn't be needed to wrap any code in a test in document ready.
assert.ok( $modal.is(":hidden"), "Modal is hidden" ); | ||
|
||
// Set the page scroll position way down the page | ||
var done = assert.async(); |
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.
If the test is async, please put this declaration at the top of the test, as in other tests.
// Disable the scrollbar | ||
$('body').css('overflow', 'hidden'); |
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.
Is this necessary? Why? All such code modifying global elements needs to be reset manually at the end of the test or it may affect other ones.
// Initialize datepickers | ||
$modal.find('input').datepicker(); | ||
|
||
setTimeout(() => { |
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.
Why is the setTimeout
needed, especially with such a long delay?
|
||
$inputTwo.focus(); | ||
assert.ok( $("#ui-datepicker-div").is(":visible"), "Datepicker is visible" ); | ||
done(); |
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 not call done before all the code is run, and we have some below.
@mgol thanks for the feedback on this. The reality here is that I am not familiar with qunit, or this lib's unique testing setup that comes with lots of pre-build assumptions. Nor is there any documentation on testing (linting, etc). The goal of the test is to create a scenario where the datepicker is initialized in a fixed position container, but with varying alterations to the DOM that affect it's calculated There appear to be a number of race conditions within tests as well, hence the timeout and I really don't have enough familiarity with all of this to generate a better test. I can clean this one up. But that's about it, and the time spent on this has already exceeded my goals by about 10x. |
See #2057. This still needs merging.