@@ -191,7 +191,7 @@ I'm adding the code inline, in a `<script>` tag
191
191
at the bottom of our _base.html_ template:
192
192
193
193
[role="sourcecode"]
194
- .lists/templates/base.html
194
+ .lists/templates/base.html (ch16l004)
195
195
====
196
196
[source,javascript]
197
197
----
@@ -398,7 +398,8 @@ src/lists/static/tests
398
398
└── jasmine_favicon.png
399
399
----
400
400
401
- We need to go edit the _SpecRunner.html_ file to take into account the things we've moved around:
401
+ We need to go edit the _SpecRunner.html_ file
402
+ to take into account the things we've moved around:
402
403
403
404
404
405
[role="sourcecode"]
@@ -593,55 +594,120 @@ so that one test can't affect another.
593
594
594
595
595
596
Let's now have a play with our testing framework,
596
- to see if we find DOM elements and make assertions on whether they are visible.
597
- We'll also try manually hiding an element, from the tests,
598
- just as an experiment, before we write any of our "real" JS code.
597
+ to see if we can find DOM elements and make assertions on whether they are visible.
598
+ We'll also try the same `style.display=none` hiding technique
599
+ that we originally used in our spiked code.
599
600
600
601
601
602
[role="sourcecode"]
602
603
.lists/static/tests/Spec.js (ch16l011)
603
604
====
604
605
[source,javascript]
605
606
----
606
- it("smoke test for checking visibility", () => {
607
- const errorDiv = document.querySelector("div.invalid-feedback"); //<1>
608
- expect(errorDiv.checkVisibility()).toBe(true, "error div should be visible on load"); //<2>
609
- errorDiv.style.display = "none"; //<3>
610
- expect(errorDiv.checkVisibility()).toBe(false, "js hiding should work"); //<4>
607
+ it("sense check our html fixture", () => {
608
+ const errorMsg = document.querySelector("div.invalid-feedback");
609
+ expect(errorMsg.checkVisibility()).toBe(true); //<1>
610
+ });
611
+
612
+ it("check we know how to hide things", () => {
613
+ const errorMsg = document.querySelector("div.invalid-feedback");
614
+ errorMsg.style.display = "none"; //<2>
615
+ expect(errorMsg.checkVisibility()).toBe(false); //<3>
611
616
});
612
617
----
613
618
====
614
619
615
- <1> We retrieve our error div with `document.querySelector`,
616
- which is probably the easiest way to find a particular piece of the DOM,
617
- in modern plain-old JavaScript (does anyone still remember jQuery?).
618
-
619
- <2> Another fairly new API in JavaScript-Land is `checkVisibility()`.
620
- Notice we're also adding a second argument in the `.toBe()` clause,
621
- which is the message that will be printed if the test fails.
620
+ <1> We retrieve our error div with `querySelector` again,
621
+ and then use another fairly new API in JavaScript-Land called `checkVisibility()`.
622
622
623
623
<3> We manually hide the element in the test,
624
624
by setting its `style.display` to "none".
625
625
626
626
<4> And we check it worked, with `checkVisibility()` again.
627
627
628
628
629
- TODO: on-fail messages are deprecated in jasmine,
630
- split out separate `it()` for default state.
629
+ Notice that I'm being really good about splitting things out into multiple tests,
630
+ with one assertion each.
631
+ Jasmine encourages that, for example, by deprecating the ability to pass
632
+ on-failure messages into individual `expect/toBe` expressions.
633
+
631
634
632
635
If you refresh the browser, you should see that all passes:
633
636
637
+
634
638
.Expected results from Jasmine in the browser
635
639
====
636
640
[role="jasmine-output"]
637
641
----
638
- 1 spec , 0 failures, randomized with seed 12345 finished in 0.009s
642
+ 2 specs , 0 failures, randomized with seed 12345 finished in 0.01s
639
643
640
644
Superlists tests
641
- * smoke test for checking visibility
645
+ * check we know how to hide things
646
+ * sense check our html fixture
642
647
----
643
648
====
644
649
650
+ (I'll show the Jasmine outputs as text, like the above, from now on,
651
+ to avoid filling the chapter with screenshots.)
652
+
653
+
654
+ ////
655
+ rough content, i think i prefer doing it the real way tho.
656
+
657
+
658
+ ==== Testing Bootsrap-related functionality
659
+
660
+ When hacking about in devtools, we found out that what we actually
661
+ want to do is remove the `is-invalid` class from the input element.
662
+ Let's just see if that works
663
+
664
+ [role="sourcecode"]
665
+ .src/lists/static/tests/Spec.js (ch16l012)
666
+ ====
667
+ [source,python]
668
+ ----
669
+ it("check we know how to hide things", () => {
670
+ const textInput = document.querySelector("#id_text");
671
+ const errorMsg = document.querySelector(".invalid-feedback");
672
+ // errorMsg.style.display = "none"; //<1>
673
+ textInput.classList.remove("is-invalid"); //<2>
674
+ expect(errorMsg.checkVisibility()).toBe(false);
675
+ });
676
+ ----
677
+ ====
678
+
679
+ <1> Let's comment out our `style.display` hackery for now
680
+ <2> Instead we'll try removing the `is-invalid` class,
681
+ using the `.classList` API (https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)
682
+
683
+
684
+ ===== An Unexpected Failure
685
+
686
+ Nope, an unexpected failure:
687
+
688
+
689
+ [role="jasmine-output"]
690
+ ----
691
+ 2 specs, 1 failure, randomized with seed 12345 finished in 0.01s
692
+ Spec List | Failures
693
+
694
+ Superlists tests > check we know how to hide things
695
+ Expected true to be false.
696
+ <Jasmine>
697
+ @file:///...goat-book/src/lists/static/tests/Spec.js:37:40
698
+ <Jasmine>
699
+ ----
700
+
701
+
702
+
703
+ <link rel="stylesheet" href="lib/jasmine-4.6.1/jasmine.css">
704
+
705
+ <!-- Bootstrap CSS -->
706
+ <link href="../bootstrap/css/bootstrap.min.css" rel="stylesheet">
707
+
708
+ <script src="lib/jasmine-4.6.1/jasmine.js"></script>
709
+ ////
710
+
645
711
646
712
647
713
=== Building a JavaScript Unit Test for Our Desired Functionality
@@ -657,46 +723,39 @@ we can switch back to just one test and start to write the real thing:
657
723
====
658
724
[source,javascript]
659
725
----
660
- it("error message should be hidden on input", () => { //<1>
661
- const inputSelector = "input#id_text";
662
- const errorSelector = "div.invalid-feedback";
663
- const textInput = document.querySelector(inputSelector); //<2>
664
- const errorDiv = document.querySelector(errorSelector);
665
- expect(errorDiv.checkVisibility()).toBe(true, "error div should be visible on load"); //<3>
726
+ it("sense-check our html fixture", () => { //<1>
727
+ const errorMsg = document.querySelector(".invalid-feedback");
728
+ expect(errorMsg.checkVisibility()).toBe(true);
729
+ });
666
730
667
- initialize(textInput, errorDiv); //<4>
731
+ it("error message should be hidden on input", () => { //<2>
732
+ const textInput = document.querySelector("#id_text"); //<3>
733
+ const errorMsg = document.querySelector(".invalid-feedback");
668
734
669
- expect(errorDiv.checkVisibility()).toBe(true, "error div should not be hidden by initialize()") ; //<5 >
735
+ textInput.dispatchEvent(new InputEvent("input")) ; //<4 >
670
736
671
- textInput.dispatchEvent(new InputEvent("input")); //<6>
672
- expect(errorDiv.checkVisibility()).toBe(false, "error div should be hidden on input"); //<7>
737
+ expect(errorMsg.checkVisibility()).toBe(false); //<5>
673
738
});
674
739
----
675
740
====
676
741
677
- <1> Let's change our test name to a description of what we want to happen;
742
+ <1> Let's keep the first smoke test, it's not doing any harm.
743
+
744
+ <2> Let's change the second one, and give it a name that describes
745
+ what we want to happen;
678
746
our objective is that, when the user starts typing into the input box,
679
747
we should hide the error message.
680
748
681
- <2 > We retrieve the `<input>` element from the DOM,
749
+ <3 > We retrieve the `<input>` element from the DOM,
682
750
in a similar way to how we found the error message div.
683
751
684
- <3> We leave our old assertion in-place,
685
- just to sense-check that our fixtures start out with the error visible,
686
- like the real page will when we render an error for the user.
752
+ <4> Here's how we simulate a user typing into the input box.
687
753
688
- <4> Here's where we start "programming by wishful thinking".
689
- Let's imagine we have an `initialize()` function to set up our auto-hiding behaviour.
690
- We pass in the input element to watch for input events,
691
- and the error div that we want to hide.
692
-
693
- <5> Let's sense-check once again that our `initialize()` function doesn't
694
- just cheekily hide the error div immediately.
754
+ <5> And here's our real assertion: the error div should be hidden after
755
+ the input box sees an input event.
695
756
696
- <6> Here's how we simulate a user typing into the input box.
697
757
698
- <7> And here's our real assertion: the error div should be hidden after
699
- the input box sees an input event.
758
+ TODO resume here
700
759
701
760
702
761
And that gives us a fairly silly error,
0 commit comments