<?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: Ray</title>
    <description>The latest articles on DEV Community by Ray (@fluentinstroll).</description>
    <link>https://dev.to/fluentinstroll</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%2F470474%2F6c777818-7d03-4b2d-aa06-369fb2b24878.jpg</url>
      <title>DEV Community: Ray</title>
      <link>https://dev.to/fluentinstroll</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fluentinstroll"/>
    <language>en</language>
    <item>
      <title>The Spring Workload and Auditing My Progress</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Wed, 12 May 2021 22:18:42 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/the-spring-workload-and-auditing-my-progress-791</link>
      <guid>https://dev.to/fluentinstroll/the-spring-workload-and-auditing-my-progress-791</guid>
      <description>&lt;h1&gt;
  
  
  Where Ya Been
&lt;/h1&gt;

&lt;p&gt;I planned to write a blog post at the end of February talking about how much I got done in the month - reading that post I laid out some pretty hefty goals for a single month. Especially while I was still working.&lt;/p&gt;

&lt;p&gt;However, at the time I was working maybe 16 hours a week? At the very least it was an amount that made me feel as if I could have multiple days off a week to work on projects.&lt;/p&gt;

&lt;p&gt;That didn't exactly go as planned. As one might be able to tell.&lt;/p&gt;

&lt;p&gt;The main purpose of this blog is to audit the amount of work I got done over the last 3 and a half months and plot a course for the next couple. It's not meant to be a big long document where I kick myself for not working hard enough because frankly, that's unhealthy. Plus I have good reasons for not getting any work done!&lt;/p&gt;

&lt;p&gt;These last few months have been... well not &lt;em&gt;stressful&lt;/em&gt;, but busy. Work picked up in a way that I did not expect as inventory and the spring seasonal came in full force over March and April. I was working between 30 and 40 hours a week at that time and I don't blame myself for not having worked on projects. Likewise, for the last half of April I tested positive for covid-19 which is not an illness that is easy to work on the computer with, I'll tell you.&lt;/p&gt;

&lt;p&gt;So fine, I don't think kicking myself for not getting that lengthy list of projects done is helpful so I won't do it. However, like I said previously, I &lt;em&gt;would&lt;/em&gt; like to take a look at that list and plan how I will get it finished soon and move on to the many other ideas in my head.&lt;/p&gt;

&lt;h1&gt;
  
  
  Goals 2
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Implement my second feature into RayAi
&lt;/h2&gt;

&lt;p&gt;This was not done for a reason I'll reveal in a bit, but as well, I didn't work on it because I haven't felt terribly inspired to work on it. I think at least 1 more feature is something I want to get done pronto but after that I think I'll put this one on the back burner for some new projects I have in mind. It's already on the back burner for... &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Move my personal website to a better url
&lt;/h2&gt;

&lt;p&gt;This one was simple in hindsight but annoying the way I did it. So I was recommended to a friend to use a VPS provided by a cheap and efficient provider. I thought this was a great idea at first, but I quickly realized setting it up was much more annoying than a slightly more expensive provider that made things easier. I fooled around with the VPS for a while and after deciding that I didn't want to be a server administrator and instead wanted to be a developer, I switched to a much simpler provider that allowed me to deploy my static site at &lt;a href="https://raymondrambo.ca/"&gt;https://raymondrambo.ca/&lt;/a&gt; overnight.&lt;/p&gt;

&lt;p&gt;So that's a win!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Start on a React project
&lt;/h2&gt;

&lt;p&gt;This one actually got done too! A family member has a small business and I offered to build them an e-commerce website from the ground up. I've run into a snag or two from learning more about React and I'm at the point in my development where I'm realizing I need to integrate the e-commerce elements from the start. But hopefully, I can finish this project up, since it feels like it's moving quickly, and move onto another React project.&lt;/p&gt;

&lt;h1&gt;
  
  
  So what's next?
&lt;/h1&gt;

&lt;p&gt;Well, I don't think I'll be making a big showing of it in this blog post, but I have a few goals that I would like to accomplish before I write another. &lt;/p&gt;

&lt;p&gt;The first is to finish up this e-commerce platform and put it under my belt. Having a project like this I feel will look really good and give a huge sense of satisfaction. Plus I can commission friends who have small businesses to build them something similar once I know how to do everything. :)&lt;/p&gt;

&lt;p&gt;The second is to finally get to work on that Discord bot again. I like developing this bot for Discord but it takes a lot of time and I don't usually have the patience for it. It's nice the see the fruits of your labour though. I have ideas.&lt;/p&gt;

&lt;p&gt;Finally, I would like to get started on a &lt;em&gt;NEW&lt;/em&gt; new project, probably in React, and as well as the Discord bot, I have some ideas.&lt;/p&gt;

&lt;p&gt;So these goals are in chronological order and if I get through the e-commerce platform and the Discord bot but don't start a new project, I'll be ok. But I absolutely would like to see these to fruition quickly. &lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>February Start to Finish</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Thu, 04 Feb 2021 20:00:43 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/february-start-to-finish-38m7</link>
      <guid>https://dev.to/fluentinstroll/february-start-to-finish-38m7</guid>
      <description>&lt;h1&gt;
  
  
  Housekeeping
&lt;/h1&gt;

&lt;p&gt;At the beginning of January, I wrote &lt;a href="https://dev.to/fluentinstroll/the-first-after-school-project-396b"&gt;The first After-School Project&lt;/a&gt; that focused on how I would build my personal website. I learned a lot about simple, static, website designs and I still intend to keep working on that site and learn more about web hosting so I can move off GitHub pages, at least for my newer projects that aren't static. However, I'd like to talk about something besides that - namely, my newest project, and what I plan to have finished by the end of February.&lt;/p&gt;

&lt;p&gt;We can easily ascertain the goal of most fledgling developers because it tends to be the goal of almost everyone in my position: find fulfilling, well-paying work in my field of choice. Namely: web development. To that end, I need to build up a portfolio of projects that I can show off as proof of my strong, unending deluge of programming skills.&lt;/p&gt;

&lt;p&gt;Ok ok ok, that's enough housekeeping, let's talk about my project.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Project
&lt;/h1&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F52toybkyqhz0q4osx15z.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F52toybkyqhz0q4osx15z.png" alt="februarystarttofinish_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is a Discord bot. It's not terribly removed from what I've worked on before since I also worked a little on &lt;a href="https://github.com/AardWolf/MHTimerBot" rel="noopener noreferrer"&gt;MHTimerBot&lt;/a&gt; adding a new feature and creating tests, as well as simple bug fixes.&lt;/p&gt;

&lt;p&gt;Currently, the bot has 1 2-in-1 feature.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqefra5tym1eo1u90kdy.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqefra5tym1eo1u90kdy.png" alt="februarystarttofinish_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now, you can type &lt;code&gt;ai nyaa&lt;/code&gt; and then a search keyword, and the bot will scour nyaa.si looking for hits that match your keyword. Then, you can react to the post and get a link to the download of the hit you're looking for.&lt;/p&gt;

&lt;p&gt;You can take a look at the project here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/fluentinstroll" rel="noopener noreferrer"&gt;
        fluentinstroll
      &lt;/a&gt; / &lt;a href="https://github.com/fluentinstroll/RayAi" rel="noopener noreferrer"&gt;
        RayAi
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Ray's Discord bot, meant to do whatever he finds to be needed - built in an entirely selfish way. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;RayAi&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Personal Discord Bot&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;RayAi is being built to facilitate whatever random things I want to have access to in a discord bot.&lt;/p&gt;
&lt;p&gt;Features included:&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;nyaa.si lookup:&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;type &lt;code&gt;ai nyaa &amp;lt;search string&amp;gt;&lt;/code&gt; to get the first 10 results of the nyaa.si search&lt;/li&gt;
&lt;li&gt;react to the search to get a torrent link to the cooresponding item&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/fluentinstroll/RayAi" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h1&gt;
  
  
  Goals
&lt;/h1&gt;

&lt;p&gt;What I'd like to do now that I've introduced my new project is lay out some goals that I'd like to achieve by the end of February.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Implement my second feature into RayAi
&lt;/h3&gt;

&lt;p&gt;Right now I have 1 real feature and I'd like to bump that up to 2 by the end of the month. My plan for the next feature is Monster Hunter related, I'd like to allow users to look up a monster or hunt, or something of the like and see possible drops or rewards. There can be a lot here and perhaps I can expand a command like this to multiple features but for now I'd like to stick to &lt;code&gt;lookup hunt/monster to see rewards/drops&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Move my personal website to a better url
&lt;/h3&gt;

&lt;p&gt;So for now I'm using fluentinstroll.github.io but that doesn't look great on an Indeed profile or a resume. To that end, I purchased a domain that better represents me and I plan to move my personal website to that.&lt;/p&gt;

&lt;p&gt;I don't really know how to do that yet but at some point this month and look into it and quickly get it done.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Start on a React project
&lt;/h3&gt;

&lt;p&gt;The next thing I want to do is learn more about how Reactjs works and how to build React apps. I have a couple of ideas for this but I'll keep them to myself for now. The goal for this is not to finish something substantial but to start something substantial that will have potential and will show off my abilities well.&lt;/p&gt;

&lt;p&gt;Even if I get into March with a &lt;em&gt;started&lt;/em&gt; project but not a full realized one, I'll consider this a success but I still intend on doing as much work on it as I can and hopefully can have a 0.1.0 release finished in time for March.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Refactor the RayAi code
&lt;/h3&gt;

&lt;p&gt;Right now RayAi is a learning experience that I've learned a lot from but it's not necessarily a great example of stellar code. I think I need to refactor my current code, maybe even before working on the new feature, so that I can outline good practices for going forward.&lt;/p&gt;

&lt;p&gt;A 4.1 for this might be to add a linter and code formatter to help keep the code uniform as well.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;That's all I have to say for this blog, I think I laid out a decent number of attainable objectives here and I feel that I really can get this finished. Look forward to my end of February/ beginning of March blog post where I decide if I succeeded or failed in my quest to do literally any work.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The first After-School Project</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Thu, 07 Jan 2021 04:44:17 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/the-first-after-school-project-396b</link>
      <guid>https://dev.to/fluentinstroll/the-first-after-school-project-396b</guid>
      <description>&lt;p&gt;Finishing OSD600 was a major milestone in my development as a programmer and as a software maintainer. I genuinely cannot express how happy taking that class has made me and how ready I feel to take on the next big project.&lt;/p&gt;

&lt;h2&gt;
  
  
  But first...
&lt;/h2&gt;

&lt;p&gt;I want to make something simple. I took a break from coding for about a week after my class ended (and thus my stint at Seneca College in general), and decided to enjoy the holidays with the many hours I was given at my part-time job and my girlfriend, with whom I spent lots of time cooking food with on Christmas Day.&lt;/p&gt;

&lt;p&gt;But back to the project. I want it to be simple and brush me back up on coding for the front-end. Though the projects I was working on in OSD600 were fun and great, I loved creating &lt;a href="https://github.com/fluentinstroll/Link-Checker"&gt;link checker&lt;/a&gt; and &lt;a href="https://dev.to/fluentinstroll/creating-the-first-release-and-link-checker-1-0-30o3"&gt;releasing it&lt;/a&gt; as well as &lt;a href="https://dev.to/fluentinstroll/release-0-4-and-the-end-4d75"&gt;working on other Javascript-heavy projects&lt;/a&gt;, I do feel like my back-end skills have been worked hard for now and though I will return to that, I want to learn more about webpage design and front-end frameworks like React and Vue (having worked largely with Angular the last year).&lt;/p&gt;

&lt;p&gt;However, this first project won't be in either of those - it will be with Jekyll.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H5wRkm8D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pp89cgbfyupgdjq12ow7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H5wRkm8D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pp89cgbfyupgdjq12ow7.png" alt="githubPagesScreenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, that's right, I building a personal website for myself. The project every software developer ruins into at least once. Allow me to outline what I want to build and what I would like to learn:&lt;/p&gt;

&lt;h2&gt;
  
  
  I would like to learn how to design appealing-looking web pages
&lt;/h2&gt;

&lt;p&gt;The biggest thing for me is that as a software developer, I don't have a terribly great eye for beauty. That doesn't mean I don't understand the basics of how to make something pleasing to look at, it just means that I don't the skill required to design something that's more complicated than, say, a simple blog or table of information. I also am not that confident in my CSS knowledge and I'd like to fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  I would like to learn Jekyll
&lt;/h2&gt;

&lt;p&gt;I was originally going to build my website in vanilla Javascript, but I think now that was foolish and instead I'd like to learn a static site generator that will work for simple webpages because even though I love Javascript, I don't want to work for a simple website.&lt;/p&gt;

&lt;h2&gt;
  
  
  I would like to learn about GitHub Pages
&lt;/h2&gt;

&lt;p&gt;Frankly, I think being able to host my projects straight from GitHub would be such a great option since all my code is going to be there anyway. I know locking yourself into an ecosystem is kind of a bad idea but I don't see anyone raising alarms about it so I'm not too perturbed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's start
&lt;/h1&gt;

&lt;p&gt;First, I created my &lt;a href="https://pages.github.com/"&gt;GitHub pages&lt;/a&gt; repository and connected it to a local git repo, then I started getting into Jekyll. I recommend &lt;a href="https://www.vgemba.net/blog/Setup-Jekyll-WSL/"&gt;this blog post&lt;/a&gt; if, like me, you've gotten used to using WSL in vscode for your web development work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jekyll
&lt;/h2&gt;

&lt;p&gt;Getting started with Jekyll is pretty easy. &lt;a href="https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/creating-a-github-pages-site-with-jekyll"&gt;GitHub Pages&lt;/a&gt; even has a section on initializing the Jekyll site with Pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZHC9csIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v9e9m1grvdlhvsnhv4ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZHC9csIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v9e9m1grvdlhvsnhv4ao.png" alt="JekyllBlog_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not that I have a templated site on my Pages domain, I'd like to make this blog, my dev.to blog, display on my site.&lt;/p&gt;

&lt;p&gt;A great GitHub repo for this is &lt;a href="https://github.com/equalcoding/equalcoding.github.io"&gt;equalcoding.github.io&lt;/a&gt;, with this template I managed to build a website in about 30 minutes that would display all my dev.to blogs and my GitHub repos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vrGbHvgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fyxkpbnnouxemodmq826.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vrGbHvgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fyxkpbnnouxemodmq826.png" alt="JekyllBlog_2"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;p&gt;The next things I would like to do are change up the look of the site and maybe add repos that I've recently contributed to? Or are in general involved with.&lt;/p&gt;

&lt;p&gt;Though I didn't particularly learn a ton about Jekyll, since the site I cloned used a lot of vanilla Javascript and HTML, I think themes are very important and I can't wait to explore them more.&lt;/p&gt;

&lt;p&gt;If you;d like to take a look at my site, you can see it &lt;a href="https://fluentinstroll.github.io/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Until next time! &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Release 0.4 and the End</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sat, 12 Dec 2020 04:50:40 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/release-0-4-and-the-end-4d75</link>
      <guid>https://dev.to/fluentinstroll/release-0-4-and-the-end-4d75</guid>
      <description>&lt;p&gt;I wanted to write this blog post on a triumphant, feel-good haze of power from smashing my biggest hurdle yet. However, I'm actually pretty behind on my open-source classwork. &lt;/p&gt;

&lt;p&gt;I'll admit I started a little late, as my &lt;a href="https://dev.to/fluentinstroll/release-0-4-the-halfway-point-26b3"&gt;mid-point blog post&lt;/a&gt; laments, and the last night of work has been stressful, but I think I won't mind too much.&lt;/p&gt;

&lt;p&gt;Not to say I won't miss the marks - but I'd be remiss if I didn't admit that the real reason I took this class and stuck with it was because it was a new experience that let me learn so many new things that I can apply to life as a developer.&lt;/p&gt;

&lt;p&gt;I encourage you to read that mid-point blog post as well because it highlights everything I did while working on &lt;a href="https://github.com/AardWolf/MHTimerBot/pull/220"&gt;this pull request&lt;/a&gt; with a couple of exceptions I'll discuss here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building
&lt;/h2&gt;

&lt;p&gt;My biggest fear was also my most correct prediction: working within other developers' codebases would be the most difficult part of this endeavor. I think figuring out that &lt;code&gt;getMice&lt;/code&gt; leads to &lt;code&gt;getSearchedEntity&lt;/code&gt; which then sends the info back to &lt;code&gt;sendInteractiveSearchResult&lt;/code&gt; which then uses &lt;code&gt;formatMice&lt;/code&gt; to build a table which then finally prints the message out for the Discord bot to say was a very difficult line to follow and I think it really highlights how starting early on something like this can help. I think that if I had started even a few days earlier, I would've had this line figured out and could've plotted my own with my own functions much sooner and with greater confidence.&lt;/p&gt;

&lt;p&gt;The other difficult part of writing this feature was the testing. Frankly, working with testing frameworks has been the bane of my existence. I finally got used to Jest and now there's a whole other one I have to learn! Truly exhausting.&lt;/p&gt;

&lt;p&gt;But seriously, the most difficult part of working with another developer's code is that it's &lt;em&gt;their code&lt;/em&gt;. And it really makes the most sense just to them.&lt;/p&gt;

&lt;p&gt;So if you remember from my last post, I described where I needed to go with my code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The process is similar to the code in the other commands, it will include a way to search the agiletravels database for the correct item, then print a list of items that can be found in it for the user to peruse. Seems pretty easy right?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is basically what I did, but following the lead with other code blocks, I created my own line through the program to get me to print out my own table of items. It turned out to be not that hard and I almost feel proud that I managed to get it working with relative ease. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0nJSWD7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/88p12b9q0etw45svt4uj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0nJSWD7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/88p12b9q0etw45svt4uj.png" alt="r4_Session_3_02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started this post by lamenting that I wanted to feel triumphant about my work, but to be quite honest, I am. I think that creating a feature like this to add to a program that with sit in dozens of discord servers and maybe be used by hundreds of people - I think it's a really great thing and I'm really happy to have developed a feature like this. If you want to take a look at the pull request and see how I'm doing you can look &lt;a href="https://github.com/AardWolf/MHTimerBot/pull/220"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think the biggest thing that I missed out on was leveraging the open-source community, especially the one in the OSD600 slack channel. Everyone there is quite adept and is always working on stuff. Though I never really felt like I need to ask any questions, I think doing so would've helped me out in a lot of places.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons
&lt;/h2&gt;

&lt;p&gt;So before I close out this blog post, I wanted to talk a bit about what I learned. Not just that other peoples' code is hard to read. But more about what I learned about collaborating and the technical aspects of open source development.&lt;/p&gt;

&lt;p&gt;One thing I learned is everyone on GitHub is always trying to be polite but sometimes just can't help themselves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--defPJFqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vdbq8bmczu4o8fy5oc48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--defPJFqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vdbq8bmczu4o8fy5oc48.png" alt="r4_Session_3_01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also that while git just loves to screw up your line endings, it's really the repo owner's fault if they don't have a code formatter that runs before each commit isn't it?&lt;/p&gt;

&lt;p&gt;Or at least, if git does go ahead and ruin your line endings, you can at least roll back and force push the good version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HYGMKdvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3rdka42imwihl7zy586w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HYGMKdvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3rdka42imwihl7zy586w.png" alt="r4_Session_3_03"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Actually, nevermind that one.&lt;/p&gt;

&lt;p&gt;I think as I get better as a developer I'll have a little more confidence and be a little more open about asking for help from others but for now, the biggest learning experiences have come from learning how to work the robust architecture of git and using ti to work with so many different people and I can't wait to apply it to my next project.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Release 0.4, the Halfway Point</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Mon, 07 Dec 2020 23:43:53 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/release-0-4-the-halfway-point-26b3</link>
      <guid>https://dev.to/fluentinstroll/release-0-4-the-halfway-point-26b3</guid>
      <description>&lt;p&gt;Phew! It's been kind of a wild weekend, and a wild previous week. Unfortunately, this blog post was meant to be written at the end of last week, not the beginning of this week. However, life and work have their ways of messing with our plans.&lt;/p&gt;

&lt;p&gt;I decided to take on a &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/137"&gt;feature request&lt;/a&gt; on the Mousehunt Timer Bot and have been plugging away at it.&lt;/p&gt;

&lt;p&gt;The process is similar to the code in the other commands, it will include a way to search the &lt;a href="https://agiletravels.com/converter.php"&gt;agiletravels database&lt;/a&gt; for the correct item, then print a list of items that can be found in it for the user to peruse. Seems pretty easy right?&lt;/p&gt;

&lt;p&gt;The first step will be to take a look at other commands' code and think about how I can write a command that looks and acts like them. Then I need to look into how the bot displays the information (which I have done when I fixed a bug previously) and set up the correct message to display.&lt;/p&gt;

&lt;p&gt;This will be another living document that I'll update as I work on this issue. Please stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Session One
&lt;/h2&gt;

&lt;p&gt;In my first work session, I started by laying out the process for creating this command.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Research the other commands and figure out how the internals of the discord bot really work - get to know the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up my command with copy-pasted code from a different command to show that I can at least get the bot to spit out information from my new file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write the actual command, taking code structure and design cues from the code of the other commands.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bug test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write tests for my command and perform pull request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review critique on the PR and get the issue closed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, I worked on points 1 and 2. the goal of this session was to simply get the bot to spit out information that I coded exactly as I said above.&lt;/p&gt;

&lt;p&gt;I decided to copy over the code from the &lt;code&gt;next&lt;/code&gt; command because it seemed like the most straightforward - it required no arguments from the user so I could quickly get to know how a discord bot truly works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hwgAlbef--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ghf9fwnkjauo0fbxr1g6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hwgAlbef--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ghf9fwnkjauo0fbxr1g6.png" alt="R4_Session_1_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So how does a discord bot's commands work? Basically, in your index.js file (here called MHTimer.js), you create a collection and then just populate it with the contents of the commands folder using the following code. It's actually quite simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Discord = require('discord.js');
const client = new Client({ disabledEvents: ['TYPING_START'] });
client.commands = new Collection();
 const commandFiles = fs.readdirSync('src/commands').filter(file =&amp;gt; file.endsWith('.js'));
for (const file of commandFiles) {
    try {
        const command = require(`./commands/${file}`);
        if (command.name) {
            if (typeof(command.canDM) === 'undefined') {
                command.canDM = true;
                Logger.log(`Set canDM to true for ${command.name}`);
            }
            if (command.initialize) {
                command.initialize().catch((err) =&amp;gt; {
                    Logger.error(`Error initializing ${command.name}: ${err}`);
                    throw err;
                });
            }
            client.commands.set(command.name, command);
        } else {
            Logger.error(`Error in ${file}: Command name property is missing`);
        }
    } catch (e) {
        Logger.error(`Could not load ${file}:`, e);
    }
}
Logger.log(`Commands: Loaded ${client.commands.size} commands: ${oxfordStringifyValues(client.commands.map(command =&amp;gt; command.name))}`);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please be aware that this code is from MHTimerBot and is not at all universally applicable. See &lt;a href="https://discordjs.guide/command-handling/#individual-command-files"&gt;the Discord docs&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;This session was pretty short so I also decided to figure out what the author of the issue had in mind when they specified "Can use the loot nicknames used by ifind."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const all_loot = getLoot(searchString, message.client.nicknames.get('loot'));
        if (all_loot &amp;amp;&amp;amp; all_loot.length) {
            // We have multiple options, show the interactive menu
            urlInfo.qsParams = opts;
            sendInteractiveSearchResult(all_loot, message.channel, formatLoot,
                ['dm', 'group'].includes(message.channel.type), urlInfo, searchString);
            theResult.replied = true;
            theResult.success = true;
            theResult.sentDM = ['dm', 'group'].includes(message.channel.type);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I believe this is the code block they're referring to when they said that so I'll try to incorporate that when I'm writing the command in my second session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session Two
&lt;/h2&gt;

&lt;p&gt;I started off the second session with a bit of a roadblock. &lt;/p&gt;

&lt;p&gt;Ending the last session on what was basically a baseline command may not have been a mistake but it did mean I had a lot of work to get done. The roadblock came from not really feeling like I knew how the discord bot operated. After fumbling about for half an hour trying to figure out how to write my command by just staring at the others, I decided to map out exactly what my command needed to do, and where, in the code, it needed to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message -&amp;gt; 

getConvertibles() [match search term with database items] -&amp;gt; 

formatConvertibles() [get possible items and quantity, display in columns]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a rough line I want my command to go through. I also mirrors the line the find command for mice and loot takes.&lt;/p&gt;

&lt;p&gt;After figuring this out, I could start on my coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main code from whatsin.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const theResult = new CommandResult({ message, success: false, sentDM: false });
    let reply = '';
    const opts = {};
    const urlInfo = {
        qsParams: {},
        uri: 'https://agiletravels.com/converter.php',
        type: 'convertible',
    };
    if (!tokens)
        reply = 'I just cannot find what you\'re looking for (since you didn\'t tell me what it was).';
    else {
        const searchString = tokens.join(' ').toLowerCase();
        const all_convertibles = getConvertibles(searchString, message.client.nicknames.get('mice'));
        if (all_convertibles &amp;amp;&amp;amp; all_convertibles.length) {
            // We have multiple options, show the interactive menu
            urlInfo.qsParams = opts;
            sendInteractiveSearchResult(all_convertibles, message.channel, formatConvertibles,
                ['dm', 'group'].includes(message.channel.type), urlInfo, searchString);
            theResult.replied = true;
            theResult.success = true;
            theResult.sentDM = ['dm', 'group'].includes(message.channel.type);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty close to what the find.js or ifind.js looks like. Since what I'm trying to do is work with the same api that command is in order to do almost the exact same thing, I believed I could reuse a lot of that code.&lt;/p&gt;

&lt;p&gt;I had a few setback this session, but most were easy to deal with. The only one that gave me trouble was resolving in issue with the .map() function. I was accidentally using a filter when I didn't need to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Excerpt from formatConvertibles()
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const converter = results
        .map(convertible =&amp;gt; {
            return {
                item: convertible.item.substring(0, 20),
                average_qty: convertible.total_items / convertible.total,
            };
        });
    const order = ['item', 'average_qty'];
    const labels = { item: 'Item', average_qty: 'Average Qty' };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end of the second session, I feel very confident and am ready to begin work on the tests next session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session 3
&lt;/h2&gt;

&lt;p&gt;This is the last session, or at least, that last planned session.&lt;/p&gt;

&lt;p&gt;All that this session consisted of was me cleaning up the code a bit and sending the pull request off to the main developers.&lt;/p&gt;

&lt;p&gt;That said, if there are any changes they need me to make, or if they ask me to add tests, I will document the process here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4ey8PFVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3ing18ki8iuiuosohi7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4ey8PFVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3ing18ki8iuiuosohi7t.png" alt="r4_Session_3_01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what we need to do following this is 2 things: follow-up on creating the tests and fix our line endings. Two fairly simple things.&lt;/p&gt;

&lt;p&gt;The code for the tests is written with sinon.js, a framework that I'm not terribly familiar with but shouldn't pose too much of a problem.&lt;/p&gt;

&lt;p&gt;That said, I had a little trouble figuring out how I should go about doing my tests. Should I add tests in the mhct-lookup file to cover the new functions I built in the sister file? Or should I create my own test file for my new command? I figured I should do both.&lt;/p&gt;

&lt;p&gt;Then, after working with the test files for &lt;em&gt;hours&lt;/em&gt; I figured out that when I mock a function in one file, and it's mocked in another, it completely demolishes the second file and breaks the test. I needed to either scale down my testing or find some kind of workaround. &lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Creating the First Release and Link Checker 1.0</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sun, 06 Dec 2020 04:17:14 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/creating-the-first-release-and-link-checker-1-0-30o3</link>
      <guid>https://dev.to/fluentinstroll/creating-the-first-release-and-link-checker-1-0-30o3</guid>
      <description>&lt;p&gt;For a few months now, I've been working on an &lt;a href="https://github.com/fluentinstroll/Link-Checker"&gt;app to check links&lt;/a&gt; in files. This app has grown with me through these months while I worked on other open-source projects and although I don't feel like it's perfect, I do feel like I achieved something really important to myself.&lt;/p&gt;

&lt;p&gt;Today, I'm releasing &lt;a href="https://www.npmjs.com/package/l-checker"&gt;Link Checker through npm&lt;/a&gt; and I can't wait to take well-deserved break from the work, but also to continue development on the app if only to clean it up and fix more bugs.&lt;/p&gt;

&lt;p&gt;Creating a release actually isn't too difficult for Node cli developers. One must simply &lt;a href="https://www.npmjs.com/signup"&gt;create an account&lt;/a&gt; on the npm website and &lt;a href="https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry"&gt;start into publishing the app&lt;/a&gt;. I found hte process relatively painless, aside from &lt;a href="https://docs.npmjs.com/cli/v6/commands/npm-adduser"&gt;figuring out how to connect my npm account to my local version&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Learning how to set up npm and publish these things will be invaluable in the future, especially if I create a Node package that I use in a different project - I absolutely needed to know these things and I'm so happy I learned. &lt;/p&gt;

&lt;p&gt;For other users, it might be different, but I didn't alter my code too much. I spent some time changing my version number and reading up about &lt;a href="https://docs.npmjs.com/cli/v6/configuring-npm/package-json"&gt;package.json&lt;/a&gt; and how it affects my app but otherwise, I felt totally comfortable simply publishing the app and testing it out in other folders to a smooth release.&lt;/p&gt;

&lt;p&gt;However, I ran into a snag when I contacted a friend of mine, who worked with me on our &lt;a href="https://github.com/PhilipMroczkowski/Social-Interactions"&gt;PRJ666 project&lt;/a&gt; and asked him to test out the app and let me know if he is confused at all.&lt;/p&gt;

&lt;p&gt;Well, he wasn't. The instructions are pretty simple for a developer to understand! On Linux at least.&lt;/p&gt;

&lt;p&gt;On Windows, however, it's not so easy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CgIlz22P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/acnwx988oqihnqognynn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CgIlz22P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/acnwx988oqihnqognynn.png" alt="lab9_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hmm... I wonder why that's the case...&lt;/p&gt;

&lt;p&gt;So I spent some time looking up fixes and reasons why npm scripts might not play nice with Windows and eventually settled on... well that they just don't play nice. And without a kind of step-by-step instruction for changing environment variables and installing npm globally (which I'm not even sure is the problem), I don't think I'll have Windows working in the way I intended. So I figured out a little workaround. If the user installs Link Checker with npx, npm will then install the app and run it at the same time - essentially performing the &lt;code&gt;node index.js&lt;/code&gt; from within its own little framework. This works well enough to run the program on windows and if my developer friend finds it easy to use - we can close the book on that one.&lt;/p&gt;

&lt;p&gt;So here it is. &lt;a href="https://www.npmjs.com/package/l-checker"&gt;Link Checker&lt;/a&gt;. You should be able to follow the instructions in the description but here's a little more in-depth information.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You must have some kind of text file. When I used this app on a docx file it took from it the links to the pictures used in the file but not the links - weird stuff but I want to take a look at that. Any file that has text in it will work, doesn't matter if it's a .log or a .src, if it has text, it works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'm fairly certain you would be able to use it in a Node project of your own through require() but it's not built for that and I have no documentation on how that would work. It's a good next step though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, as said in the description - just &lt;code&gt;npm install l-checker&lt;/code&gt; and go wild. The description has everything you might need to know about how to use it and I'll update it as I add more features.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to contribute, please visit the &lt;a href="https://github.com/fluentinstroll/Link-Checker"&gt;git repository&lt;/a&gt; and shoot me a pull request.&lt;/p&gt;

&lt;p&gt;That's it for now, the culmination of a semester's worth of work and one of the most informative courses I've ever taken. It's not over though, tomorrow I'll be writing about my progress in working on my final assignment or Release 0.4, and at the end of next week I'll have a whole lot to write about what I learned in this course and how valuable I think all of it was.&lt;/p&gt;

&lt;p&gt;For now. Peace.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Lab 8 and Testing Apps</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sat, 28 Nov 2020 01:59:26 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/lab-8-and-testing-apps-2gci</link>
      <guid>https://dev.to/fluentinstroll/lab-8-and-testing-apps-2gci</guid>
      <description>&lt;p&gt;Testing: the backbone of any project. A project without the ability to test its code will inevitably bloat in a way that breaks EVERYTHING.&lt;/p&gt;

&lt;p&gt;I don't think I need to actually explain the philosophy, but I will anyway. Basically, you need tests to make sure no one breaks the project as they're working. When you have a project of any reasonable size, you can expect that someone will fix a bug or add a feature that causes a different part of your project to not work. So we need to automate tests that will check to make sure we haven't done that before we go to add the feature or bug fix.&lt;/p&gt;

&lt;p&gt;So to that end, let's write some tests!&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest test for printing a working url
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test('print good url', async () =&amp;gt; {
        const expected = chalk.green('[200] GOOD http://www.google.ca')
        const result = isValid.displayStatusCode(200, 'http://www.google.ca')

        expect(result).toEqual(expected)
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Framework
&lt;/h2&gt;

&lt;p&gt;So we decided to use Jest! It's a great framework for testing Javascript projects. To do this, we simply use &lt;code&gt;npm install --save-dev jest&lt;/code&gt; and go off! I created a test folder and put my testing files in there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LhRyaYK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/imffgy3qhbwsnmhftq5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LhRyaYK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/imffgy3qhbwsnmhftq5w.png" alt="lab8_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside the testing file, we define the files we're using and start writing tests! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T9mUvYTP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xrsmbxbaimjlhp50srfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T9mUvYTP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xrsmbxbaimjlhp50srfo.png" alt="lab8_2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tests
&lt;/h2&gt;

&lt;p&gt;The first test I wrote was the most difficult. Actually, that applies to every category of test. Because we're testing the same function - just different lines through - we need to write one good test, and we can kind of reuse it for our other lines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uwSGnLCp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gulgx8oieqph97z89342.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uwSGnLCp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gulgx8oieqph97z89342.png" alt="lab8_3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, there wasn't anything particular that stood out to me as supremely difficult.&lt;/p&gt;

&lt;p&gt;No particular bugs either, though I did learn about how my code works a bit more and had to check for undefined in some tests (which is, forgive the rhyme, rather unrefined a solution). I also realized I had to modulate my code a bit and separate some functions into their own files. This will be extremely beneficial for the future in general.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mock Tests
&lt;/h2&gt;

&lt;p&gt;One of the most important parts of my app is checking for a response from a website. We want to know if the website will return 200 good or 404 broken, you know? However, you can't really check a real site in tests because what if it goes down? That's what mocking is for.&lt;/p&gt;

&lt;h3&gt;
  
  
  A test function that mocks a link to always output 405 status code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const host = 'https://www.youtube.com'
const path = '/'

test('get 405 response for unknown url', async () =&amp;gt; {
        nock(host).head(path).reply(405)
        const url = `${host}${path}`
        const expected = chalk.gray(`[405] UNKNOWN ${url}`)
        const result = await isValid.isValid(url)

        expect(result).toEqual(expected)
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use &lt;a href="https://github.com/nock/nock"&gt;nock&lt;/a&gt; here to easily mock an address and send it to our function.&lt;/p&gt;

&lt;p&gt;Easy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Coverage
&lt;/h2&gt;

&lt;p&gt;Code coverage is a description of exactly how much of your code is being tested by your tests. For example, if I'm writing 1 test that goes through 1 line of a function while there are 3 possible lines, my code coverage is 1/3 (realistically more but for the purposes of explanation let's say 1/3). So I need to write some more tests to expand that.&lt;/p&gt;

&lt;p&gt;Also, there are tools one can use to inspect how much code is being covered by our tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FKYmUpyk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d275hhr30ted1o1actie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKYmUpyk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d275hhr30ted1o1actie.png" alt="lab8_4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jest has such a feature! pictured above, all you have to do is specify --coverage when you run jest.&lt;/p&gt;

&lt;h3&gt;
  
  
  package.json excerpt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "test": "jest --detectOpenHandles --coverage",
    "prettier": "npx prettier --write .",
    "lint": "npx eslint ."
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think it would be good to set coverage as a separate option, but also I think it should run for any user who is submitting tests because who wouldn't want as much coverage as possible?&lt;/p&gt;

&lt;p&gt;My test cases for my isValid file covered everything. I wanted to leave some for others to do if they decided so I left spots in the other files.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;Also, I was required to create a testing suite for GitHub - this way, anyone who wants to submit a pull request has to pass my tests! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KZ-xjM8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cs0iz0hxfxvgw9ejasx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KZ-xjM8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cs0iz0hxfxvgw9ejasx5.png" alt="lab8_5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above is my YAML file. It's pretty straightforward and just runs my test command upon upload. I used the boilerplate settings for GitHub Actions and I think I'll expand on it in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Stranger's Tests
&lt;/h2&gt;

&lt;p&gt;My &lt;a href="https://github.com/StellaJung-Student"&gt;partner's&lt;/a&gt; repo wasn't wholly different, and she used the same framework for testing (Jest) so I knew some of the syntaxes. There were marked differences though like that she used mock functions and I wasn't quite sure how they worked. So it took a little acclimation but once I found some work to do I got to it. Her regular program was different too and I don't think I realized how difficult it is to immerse yourself in a different code base and anticipate the &lt;br&gt;
outputs from my testing inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;So firstly, I have done testing a bit. I created tests for MHTimer and Telescope respectively so I'm not a stranger to tests.&lt;/p&gt;

&lt;p&gt;However, working on my own tests gives me a sense of productivity that I hadn't realized before. It's really nice to set up and let grow as a project within the project.&lt;/p&gt;

&lt;p&gt;I really like developing tests and think that it also helps me acclimate to other code bases and I for sure will do it in the future, especially for features and bugfixes I write.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Release 0.4 Defined and Colourblindness</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sat, 21 Nov 2020 20:12:03 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/release-0-4-defined-and-colourblindness-299j</link>
      <guid>https://dev.to/fluentinstroll/release-0-4-defined-and-colourblindness-299j</guid>
      <description>&lt;p&gt;This blog post is a living document of sorts, where I'm going to document my journey to finding the right issue to work on for Release 0.4. So, to that end, I'm going to take a look at all the projects David linked me and try to find something important to work on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Start
&lt;/h2&gt;

&lt;p&gt;This week we got our first glimpse of what Release 0.4 would look like. &lt;/p&gt;

&lt;p&gt;Due December 11th, the requirements for Release 0.4 are simple: do something larger than we've ever done before. Examples were a feature, a number of bug fixes (like 3), or a large bug fix in a large repo.&lt;/p&gt;

&lt;p&gt;That's a lot to choose from and I think it's a great way to step up to another level in our open source journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  What would I want to work on?
&lt;/h2&gt;

&lt;p&gt;Ideally, I want to make a meaningful contribution in the form of a feature to a project. I think that's the next step that makes the most sense to me.&lt;/p&gt;

&lt;p&gt;So far my experience in working on open source projects has been in fixing bugs or adding a feature that was meant to already be there like in MHTimer, cleaning up code, or moving from one type of authentication rule to another like in Telescope. I don't feel like I've contributed to a project in a way that I can be really proud of. Not to say I don't think my contributions so far have been good - I think they've helped me learn to get immersed in different code bases and styles and trace sequences of code through different modules and all that. And that's useful! But I really think adding a feature would round out my knowledge and give me something I can be really proud of, which is what I want to get out of this class.&lt;/p&gt;

&lt;p&gt;This brings us to colorblindness, weirdly enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kcOggjO0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iwvaf1gdc8yfs12l8fn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kcOggjO0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iwvaf1gdc8yfs12l8fn0.png" alt="release0.4b1p1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ExpQgsS---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hf5jnnra0xzs30nsrcov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ExpQgsS---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hf5jnnra0xzs30nsrcov.png" alt="release0.4b1p2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't find colorblindness to be a thing that defines me and I think acting like it is would be in poor taste toward people with more inhibitive accessibility issues, but I think as someone who's affected by deuteranopia, I can give some insight into how some IDEs highlight their code and how it can be exclusionary to colourblind people. And how to fix it!&lt;/p&gt;

&lt;p&gt;For example, I can't tell the difference between these two colours unless they're blown up.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZZIqWIqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zpktv1a2yi4n1n66s1vs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZZIqWIqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zpktv1a2yi4n1n66s1vs.png" alt="release0.4b1p3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A high contrast vscode theme would greatly help someone like me - unfortunately, there's little to no extensions that do this.&lt;/p&gt;

&lt;p&gt;If you're also colourblind, please check out &lt;a href="https://marketplace.visualstudio.com/items?itemName=PedroFonsecaDEV.dark-plus-colorblind&amp;amp;ssr=false#overview"&gt;https://marketplace.visualstudio.com/items?itemName=PedroFonsecaDEV.dark-plus-colorblind&amp;amp;ssr=false#overview&lt;/a&gt; and give him all your feedback.&lt;/p&gt;
&lt;h2&gt;
  
  
  The first issue
&lt;/h2&gt;

&lt;p&gt;So, keeping in mind that I want to work ona  feature for an app, I thought I would go through some of the old repos that I've worked on in the past. I found this issue in the MHTimerBot&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/212"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Loot Plurals should be squashed some of the time
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#212&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/AardWolf"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--qJe3oGdQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars1.githubusercontent.com/u/115027%3Fv%3D4" alt="AardWolf avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/AardWolf"&gt;AardWolf&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/212"&gt;&lt;time&gt;Oct 09, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;searchByItem now returns singular and plural names for loots. So a search for "cloud curd" matches cloud curd and cloud curds. They both point to the same time but the result menu makes it look like there are two matches.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/AardWolf/MHTimerBot/issues/212"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;While I'd like to work on it, and it's not labeled a bug, I think I would consider this a bug and would therefore probably not be in my purview of work. However, I think if I really wanted to, I could work on this and be fulfilled in some way. so it's an option.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/63"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add Ability To Find Things in Shops
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#63&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/AardWolf"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--qJe3oGdQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars1.githubusercontent.com/u/115027%3Fv%3D4" alt="AardWolf avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/AardWolf"&gt;AardWolf&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/63"&gt;&lt;time&gt;Mar 02, 2018&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Mrs Flibble / kipper has offered to help.&lt;/p&gt;
&lt;p&gt;Something like current find query but that would show things like:
charmbits are buyable for X gold in ...
charmbits can be dropped in .... (location)
charmbits can be looted from ... (convertible)&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/AardWolf/MHTimerBot/issues/63"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The issue above is another one I'm thinking of taking up, but I think it's already being worked on? Or perhaps in on hold - it's from 2018 after all. I wouldn't want to step on any toes but it's been so long that I think maybe it could be something I work on.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Release 0.3 part 2, Telescope</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Thu, 19 Nov 2020 02:56:07 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/release-0-3-part-2-telescope-12ae</link>
      <guid>https://dev.to/fluentinstroll/release-0-3-part-2-telescope-12ae</guid>
      <description>&lt;p&gt;The second task for our Release 0.3 was to fix and issue and merge a pull request into &lt;a href="https://github.com/Seneca-CDOT/telescope/" rel="noopener noreferrer"&gt;telescope&lt;/a&gt;. This involves finding an issue, fixing it, collaborating with the telescope slack channel, and finally getting feedback and eventually merging the pull request.&lt;/p&gt;

&lt;p&gt;This sounds like a lot of steps but depending on the issue, they can take very little time and produce very little headache.&lt;/p&gt;

&lt;p&gt;This is not the case with mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The issue
&lt;/h2&gt;

&lt;p&gt;So my issue was this: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/1308" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add query params validation for DELETE /feeds/:id route using Express Validator and unit tests
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1308&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/tonyvugithub" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars2.githubusercontent.com%2Fu%2F55034244%3Fv%3D4" alt="tonyvugithub avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/tonyvugithub" rel="noopener noreferrer"&gt;tonyvugithub&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/1308" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 11, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      
&lt;p&gt;&lt;strong&gt;What would you like to be added&lt;/strong&gt;:
Request to add query params validation for DELETE /feeds/:id route using &lt;a href="https://express-validator.github.io/docs/" rel="nofollow noopener noreferrer"&gt;Express-validator&lt;/a&gt; and also unit tests to ensure that it works&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why would you like this to be added&lt;/strong&gt;:
It would be better to validate the query before it reach the route handler.&lt;/p&gt;
&lt;p&gt;reference: &lt;a href="https://express-validator.github.io/docs/check-api.html" rel="nofollow noopener noreferrer"&gt;https://express-validator.github.io/docs/check-api.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;All logic for the middleware should be place inside &lt;code&gt;backend/web/validation.js&lt;/code&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Seneca-CDOT/telescope/issues/1308" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Basically, I'm meant to go into the backend for Telescope and add some query parameters with express-validator. Then I have to link them to the DELETE feed route and write tests for it.&lt;/p&gt;

&lt;p&gt;First, what I did was add a new validation parameter to the validation.js, but after some review, we decided it was better to use what already existed to not bloat our code.&lt;/p&gt;

&lt;h3&gt;
  
  
  validation.js excerpt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const feedsIdParamValidationRules = [
  param('id', 'Id Length is invalid').isLength({ min: 10, max: 10 }),
];

module.exports = {
  validateNewFeed,
  validateQuery: () =&amp;gt; validate(queryValidationRules),
  validatePostsQuery: () =&amp;gt; validate(postsQueryValidationRules),
  validatePostsIdParam: () =&amp;gt; validate(postsIdParamValidationRules),
  validateFeedsIdParam: () =&amp;gt; validate(feedsIdParamValidationRules),
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A fairly simple piece of code that establishes a rule that an id must be a minimum 10, and a maximum 10 (aka exactly 10) characters long.&lt;/p&gt;

&lt;p&gt;Then, in our feeds.js file, which holds our routes for blog feeds, we have to make sure our delete feeds route checks our new rule.&lt;/p&gt;
&lt;h3&gt;
  
  
  delete feeds route
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feeds.delete('/:id', validateFeedsIdParam(), protect(), async (req, res) =&amp;gt; {
  const { user } = req;
  const { id } = req.params;
  try {
    const feed = await Feed.byId(id);
    if (!feed) {
      return res.status(404).json({ message: `Feed for Feed ID ${id} doesn't exist.` });
    }
    if (!user.owns(feed)) {
      return res.status(403).json({ message: `User does not own this feed.` });
    }
    await feed.delete();
    return res.status(204).json({ message: `Feed ${id} was successfully deleted.` });
  } catch (error) {
    logger.error({ error }, 'Unable to delete feed to Redis');
    return res.status(503).json({
      message: 'Unable to delete to Feed',
    });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice the promise call that includes &lt;code&gt;validateFeedsIdParam()&lt;/code&gt;, this is our rule that will be tested against when we submit an id to the delete request.&lt;/p&gt;
&lt;h3&gt;
  
  
  the test
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should return 400 when id is less than 10 characters', async () =&amp;gt; {
    const id = '123456789';
    const res = await request(app).delete(`/feeds/${id}`);

    expect(res.status).toEqual(400);
  });

  it('should return 400 when id is more than 10 characters', async () =&amp;gt; {
    const id = '123456789123456789';
    const res = await request(app).delete(`/feeds/${id}`);

    expect(res.status).toEqual(400);
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;keep in mind this is after a multitude of critique.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsj6rk3cqqe6m2n4ihlmr.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsj6rk3cqqe6m2n4ihlmr.png" alt="1telescopecomments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops!&lt;/p&gt;

&lt;p&gt;so now that we have our code working, our test working properly, all that's left is to merge into the project right?&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jd8mb8tjibv863xvabf.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jd8mb8tjibv863xvabf.png" alt="2release0.3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not quite. That's pretty easy, let's just rebase on GitHub since it's only one line that seems to be wrong!&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fot68x8hamub4hlh126mj.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fot68x8hamub4hlh126mj.png" alt="release0.33"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops. Again. &lt;/p&gt;

&lt;p&gt;Ok ok ok this is fixable, all I have to do is go back, run some commands, fix up in an interactive rebase, and commit again.&lt;/p&gt;

&lt;p&gt;For those that don't know, here's a nice image that'll help you out if you end up in my situation.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxk4spo88hvkbu4vlm7d2.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxk4spo88hvkbu4vlm7d2.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait a sec, it looks like something else is wrong...&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzb8mxni45wb5uumkxl82.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzb8mxni45wb5uumkxl82.png" alt="release0.34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Huh?&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhstqhe3hi01p1cshyi5i.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhstqhe3hi01p1cshyi5i.png" alt="release0.35"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok. So here's what happened. I go ahead and run prettier on my files but I ran it through vscode, which means it's slightly different from the Telescope configuration for prettier. Now you would expect a test to check this, find it wrong, and send back an error, right? But no, it actually thinks everything is good!&lt;/p&gt;

&lt;p&gt;So what is there to do?&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/Seneca-CDOT/telescope/pull/1399" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Be more explicit with prettier config
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1399&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/humphd" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars2.githubusercontent.com%2Fu%2F427398%3Fv%3D4" alt="humphd avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/humphd" rel="noopener noreferrer"&gt;humphd&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/Seneca-CDOT/telescope/pull/1399" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 18, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;We ran into a weird issue where Prettier was not seeming to use some of our values which are implicit defaults.  This sets all prettier options explicitly.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Seneca-CDOT/telescope/pull/1399" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;So David opened up a pull request to fix the prettier config and make sure this doesn't happen again, but I'm still in a position where my code is all messed up. So I guess the only thing to do is manually fix our formatting errors.&lt;/p&gt;

&lt;p&gt;I'll spare you the screenshots.&lt;/p&gt;

&lt;p&gt;Finally, we've got our pull request. Formatting? Great! Functionality? Awesome. Tests? Work properly! Now all we have to do is commit, rebase PROPERLY, and push!&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fljapoo6qcpllnw8etk3o.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fljapoo6qcpllnw8etk3o.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes!&lt;/p&gt;

&lt;p&gt;So to conclude - this has been a very educational experience. Not just in Git and how to work with a project's contributing guidelines (and what happens when you mess it up), but how to interact in a community and get feedback from members. Until now all my PRs have been basically some sequence of being assigned, working, putting up a PR, getting little to no feedback, and instantly having it merged. This experience really helped me figure out how to take criticism and build on my first would-be contribution.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Release 0.3 part 1, more Discord!  </title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Wed, 18 Nov 2020 02:00:55 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/release-0-3-part-1-more-discord-5g10</link>
      <guid>https://dev.to/fluentinstroll/release-0-3-part-1-more-discord-5g10</guid>
      <description>&lt;p&gt;For the first part of Release 0.3, I decided to revisit my favorite repo from last month: MHTimer!&lt;/p&gt;

&lt;p&gt;If you're new to Discord bots or have started reading with this post, I recommend checking out my &lt;a href="https://dev.to/fluentinstroll/as-a-real-gamer-256b"&gt;other post&lt;/a&gt; about this bot and how I got it working as I won't be going over it again.&lt;/p&gt;

&lt;p&gt;This time I took on an issue that had to do with error handling.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/210"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        findThings sends empty response on error.
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#210&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/AardWolf"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--qJe3oGdQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars1.githubusercontent.com/u/115027%3Fv%3D4" alt="AardWolf avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/AardWolf"&gt;AardWolf&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/AardWolf/MHTimerBot/issues/210"&gt;&lt;time&gt;Oct 01, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;findThings: Error getting item item_type=mouse&amp;amp;item_id=402 - FetchError: invalid json respons&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/AardWolf/MHTimerBot/issues/210"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So basically when the bot gets a request for some information, and the website is down, the bot just prints an error in the terminal and the Discord chat has no printout!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gHINJFjS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mfhfy40m4xo5it1pzox8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gHINJFjS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mfhfy40m4xo5it1pzox8.png" alt="Nothing!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the first step was to take a look at the get call.&lt;/p&gt;

&lt;h3&gt;
  
  
  findThing function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function findThing(type, id, options) {
    if (!type || !id)
        return [];

    // If caching is ever implemented it'd be checked here
    const qsOptions = new URLSearchParams(options);
    qsOptions.append('item_type', type);
    qsOptions.append('item_id', id);
    const url = 'https://www.agiletravels.com/searchByItem.php?' + qsOptions.toString();
    return await fetch(url)
        .then((response) =&amp;gt; {
            if(response.ok){
                return response.json();
            }
            else {
                return null;
            }
        })
        .catch(err =&amp;gt; {
            Logger.log(`findThings: Error getting item ${qsOptions.toString()} - ${err}`);
        });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what this did before simply sent back an error when any problem happened. Instead, I decided to return null if the response from the server was not ok. Next, let us take a look at the function that will craft our message.&lt;/p&gt;

&lt;h3&gt;
  
  
  formatMice function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function formatMice(isDM, mouse, opts) {
    const results = await findThing('mouse', mouse.id, opts);
    if (results === null) {
        const reply = 'Looks like I\'m having a bit of trouble finding your mouse right now.' ;
        return reply;
    }
    const no_stage = ' N/A ';
    const target_url = `&amp;lt;https://www.agiletravels.com/attractions.php?mouse=${mouse.id}&amp;amp;timefilter=${opts.timefilter ? opts.timefilter : 'all_time'}&amp;gt;`;
    const attracts = results.filter(mouse =&amp;gt; mouse.total_hunts &amp;gt; 99)
        .map(mice =&amp;gt; {
            return {
                location: mice.location.substring(0, 20),
                stage: mice.stage === null ? no_stage : mice.stage.substring(0, 20),
                cheese: mice.cheese.substring(0,15),
                total_hunts: intToHuman(mice.total_hunts),
                ar: mice.rate / 100,
            };
        });
    if (!attracts.length)
        return `There were no results with 100 or more hunts for ${mouse.value}, see more at ${target_url}`;
    const order = ['location', 'stage', 'cheese', 'ar', 'total_hunts'];
    const labels = { location: 'Location', stage: 'Stage', total_hunts: 'Hunts',
        ar: '/Hunt', cheese: 'Cheese' };
    //Sort the results
    attracts.sort((a, b) =&amp;gt; parseFloat(b.ar) - parseFloat(a.ar));
    attracts.splice(isDM ? 100 : 10);
    if (attracts.every(row =&amp;gt; row.stage === no_stage))
        order.splice(order.indexOf('stage'), 1);
    // Column Formatting specification.
    /** @type {Object &amp;lt;string, ColumnFormatOptions&amp;gt;} */
    const columnFormatting = {};
    const headers = order.map(key =&amp;gt; {
        columnFormatting[key] = {
            columnWidth: labels[key].length,
            alignRight: !isNaN(parseInt(attracts[0][key], 10)),
        };
        return { 'key': key, 'label': labels[key] };
    });
    // Give the numeric column proper formatting.
    // TODO: toLocaleString - can it replace integerComma too?
    columnFormatting['ar'] = {
        alignRight: true,
        isFixedWidth: true,
        suffix: '%',
        columnWidth: 7,
    };
    let reply = `${mouse.value} (mouse) can be found the following ways:\n\`\`\``;
    reply += prettyPrintArrayAsString(attracts, columnFormatting, headers, '=');
    reply += '```

\n' + `HTML version at: ${target_url}`;
    return reply;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It's a bit long, but let us take a look at the most important part. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const results = await findThing('mouse', mouse.id, opts);
    if (results === null) {
        const reply = 'Looks like I\'m having a bit of trouble finding your mouse right now.' ;
        return reply;
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, what we do here is call our findThing function, which this function was already doing, and if our return value is null, then we craft our message and skip the rest of the validation and separation. Who needs it if we know our response is bunk?&lt;/p&gt;

&lt;p&gt;So let's put up our fix for review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5u9PdyhB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w6xoiao011ofi0eg9blx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5u9PdyhB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w6xoiao011ofi0eg9blx.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whoops! Turns out I ran prettier on my code before submitting and now it's gone and messed up tons of stuff. Let's patch it up and submit it properly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AOBQbOOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tswkcuuk2g8bcy4n4v6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AOBQbOOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tswkcuuk2g8bcy4n4v6k.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've succeeded! All in all some good work. To be honest, I didn't learn a lot doing this fix. I became more familiar with the project and the features of git - but I think what really shows my growth was how easily I was able to take an issue, fix it up, and merge it quickly! I really feel like I've progressed as a developer because of that.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Lob 7, the tools I'll never do without</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sat, 14 Nov 2020 21:14:28 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/lob-7-the-tools-i-ll-never-do-without-5aln</link>
      <guid>https://dev.to/fluentinstroll/lob-7-the-tools-i-ll-never-do-without-5aln</guid>
      <description>&lt;p&gt;This lab was all about setting up static analysis tools. Specifically, I set up &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; and &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prettier
&lt;/h2&gt;

&lt;p&gt;Prettier is a tool for Javascript that automatically organizes code to look uniform. It's nothing terribly special, though it does allow the user to specify a lot of options for how it should look. I didn't really set any though because I feel like getting used to a certain style that's not like the default would hinder me in working on other projects in the future.&lt;/p&gt;

&lt;p&gt;To be perfectly honest, choosing Prettier was just due to the fact that it was my first choice and I had seen it used all over the place. This week's lecture also spent a lot of time talking about Prettier so I thought I should get to know it. &lt;/p&gt;

&lt;h2&gt;
  
  
  ESLint
&lt;/h2&gt;

&lt;p&gt;ESLint is a tool for fixing minor syntax errors in your code. It's meant to be able to keep the code free of little problems that could end up breaking something in the future. Lint!&lt;/p&gt;

&lt;p&gt;Again, because ESLint is widely known and used I picked it because I wanted to get to know it and use that knowledge in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting it started
&lt;/h2&gt;

&lt;p&gt;For Prettier it was fairly easy. I followed the &lt;a href="https://prettier.io/docs/en/install.html"&gt;install page&lt;/a&gt; and ran the first command in my command line.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install --save-dev --save-exact prettier&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and likewise created my prettier config file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;echo {}&amp;gt; .prettierrc.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After this, I could add some custom styling in the config file but as I said above I decided not to do that.&lt;/p&gt;

&lt;p&gt;As for ESLint, I took similar steps following the ESLint &lt;a href="https://eslint.org/docs/user-guide/getting-started"&gt;getting started page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install eslint --save-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx eslint --init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All good! We can now lint any file we like with ESLint.&lt;/p&gt;

&lt;p&gt;Before I move on I also wanted to mention &lt;a href="https://github.com/prettier/eslint-config-prettier#installation"&gt;eslint-config-prettier&lt;/a&gt; because according to Prettier, this helps the two tools work together and not break each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  User experience
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Code after using Prettier
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (options.t) {
    var url = 'http://localhost:3000/posts/'

    req.get(
        {
            url: url,
            json: true,
            headers: {
                'User-Agent': 'request',
            },
        },
        (err, res, data) =&amp;gt; {
            if (err) {
                console.log('Error:', err)
            } else if (res.statusCode !== 200) {
                console.log(
                    'localhost did not respond... check to see if your local telescope session is up...',
                )
            } else {
                const urls = data.map((e) =&amp;gt; url + e.id)

                fs.writeFile(
                    'files/telescope.txt',
                    JSON.stringify(urls),
                    function (err) {
                        if (err) throw err
                    },
                )
            }
        },
    )
    //send file to be read
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the code looks a lot more readable! Prettier basically made all my code look like this and it's pretty great. The best part is I didn't even have to touch it! I clicked the button and my code was prettified.&lt;/p&gt;

&lt;h2&gt;
  
  
  ESLint
&lt;/h2&gt;

&lt;p&gt;Running ESLint with &lt;code&gt;npx eslint index.js&lt;/code&gt; revealed something...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bRWMOrgc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oy1cw1ke77f8n5aadgvd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bRWMOrgc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oy1cw1ke77f8n5aadgvd.png" alt="It caught something!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So ESLint caught the fact that we wrote createWriteStream and never used it! Great. Let's just remove it and move on.&lt;/p&gt;

&lt;p&gt;No other errors either! Which is pretty nice. Makes me feel pretty good about my code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The command line
&lt;/h2&gt;

&lt;p&gt;So, moving on from our first use of these tools, we want to allow the users to run a simple command and get these running on their own code.&lt;/p&gt;

&lt;h3&gt;
  
  
  package.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1",
    "prettier": "npx prettier --write .",
    "lint": "npx eslint ."
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see that I've written some scripts in my package.json so when the user inputs "prettier" or "lint" those tools will run! It's a fairly simple way to use the tools but there is another, even more consistent, way to get the user to run these scripts that I'll show in a moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  IDE Integration
&lt;/h2&gt;

&lt;p&gt;VSCode is a very useful IDE because you can just move over to the extensions tab and choose whatever you like, including Prettier and ESLint! You can even set shortcuts to run them on the IDE level.&lt;/p&gt;

&lt;p&gt;For new users however, I decided to recommend they install Prettier and ESLint.&lt;/p&gt;

&lt;h3&gt;
  
  
  .vscode/extensions.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "recommendations": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not 100% sure how it works but I believe with this file, any other user that wants to work on Link Checker in VSCode will be asked to install these extensions.&lt;/p&gt;

&lt;h2&gt;
  
  
  (Optional)
&lt;/h2&gt;

&lt;p&gt;I also went a little step further because I wanted to learn how to do this. I set up Prettier and ESlint in a pre-commit hook.&lt;/p&gt;

&lt;h3&gt;
  
  
  package.json excerpt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.js": "eslint --cache --fix",
    "*.{js,css,md}": "prettier --write"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can see here that &lt;a href="https://github.com/okonet/lint-staged"&gt;lint staged&lt;/a&gt; and &lt;a href="https://github.com/typicode/husky"&gt;husky&lt;/a&gt; are working together to run ESLint and Pettier before staging any commits. This means that no matter what, all commits will adhere to the linter and style guidelines! Next, I'd like to learn how to set up GitHub tests to test pull requests. If you'd like to add a pre-commit hook I recommend &lt;a href="https://prettier.io/docs/en/precommit.html"&gt;this prettier link&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;All in all, this week was very informative and I'm going to be taking these tools to every project I create and am a part of. I basically learned how useful linting and code formatting tools are and how to integrate them so that they automate themselves through pre-commit hooks. I felt that was probably the most important thing I learned this week and I'll probably come back to this blog post every time I start up a new project because this will be one of the first things I set up. &lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Lab 6 After a Break</title>
      <dc:creator>Ray</dc:creator>
      <pubDate>Sat, 07 Nov 2020 02:55:11 +0000</pubDate>
      <link>https://dev.to/fluentinstroll/lab-6-after-a-break-5dla</link>
      <guid>https://dev.to/fluentinstroll/lab-6-after-a-break-5dla</guid>
      <description>&lt;h2&gt;
  
  
  Well not much of a break.
&lt;/h2&gt;

&lt;p&gt;This week was filled with a couple of firsts. The first week of my new job and the first time using most of the programs introduced this week. It was also the first time I'll be working with &lt;a href="https://telescope.cdot.systems/"&gt;Telescope&lt;/a&gt; and the first time using git diffs and GitHub Gist. Both of which I'm not terribly sure if I have a full grasp of yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Set Up
&lt;/h2&gt;

&lt;p&gt;So for Lab 6, we were meant to set up Seneca's Telescope blog aggregator and to pump the links we get into our &lt;a href="https://github.com/fluentinstroll/Link-Checker"&gt;Link Checker&lt;/a&gt; apps. At least, we were meant to develop a proof of concept for the feature and upload the &lt;a href="https://gist.github.com/fluentinstroll/5d0e4e40f614bae68a9ebff40e01c210"&gt;diff&lt;/a&gt; to GitHub Gist.&lt;/p&gt;

&lt;p&gt;Seems easy, right? Well, it requires a little more effort than that.&lt;/p&gt;

&lt;p&gt;In order to set up Telescope we need 3 things: redis-server, Elasticsearch, and Docker. In order to properly run redis-server, we must also get WSL, a Linux subsystem for Windows.&lt;/p&gt;

&lt;p&gt;WSL was a slight pain to get working but now that I have it I think I might use it forever. Running a dual boot system for a while just to develop web apps because so cumbersome that I gave up early last year and just used Windows. But with WSL I can run a Ubuntu terminal in vscode and kill two birds with one stone. The only thing I have to look out for is accidentally having like 5 terminals open at once which... I'm doing right now to gather screenshots for this blog post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Am9KlLvj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ae4hzvhu0epn00ze6smy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Am9KlLvj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ae4hzvhu0epn00ze6smy.png" alt="It's up!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So redis-server is up, next is Elasticsearch. Now, I'm not too sure where I went wrong here but after properly installing Elasticsearch and getting it running properly, as well as verifying that all the ports were the same between them, I just couldn't get Elasticsearch to properly connect with the Telescope backend. This is unfortunate because I'd really like to get it properly working before I take a dive into Telescope for real. However, for just this lab, I was able to set up a limited Elasticsearch server to grab some blog posts from the API and help me with my work.&lt;/p&gt;

&lt;p&gt;Finally, Docker. I'm not too sure where Docker fits into everything because I ran everything separately. However, I think I'll try to get it all together in a Docker container for the future as it seems like it'll make development a lot easier. I had an issue with setting up Docker with my WSL that involved having the Hyper-V VM running which made Docker crash. Weird stuff, but after a bit of research, it was easy to fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit of coding
&lt;/h2&gt;

&lt;p&gt;The objective is this: grab links to blog posts from the Telescope backend API, pipe them into a text file, grab the links from that text file, and finally test them to make sure they're good links like my app already does.&lt;/p&gt;

&lt;p&gt;Simple, right?&lt;/p&gt;

&lt;p&gt;This is the part where I say no, but actually it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  index.js excerpt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (options.t) {

    var url = 'http://localhost:3000/posts/';

    req.get({
        url: url,
        json: true,
        headers: {
            'User-Agent': 'request'
        }
    }, (err, res, data) =&amp;gt; {
        if (err) {
            console.log('Error:', err);
        } else if (res.statusCode !== 200) {
            console.log('localhost did not respond... check to see if your local telescope session is up...');
        } else {
            const urls = data.map(e =&amp;gt; url + e.id)

            fs.writeFile('files/telescope.txt', JSON.stringify(urls), function (err) {
                if (err) throw err;
              }); 
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code basically queries the local version of the Telescope API for the post ids, then we just stick the rest of the url to the front of the id, then write it straight into a file. &lt;/p&gt;

&lt;h3&gt;
  
  
  more index.js excerpts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(options.t){
    filename = 'files/telescope.txt'
}
else {
        filename = `${argv[2]}`;
}
fs.readFile(filename, (err, fileContents) =&amp;gt; {
    try {
        var linkList = generateLinkList(fileContents);
        linkList = Array.from(linkList);
    } catch (err) {
        console.log("The app has recieved a wrong filename.")
        console.log("Please enter a correct filename.")
        exit(1);
    }
    validateLinks(linkList)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also a simple change to the rest of the code, writing an if statement to check if we've used our telescope argument, and setting the file to that if so! Easy.&lt;/p&gt;

&lt;p&gt;Frankly, I just had to add some connections to the local API and modify almost nothing else.&lt;/p&gt;

&lt;p&gt;I want to be clear that this code is a proof of concept as outline in the Lab 6 instructions, it's not mean to be comprehensive and perfect for every situation (for example, I could have it query a backend API that I host on a Heroku server or something so that I won't have to set up the local server every time to use it), but it works well for what it is. I can't wait to expand upon this feature and fix up the code to be a lot more modular, which I think is going to be my next big refactor.&lt;/p&gt;

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