What I've Coded This Week (Week 2—WWCode '100 Days of Code' Challenge)

Bianca Aspin - Jan 26 - - Dev Community

(Cover Image: The clock I created for the second project in the 'JavaScript30' course)

It's time for a recap of last week!

What I've Worked On This Week

Quick Links

JavaScript—JavaScript30 Project #2: JS and CSS Clock

I completed the second project in Wes Bos's JavaScript30 course: a clock! This exercise was an interesting challenge that gave me more experience with CSS animations (transformations and transitions), working with dates in JavaScript, and the setInterval function.

I have to admit, I spent a lot of time staring at this clock, watching the minutes tick away (for debugging... but also to admire the cubic bezier timing function that mimics the movement of physical clock hands). I thought my clock looked nice and functional as is. I hadn't even considered the possibility of adding any animation to it, but seeing the pizzazz the realistic recoil of the second hand added made me want to give it a try.

The tricky part was figuring out how to remedy the blip that occurred when a hand finished a complete rotation; it went back around to reset to its original position and then jumped back to where it was supposed to be.

In his lesson, Wes said that one way to resolve this issue would be to briefly remove the transition property when the second hand reaches 12:00. However, I later found out that when I disabled transition, the transition-timing-function wouldn't come back automatically, so I added additional logic to my code to get that working again.

const hands = [hourHand, minuteHand, secondHand]

if (secondDegrees === 90) {
    for (let hand of hands) hand.style.transition = "0s"
} else {
    for (let hand of hands) {
    hand.style.transition = "all 0.05s"
    hand.style.transitionTimingFunction = "cubic-bezier(0.1, 2.7, 0.58, 1)"
    }
}
Enter fullscreen mode Exit fullscreen mode

You can see the clock, the code, and a more detailed explanation on my GitHub.

Python—Adventures with Unit Testing

I've been continuing to work through the daily challenges in the WWCode Python Track and using them to get more practice with writing unit tests with Pytest. I learned a valuable lesson this week.

With the way I've been testing for exception handling in the challenges recently, my test would pass even before I'd written the corresponding code because a general TypeError was returned when the code failed.

def odd_or_even(integer):
    if integer % 2 == 0:
        return "Even"
    else:
        return "Odd"

def test_error():
    """Given an invalid input, return a TypeError."""
    string = "banana"
    with pytest.raises(TypeError):
        odd_or_even(string)
Enter fullscreen mode Exit fullscreen mode

The test passed, but when I ran the code myself using a string as an input, this was the message I received:

TypeError: not all arguments converted during string formatting

This message is problematic because it doesn't provide users with a clear reason why the code failed. I wanted to clarify what needs to change with the message, "Input must be an integer."

I did some research and found a very helpful resource (aside from the Pytest docs) that I will be reviewing in more detail as I continue building my unit testing skills: Pytest with Eric, in particular the post, "How To Test Python Exception Handling Using Pytest Assert (A Simple Guide)", which provided several examples of how to check for specific exceptions and messages.

From reviewing Eric's tutorial, I determined that in addition to the code I wrote above, I would need to capture the exception output in an object, excinfo (you could alias this object as anything you want, but this is how it is done in the official Pytest docs, too). That object has an attribute, value, which contains the error message. We'll convert that to a string to check against our desired message.

def test_error():
    """Given an invalid input, return a specific TypeError."""
    string = "banana"
    with pytest.raises(TypeError) as excinfo:
        odd_or_even(string)
    assert str(excinfo.value) == "Input must be an integer."
Enter fullscreen mode Exit fullscreen mode

Now our test fails:

AssertionError: assert 'not all argu...ng formatting' == 'Input must be an integer.'

E - Input must be an integer.

E + not all arguments converted during string formatting
Enter fullscreen mode Exit fullscreen mode

And now, we can modify the code to get that test to pass:

def odd_or_even(integer):
    if type(integer) is not int:
        raise TypeError("Input must be an integer.")
    if integer % 2 == 0:
        return "Even"
    else:
    return "Odd"
Enter fullscreen mode Exit fullscreen mode

React Native—Patching Packages

Following up from last week's post, where my friend and I were grappling with an issue with 'React Native Reanimated', the same errors came back to haunt us again this week. I forgot that, in addition to updating the plugins in the Babel.config.js file (which I discussed last week), there was also a change that we'd made within the 'React Native Reanimated' node package during the troubleshooting process that also contributed to resolving that issue (thanks to this GitHub issue).

But that could never be more than a temporary fix because:

  1. Whenever we next added more packages and ran npm install, that tweak would get overwritten.
  2. Because the node_modules directory is ignored by version control, anyone else installing the packages and running the code on their machine would encounter the same issue.

That's when another GitHub issue led me to the solution: the patch-package library. Here's how I used patch-package to fix this issue.

  1. I followed the instructions to install the library and updated "scripts" in package.json to run patch-package after each install.
"scripts": {
    "postinstall": "patch-package"
 }
Enter fullscreen mode Exit fullscreen mode
  1. I went into node_modules/react-native-reanimated/lib/module/index.web.js and updated the export default from export { _default as default }; to export default _default; as the GitHub issue conversation suggested.
  2. I ran npx patch-package react-native-reanimated.
  3. This generated a new directory, patches, with a patch file containing the diff for the package, that gets accessed with each npm install.

'Patches' directory created in repository containing the 'React-Reanimated' patch file

With this issue now put back to bed, I'm looking forward to doing a deep dive into React Native Calendars over this next week.

Looking Ahead

That's a wrap for this week!

Here's what's in the works ahead of next week:

I'll check in again next week to let you know how it all goes—stay tuned!

. . . . . . . .