(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
- Python—Adventures with Unit Testing
- React Native—Patching Packages
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)"
}
}
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)
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."
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
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"
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:
- Whenever we next added more packages and ran
npm install
, that tweak would get overwritten. - 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.
- I followed the instructions to install the library and updated "scripts" in
package.json
to runpatch-package
after each install.
"scripts": {
"postinstall": "patch-package"
}
- I went into
node_modules/react-native-reanimated/lib/module/index.web.js
and updated the export default fromexport { _default as default };
toexport default _default;
as the GitHub issue conversation suggested. - I ran
npx patch-package react-native-reanimated
. - This generated a new directory,
patches
, with a patch file containing the diff for the package, that gets accessed with eachnpm install
.
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:
- Continuing to explore React Native Calendars
- Continuing JavaScript30 and Python Daily Challenges
- Starting Kevin Powell's Responsive Design Course
I'll check in again next week to let you know how it all goes—stay tuned!
Top comments (0)