<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rafał Garbowski</title>
    <description>The latest articles on Forem by Rafał Garbowski (@rg9).</description>
    <link>https://forem.com/rg9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F939488%2F4c9402fb-8b8c-4637-b14c-5d0d443b2dee.jpg</url>
      <title>Forem: Rafał Garbowski</title>
      <link>https://forem.com/rg9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rg9"/>
    <language>en</language>
    <item>
      <title>AssertJ custom representation of asserted object</title>
      <dc:creator>Rafał Garbowski</dc:creator>
      <pubDate>Sat, 17 Jun 2023 10:13:38 +0000</pubDate>
      <link>https://forem.com/rg9/assertj-custom-representation-of-asserted-object-n2j</link>
      <guid>https://forem.com/rg9/assertj-custom-representation-of-asserted-object-n2j</guid>
      <description>&lt;p&gt;I really enjoy asserting collections with AssertJ.&lt;br&gt;
Usually it's safer and simpler to use &lt;code&gt;containsExactlyInAnyOrder&lt;/code&gt; rather than asserting individual elements (&lt;code&gt;collection.get(0)&lt;/code&gt;) - even if there is only one element, because it may change in the future.&lt;br&gt;
The challenge starts when asserting collection containing complex objects, because constructing an entire object as expected element can be tedious.&lt;br&gt;
To extract only certain properties, we can use &lt;code&gt;.extracting(Foo::field1, Foo::field2)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;players&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Player&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Michael Jordan"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Team&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bulls"&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Player&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kobe Bryant"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Team&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Lakers"&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;

        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extracting&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Player:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsExactly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Michael Jordan"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bulls"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kobe Bryant"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Lakers"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, I tend to concatenate properties to string because I wasn't fond of working with tuples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extracting&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" | "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containsExactly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Michael Jordan | Bulls"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Kobe Bryant | Lakers"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason is that, by default, AssertJ provides a generic "tuple" representation in the "actual" section.&lt;br&gt;
When copied, this has to be manually adapted to Java code, which can be inconvenient.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expecting actual:
  [("Michael Jordan", "Bulls"),
    ("Kobe Bryant" "Lakers")]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I want is an "easy-to-copy" representation of the asserted object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expecting actual:
  [tuple("Michael Jordan", "Bulls"),
    tuple("Kobe Bryant" "Lakers")]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately, there's an easy way to globally fix this in 3 simple steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a custom representation:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomAssertJRepresentation&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;StandardRepresentation&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CustomAssertJRepresentation&lt;/span&gt; &lt;span class="no"&gt;INSTANCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomAssertJRepresentation&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toStringOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"tuple"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toStringOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Then add it to the global configuration:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomAssertJConfiguration&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Representation&lt;/span&gt; &lt;span class="nf"&gt;representation&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CustomAssertJRepresentation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"CustomAssertJConfiguration applied"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Lastly, register the global config in this file:
&lt;code&gt;/src/test/resources/META-INF/services/org.assertj.core.configuration.Configuration&lt;/code&gt;
which will contain:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my.package.CustomAssertJConfiguration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer to the official documentation for more information: &lt;a href="https://assertj.github.io/doc/#assertj-core-representation" rel="noopener noreferrer"&gt;https://assertj.github.io/doc/#assertj-core-representation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>assertj</category>
      <category>java</category>
      <category>dx</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Introducing safe-eyes-cli: strict break reminder based on YAD</title>
      <dc:creator>Rafał Garbowski</dc:creator>
      <pubDate>Sat, 08 Apr 2023 16:33:07 +0000</pubDate>
      <link>https://forem.com/rg9/introducing-safe-eyes-cli-protect-your-eyes-while-coding-on-linux-40b6</link>
      <guid>https://forem.com/rg9/introducing-safe-eyes-cli-protect-your-eyes-while-coding-on-linux-40b6</guid>
      <description>&lt;p&gt;I'm excited to share with you a new tool that I've been using to help protect my eyes while working on my computer. It's called &lt;code&gt;safe-eyes-cli&lt;/code&gt; and it's inspired by the popular Safe Eyes application.&lt;/p&gt;

&lt;p&gt;It's a "strict" break reminder based on &lt;a href="https://github.com/v1cont/yad" rel="noopener noreferrer"&gt;YAD&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A "strict break reminder program" is a software application designed to remind users to take regular breaks from their computer work. It enforces strict rules for breaks, such as locking the screen, displaying full-screen reminders, or disabling input devices during the break period. This ensures that users take breaks and rest their eyes, helping to prevent eye strain, repetitive stress injuries, and promoting overall wellbeing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The tool is &lt;strong&gt;customizable&lt;/strong&gt;, allowing to set the frequency and duration of breaks.&lt;/p&gt;

&lt;p&gt;One of the great things about &lt;code&gt;safe-eyes-cli&lt;/code&gt;  is &lt;strong&gt;simplicity&lt;/strong&gt;. It's a shell script, that anyone can easily modify and adapt for special needs. Another killer feature is that it can &lt;strong&gt;automatically pause during calls&lt;/strong&gt;, so you don't have to worry about interruptions while you're on an important call.&lt;/p&gt;

&lt;p&gt;If you're interested in trying out &lt;code&gt;safe-eyes-cli&lt;/code&gt; for yourself, you can find it on GitHub at &lt;a href="https://github.com/RG9/safe-eyes-cli" rel="noopener noreferrer"&gt;https://github.com/RG9/safe-eyes-cli&lt;/a&gt;. The installation instructions are straightforward and easy to follow.&lt;/p&gt;

&lt;p&gt;Let me know if you have any questions or feedback!&lt;/p&gt;

</description>
      <category>breakreminder</category>
      <category>eyeshealth</category>
      <category>linux</category>
      <category>bash</category>
    </item>
    <item>
      <title>Three ways to configure HTTP Proxy in Playwright</title>
      <dc:creator>Rafał Garbowski</dc:creator>
      <pubDate>Thu, 23 Mar 2023 23:26:40 +0000</pubDate>
      <link>https://forem.com/rg9/three-ways-to-configure-http-proxy-in-playwright-23n</link>
      <guid>https://forem.com/rg9/three-ways-to-configure-http-proxy-in-playwright-23n</guid>
      <description>&lt;p&gt;TL;DR&lt;/p&gt;

&lt;p&gt;In fact, in Playwright &lt;code&gt;v.1.31.1&lt;/code&gt; there are &lt;strong&gt;three&lt;/strong&gt; ways to configure an HTTP proxy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;chromium.launch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;browser.newContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;page.setExtraHTTPHeaders&lt;/code&gt;, but works only on Firefox&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Today I was struggling with proxy setup for Browserless ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.browserless.io/docs/using-a-proxy" rel="noopener noreferrer"&gt;Official docs&lt;/a&gt; says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Both browserless, and Chrome itself, support the usage of external proxies. In order to fully utilize a 3rd-party proxy you'll need to do two things:
&lt;span class="p"&gt;
-&lt;/span&gt;   Specify the address of where the proxy is with the &lt;span class="sb"&gt;`--proxy-server`&lt;/span&gt; switch.
&lt;span class="p"&gt;-&lt;/span&gt;   Optionally, you'll also need to send in your username and password if the proxy is authenticated.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so I need to set &lt;code&gt;--proxy-server&lt;/code&gt;. I was using a Docker image to run Browserless locally. I discovered that there is an environment variable called &lt;code&gt;PROXY_URL&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;podman run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"PROXY_URL=my-proxy-url"&lt;/span&gt; browserless/chrome:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fine, but how do I pass on the username and password?&lt;br&gt;
Docs say there are two methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Using username and password&lt;/span&gt;
&lt;span class="gu"&gt;### Method 1: page.authenticate&lt;/span&gt;
&lt;span class="gu"&gt;### Method 2: page.setExtraHTTPHeaders&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using &lt;code&gt;playwright-java&lt;/code&gt; and there is no method &lt;code&gt;page.authenticate&lt;/code&gt;, so &lt;code&gt;page.setExtraHTTPHeaders&lt;/code&gt; left, I thought.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setExtraHTTPHeaders&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Proxy-Authorization"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Basic "&lt;/span&gt;  
   &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEncoder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;encode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username:password"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;()))));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, it does not work. I received the following strange error: &lt;code&gt;net::ERR_INVALID_ARGUMENT&lt;/code&gt;. Besides there was no errors in container's logs. What's the hack?&lt;/p&gt;

&lt;p&gt;Google's top two results for &lt;code&gt;playwright Proxy-Authorization&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/67478486/how-do-i-authenticate-a-proxy-in-playwright" rel="noopener noreferrer"&gt;node.js - How do I authenticate a proxy in playwright - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/playwright-python/issues/443" rel="noopener noreferrer"&gt;Proxy-Authorization header not working in Chromium · Issue #443 · microsoft/playwright-python · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I quickly checked the first link. The answer says that there are &lt;strong&gt;two&lt;/strong&gt; ways. I didn't read further, because I thought that I know these ways - one is method I'm struggling with and second &lt;code&gt;chromium.launch&lt;/code&gt;, right? :) &lt;em&gt;Later it turned out that I was wrong!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The second link looks like what I need. However issue was closed without any conclusion. The alternative shown, was one that I already knew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;playwright&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost:8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The case was that I didn't want to &lt;code&gt;lanuch&lt;/code&gt; browser, but rather &lt;code&gt;connect&lt;/code&gt; to one created inside container.&lt;/p&gt;

&lt;p&gt;I dug even deeper and found another similar issue in Playwright project:&lt;br&gt;
&lt;a href="https://github.com/microsoft/playwright/issues/11967" rel="noopener noreferrer"&gt;# [Feature] Directly set Proxy-Authorization in Chrome without configuring any other proxy settings&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The problem (in Chrome/Chromium anyway) is that &lt;code&gt;Proxy-Authorization&lt;/code&gt; may not be set explicitly via &lt;code&gt;extraHTTPHeaders&lt;/code&gt;. If you do this and then try to navigate to any page Chrome will give you the following error: &lt;code&gt;net::ERR_INVALID_ARGUMENT&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I was lost, considering changing my approach...&lt;/p&gt;

&lt;p&gt;Fortunately, my teammate assisted me by showing some examples of where I found a missing piece:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NewContextOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NewContextOptions&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;  
   &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProxy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Proxy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my-proxy-url"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setUsername&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;  
&lt;span class="nc"&gt;BrowserContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ta da! As simple as that! 😃&lt;/p&gt;

&lt;p&gt;I checked the &lt;a href="https://playwright.dev/docs/network#http-proxy" rel="noopener noreferrer"&gt;playwright docs&lt;/a&gt; and it appears to be possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Proxy can be either set globally for the entire browser, or for each browser context individually.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unluckily there is no example, so it's hard to spot.&lt;/p&gt;

&lt;p&gt;I also double-checked &lt;a href="https://stackoverflow.com/questions/67478486/how-do-i-authenticate-a-proxy-in-playwright" rel="noopener noreferrer"&gt;node.js - How do I authenticate a proxy in playwright - Stack Overflow&lt;/a&gt; and configuring proxy via &lt;code&gt;browser.newContext&lt;/code&gt; was actually there, but I missed it (confused by Browserless docs?):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;per-context&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://myproxy.com:3128&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Getting to the point: &lt;br&gt;
&lt;em&gt;Festina lente&lt;/em&gt; ("hurry slowly") and read comprehension!&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>browserless</category>
      <category>java</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>JUnit's @CsvSource.quoteCharacter</title>
      <dc:creator>Rafał Garbowski</dc:creator>
      <pubDate>Sat, 18 Feb 2023 16:40:14 +0000</pubDate>
      <link>https://forem.com/rg9/junits-csvsourcequotecharacter-4p0d</link>
      <guid>https://forem.com/rg9/junits-csvsourcequotecharacter-4p0d</guid>
      <description>&lt;p&gt;&lt;code&gt;@CsvSource&lt;/code&gt; used with &lt;strong&gt;text blocks&lt;/strong&gt; is really awesome! Similarly to &lt;a href="https://github.com/cronn/validation-file-assertions" rel="noopener noreferrer"&gt;validation files&lt;/a&gt;, it can be used to create easily readable tests with readily visible inputs and outputs placed side by side.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
    &lt;span class="nd"&gt;@CsvSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delimiterString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-&amp;gt;"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;textBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
        ABC -&amp;gt; abc
        Abc -&amp;gt; abc
        """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;toLowercase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What recently confused me was the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.junit.jupiter.api.extension.ParameterResolutionException:
No ParameterResolver registered for parameter [java.lang.String arg1] in method [void MyTest.test(java.lang.String,java.lang.String)].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It came out that it was caused by a parameter value starting with a single quote &lt;code&gt;'&lt;/code&gt;, that wasn't closed by another &lt;code&gt;'&lt;/code&gt; at the end of value. In my case the culprit was &lt;code&gt;'S-GRAVENHAGE&lt;/code&gt;, which is Belgian street name.&lt;/p&gt;

&lt;p&gt;The solution is to set parameter &lt;code&gt;quoteCharacter&lt;/code&gt; to double quote &lt;code&gt;"&lt;/code&gt;, provided we are using &lt;em&gt;text block&lt;/em&gt;. This way we can test empty string with &lt;code&gt;""&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@ParameterizedTest&lt;/span&gt;
    &lt;span class="nd"&gt;@CsvSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quoteCharacter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\"'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delimiterString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"-&amp;gt;"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;textBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
        'S-GRAVENHAGE -&amp;gt; 's-gravenhage
        "" -&amp;gt; ""
        """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;toLowercase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEqualTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope it was helpful, cheers!&lt;/p&gt;

</description>
      <category>junit</category>
      <category>java</category>
      <category>todayilearned</category>
    </item>
  </channel>
</rss>
