Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions tests/snapshots/goodbye-cruel-world.snapshot.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
</head>
<body>
<div class="container">
<header class="d-flex flex-wrap justify-content-between align-items-center py-3 mb-4 border-bottom"><a href="/" class="flex text-muted text-decoration-none"><span class="fs-4">Johnathan Irvin</span></a><a href="/images" class="flex text-muted"><span>Images</span></a>
<header class="d-flex flex-wrap justify-content-between align-items-center py-3 mb-4 border-bottom"><a href="/" class="flex text-muted text-decoration-none"><span class="fs-4">Johnathan Irvin</span></a>
<div class="flex"><a href="/faq" class="text-decoration-none text-muted p-2"><span>faq</span></a><a href="/images" class="text-decoration-none text-muted p-2"><span>images</span></a>
</div>
</header>
</div>
<main id="main" class="container">
Expand Down Expand Up @@ -312,11 +314,11 @@ <h2 id="next-sprint">Next Sprint</h2>
</li>
</ul>
<ul class="nav list-unstyled d-flex col-md-12 justify-content-start d-flex">
<li class="ms-3"><a href="/rss.xml" class="text-muted">RSS Feed</a>
<li class="ms-3"><a href="/rss.xml" class="text-muted">rss feed</a>
</li>
<li class="ms-3"><span>| </span>
</li>
<li class="ms-3"><a href="/sitemap.xml" class="text-muted">Sitemap</a>
<li class="ms-3"><a href="/sitemap.xml" class="text-muted">sitemap</a>
</li>
</ul>
</footer>
Expand Down
8 changes: 5 additions & 3 deletions tests/snapshots/hello-world.snapshot.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
</head>
<body>
<div class="container">
<header class="d-flex flex-wrap justify-content-between align-items-center py-3 mb-4 border-bottom"><a href="/" class="flex text-muted text-decoration-none"><span class="fs-4">Johnathan Irvin</span></a><a href="/images" class="flex text-muted"><span>Images</span></a>
<header class="d-flex flex-wrap justify-content-between align-items-center py-3 mb-4 border-bottom"><a href="/" class="flex text-muted text-decoration-none"><span class="fs-4">Johnathan Irvin</span></a>
<div class="flex"><a href="/faq" class="text-decoration-none text-muted p-2"><span>faq</span></a><a href="/images" class="text-decoration-none text-muted p-2"><span>images</span></a>
</div>
</header>
</div>
<main id="main" class="container">
Expand Down Expand Up @@ -61,11 +63,11 @@ <h2 id="conclusion">Conclusion</h2>
</li>
</ul>
<ul class="nav list-unstyled d-flex col-md-12 justify-content-start d-flex">
<li class="ms-3"><a href="/rss.xml" class="text-muted">RSS Feed</a>
<li class="ms-3"><a href="/rss.xml" class="text-muted">rss feed</a>
</li>
<li class="ms-3"><span>| </span>
</li>
<li class="ms-3"><a href="/sitemap.xml" class="text-muted">Sitemap</a>
<li class="ms-3"><a href="/sitemap.xml" class="text-muted">sitemap</a>
</li>
</ul>
</footer>
Expand Down
56 changes: 56 additions & 0 deletions tests/test_integrations/test_faq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) 2022 Johnathan P. Irvin
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import pytest


def test_faq(client):
"""
Test the FAQ page.

Args:
client (test_client): The test client.
"""
response = client.get('/faq')

assert response.status_code == 200
assert 'Frequently Asked Questions' in response.text

@pytest.mark.parametrize('question', [
"What experience do you have in the field of software development?",
"How did you get into software development?",
"What are your strengths and weaknesses?",
"What salary are you looking for?",
"Are you willing to relocate?",
"When can you start?",
"Describe a time when you had to overcome a challenge at work.",
"Describe a time when you made a mistake at work and how you handled it.",
])
def test_faq_questions(client, question: str):
"""
Test the FAQ questions.

Args:
client (test_client): The test client.
question (str): The question to test.
"""
response = client.get('/faq')

assert question in response.text
55 changes: 55 additions & 0 deletions website/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@

@app.route('/')
def index() -> str:
"""
Render the index page.

Returns:
str: The rendered index page.
"""
return flask.render_template(
'index.pug',
posts=sorted(
Expand Down Expand Up @@ -77,6 +83,18 @@ def image(name: str) -> str:

@app.route('/articles/<int:year>/<int:month>/<int:day>/<string:description>')
def article(year: int, month: int, day: int, description: str) -> str:
"""
Returns the article with the given description.

Args:
year (int): The year of the article.
month (int): The month of the article.
day (int): The day of the article.
description (str): The description of the article.

Returns:
str: The rendered template.
"""
try:
post = blog_repo.get(f"{year}/{month}/{day}/{description}")
except Repository.NotFound:
Expand All @@ -98,6 +116,12 @@ def article(year: int, month: int, day: int, description: str) -> str:
@app.route('/rss')
@app.route('/feed')
def rss() -> str:
"""
Returns the RSS feed.

Returns:
str: The rendered template.
"""
sorted_items = sorted(
blog_repo.get_all(),
key=lambda post: post.date,
Expand All @@ -119,6 +143,12 @@ def rss() -> str:
@app.route('/sitemap.xml')
@app.route('/sitemap')
def sitemap() -> str:
"""
Returns a sitemap of the website.

Returns:
str: The rendered template.
"""
sorted_items = sorted(
blog_repo.get_all(),
key=lambda post: post.date,
Expand All @@ -133,6 +163,31 @@ def sitemap() -> str:
response.mimetype = 'application/xml'
return response


with open('website/static/faq.md', 'r') as file:
QUESTION_MARKDOWN = file.read()
@app.route('/faq')
def faq() -> str:
"""
Returns the FAQ page.

Returns:
str: The rendered template.
"""
return flask.render_template(
'faq.pug',
content=markdown.markdown(
QUESTION_MARKDOWN,
extensions=['fenced_code', 'toc', 'tables'],
)
)

@app.errorhandler(404)
def not_found(error: Exception) -> str:
"""
Returns the 404 page.

Returns:
str: The rendered template.
"""
return flask.render_template('404.pug'), 404
68 changes: 68 additions & 0 deletions website/static/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
[TOC]

## What experience do you have in the field of software development?

I have written everything from the front-end user interfaces to the backend database and everything in between. I have spent time writing software multiples companies ranging from small to large. I have written software for several industries including cybersecurity, retail, and manufacturing.

I have a passion for teaching and mentoring others. I have taught software development to dozens of people over the years. I have taught in both formal and informal settings. I have also written blog posts.

## How did you get into software development?

Since I was a toddler I have had an interest in computers. I attempted to take my toys and shove them into my parents' computer to "make them work." Despite many years, I've never been able to get a 3.5-inch floppy disk to work with any of my oddly shaped plastic toys.

Later, when I was about seven years old, my father stole me away to the library. He showed me how to use the computers there. I was hooked. The library's computers had time limits. I wasn't able to explore them for more than half-an-hour. That day we went home with a book on QBasic.

## What are your strengths and weaknesses?

My biggest strength is providing creative solutions. I show promise in my attention to detail and dedication to my work. I also have experience leading teams, which has forced me into effective communication.

My weaknesses include my occasional perfectionism, which can lead to me spending too much time on minor details, and my tendency to get bogged down in the details of a problem instead of seeing the big picture.

## What salary are you looking for?

A salary should be fair and commensurate with my experience and qualifications. The proposal should also reflect the company's budget and the current market value for my skill set. If the range on the provided contract or job description is too low, I will be sure to decline professionally.

Contact me on Linkedin if you are interested in working with me.

## Are you willing to relocate?

Relocation is obsolete for software engineers. The industry has shifted to allow for work from home. These options eliminate the need for expensive relocations.

The cost of living and working in different parts of the country can be expensive, and often requires a higher salary to maintain the same standard of living. This is especially true in larger metropolitan areas.

The work from home options that are available for software engineers eliminates the need for costly relocations, and allows for a more flexible lifestyle.

## When can you start?

I need four weeks before starting a new employment. Two weeks for my current employer and two weeks for vacation.

The vacation is a reward because life is too short to work all the time.

## Describe a time when you had to overcome a challenge at work.

I once took over a team of engineers on a code base written by a single junior engineer. Code was in a terrible state, the project was behind schedule, and feature delivery time was on a downward spiral. I had to work long hours for several months to get the team back on track. The frustrated customer became happy again.

I was able to turn the team around by doing a few things:

1. I sat down with the team and discussed the current and future state of the project.
2. I set up a daily stand-up meeting so that everyone could stay on the same page.
3. I instituted a code review process for all merges.
4. I worked closely with each team member, providing daily 1-on-1 guidance.
5. I consistently under-promised and over-delivered.
6. I implemented trunk-based development.
7. I reduced deployment cycles from 1 month to 1 week with intentions for daily deployments.
8. I automated end-to-end testings, eliminating multiple-day manual quality assurance tests.

## Describe a time when you made a mistake at work and how you handled it.

I dropped a production environment.

I had just taken over a project with an "interesting" deployment strategy. It used a bunch of semi-manual jobs and required manual developer intervention. One of the extra jobs happened to be "drop production."

I was in the process of releasing a new version to a production environment when I clicked the little devil. It was late, as most production deployments are. I was the only one in the office. I remember thinking, "Oh crap, I shouldn't have done that."

Fortunately, I quickly got everything back up and running with some backups taken before I went into maintenance mode. Bonus, this software was in early beta.

The meeting with my boss in the morning was interesting. I killed the button while my boss watched.

It happens to the best of us.
8 changes: 8 additions & 0 deletions website/templates/faq.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extends layout.pug

block title
title FAQ - Johnathan Irvin

block content
h1.h1 Frequently Asked Questions
article {{ content }}
11 changes: 7 additions & 4 deletions website/templates/layout.pug
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ block header
.container: header.d-flex.flex-wrap.justify-content-between.align-items-center.py-3.mb-4.border-bottom
a(href="/").flex.text-muted.text-decoration-none
span.fs-4 Johnathan Irvin
a(href="{{ url_for('images') }}").flex.text-muted
span Images
.flex
a(href="{{ url_for('faq') }}").text-decoration-none.text-muted.p-2
span faq
a(href="{{ url_for('images') }}").text-decoration-none.text-muted.p-2
span images

block body
main#main.container
Expand All @@ -27,6 +30,6 @@ block footer
li.ms-3: a.text-muted(href="https://www.linkedin.com/in/johnnyirvin/" target="_blank")
img(src="{{url_for('static', filename='img/linkedin.svg')}}", alt="LinkedIn")
ul.nav.list-unstyled.d-flex.col-md-12.justify-content-start.d-flex
li.ms-3: a.text-muted(href="/rss.xml") RSS Feed
li.ms-3: a.text-muted(href="/rss.xml") rss feed
li.ms-3: span |
li.ms-3: a.text-muted(href="/sitemap.xml") Sitemap
li.ms-3: a.text-muted(href="/sitemap.xml") sitemap