Learning Objectives: Week of May 25, 2020

Unit Testing With NUnit

There are three stages that happen when unit testing. Create a test that fails, make this test pass, and then refactor the code you have written. When working on an individual test it is important to remember to arrange, act, and then assert. This might look like setting up objects or mock data, doing something with those objects, and then asserting the return value from a function. With unit testing, you are breaking apart the requirements of your project into smaller pieces so that your code becomes more modularized.

I am viewing unit testing as a skill that can be used even when not testing your application. My recommendation is to focus on one feature or task at a time, write the code for that task, and then test the design. So often we lose our train of thought because we are switching between the logic and the representation of this logic. Add time to compile and we waste more time being distracted.

Jest

Jest is a testing framework created by Facebook, the same company that developed React. Out of the box with a “create-react-app” instance, Jest is available without having to install any dependencies. If you need to only test individual files be sure to install the global package through either Yarn or NPM.

The only problem I had was trying to get the toThrow() matcher to work with a function that clearly would throw a new error. I have not tested to see if this works with the Jest CLI outside of a new React application.

Github Actions

Today there are over 3,800 prescripted actions to choose from. You can now set up continuous integration with actions such as when a pull request is submitted or when a brach is pushed. If you can think of an automated action, you can probably find an action for it.

I recently build two continuous integration actions, one for deploying my app to Heroku and another for running my tests. All actions you create are executed with criteria. A criterion could trigger an action when a branch is pushed or when a pull request has been created. In my case, whenever I merge my changes from my develop branch into master my app will be deployed to Heroku. My other action will run any Jest tests when I push to develop.

IndexedDB

If you need to cache data that is greater than 5 – 10MB, indexedDB will run in your browser and is a great alternative method from localStorage. In my case, I needed to use IndexedDB for caching images for my Pokemon Go Pokedex companion app. The problem was when updating a pokemon, the image associated with the monster would load an image from an absolute URL. If the request for the image fails, the image for the Pokemon does not load. Instead, I wrote a script which will go through all of the Pokemon in my database, fetches an image, gets the images buffer byte array, converts the array into a base64 string, and then saves the string and type to my cloud Mongo database in a unique collection. The time to load an image was taken just as long when fetching from a database as it was from fetching from a URL.

This is where IndexedDB comes in handy because I needed a way to cache an image on subsequent visits. With IndexedDB I learned that the structure of saving data is different than rows saved in SQL. IndexedDB is a key value-based storage system which is similar to Redis. Below is a synopsis of what it takes to use IndexedDB, however you can also use the getting started guide.

  1. With IndexedDB you have to check for browser compatibility
  2. Open a new instance of a database and assign to a variable such as “request”
  3. Check if the “request” was successful and assign a variable to the result of the request
  4. Use the onupgradedneeded function to set up the structure of your database
  5. To read or write, open a new transaction with the type readwrite or readonly
    1. Set up a new object store and attach an action method: add({}), delete(id), etc
    2. Check that the object store transaction was successful or not using a callback method: onsuccess()or onerror()




Learning Objectives: Week of May 18, 2020

MongoDB

I was having issues connecting to my Atlas MongoDB server using the Git Bash prompt. The solution on Windows is switching to PowerShell. You can also check to see if your external IP is being restricted through the networking whitelist page.

You need to have a premium account with Atlas in order to use $and. If you need to combine two aggregation methods you can set two async methods to individual variables and then use prototype.Array.Concat to combine the two together. Below is an example of two aggregate functions I used for my Pokemon Pokedex application:

const milesRemaining = await pokeDex.aggregate([{ $match: {"milesRemaining": {$exists:true}}}, {$sort: {milesRemaining: 1}}]).exec();
const nonMilesRemaining = await pokeDex.aggregate([{ $match: {"milesRemaining": {$exists:false}}}, {$sort: {name: 1}}]).exec();
res.json([...milesRemaining, ...nonMilesRemaining]);

React & DataTables

There is a YouTube video that describes how you can include DataTables within a ReactApp.You can either follow along with the video or follow the below steps. React supports other libraries and there is even a helpful article that goes through the building blocks.

Your app can support other plugins from npm.js such as buttons, responsive design, and more. After you have assigned Jquery to your $ variable you would then require any additional plugins you need. Ex: require(‘datatables.net-responsive’)(window, $);

  • Install jquery and datatables.net from npm: npm i --save jquery datatables.net
  • Create a new table component
  • Include JQuery and DataTables using the following require statements
const $ = require(‘jquery’);
 $.DataTable = require(‘datatables.net’);
  • Return your dataset either using the built-in AJAX DataTables property or pass an array of objects to you child component from your parent component
  • Include a global reference to your table element using the ref attribute
<table className=”display” width=”1000% ref={el => this.el = el}
  • Create a new reference to your DOM table element
ComponentDidMount(){
    this.$el = $(this);
    this.$el.DataTable(
        { // set column information and other settings here }
    )
}
  • Destroy the table after using in your ComponentWillUnmount method:
this.$el.DataTable().destroy()

Zen Barcode Image With Text

After switching from BarcodeRender, I have found that creating a barcode with Zen Barcode is very straightforward apart from attaching the barcode text to the rendered image. Below is a basic outline of how to set this up in a C# project. You can use my sample static class to get started. 

  1. Assign a variable of type Code{barcodeType}Draw to the BarCodeDrawFactory class. 
  2. Create a new memory stream
  3. Draw the barcode
  4.  Set the max-width of the barcode and add padding for barcode bottom text
  5. Set up graphics, font, brush, and string format classes
  6. Set alignment of the text
  7. Draw the barcode text string to the image you drew earlier
  8. Save the image

C# Dictionaries

If you are quick to reuse a switch statement a better solution is to use a Dictionary. The dictionary is very straightforward and you can check if a value exists and if not return a default value.

DateRangeDescDict = new Dictionary<int, string>();
DateRangeDescDict.Add(0, "30 Days");
DateRangeDescDict.Add(1, "60 Days");
DateRangeDescDict.Add(2, "1 Year");
DateRangeDescDict.Add(3, "All");

public string DateRangeDescription(int selectVal){
    return (!DateRangeDescDict.ContainsKey(selectVal)) ? "30 Days" : 
        DateRangeDescDict[selectVal]; 
}

Learning Objectives: Week of May 11, 2020

NeedTree

Installed my first VIM plugin, NerdTree. I followed the instructions on Vim Awesome and placed the files in my vim82 folder. My only concern is that I have been using Chocolatey as my package manager, so if VIM gets updated to 8.3+ I am concerned about the possibility of losing any plugins which reside in the vim installation folder.

Update: I added vim-plug a plugin manager for Vim. I also updated my _vimrc file with a line for NERDTree. I then opened a new Vim editor and typed :PlugInstall which went ahead with the installation. I also added my Windows config file to GitHub for later reference. 

I’ve discovered that out of the box, the plugin isn’t very intuitive. Without mouse support, I learned quickly the importance of reading up on the documentation. For example, I didn’t know how to focus on the tree panel using :NERDTreeFocus.

Update: if you use `ctrl+w’ twice it will move your cursor to a different window. Also, the h key moves the cursor left, j down, k up, and l right.

Redux

Redux allows you to keep track of your React application component state in an easier way through the use of a parent object-store. You only change the global state when you call a reducer function that accepts an action (descriptive “why” string) and a state. This process makes it easier to manage and organize your applications’ state.

I had been working on a mapping app for my local church. The app has several components for filtering a map with form controls, page routing, and specific leaflet mapping components. There are several components that are similar to one another and a three-tier layered component tree. At times tracking parent and child state has been tedious. I am learning Redux so that I can more easily manage state and reduce developer time in the future. 

I went ahead and followed along with a YouTube tutorial video. Unfortunately, I ended up more confused than when I started. The most valuable asset I learned about was the ES7 React/Redux/GraphQL/React-Native snippets plugin for VS Code and the Redux DevTools for Google Chrome.

Blazor

You don’t have to create a new application in order to use Blazor. You can incorporate Blazor in an existing MVC app.

  1. Add Blazor services to startup.cs
  2. Create a new component
  3. Add Blazor JS file to razor view
  4. Attach the `html.RenderComponentAsyc` method to a HTML tag helper

Blazor shares a lot of commonalities with Web Forms in that there is a presentational code layer. If you have a variable you want to data bind to a form element, you would write the associated code in a razor file. You can, however, decouple the two by placing the associated code in a new file with the same file with the “.cs” extension name.

Clean Architecture With ASP.NET Core

Jason Taylor created a great video where he describes how to keep your projects simple with the use of a clean architecture template. You are not forced to use Angular or a specific database storage instance even though those are included out of the box. The template includes the following layers for organizing and simplifying your work:

  • The domain layer contains enterprise-wide logic and types
    • Entities, value objects, enumerations, logic, and exceptions
  • The application layer contains business logic and types
  • Infrastructure layer contains all external concerns
  • Presentation and Infrastructure layer only depends on the application layer

ES6

Learned about deconstructing arrays and object parameters. 

VIM

I completed the free VIM Adventures game and learned about b(move back a word), x(delete a character), w(move to the next word), and e(move to the end of either the current or next word in the sentence).

Below is a list of commands I learned about using vimtutor:

  • G: go to the end of the file
  • gg: go to the beginning of the file
  • 2G: go to line number 2
  • / + word + enter: search doc for word
    • n: search next word
    • N: search the previous word
  • dd: delete line
  • p: put a deleted line
  • d2w: delete two words
  • $: to end of line

Deno

One of the original authors of NodeJS was disappointed in the evolution of the Node.js runtime. He decided to create his own version, DenoJS, with several changes. Specific changes address security, dependencies, and typescript

 Deno now is a more secure version of NodeJS in that when running your apps, you need to pass flags to allow features such as HTTP and file access.

Out of the box, Deno no longer uses a node_modules folder and can easily run TypeScript files without the need for ‘ts-node”. Instead, dependencies have been decoupled, you can now pass in URL’s, hard drive paths, or GitHub links. 

I have discovered through trial and error that Deno does not work on non-64 bit operating systems. You are out of luck if you want to install this on a Raspberry Pi.

Learning Objectives: Week of May 4th, 2020

Linux Subsystem on Windows

I have been trying to find more ways to be a productive developer. There are several times where I want to run multiple scripts using PowerShell but I am not able to neatly organize my sessions in a single window. Currently, Windows does not support tabs or windows in CMD, PowerShell, or Bash unless you use TMUX in Cygwin, but the process runs slow. One could always use Visual Studio Code however, my learning objective is to learn more about VIM and limit my need to touch my mouse. I have also tried cmder, however, the prompt does not play well with VIM.

Installation was very simple. You allow access rights and then install a distro. Distros can be found in the Microsoft Windows Store. After you have the distro installed, you just need to run the application. After I had installed my distro, the first thing I learned was how to access my windows C drive. You can find your drive by letter in the “/mnt” directory. You can also direct your current working directory in windows by opening PowerShell from your file explorer window and typing wsl.

If you need to install NodeJS and NPM follow the installation instructions from Github and then install NPM using sudo apt-get install npm.

TMUX

After installing the Linux subsystem, I went to work learning about TMUX key bindings. I learned about managing windows, listing them, and creating new ones. I also learned about displaying a large clock, splitting panes horizontally and vertically, creating new sessions by name, renaming windows, and detaching from sessions. TMUX allows you to walk away from a terminal prompt while setting up jobs in the background.

ASP.NET Strongly-Typed Validation With Fluent Validation

You might want to create a new view model if you want to have different validation rules for the same property. You might be tempted to create a new view, and in turn, set up new controller and service methods. There is a better way! Welcome to fluentvalidation.net. Fluent Validation allows you to create strict validation rules. Have you ever wanted to use a “RequireIf” validation attribute or setup validation on complex objects? What about validation rules on a list of child objects? Setup is simple, you install the NuGet package, include in your middle-ware, set up a new validation class, and then instantiate the class in your Setup.cs file. Check out the documentation for more information.

JavaScript Regular Expression Cheat Sheet

I have taken the following descriptions of regular expressions from FreeCodeCamp.com. Below is a high-level overview of these expressions.

/expression/ = expression starts and ends with /. Flags are appended
/g = find expression globally
/i = ignore case (a or A)
string.method(expression) = common regex structure
.test() = return a boolean if the expression is true
.match() = returns value from match
.replace() = (regularExp, string)
[abc] = character list (looks for either a,b,or c)
[-] = range of characters (a-z, 0-9)
[^abc] = do not look for these characters
+ = character repeats one after another
* = character repeats 0 or more times
^ = outside set, search from beginning
$ = search end of string
\w = [A-Za-z0-9_] \W = negate
\d = [0-9] \D = negate
\s = \s\t\f\n\v (string, tab, form feed, new line)
{lower, upper} = # of occurences, range or exact match
? = 0 or more optional
Positive lookahead: Make sure element in search pattern is there but won’t match the pattern.
(?=...) = … (expression) required expression but not matched.
Negative lookahead: Make sure element in search patter is not there
(!=...) = …(expression) pattern you don’t want
() = find repeated substrings \# = number of matches

Web API’s You [Probably] Didn’t Know Existed Video Review

I had just graduated from high school in 2008 so I don’t really remember learning about the HTML 5 specification being a thing. When I was in college at Ivy Tech we learned HTML and CSS through the use of DreamWeaver. At that time web development was very bare bones. We would cut a PhotoShop comp using the slice tool into separate images and then place these images in a table based design. Yuck!

It wasn’t until my third year of college at IUPUI that I remember hearing about HTML 5 being released. Then, I saw HTML 5 as being very powerful especially with new support for canvas and video. Also, who couldn’t complain when you no longer had to include a specific doctype?

in 2011, Flash was very popular along with ActionScript. ActionScript was the first object-oriented programming language I had learned. In another class, I learned about different bit rates and how to create video profiles based on a users internet connection. At that time Flash was highly hated because of the lack of support from Apple. So HTML 5 felt like a move away from Flash. After college, I never touched ActionScript again.

Below is a list of features from the video I have never used before but that I find the most interesting:

  • See if a user has access to the internet using online state and show new results to a user when reconnected
  • Check the visibility of a page. Great for games and videos
  • Support for phone vibration which can be used for if a form is invalid
  • Ambient light allows you to change what happens to a page based on the light that enters a laptop camera ( only supported in Firefox). You could detect lighting on your mobile device to make reading easier.
  • Battery status for long forms and remaining time notifications

How To Fix VLC Frame Skipping

Always makes sure that you determine a video’s dimensions before playback. If the video is in 4k or higher than 1980×1080 your computer’s hardware will more than likely not have the acceleration to play the video without frame skipping. You can add the flag -vf scale=1920x1080 when using FFmpeg to fix this.

The 4K video playback with VLC has strict requirements on the computer’s processor and graphics chip. Sometimes, even if your computer meets the requirements, you may find that 4K video plays back choppy. This is due to the immense processing power required to play 4K.

PavTube.com

When converting your file to .ogv make sure that you use the correct video format settings.

If you omit -qscale:v (or the alias -q:v) then ffmpeg will use the default -b:v 200k which will most likely provide a poor quality output, and libtheora may drop/skip frames if the bitrate is too low.

FFMPEG

Visual Studio Code JavaScript IntelliSense with JSDoc

If you are having difficulty adding custom documentation to your JavaScript files in Visual Studio code the best solution is through the use of JSDoc. Unfortunately, there are a couple of changes that need to take place before the IntelliSense will begin to show up. When I first started to write comments in Visual Studio code I was using the existing format used for C# programming. These comments look like:

<summary>Description</summary>
<returns>Return info</returns>

Instead you can use jSDoc which has the following syntax sugar:

/**
* Description of your class, function, etc
* @param {type} param - description
* @param {type} param2 - description 2
* @returns {type} obj - description
*/ 

In my opinion, I like this format better than the use of XML comments because of each @tag is color decorated which stands out and helps with readability. The caveat of using this syntax is that you have to abandon your use of the require keyword but instead need to use import and export keywords such as familiar with Typescript.

Old Syntax: module.exports={} exports.funcName... and const funcName = require ('jsfile');
New Syntax: export class{...} or export {funcName} and import * as funcName from 'jsFile'

import is recognized as an ES6 feature which node will know nothing about. We will need to convert this syntax into the”require” keyword by installing Babel. Below are the following new packages that you should install to your dev dependencies. As a note, anything that is not required in order for the app to run should be in your dev dependencies.

  1. babel-cli
  2. babel-preset-es2015
  3. optional: watch

You will then need to add the es2015 present to a .babelrc file. Then you can set up a new script in package.json that will watch for any changes that happen and then use babel to recompile those modified files.

//.babelrc
{
     "presets": ["babel-preset-es2015"]
}

//package.json
"scripts": {
    "dev": "watch 'npm run build' src", //optional with watch
    "build": "babel src -d build"
}

Sitespeed.io Mac Installation Fix

  1. Make sure that npm is compatible with Node.js. If not uninstall using npm uninstall -g npm and then reinstall using the Node.js website selecting the most recent version.
    1. This is a common issue with installing Node.js with Homebrew
  2. If you are having problems with permission on global node_modules folder check permissions.
    1. See who owns the directory ls -la /usr/local/lib/
    2. return your current username: id -un
    3. Change the owner and group sudo chown -R [owner]:[owner] /usr/local/lib/node_modules
  3. Uninstall and reinstall sitepseed.io using sudo
    1. npm uninstall -g sitespeed.io
    2. sudo npm install -g sitespeed.io
  4. Test with sitespeed.io https://sitespeed.io in a home child directory
    1. Upgrade Chrome if problems with the driver