In the tests for nameLens on the Lens Person exercise, I think there may be an issue.
The test for ensuring immutability expects that the test data person object’s name should not equal “Sara Lakshamanan”.
I think there are several issues causing this test to always pass.
First, it only applies to the “forename” test, where the lens is used to set a new name of “Sara Lakshmanan”. This test doesn’t make sense at all if the “surname” test is not skipped, since in an “incorrect” solution, where the object is mutated, it would then equal “Saravanan Laksh”.
The other issue is that: “Lakshamanan” and “Lakshmanan” are not equal, so even with skipping the “surname” test, this test will always pass.
There is a second typo issue in the streetLens, since “street” and “Street” are not equal.
The first issue doesn’t apply to the other test groups, as they only have one .set test, however I think it would still be better to replace each of these with a test positively checking the specific property of person, or the full expected object:
I may just not be understanding the exercise, but get(person) and set(person, value) are defined in the Lens class, but they aren’t necessary since the values provided when using the class replace them.
Also I think there should be more tests, to discourage hard-coding.
Opinion
Also I don’t think the premise of this exercise is entirely valid?
The example given from Haskell does indeed seem very messy, but it isn’t nearly as bad in JavaScript.
Plus why is there a need for an exercise about this functional programming concept in (what I believe to be) an object-oriented language?
@FriendlyUser1 In my humble opinion Javascript, as it is used today in most environments, is very much a functional language. Yes, it supports OOP functionality but with most modern frameworks it feels like that’s really not the focus. It’s very much a matter of choice tho.
AS for the exercise tests, PRs are welcome if you have the time and energy to work on this. You’d also want to discuss with @SleeplessByte (our resident JS track maintainer (sorry for the ping)).
I have found another issue with the tests in this exercise. None of the tests for the lens.set method check that the value has actually been set, they just check that the original object hasn’t been mutated. Not a big issue, but kinda fun that this little snippet passes the tests:
Wow, indeed. The tests check whether the “lens” get value (nameLens(obj)) equals to the “long way round” value (obj.name), but not what that value actually is.
You don’t even have to copy anything, really. You can get away with o => o.
I think this exercise should be redesigned. I should probably open a new thread, but in short:
I looked into what Lenses actually are. A big property of theirs is that they’re composable. So streetLens should be created with lens('address') + lens('street') (preudocode)
A really simplified explanation on Lenses I’ve found here.
So just writing new Lens(p => p.name, (p, v) => { ...o, name: v }) is not using lenses.
Even the Haskell and Scala track don’t require the lens-related functions to be provided to the tests, just the final wrapper that returns the name, address, etc… The “proper” solution is to implement and use lenses within your code, going on that wiki page for Haskell.
The fact that you can solve the exercise without actually interacting with the topic might be a teachable moment in Haskell/Scala - I’m not sure - if the non-lens way is longer and more tedious than the functional way; but in JS a method that accesses a field is rather trivial.