<?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>DEV Community: Dani Meier</title>
    <description>The latest articles on DEV Community by Dani Meier (@flyingdot).</description>
    <link>https://dev.to/flyingdot</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%2F138516%2Ff3924075-f919-448b-a04d-90bb0b3f0a5d.jpeg</url>
      <title>DEV Community: Dani Meier</title>
      <link>https://dev.to/flyingdot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flyingdot"/>
    <language>en</language>
    <item>
      <title>How we enable our developers to attend conferences</title>
      <dc:creator>Dani Meier</dc:creator>
      <pubDate>Tue, 06 Apr 2021 10:46:13 +0000</pubDate>
      <link>https://dev.to/snapbean/how-we-enable-our-developers-to-attend-conferences-2gke</link>
      <guid>https://dev.to/snapbean/how-we-enable-our-developers-to-attend-conferences-2gke</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@austindistel"&gt;Austin Distel&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/rxpThOwuVgE"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I love conferences. It's a wonderful thing to attend one. To spend a couple of days with some buddies, meet new people, learn something new, be nerdy, and get inspired.&lt;/p&gt;

&lt;p&gt;Unfortunately, in my experience, attending conferences always led to discussions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Devs want to attend them because they get energized and inspired about it. They want to hear about the latest shit in their tech stack.&lt;/li&gt;
&lt;li&gt;Bosses think their devs are only looking for a good time (what is bad about that anyway?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I am a developer - with all my heart. I am also the owner of a small Software Shop, so I'm also kind of a boss. Most discussions about conferences arise because they are misunderstood and create false expectations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A conference is not training&lt;/strong&gt;. You will learn something for sure. But much more you will learn about new ideas, new ways of thinking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most of what you see and learn at a conference is not directly applicable to your job&lt;/strong&gt;, at least not immediately and without any effort. But it will inspire you. It will make you even more open-minded. You will profit from it in the long run, and so will your employer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's not a waste of money to send more than one person to the same conference.&lt;/strong&gt; There's no value in it to give your co-workers a summary of all the sessions you've attended. Because they lack the whole around, it's perfectly ok, to sit in the same session as your co-workers do or to enjoy a beer after the conference with them. Even better, you can exchange ideas, and maybe you can find some opportunities to introduce some of the topics to your daily work!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attending a conference is fun&lt;/strong&gt;. But it's also hard work. I cannot tell you how exhausted you are after a full day at the conference venue: so many people, so many impressions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bottom line, we should lower the expectations we have on conferences. It's about having a good time and getting different perspectives.&lt;/p&gt;

&lt;p&gt;This article will show you how we handle conferences in a very self-organized way, and we are so happy about it!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Principles
&lt;/h2&gt;

&lt;p&gt;Of course, there are always strings attached - but only two here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there is a 💸-budget&lt;/li&gt;
&lt;li&gt;there is a ⌚️-budget&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond that, there was no framework. So we defined some principles that represented our values and ideas:&lt;/p&gt;

&lt;h3&gt;
  
  
  Every developer who wants to attend a conference should be able to do so at least once a year.
&lt;/h3&gt;

&lt;p&gt;Why? Because we love conferences and appreciate their value to our organization and our employees.&lt;/p&gt;

&lt;h3&gt;
  
  
  The whole process is fully transparent and predictable. No feelings or individual decisions are involved. It's just math.
&lt;/h3&gt;

&lt;p&gt;Why? Because it's not right otherwise.&lt;/p&gt;

&lt;p&gt;Individual recognitions are always tricky and tend to be unfair. Is employee A better than B, or is A just working on more visible and more thankful tasks? While it's a good thing to appreciate high performers' work, it's crucial to invest in average developers' motivation and inspiration. &lt;/p&gt;

&lt;h3&gt;
  
  
  Private participation is assumed.
&lt;/h3&gt;

&lt;p&gt;Why? We think attending a conference is a privilege. It is a privilege we want to make possible for those who see its value.&lt;/p&gt;

&lt;p&gt;How much should this be? Well, this depends on your concrete situation and budget. In our case, it's 10% of the financial costs and 50% of the time. But honestly, it's not so important. Just make sure not to exclude anyone. It should not be a question of money if someone can attend a conference or not. It's less about the amount and more about the involvement itself.&lt;/p&gt;

&lt;p&gt;Do you have enough budget to cover everything? Nice, but still, demand private participation and instead invest some of it in drinks and food after work.&lt;/p&gt;

&lt;h3&gt;
  
  
  The choice of the conference is up to the participant and doesn't get evaluated.
&lt;/h3&gt;

&lt;p&gt;Why? First and foremost, our employees participate in a conference to advance themselves. We encourage them and ourselves to think outside the box all the time. A conference is a superb opportunity to get in touch with technologies, people, and ideas outside your daily work. &lt;/p&gt;

&lt;p&gt;So is it ok to attend a React conference as an Angular developer? Of course! &lt;br&gt;
Is it ok to attend a conference about software testing for a project leader? Sure, have fun!&lt;br&gt;
Is it ok to join a florist convention as a Scrum Master? Well, I don't get it, and I'm interested in your thoughts about it. But I trust you. So if you think this is valuable for you as a member of our company, then we're good.  &lt;/p&gt;

&lt;p&gt;We are all grown up, and we trust each other every day to do the right thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modus Operandi
&lt;/h2&gt;

&lt;p&gt;It's always good to have some good-sounding principles defined. You can print them with lovely big letters and hang them on the wall. But the hard part is actually to live those principles. To recognize what works well and what does not work at all. To reflect whether our actions still correspond to our principles, our values.&lt;/p&gt;

&lt;p&gt;So let's be specific, this is how we are doing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everyone who wants to attend a conference enters its information, like price and duration, into a sheet until the end of January. It's excellent to apply to more than one conference, but one must prioritize each entry.&lt;/li&gt;
&lt;li&gt;At the end of January, there is always someone who can hardly wait to see the results. So this is the one who makes the calculation. There is no decision-making or evaluations involved.&lt;/li&gt;
&lt;li&gt;We check if we have enough budget to fulfill all the entries. If yes, we're good to go, and all applications get granted automatically.&lt;/li&gt;
&lt;li&gt;If the budget is not enough, we cut entries based on their priority. But we never cut the entries with the highest priority. Suppose the budget is then sufficient, all good. Otherwise, we distribute the amount (time and money) above budget over the remaining entries.&lt;/li&gt;
&lt;li&gt;After attending the conference, the attendees will create a short (internal) blogpost about their experience to overview the conference to their colleagues. For example, they highlight some sessions, convey the inspiring mood at the venue or rave about the excellent food. But they explicitly don't have to share the contents of the session. If it makes sense to do so, this will happen automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, there are some possible glitches and some rough edge cases - but it does not have to be bulletproof. It just has to work for us. &lt;/p&gt;

&lt;h2&gt;
  
  
  Is it working?
&lt;/h2&gt;

&lt;p&gt;Hell yeah! These conference visits are highlights each year. In these Covid times, we have chosen beautiful places to create our own conference locations for attending the virtual events.&lt;/p&gt;

&lt;p&gt;Are there discussions and glitches about the rules? They are rare - because we are in absolute agreement about them and share their ideas and values. Why? Because we defined them for ourselves. &lt;strong&gt;That's the power of self-organizing.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;And if it does not work well? We improve. &lt;strong&gt;That's the power of "inspect and adapt".&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm happy to read about your opinion and experiences in the comments.&lt;/p&gt;

</description>
      <category>conferences</category>
      <category>learning</category>
      <category>agile</category>
      <category>inspiration</category>
    </item>
    <item>
      <title>Configure Git for Work and Personal stuff</title>
      <dc:creator>Dani Meier</dc:creator>
      <pubDate>Fri, 06 Nov 2020 19:24:56 +0000</pubDate>
      <link>https://dev.to/flyingdot/configure-git-for-work-and-personal-stuff-434j</link>
      <guid>https://dev.to/flyingdot/configure-git-for-work-and-personal-stuff-434j</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@maddybakes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Maddy Baker&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/branch-wide?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are like me and work for different companies, have several side hustles and fun projects, you will probably have the same problem as I have:&lt;br&gt;
You want to use different configurations, like E-Mail Addresses, for those repositories.&lt;br&gt;
Of course, you can always apply a local configuration to each repository or even use some scripts or aliases to help you out. But again, if you are like me, you won’t be happy with it, because you will forget to apply it over and over again. &lt;/p&gt;
&lt;h2&gt;
  
  
  Conditional Configuration
&lt;/h2&gt;

&lt;p&gt;Git allows you to include external configuration-files based on conditions, like the current directory. With this in mind, the problem above is actually easily solvable. &lt;/p&gt;

&lt;p&gt;First use different base-directories for each “area”, like your different work-places and personal stuff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/me/
    dev-work-a/
    dev-work-b/
    dev-personal/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a .gitconfig-file for each of those areas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/me/
    .gitconfig (your main configuration)
    .gitconfig-work-a (specific configuration for work a)
    .gitconfig-work-b (specific configuration for work b)
    .gitconfig-personal (specific configuration for personal projects)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your main .gitconfig-File, instead of the actual values, you conditionally include the other files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitconfig
[includeIf "gitdir:~/dev-work-a/"]
    path = .gitconfig-work-a
[includeIf "gitdir:~/dev-work-b/"]
    path = .gitconfig-work-b
[includeIf "gitdir:~/dev-personal/"]
    path = .gitconfig-personal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and in the specific files, you just define the specific configuration values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitconfig-work-a
[user]
    name = Scooby Doo
    email = scooby@worka.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitconfig-work-b
[user]
    name = Scooby Doo, Food-Department
    email = scooby@workb.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitconfig-personal
[user]
    name = Scooby
    email = me@scoobydoo.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s basically it. So now, when you are for example in &lt;code&gt;~/dev-personal/bigbang-side-hustle&lt;/code&gt; Git will get your user-configuration from &lt;code&gt;.gitconfig-personal&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  One more thing
&lt;/h2&gt;

&lt;p&gt;Well, of course, you cannot use conditional configuration for user-configurations like name and e-mail only, it’s just a very common use case. But in fact, you can use it for whatever configuration you like.&lt;/p&gt;

&lt;p&gt;There are also two more conditions like &lt;code&gt;gitdir&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onbranch&lt;/code&gt; lets you apply configurations based on the branch you are on&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gitdir/i&lt;/code&gt; like &lt;code&gt;gitdir&lt;/code&gt;, but case-insensitive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's worth mentioning that this works on all platforms and is very &lt;a href="https://www.atlassian.com/git/tutorials/dotfiles"&gt;Dotfiles&lt;/a&gt;-friendly.&lt;br&gt;
Also see &lt;a href="https://git-scm.com/docs/git-config#_conditional_includes"&gt;documentation&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;Have fun!&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Data-driven Unit Tests with Jest</title>
      <dc:creator>Dani Meier</dc:creator>
      <pubDate>Mon, 09 Sep 2019 19:02:31 +0000</pubDate>
      <link>https://dev.to/flyingdot/data-driven-unit-tests-with-jest-26bh</link>
      <guid>https://dev.to/flyingdot/data-driven-unit-tests-with-jest-26bh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@markusspiske?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Markus Spiske&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/developer?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Data-driven Unit Tests are an easy and efficient way to run a test with a range of input data. That can be useful in situations like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testing against a broader range of values&lt;/li&gt;
&lt;li&gt;testing for null and undefined values&lt;/li&gt;
&lt;li&gt;testing against edge cases, e.g., for dates (beginning of the month, end of the month, …)&lt;/li&gt;
&lt;li&gt;or to tweak your unit test stats - because each input row counts as a separate test. Your manager will be impressed. 😉&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Simple sample
&lt;/h2&gt;

&lt;p&gt;Let’s define a simple test to check if a number is even:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should be even&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ✓ is even
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To check a series of numbers, we can use Jest’s &lt;code&gt;it.each&lt;/code&gt; (or &lt;code&gt;test.each&lt;/code&gt;, since &lt;code&gt;it&lt;/code&gt; is just an alias of &lt;code&gt;test&lt;/code&gt;). We pass the input data as an array, each item is then tested individually (&lt;code&gt;n&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should be even&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="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ should be even
✓ should be even
✓ should be even
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can use &lt;a href="https://jestjs.io/docs/en/api#testeachtable-name-fn-timeout"&gt;several predefined&lt;/a&gt; tokens to improve the name of the test, which makes it easier to locate a failing test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%i should be even&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="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ 2 should be even
✓ 4 should be even
✕ 5 should be even
✓ 6 should be even
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Multiple parameters
&lt;/h2&gt;

&lt;p&gt;You can pass multiple parameters to your test as well. In the next sample, we pass the expected value to the test as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;]])(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;can square %i to %s&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="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&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;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ can square 2 to 4
✓ can square 6 to 36
✓ can square 8 to 64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The input table is defined as an array of arrays. Each inner array is one row of the input table.&lt;/p&gt;

&lt;p&gt;I like tests to be well readable, understandable and clear in their intention. The focus should be on the actual test and not on the implementation. Jest provides a syntax that supports exactly that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="s2"&gt;`
      n     | expected
      &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;  | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;  | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;  | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
    `&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;can square $n to $expected&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="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&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;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ can square 1 to 1
✓ can square 2 to 4
✓ can square 4 to 16
✓ can square 12 to 144
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The input table now looks like an actual table. It is defined as a template string, in which the first row contains the variables names separated by a pipe &lt;code&gt;|&lt;/code&gt;. Each subsequent row is one combination of input data to run the test against, defined as a template literal expression.&lt;br&gt;
You can reference the variable names inside the test name with &lt;code&gt;$variable&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Run multiple tests
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;.each&lt;/code&gt; is also available for &lt;code&gt;describe&lt;/code&gt;-Blocks, which makes it easy to run multiple tests or even a whole test suite against a set of input data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="s2"&gt;`
    x     | y
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;  | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;  | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;With x=$x and y=$y&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x should be larger then y&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeGreaterThan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should x should by dividable by y without rest&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&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;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;With x=10 and y=2
    ✓ x should be larger then y
    ✓ should x should by dividable by y without rest
With x=9 and y=3
    ✓ x should be larger then y (1ms)
    ✓ should x should by dividable by y without rest
With x=8 and y=4
    ✓ x should be larger then y
    ✓ should x should by dividable by y without rest (1ms)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can even combine &lt;code&gt;describe.each&lt;/code&gt; and &lt;code&gt;it.each&lt;/code&gt;, but keep an eye on comprehensibility.&lt;/p&gt;

</description>
      <category>jest</category>
      <category>tdd</category>
      <category>unittests</category>
      <category>testautomation</category>
    </item>
    <item>
      <title>Angular and RxJS: How to actually avoid subscriptions</title>
      <dc:creator>Dani Meier</dc:creator>
      <pubDate>Mon, 08 Apr 2019 21:06:29 +0000</pubDate>
      <link>https://dev.to/flyingdot/angular-and-rxjs-how-to-actually-avoid-subscriptions-2bj9</link>
      <guid>https://dev.to/flyingdot/angular-and-rxjs-how-to-actually-avoid-subscriptions-2bj9</guid>
      <description>&lt;p&gt;We all know it - we &lt;a href="https://blog.angularindepth.com/angular-question-rxjs-subscribe-vs-async-pipe-in-component-templates-c956c8c0c794"&gt;shouldn’t subscribe to observables directly. Instead, we should use the async pipe&lt;/a&gt;. It all totally makes sense, but then we leave our comfy reading chair, sit at our desk again, start coding… and subscribing. There are situations that aren’t just that obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our example
&lt;/h2&gt;

&lt;p&gt;We’re displaying a list of customers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CustomerComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomerService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&lt;/span&gt;&lt;span class="p"&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;and in the template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let customer of customers | async"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ customer.name }}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, that was easy. No subscribe here, yay! Angular is handling the subscription for us with its async pipe.&lt;/p&gt;

&lt;p&gt;Ok now let’s move on. We want to add new customers to the list. So we introduce a little form-component and emit an event to our CustomerComponent when a new entry gets submitted. We save the new entry and after that, we’re reloading the whole list. Shouldn’t be that hard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;onCustomerCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&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;Ok, one subscribe, but that seems reasonable since we want to wait until the create-action completes. But mh… that’s not working because we’re replacing the reference on &lt;code&gt;customers&lt;/code&gt;. Ok, every problem can be fixed with a subject:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CustomerComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;customers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomerService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadCustomers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;onCustomerCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadCustomers&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;loadCustomers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;loadedCustomers&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadedCustomers&lt;/span&gt;&lt;span class="p"&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;This seems fine. But - we’re subscribing to the load action again, which is feeling wrong. And it is wrong. But in one thing we were right, we can fix it with a subject:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CustomerComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;refreshTrigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomerService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;onCustomerCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&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;Now we aren’t using the subject as the source. Instead, we are using it as a trigger to load the customer-data. Like this, we can use the same observable-instance as source and push new data in it, if a refresh gets triggered. And we still can rely on the async-pipe to manage our subscription.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Blue-Green deployment with Cloud Foundry</title>
      <dc:creator>Dani Meier</dc:creator>
      <pubDate>Fri, 29 Mar 2019 09:44:22 +0000</pubDate>
      <link>https://dev.to/flyingdot/blue-green-deployment-with-cloud-foundry-3mgf</link>
      <guid>https://dev.to/flyingdot/blue-green-deployment-with-cloud-foundry-3mgf</guid>
      <description>&lt;p&gt;You have a fully automated deployment process which gets automatically triggered by your commits. Downtime? No there’s not, just a few seconds when you replace your application. But that few seconds can be critically and let’s face it, how cool would it be to deploy without any downtime at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is blue-green deployment?
&lt;/h2&gt;

&lt;p&gt;Blue-green deployment is a straightforward way to achieve deployments without any downtime, especially in those fancy, cloudy times we’re living in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjgnkfmesucad1w05h9mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjgnkfmesucad1w05h9mz.png" title="Blue-green Deployment"&gt;&lt;/a&gt;&lt;br&gt;
In this example, the blue instance is productive now. You deploy your new application-instance (green) besides the actual running one, wait until it is up and running, execute some automated tests on it, and if everything is fine, switch the route to the new instance, and we’re done.&lt;/p&gt;

&lt;p&gt;I highly recommend &lt;a href="https://martinfowler.com/bliki/BlueGreenDeployment.html" rel="noopener noreferrer"&gt;this article&lt;/a&gt; about Blue-Green Deployment by Martin Fowler.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step by step
&lt;/h2&gt;

&lt;p&gt;Ok, let’s do this step by step. We assume, there’s already one application-instance running (the blue one :-)). Let’s push our new fancy update out to the world:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cf login &lt;span class="nt"&gt;-a&lt;/span&gt; https://super.cloud &lt;span class="nt"&gt;-u&lt;/span&gt; me &lt;span class="nt"&gt;-p&lt;/span&gt; my-password
cf push myapp-green &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"myapp_publish"&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; http &lt;span class="nt"&gt;--endpoint&lt;/span&gt; /healthcheck &lt;span class="nt"&gt;--hostname&lt;/span&gt; &lt;span class="s2"&gt;"myapp-green"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important parts here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement a useful naming-scheme for the blue/green containers. The name shouldn’t be generated. It should be a predictable name, and it makes it much easier to work with it during your CI/CD pipeline.&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;-u http --endpoint /healthcheck&lt;/code&gt; we can tell Cloud Foundry how to check if our app is ready. The health check endpoint is part of your application so that you can define your logic in there (e.g. check if some initial jobs are done). There are more options to implement a health check, see the Cloud Foundry docs for more information.
So now our application is pushed and reachable through the “myapp-green”-route (as defined with the hostname-parameter), but it’s not yet productive, because you’re using the “green-route”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can execute some verifications against the green container:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute some Smoke Tests on UI and API Level&lt;/li&gt;
&lt;li&gt;Measure some performance KPI’s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything is ok, you’re ready to take the green container to production. Basically, we are just telling the CF Router to map the production route to the green-container now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# map the production route to the new green container&lt;/span&gt;
cf map-route myapp-green &lt;span class="nt"&gt;--hostname&lt;/span&gt; myapp
&lt;span class="c"&gt;# unmap the green route from the green container&lt;/span&gt;
cf unmap-route myapp-green &lt;span class="nt"&gt;--hostname&lt;/span&gt; myapp-green
&lt;span class="c"&gt;# unmap the production route from the original outdated container&lt;/span&gt;
cf unmap-route myapp &lt;span class="nt"&gt;--hostname&lt;/span&gt; myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last but not least, we’re doing some housekeeping. We rename the green-container to match our production naming convention and then clean up everything that is not needed anymore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cf rename myapp myapp-tmp
cf rename myapp-green myapp
cf delete myapp-tmp &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. The described scenario is relatively simple. Of course, we can think of far more complex ones, for example, we could run the (new) green and the old (blue) container in parallel and do some verifications in production, like check performance KPI’s, monitor logging-events, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  And what about user sessions?
&lt;/h2&gt;

&lt;p&gt;Of course, you cannot use InProc-Sessions in such a setup because you would just kill them by taking the production container down. You definitely should use a distributed solution to store user sessions, like Redis.&lt;/p&gt;

</description>
      <category>cloudfoundry</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Git Magic 1: Undo git amend</title>
      <dc:creator>Dani Meier</dc:creator>
      <pubDate>Mon, 04 Mar 2019 16:03:47 +0000</pubDate>
      <link>https://dev.to/flyingdot/git-magic-1-undo-git-amend-196g</link>
      <guid>https://dev.to/flyingdot/git-magic-1-undo-git-amend-196g</guid>
      <description>&lt;p&gt;Git allows you to build up your history in a way so that it has an actual value instead of just being a bunch of hashes with meaningless descriptions.&lt;/p&gt;

&lt;p&gt;One of the easier possibilities to keep your history clean is by using &lt;code&gt;git commit —amend&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;&lt;span class="nb"&gt;touch &lt;/span&gt;a.txt
git add a.txt
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'Add files'&lt;/span&gt;
git log
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 175ec0b 4 seconds ago Dani &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; Add files

&lt;span class="nb"&gt;touch &lt;/span&gt;b.txt
git add b.txt
git commit &lt;span class="nt"&gt;--amend&lt;/span&gt;
git log
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; d5538f2 48 seconds ago Dani &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; Add files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here we’re amending our previous commit with the added file. But, what if we made a mistake while changing our commit by adding stuff that shouldn’t be added or amended to the last commit?&lt;/p&gt;

&lt;h2&gt;
  
  
  Shadow world
&lt;/h2&gt;

&lt;p&gt;The hashes in the example above made very clear, that our &lt;code&gt;amend&lt;/code&gt; did not actually change the commit, instead it created a new one (175ec0b and d5538f2).&lt;br&gt;
You won’t lose anything in Git that you’ve committed once. So also the first commit from above (175ec0b).&lt;/p&gt;

&lt;p&gt;Our graph for the example now looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnghaae1gx1z2ndob6o70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnghaae1gx1z2ndob6o70.png" title="Git Graph" alt="Git Graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The commit 175ec0b is still around, but it is not reachable through the graph. With this information, it’s pretty easy and obvious how we can undo our amend.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset 175ec0b &lt;span class="nt"&gt;--soft&lt;/span&gt;
git status
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;...&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Untracked files:
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   b.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or without using the hash explicitly with offsets on the head pointer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="s1"&gt;'HEAD@{1}'&lt;/span&gt; &lt;span class="nt"&gt;--soft&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we’re resetting to one commit before the current HEAD. The changes are now unstaged again and you can commit them again.&lt;/p&gt;

&lt;p&gt;Of course, you can also use &lt;code&gt;git reflog&lt;/code&gt; to locate the commit.&lt;/p&gt;

&lt;p&gt;Now the graph looks the opposite:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3t0b148al82ty7s3fkf2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3t0b148al82ty7s3fkf2.png" title="Git Graph" alt="Git Graph"&gt;&lt;/a&gt;&lt;br&gt;
Again: the commit which was the result from the amend operation is still existing.  So the falsely amended commit is still present but orphaned.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
  </channel>
</rss>
