<?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: Benjamin Petetot</title>
    <description>The latest articles on DEV Community by Benjamin Petetot (@bpetetot).</description>
    <link>https://dev.to/bpetetot</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%2F192550%2F823bb6f8-8b3b-44a1-925f-d3a16a333cab.png</url>
      <title>DEV Community: Benjamin Petetot</title>
      <link>https://dev.to/bpetetot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bpetetot"/>
    <language>en</language>
    <item>
      <title>Build your own Codelab with Google Codelab</title>
      <dc:creator>Benjamin Petetot</dc:creator>
      <pubDate>Thu, 09 Jan 2020 16:54:19 +0000</pubDate>
      <link>https://dev.to/bpetetot/build-your-own-codelab-with-google-codelab-1hdi</link>
      <guid>https://dev.to/bpetetot/build-your-own-codelab-with-google-codelab-1hdi</guid>
      <description>&lt;p&gt;Codelabs and workshops are a great way to learn new technologies or languages, but it's time-consuming to write and structure. They are very useful as documentation so if you don't want to read this post further, you can follow &lt;a href="https://bpetetot.github.io/claat-image" rel="noopener noreferrer"&gt;the codelab&lt;/a&gt; 😉.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codelabs.developers.google.com" rel="noopener noreferrer"&gt;Google has a great platform&lt;/a&gt; providing guided tutorials about their products or technologies. &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%2Fce9tqdwtohb9e9xa2v0e.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%2Fce9tqdwtohb9e9xa2v0e.png" alt="Google Developer platform with over 500 codelabs"&gt;&lt;/a&gt;&lt;/p&gt;
Google Developer platform with over 500 codelabs




&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%2F7fk4z58h97evdb955en5.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%2F7fk4z58h97evdb955en5.png" alt="A codelab using codelab tool suite"&gt;&lt;/a&gt;&lt;/p&gt;
A codelab using google tool suite




&lt;p&gt;Thanks to their experience, they provide a suite of tools for authoring and serving codelabs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write a codelab
&lt;/h3&gt;

&lt;p&gt;There are two ways to write a codelab. Either directly in a Google Doc, where you can easily collaborate with multiple contributors, but you can't easily manage the source control. Either you can use a simple markdown file to write a complete codelab and push it in any git repository.&lt;/p&gt;

&lt;p&gt;So first, you need to create a simple Markdown file, it will contain all the codelab content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;id: id-of-the-codelab
summary: The codelab description
authors: Your name

&lt;span class="gh"&gt;# Here the main title of the codelab&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ------------------------ --&amp;gt;&lt;/span&gt;
&lt;span class="gu"&gt;## Step 1 heading here &lt;/span&gt;
Duration: 1

&lt;span class="gu"&gt;### Here a sub heading&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; How to foo.
&lt;span class="p"&gt;-&lt;/span&gt; How to bar.

&lt;span class="c"&gt;&amp;lt;!-- ------------------------ --&amp;gt;&lt;/span&gt;
&lt;span class="gu"&gt;## Step 2 heading here &lt;/span&gt;
Duration: 5

Lot of features are available, you can:
&lt;span class="p"&gt;-&lt;/span&gt; add code snippets
&lt;span class="p"&gt;-&lt;/span&gt; use hyperlinks
&lt;span class="p"&gt;-&lt;/span&gt; embed images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
A simple example of the Markdown syntax






&lt;p&gt;On the top of the file, some metadata describes the codelab (id, summary, category, authors, etc.). Markdown &lt;code&gt;heading&lt;/code&gt; levels define the codelab structure and the different steps. You can find a &lt;a href="https://github.com/googlecodelabs/tools/blob/master/FORMAT-GUIDE.md" rel="noopener noreferrer"&gt;complete Codelab Formatting Guide&lt;/a&gt; explaining the codelab structure with Markdown.&lt;/p&gt;

&lt;p&gt;Lot of features are available, you can use all the power of Markdown by adding code snippets, hyperlinks or images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build a codelab
&lt;/h3&gt;

&lt;p&gt;Google provides a CLI named &lt;a href="https://github.com/googlecodelabs/tools/tree/master/claat" rel="noopener noreferrer"&gt;claat tool&lt;/a&gt; (Codelabs as a Thing). It generates HTML files from a Markdown file or a Google doc. But it needs some prerequisites: &lt;code&gt;Go&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; have to be installed on your computer. To avoid this annoying install process, I made a &lt;a href="https://hub.docker.com/r/bpetetot/claat" rel="noopener noreferrer"&gt;light docker image&lt;/a&gt; to use claat.&lt;/p&gt;

&lt;p&gt;First pull the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker pull bpetetot/claat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then execute claat on your markdown file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker container run -it -v $(pwd):/app bpetetot/claat export my-codelab.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a full HTML static codelab, you can deploy it with your favorite hosting provider.&lt;/p&gt;

&lt;p&gt;When you are working on the codelab, you can serve it on localhost:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker container run -it -p 9090:9090 -v $(pwd):/app bpetetot/claat serve -addr 0.0.0.0:9090 my-codelab.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can create amazing codelabs and documentation. 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Here a simple example
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The markdown file:
&lt;a href="https://github.com/bpetetot/claat-image/blob/master/howto.md" rel="noopener noreferrer"&gt;https://github.com/bpetetot/claat-image/blob/master/howto.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The codelab online:
&lt;a href="https://bpetetot.github.io/claat-image" rel="noopener noreferrer"&gt;https://bpetetot.github.io/claat-image&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Some useful resources:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google codelabs tools on GitHub: &lt;a href="https://github.com/googlecodelabs/tools" rel="noopener noreferrer"&gt;https://github.com/googlecodelabs/tools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Formatting guide: &lt;a href="https://github.com/googlecodelabs/tools/blob/master/FORMAT-GUIDE.md" rel="noopener noreferrer"&gt;https://github.com/googlecodelabs/tools/blob/master/FORMAT-GUIDE.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Claat image on Docker Hub:
&lt;a href="https://hub.docker.com/r/bpetetot/claat" rel="noopener noreferrer"&gt;https://hub.docker.com/r/bpetetot/claat&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Claat image on GitHub:
&lt;a href="https://github.com/bpetetot/claat-image" rel="noopener noreferrer"&gt;https://github.com/bpetetot/claat-image&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Useful JS libs in my web developments</title>
      <dc:creator>Benjamin Petetot</dc:creator>
      <pubDate>Thu, 02 Jan 2020 18:26:23 +0000</pubDate>
      <link>https://dev.to/bpetetot/useful-js-libs-in-my-web-developments-1l61</link>
      <guid>https://dev.to/bpetetot/useful-js-libs-in-my-web-developments-1l61</guid>
      <description>&lt;p&gt;Useful JS libraries I'm using in my web projects, some are famous, some should be. None are framework oriented, you can use it with React, Angular, Vue, JQuery etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  lodash
&lt;/h3&gt;

&lt;p&gt;Always useful, &lt;strong&gt;&lt;a href="https://lodash.com"&gt;lodash&lt;/a&gt;&lt;/strong&gt; is a set of utilities to handle strings, iterables, collections, functions. Don't reinvent the wheel, you will find what you need in lodash. 2 things to keep in mind when you use it in a webapp.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't forget to import only the module you need. You don't want to import all lodash utilities in your final bundle.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lodash/fp&lt;/code&gt; module will you give the ability to use it in a functional programming style.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import only the debounce function from lodash/fp&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash/fp/debounce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;debounced&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// debounce the search function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  date-fns
&lt;/h3&gt;

&lt;p&gt;Like lodash, &lt;strong&gt;&lt;a href="https://date-fns.org"&gt;date-fns&lt;/a&gt;&lt;/strong&gt; has a bunch of functions but dedicated to handle dates. This is a great alternative to &lt;a href="https://momentjs.com"&gt;moment.js&lt;/a&gt; It uses the native Javascript &lt;code&gt;Date&lt;/code&gt; object and you can import only the modules you need. Formatting, parsing, operations... most of date use cases can be done with date-fns.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;formatRelative&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date-fns/formatRelative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;subDays&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date-fns/subDays&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;formatRelative&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;//=&amp;gt; "last Friday at 7:26 p.m."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/iamkun/dayjs"&gt;Day.js&lt;/a&gt;&lt;/strong&gt; is also a good alternative to moment.js. It is a minimalist lib (only 2KB) with almost the same complete API.&lt;/p&gt;

&lt;h3&gt;
  
  
  validator.js
&lt;/h3&gt;

&lt;p&gt;In web development, you always need to validate user's inputs. &lt;strong&gt;&lt;a href="https://github.com/validatorjs/validator.js"&gt;validator.js&lt;/a&gt;&lt;/strong&gt; contains all the validation functions you need: email, alpha, currency, credit cards, MAC address, etc. More than 60 validators!&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;isEmail&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;validator/lib/isEmail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo@bar.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  intl-messageformat
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/formatjs/formatjs/tree/master/packages/intl-messageformat"&gt;intl-messageformat&lt;/a&gt;&lt;/strong&gt; provides a way to manage and format your app's string messages into localized strings. It uses the &lt;a href="http://userguide.icu-project.org/formatparse/messages"&gt;ICU Message syntax&lt;/a&gt; and works for all &lt;a href="http://cldr.unicode.org"&gt;CLDR languages&lt;/a&gt; which have pluralization rules defined.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;IntlMessageFormat&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;intl-messageformat&lt;/span&gt;&lt;span class="dl"&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;photos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You have {numPhotos, plural,
    =0 {no photos.}
    =1 {one photo.}
    other {# photos.}
}`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&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;IntlMessageFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;numPhotos&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="c1"&gt;// =&amp;gt; "You have no photos."&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;numPhotos&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="c1"&gt;// =&amp;gt; "You have one photo."&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;numPhotos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; "You have 1,000 photos."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DOMPurify
&lt;/h3&gt;

&lt;p&gt;In some webapp, I needed to sanitize HTML string coming from the user or external sources. Most of libs I found were very heavy. &lt;a href="https://github.com/cure53/DOMPurify"&gt;DOMPurify&lt;/a&gt; is one of the lowest and fastest sanitizer. Very easy to use, you can also override its default configuration.&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;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;img src=x onerror=alert(1)//&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// becomes &amp;lt;img src="x"&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;svg&amp;gt;&amp;lt;g/onload=alert(2)//&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// becomes &amp;lt;svg&amp;gt;&amp;lt;g&amp;gt;&amp;lt;/g&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;p&amp;gt;abc&amp;lt;iframe/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;/src=jAva&amp;amp;Tab;script:alert(3)&amp;gt;def&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// becomes &amp;lt;p&amp;gt;abcdef&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;math&amp;gt;&amp;lt;mi//xlink:href="data:x,&amp;lt;script&amp;gt;alert(4)&amp;lt;/script&amp;gt;"&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// becomes &amp;lt;math&amp;gt;&amp;lt;mi&amp;gt;&amp;lt;/mi&amp;gt;&amp;lt;/math&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;TABLE&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;HELLO&amp;lt;/tr&amp;gt;&amp;lt;/TABL&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// becomes &amp;lt;table&amp;gt;&amp;lt;tbody&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;HELLO&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/tbody&amp;gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Feather icons
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://feathericons.com"&gt;Feather icons&lt;/a&gt; is just an awesome set of beautiful open source icons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UROkAT6A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zbrjarp212roq9zmkitz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UROkAT6A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/zbrjarp212roq9zmkitz.png" alt="Feather icons" width="880" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Faker.js
&lt;/h3&gt;

&lt;p&gt;You are tired to use lorem ipsum text or &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt;, &lt;code&gt;baz&lt;/code&gt; in your unit tests and mockups. So. You have to check &lt;strong&gt;&lt;a href="https://github.com/marak/Faker.js"&gt;faker.js&lt;/a&gt;&lt;/strong&gt;. It can generate addresses, company names, account numbers, phone numbers, images and so on. It supports multiple languages and locales. &lt;a href="https://rawgit.com/Marak/faker.js/master/examples/browser/index.html"&gt;Here a complete demo&lt;/a&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Rowan Nikolaus&lt;/span&gt;
&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Kassandra.Haley@erich.biz&lt;/span&gt;
&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createCard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// random contact card containing many properties&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;And you. Which lib do you use in your web projects?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Firebase callable functions tests with emulator suite</title>
      <dc:creator>Benjamin Petetot</dc:creator>
      <pubDate>Tue, 17 Dec 2019 13:12:02 +0000</pubDate>
      <link>https://dev.to/zenika/firebase-callable-functions-tests-with-emulator-suite-42ik</link>
      <guid>https://dev.to/zenika/firebase-callable-functions-tests-with-emulator-suite-42ik</guid>
      <description>&lt;p&gt;The Firebase emulator suite brings lot of new capabilities to test your Firebase code. In this article, I will experiment testing callable functions with jest and the Firestore emulator.&lt;/p&gt;

&lt;p&gt;Here is a short callable function incrementing a counter document:&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="c1"&gt;// increment.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions&lt;/span&gt;&lt;span class="dl"&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;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;counterId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// get the counter document&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&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;admin&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counters&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;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&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;counter&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;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// increment and save the new counter value&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counters&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;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;increment&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;To test the function with jest and the emulator we will need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute jest and the emulator&lt;/li&gt;
&lt;li&gt;Mock &lt;code&gt;firebase-functions&lt;/code&gt; and &lt;code&gt;firebase-admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write the test&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Execute the emulator with jest
&lt;/h3&gt;

&lt;p&gt;Following the &lt;a href="https://firebase.google.com/docs/firestore/security/test-rules-emulator"&gt;Firebase emulator documentation&lt;/a&gt;, you need to install the emulator with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase setup:emulators:firestore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, execute the emulator and the jest test suite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase emulators:exec &lt;span class="nt"&gt;--only&lt;/span&gt; firestore &lt;span class="s2"&gt;"jest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The emulator will start, then run the test suite, finally shut down the emulator after the tests run. You can add it as a test script in your &lt;code&gt;package.json&lt;/code&gt; file. If you want to run jest in watch mode, just set &lt;code&gt;"jest --watch"&lt;/code&gt; in the previous command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock &lt;code&gt;firebase-functions&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;For the test, we will directly execute the function, without using &lt;code&gt;firebase-functions&lt;/code&gt;. So let's create a simple mock to retrieve exported callable function. Add a file &lt;code&gt;firebase-functions.js&lt;/code&gt; in a &lt;code&gt;__mocks__&lt;/code&gt; folder:&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="c1"&gt;// __mocks__/firebase-functions.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onCall&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;func&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 mock will directly return the function given to &lt;code&gt;functions.https.onCall&lt;/code&gt;, so we will able to execute it directly within the tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock &lt;code&gt;firebase-admin&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;firebase-admin&lt;/code&gt; is used to get the Firebase &lt;code&gt;app&lt;/code&gt; instance. We will replace it by the &lt;code&gt;@firebase/testing&lt;/code&gt; app to be able to use the emulator. Add a file the &lt;code&gt;firebase-admin.js&lt;/code&gt; in the &lt;code&gt;__mocks__&lt;/code&gt; folder:&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="c1"&gt;// __mocks__/firebase-admin.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@firebase/testing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initializeAdminApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;projectId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now we are ready to write tests and we will be able to use Firestore emulator to store, retrieve and test data.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the tests
&lt;/h2&gt;

&lt;p&gt;Thanks to the mocks, the emulator and &lt;code&gt;@firebase/testing&lt;/code&gt;, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Directly execute your function.&lt;/li&gt;
&lt;li&gt;Create and retrieve documents in your test.&lt;/li&gt;
&lt;li&gt;Clear firestore database before each tests to get isolated tests.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// increment.spec.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@firebase/testing&lt;/span&gt;&lt;span class="dl"&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;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// use mocks&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./increment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Increment function&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;afterAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="c1"&gt;// close connexions to emulator&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="c1"&gt;// clear firestore data before each tests&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clearFirestoreData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;projectId&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;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 able to increment the given counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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="c1"&gt;// create a counter document&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counter1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counters&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;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;value&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="c1"&gt;// call the 'increment' function&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;counterId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// get the counter to test the incremented value&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedCounter&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;admin&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counters&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;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// check if we correctly get the counter document&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assertSucceeds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedCounter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// check the counter value&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&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;updatedCounter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;value&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;30&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;Here you can now test your cloud functions locally and in isolation using Firestore emulator. 🎉&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>firebase</category>
    </item>
    <item>
      <title>Understanding software licenses</title>
      <dc:creator>Benjamin Petetot</dc:creator>
      <pubDate>Tue, 10 Dec 2019 14:43:10 +0000</pubDate>
      <link>https://dev.to/zenika/understanding-software-licenses-1a0o</link>
      <guid>https://dev.to/zenika/understanding-software-licenses-1a0o</guid>
      <description>&lt;p&gt;As a developer or an open source project maintainer, it's essential to have knowledge of the different types of licenses. What are your rights and duties when you use them? Which license should you use for your project?&lt;/p&gt;

&lt;p&gt;There are several types of licenses available and each may have pros and cons that should be measured before choosing. You must remain vigilant, there may be confusion between different categories of "free" software (OSS, freeware, public domain ...). It exists dozens of free licenses, some of which are viral. This article is intended to help you understand the different features of licenses and choose the most suitable for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free Software &amp;amp; Open Source
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Free Software Foundation&lt;/strong&gt; (&lt;a href="//www.fsf.org"&gt;FSF&lt;/a&gt;), an American non-profit company founded in 1985 by R. Stallman, supports the GNU operating system and manages "GPL" licenses.&lt;/p&gt;

&lt;p&gt;This foundation gives a definition of free software based on four irrevocable freedoms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Freedom to use the software.&lt;/li&gt;
&lt;li&gt;Freedom to copy the software (includes the freedom to sell copies).&lt;/li&gt;
&lt;li&gt;Freedom to study the software (suppose access to the source code).&lt;/li&gt;
&lt;li&gt;Freedom to modify the software and redistribute the modified versions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Free license works are not always available for free and you will often paid for associated services (development, warranties, support, etc.). A work contaminated by a free license, which could initially be available only against payment, must be rebroadcast freely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« Think Free as Free speech and not Free beer »&lt;/p&gt;

&lt;p&gt;&lt;em&gt;R. Stallman&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the &lt;strong&gt;Open Source Initiative&lt;/strong&gt; (&lt;a href="http://opensource.org/"&gt;OSI&lt;/a&gt;), an American non-profit society founded in 1998 by E. Raymond &amp;amp; B. Perens, promotes open source code.&lt;/p&gt;

&lt;p&gt;According to OSI, for software to be open source, its license must meet the following 10 criterias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free redistribution.&lt;/li&gt;
&lt;li&gt;Provision of the source code.&lt;/li&gt;
&lt;li&gt;Allow derivative works and modifications.&lt;/li&gt;
&lt;li&gt;Integrity of the source code of the author.&lt;/li&gt;
&lt;li&gt;No discrimination between individuals or groups.&lt;/li&gt;
&lt;li&gt;No discrimination between the fields of application.&lt;/li&gt;
&lt;li&gt;No restriction on the distribution of the license (vs NDA).&lt;/li&gt;
&lt;li&gt;The license must not be specific to a product.&lt;/li&gt;
&lt;li&gt;The license must not restrict other software.&lt;/li&gt;
&lt;li&gt;The license must be technologically neutral.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Both terms describe virtually the same category of software. But they represent views based on fundamentally different values.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;R. Stallman&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;h2&gt;
  
  
  Copyright, copyleft and public domain
&lt;/h2&gt;

&lt;p&gt;Before presenting the different types of licenses available, it is necessary to understand the different types of rights applied to projects. Here is an explanation, in simple terms, of the 3 major license types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copyright&lt;/strong&gt; is a right granted to the author of the original work, including the right to authorize or prohibit the publication or distribution of their work. It protects authors from copying or unauthorized sale of their works. Copyright is granted for a limited period of time, then the work enters the public domain.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;public domain&lt;/strong&gt; includes all creations where no intellectual property rights is applied. These rights may be expired, confiscated, expressly waived or inapplicable. Copyright is generally valid until 50 to 100 years after the author's death. In simple terms, anyone can use, modify and sell these creations without permission from the author.&lt;/p&gt;

&lt;p&gt;For example, Beethoven's compositions entered the public domain 70 years after his death in 1827. His musical compositions are available for use and sale by all.&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;copyleft&lt;/strong&gt;, everyone can edit and distribute the work. It requires only one condition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the same freedom must be preserved in modified versions of the original work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;People can use, modify and distribute the work as they wish. However, copyleft requires modified work to be distributed on the basis of the same license.&lt;/p&gt;

&lt;p&gt;The GNU General Public License, originally written by Richard Stallman, was the first copyleft license.&lt;/p&gt;

&lt;h2&gt;
  
  
  What type of license to choose or use?
&lt;/h2&gt;

&lt;p&gt;A free software always has a license (contract) of use associated, it is necessary to analyze the conditions of use, the rights and the obligations resulting from it.&lt;/p&gt;

&lt;p&gt;To facilitate the understanding of the different types of licenses, we can classify them according to the degree of freedom they grant to the user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Strong Copyleft"&lt;/li&gt;
&lt;li&gt;"Low Copyleft"&lt;/li&gt;
&lt;li&gt;"Permissive"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Strong Copyleft
&lt;/h3&gt;

&lt;p&gt;A license with a strong copyleft has &lt;strong&gt;a highly contaminating character&lt;/strong&gt;. If a software component is under a copylefted license, the same license is imposed on all the software which contains this component. This is known as a "contaminating" or "viral" license. It forces to make available the associated source code and to distribute the entire program (free and proprietary) under the same license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some strong copyleft licenses:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPL: General Public License V3&lt;/li&gt;
&lt;li&gt;AGPL: Affero General Public License&lt;/li&gt;
&lt;li&gt;CC: Creative Commons declined in 6 licenses, some permissive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the case of the GPL license, there are some explicit use cases that do not trigger the phenomenon of contamination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either by exception clauses included in the license: For example, the &lt;a href="https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html"&gt;GCC Runtime&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Either in the case of independent binaries, ie your software uses a program with the GPL license, but does not distribute it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stack Overflow threads are also licensed. When you copy and paste a piece of code from the forum, it is important to know that all code snippets posted are under the CC Creative Commons license. 😱&lt;/p&gt;

&lt;h3&gt;
  
  
  Low Copyleft
&lt;/h3&gt;

&lt;p&gt;A license with a low copyleft, &lt;strong&gt;a weakly contaminating character&lt;/strong&gt;, forces to distribute the modified free software under the same license and to make available the associated source code. But you can freely use a component with a low copyleft in a proprietary software without constraining it to have the same licence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some low copyleft licenses:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LGPL: Lesser GPL&lt;/li&gt;
&lt;li&gt;EPL: Eclipse Public License&lt;/li&gt;
&lt;li&gt;MPL: Mozilla Public License&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here some software and librairies using LGPL license: VLC media player, 7-Zip, GLib, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive
&lt;/h3&gt;

&lt;p&gt;Permissive licenses offer the greatest freedom with unconditional sharing. In general, only the citation of the original authors is requested and allow any actor to change the license under which the software is distributed and without obligation of diffusion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some permissive licenses:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BSD: Berkeley Software Distribution&lt;/li&gt;
&lt;li&gt;MIT: Massachussetts Institute of Technology&lt;/li&gt;
&lt;li&gt;Apache2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Apache license is the second most popular license in the Free and open source domain after MIT license. If you want to open source your project, I recommend using Apache2 or MIT licence. &lt;/p&gt;

&lt;p&gt;There are also more esoteric permissive licenses. Like the &lt;a href="https://en.wikipedia.org/wiki/Postcardware"&gt;Postcard license&lt;/a&gt;, which only obligation is to send a postcard to the author. Or the &lt;a href="http://www.wtfpl.net/"&gt;WTFPL&lt;/a&gt; (Do What the Fuck You Want to Public License), the name speaks for itself. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As a developer, if you use libraries or software, do not forget to check their licenses because it can impact your software. As an open source project maintainer, choose your license properly to protect your work or its use. I hope this article help you to know more about different type and categories of licences. Finally I recommend you the website &lt;a href="https://choosealicense.com/"&gt;"Choose a license"&lt;/a&gt; to compare and choose your license according to your usage.&lt;/p&gt;

&lt;p&gt;If you want further news about our projects or future articles consider following our twitter &lt;a href="https://twitter.com/ZenikaOSS"&gt;@ZenikaOSS&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>license</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Getting started in open source</title>
      <dc:creator>Benjamin Petetot</dc:creator>
      <pubDate>Tue, 30 Jul 2019 12:48:29 +0000</pubDate>
      <link>https://dev.to/zenika/getting-started-in-open-source-2pf2</link>
      <guid>https://dev.to/zenika/getting-started-in-open-source-2pf2</guid>
      <description>&lt;p&gt;The world of open source is vast, it is very easy to get lost. When starting, this world can feel unaccessible and intimidating. Where to start? What are the rules and codes to follow? Can I contribute even if I do not code?&lt;br&gt;
No worries, in this article we will give you all the tips you need to start well, choose the right project and submit your first contribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  First steps 🐣
&lt;/h2&gt;

&lt;p&gt;First of all, you have to decide on which project you want to start your first contribution. Since there are millions of open source projects, it can be difficult to find one's way.&lt;/p&gt;

&lt;p&gt;A first idea, which is perhaps the simplest, is &lt;strong&gt;to identify projects that you like, that you often use or projects that mean a lot to you.&lt;/strong&gt; It will be easier to start in a familiar environment which will keep you motivated in the long term.&lt;/p&gt;

&lt;p&gt;It is also important to take into account the maturity of the project and its size. It is tempting to start with large frameworks, libraries or tools like VS Code, MongoDB, Android, React…. These kind of projects have many contributors, many bugs to fix or features to add. Contributions on these projects bring some satisfaction when they are merged. But these projects, with millions of lines of code, are not the best choice to get started in open source. Their communities are already well developed and many people are offering contributions for a limited number of maintainers. It can take a while before your contribution is studied and potentially accepted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Starting on smaller projects with potential is a better way to get started.&lt;/strong&gt; Keep an eye out for growing projects, on the &lt;a href="https://github.com/trending/javascript?since=monthly"&gt;GitHub trending&lt;/a&gt; for example,and find the ones that match your interests.&lt;/p&gt;

&lt;p&gt;Another good way to identify a suitable project is to &lt;strong&gt;select those which are actively looking for contributors.&lt;/strong&gt; Several websites and tools can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/MunGell/awesome-for-beginners"&gt;Awesome for beginners&lt;/a&gt; is a list of projects looking for contributors (beginners or not) by listing their &lt;em&gt;"Good First Issues"&lt;/em&gt;. In the same way, the website &lt;a href="https://up-for-grabs.net"&gt;Up for grabs&lt;/a&gt; makes it possible to find projects in need of contributors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.codetriage.com/"&gt;CodeTriage&lt;/a&gt; is a tool for subscribing to open source projects and receiving new requests for contributions every day.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://firstcontributions.github.io/"&gt;First contributions&lt;/a&gt; is a little different, it is a workshop to make your first contribution in less than five minutes. It introduces the basis of the Git workflow to make contributions on GitHub. In addition to this tutorial, the website offers links to &lt;em&gt;"Good First Issues"&lt;/em&gt; of large GitHub projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evenings or community events like &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;HacktoberFest&lt;/a&gt; are also a good way to get started on projects looking for contributors. For example, the &lt;a href="https://hack-commit-pu.sh/"&gt;hack.commit.push&lt;/a&gt; organizes an open source development day, open to everyone, regardless of your level. At the beginning of the day, introductory workshops are presented, followed by open source contributions with mentors.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have found your dream project(s), you will need to start reading up on these projects, The README is a good entry point for project overview. The Code of Conduct and the Contribution Guide are more focused on how to interact with the project and its community. It doesn’t take long, but it is mandatory before starting a contribution. It will give you the tips, rules and procedures you need to follow, allowing consistency and maintenance of the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code of conduct&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Most open source projects have a code of conduct.&lt;/strong&gt; It allows maintainers to define rules and behaviors to adopt on their project.&lt;/p&gt;

&lt;p&gt;The essential points of this code define the rules to be followed by the participants. Learn to respect different points of view, listen and accept feedback on your contributions. Potential disagreements are to be expected. Do not take them personally. Sometimes, during reviews, it is possible that individuals do not agree on some decisions or approaches taken. It is therefore very important to stay professional and respect the code of conduct. Any feedback is valuable and it is during these discussions that we learn the most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is also very important to be patient.&lt;/strong&gt; Many open source projects are maintained on personal time. It may take some time before your contribution is reviewed or accepted.&lt;/p&gt;

&lt;p&gt;Here is an example of a code of conduct used by many projects: &lt;a href="https://www.contributor-covenant.org/"&gt;&lt;em&gt;Contributor convenant&lt;/em&gt;&lt;/a&gt;. The rules it defines should be applied in both open source and professional environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The contribution guide&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It defines workflows and ways of coding on the project, it helps understanding the standards and expectations of the community. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to set up my development environment?&lt;/li&gt;
&lt;li&gt;How to post an issue?&lt;/li&gt;
&lt;li&gt;What are the commit standards?&lt;/li&gt;
&lt;li&gt;What are the expectations on the tests?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a contribution does not follow these recommended practices, it may be rejected before it has even been reviewed. These standards serve to maintain coherence in the project but also to save time for the project maintainers. So read it carefully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Join the community&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A project is not limited to documentation and source code. It is also important to understand and interact with the project community. There are different roles in an open source project, the three main ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The maintainers or core contributors, who are at the origin of the project or have been invited to this role thanks to all the contributions they have made.&lt;/li&gt;
&lt;li&gt;Contributors, who participate in the life of the project by offering contributions (documentation, bug fixes...), answering questions or opening user tickets.&lt;/li&gt;
&lt;li&gt;And users, who will of course use the project but mostly give feedback, post bugs, propose improvements or ask questions on forums.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The means of communication in the community vary based on the project. It can be a mailing list, a Slack, a Discord or any other tool of this kind. You will be able to ask questions, help defining roadmaps, or simply discussing amongst enthusiasts.&lt;/p&gt;

&lt;h2&gt;
  
  
  First contribution 🐥
&lt;/h2&gt;

&lt;p&gt;Now that you have identified a project that interests you and you have read the necessary documentation to get started, you are ready to offer your first contribution.&lt;/p&gt;

&lt;p&gt;Above all, you do not need to know how to code to contribute to open source projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do you like to write? Correct or develop the project’s documentation.&lt;/li&gt;
&lt;li&gt;Do you master design? Create the logo or project website.&lt;/li&gt;
&lt;li&gt;Do you like to communicate? Answer questions from the community.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All contributions are good and help the project. Here is a non-exhaustive list of tasks you can do to help open source projects:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documenting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write and correct the project’s documentation;&lt;/li&gt;
&lt;li&gt;Translate the documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Organizing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Submit bugs or new features;&lt;/li&gt;
&lt;li&gt;Answer issues, file them and close them if necessary;&lt;/li&gt;
&lt;li&gt;Answer questions (e.g. on GitHub, Stack Overflow...).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Communicating&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write articles or tutorials;&lt;/li&gt;
&lt;li&gt;Organize meetups or conferences about the project;&lt;/li&gt;
&lt;li&gt;Communicate on Twitter (new releases, contributions...);&lt;/li&gt;
&lt;li&gt;Create a design for the project (logo, colors...);&lt;/li&gt;
&lt;li&gt;Develop a website for the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Coding&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conduct code reviews;&lt;/li&gt;
&lt;li&gt;Develop tests;&lt;/li&gt;
&lt;li&gt;Automate the project (CI...);&lt;/li&gt;
&lt;li&gt;Fix bugs;&lt;/li&gt;
&lt;li&gt;Add new features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you do not know where to start, go through the list of open issues on the project. In many projects, some tickets are identified as &lt;em&gt;"Good First Issues"&lt;/em&gt; or &lt;em&gt;"Beginner"&lt;/em&gt;. They are identified by the main contributors as simple contributions and good entry points into the project. Also look out for &lt;em&gt;"Help needed/wanted"&lt;/em&gt; categorized tickets waiting for a contributor to assign themselves.&lt;/p&gt;

&lt;p&gt;When you have identified an issue or a ticket you wish to contribute to, you must position yourself on it. Do not hesitate to ask other contributors for information. Discussions and exchange are essential to properly start a new contribution. They will guide you towards the expectations of the community, validate a technical solution or identify potential constraints or difficulties.&lt;/p&gt;

&lt;p&gt;Before you publish your first contribution, check your code and do not forget to test it before submitting. Do not hesitate to explain the context and document your contribution. Anything that will help other contributors and maintainers to review it will speed up its integration.&lt;/p&gt;

&lt;p&gt;Finally, when you have made your first contribution, do not forget to communicate on it and share it with the world on Twitter, Facebook, or your favorite social network.&lt;/p&gt;

&lt;p&gt;If you want further news about our projects or future articles don't forget to follow our twitter &lt;a href="https://twitter.com/@ZenikaOSS"&gt;@ZenikaOSS&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Themify your app with Custom Properties</title>
      <dc:creator>Benjamin Petetot</dc:creator>
      <pubDate>Wed, 10 Jul 2019 13:41:24 +0000</pubDate>
      <link>https://dev.to/bpetetot/themify-your-app-with-custom-properties-2kke</link>
      <guid>https://dev.to/bpetetot/themify-your-app-with-custom-properties-2kke</guid>
      <description>&lt;p&gt;My current side-project is an open SaaS platform to manage call for papers called &lt;a href="https://github.com/bpetetot/conference-hall"&gt;Conference Hall&lt;/a&gt;. When I started it, I wanted to have different themes following the user's role. A blue theme if you are a speaker, and a red one for organizers.&lt;/p&gt;

&lt;p&gt;The application is currently built with React and there are plenty of ways to build a theming system using providers, hooks, styled components, css-in-js etc. But I wanted to keep it simple and closed to what it's supposed to be: "style". So I decided to use one of the new powers of CSS: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties"&gt;"Custom Properties"&lt;/a&gt; (or CSS variables) and its inheritance system. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here a &lt;a href="https://codepen.io/bpetetot/pen/bPzeJZ"&gt;live demo&lt;/a&gt; and explanations following.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Themify with custom properties
&lt;/h3&gt;

&lt;p&gt;First declare a default theme with all custom properties needed for the theme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.default-theme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#FFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--font-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&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;Set the default theme class to the &lt;code&gt;body&lt;/code&gt; (or an other root element). This element and its children will have access to the variables.&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;body&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"default-theme"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These variables can be used in your CSS through the &lt;code&gt;var()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--font-color&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;So, what should we do to change the theme of the app ?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Declare a new CSS class with the custom properties to override in the new theme, then apply it to the element. Thanks to the inheritance of custom properties you have the dark mode in your application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.dark-theme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--font-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#FFF&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 js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"default-theme dark-theme"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply theme to sub-components
&lt;/h3&gt;

&lt;p&gt;If you use the custom properties (&lt;code&gt;var()&lt;/code&gt;) in all your sub-compoments the theme will be automatically applied.&lt;/p&gt;

&lt;p&gt;But you may build your components independently from your application (with Storybook, DocZ, etc.) and the theming system implies that some of your components should use these custom properties. So if you want to have a component that renders correctly without declaring CSS variable, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pass the CSS variable through a color props to the component;&lt;/li&gt;
&lt;li&gt;Pass class or style with CSS variables to the component;&lt;/li&gt;
&lt;li&gt;Or use the CSS variable inside of it with a fallback value (2nd parameter of the &lt;code&gt;var&lt;/code&gt; function):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.my-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#DDD&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;h3&gt;
  
  
  Browser compatibility
&lt;/h3&gt;

&lt;p&gt;Most browsers already support custom properties except Internet Explorer. But if you want to keep a fallback for IE you can add an additional property in the CSS class. Of course, theme switching will not work on IE with custom properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.my-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#DDD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="n"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#DDD&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;All the theming system of my application &lt;a href="https://github.com/bpetetot/conference-hall"&gt;Conference Hall&lt;/a&gt; is entirely based on custom properties and works very well. I hope it will help you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See the live demo in codepen:&lt;/strong&gt;&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/bpetetot/embed/bPzeJZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>webdev</category>
      <category>react</category>
    </item>
  </channel>
</rss>
