Awaitility
is, per their documentation, "a DSL that
allows you to express expectations of an asynchronous system in a
concise and easy-to-read manner." Today I learned that it polls for
the provided predicate in a separate thread, which caused quite a
silly behavior. Namely, when the higher-order function utilizing
Awaitility
was used twice in the same method, the
application would start freaking out since Selenium is quite
synchronous – operations often depend on the previous ones. The fix
was simple though: I went from
Awaitility.await().until(predicate)
to
Awaitility.pollInSameThread().await().until(predicate)
.
Caution should be advised not to block the thread with something like
.forever()
with an incorrect predicate, but otherwise
it's quite nifty and solved my problem.
Today I learned that in addition to exceptions, Java's error handling
constructs include, well, errors. Both of these subclass
Throwable
, but the latter usually indicates a critical
problem that we should not try to recover from. I found out about it
because my higher-order retry
function didn't work when
some Selenium assertion failed, and that's because its class
subclasses Error
, not Exception
, so my
generic catch (Exception exc)
didn't catch them. It's
usually a bad idea to do that anyway, but in my case it's needed to
work around some of Selenium's kinks, as well as the general
sluggishness of the modern front-end applications. You can find out
more about it on, who would have guessed,
Baeldung.
Today, while trying to make sense of cron expressions like
0 * * * * *
, I learned that in Spring, there are six
space-separated fields rather than five I've been familiar with from
the command-line utility. Seems straightforward in retrospect, but
being new to the framework, I didn't even know that Spring provides a
framework for scheduling tasks, so finding the documentation was quite
tricky at first. For details, see
Baeldung
(duh), and the official Javadocs for Spring:
click!
Today I learned about the CDP (Chrome DevTools Protocol) in Selenium.
While it's destined to be sunset by their new
BiDi functionality, it's still useful to know as that's not fully implemented yet.
Utilizing it allows us to intercept and transform the requests, set
cookies, log events, and generally programmatically perform actions
normally only doable from the DevTools. Unfortunately, since it's not
stable, and not really meant for test automation, it highly depends on
the underlying driver, and in modern Selenium versions, Firefox isn't
supported. See
the documentation
to learn more.
Today I learned how to set up Java's SLF4J with Log4j 2 as its
provider. This might be just my inexperience with the language and its
ecosystem, but the instructions on doing so seemed scattered in
different places. First, after trying to write some test logs, SLF4J
couldn't find a valid provider. Turns out that Gradle was pulling
log4j-slf4j-impl
targeting an older version of SLF4J,
while I needed log4j-slf4j2-impl
(note the extra
2
). This solved the warnings and compiled just fine, but
I couldn't see any logs. I found out that Log4j 2 doesn't have a
default configuration, so I needed to add a
log4j2.xml
file with some basic Appender
s
and Logger
s.
Today I learned about Java's enum types can have fields, methods and
constructors. This makes them more versatile than the enums I'm
familiar with from other languages, and unless I'm misunderstanding
something, it essentially means that they inherit from the
enum
they're defined in, letting us have custom
functionality per type. I've already found a use case for that at
work, and I'm sure more is to come! More about Java's enums at
Baeldung.
Today, while reading peetseater's
blag, I stumbled across a
link to a chapter in Robert Nystrom's "Game Programming Patterns" book
on the
Command
pattern. While I had a knee-jerk reaction at first due to how many
layers of abstraction it introduces, the examples made it clear when
it might be useful to compose the code in such a way. I've yet to make
any actual games that are bigger than a few hundred lines of code, but
I'm definitely gonna be getting back to that book and checking it out
when I embark on a more serious project.
Today I learned more about how cosmic rays impact technology, and how
modern systems protect against them. I knew about the Mario speedrun
that has likely been impacted by them, but not much more than that or
the physics behind the phenomenon.
Veritasium's video
shed a bunch of light on the topic for me, I highly recommend checking
it out.
Spotless (Java formatting library) messed with my line endings a
little, and so I had to figure out a way to renormalize them in Git.
The comprehensive way to do so seems to be as follows. Firstly, set
git config --global core.autocrlf input
. It might be
true
on Windows by default. Secondly, configure Git's
line endings to default to LF with
git config --global core.eol lf
. Lastly,
git add --update --renormalize
will normalize the line
endings in every file tracked by Git.
Today I learned about
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
which lets you easily create a responsive grid. This particular
example calculates how many 450px-wide columns can fit on your screen,
and adjusts the column count accordingly. See more on
MDN.
Today I learned about Java's Paths.get
that provides a
cross-platform utility to assemble Path
objects from
strings or URIs. The resulting interface contains many common methods
to work with file paths. See: documentation on
Paths.get
and
Path.