-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprovided.js
More file actions
667 lines (569 loc) · 23.6 KB
/
provided.js
File metadata and controls
667 lines (569 loc) · 23.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
/*
THIS IS NOT THE CODE YOU ARE LOOKING FOR!
This file contains the provided functions and tests. The coding environment for this project are in the file script.js.
DO NOT EDIT THIS FILE!
*/
/* Variables storing an audio objects to make the various sounds. See how it's used for the 'click' sound in the provided function below. */
let clickAudio = new Audio('audio/click.wav');
let matchAudio = new Audio('audio/match.wav');
let winAudio = new Audio('audio/win.wav')
/*
OVERVIEW:
Attaches an mouseclick listener to a card (i.e. onclick), flips the card when clicked, and calls the function 'onCardFlipped' after the flip is complete.
INPUT/OUPUT
The 'cardObject' parameter is a custom card object we created in the 'createCards' function.
This function will make the card element associated with 'cardObject' clickable and call onCardFlipped with that cardObject after the flip is complete.
*/
function flipCardWhenClicked(cardObject) {
// Adds an "onclick" attribute/listener to the element that will call the function below.
cardObject.element.onclick = function() {
// THE CODE BELOW RUNS IN RESPONSE TO A CLICK.
// Card is already flipped, return.
if (cardObject.element.classList.contains("flipped")) {
return;
}
// Play the "click" sound.
clickAudio.play();
// Add the flipped class immediately after a card is clicked.
cardObject.element.classList.add("flipped");
// Wait 500 milliseconds (1/2 of a second) for the flip transition to complete and then call onCardFlipped.
setTimeout(function() {
// THE CODE BELOW RUNS AFTER a 500ms delay.
onCardFlipped(cardObject);
}, 500);
};
}
function createNewCardTest() {
const TEST_NAME = "createNewCardTest";
// Check step 1 heuristics.
let variableAndCreateElementPresentSpec =
functionSpec(createNewCard)
.contains("let")
.or("var")
.or("const")
.andThen("createElement");
let passedStep1Heuristics =
checkFunctionSpec(variableAndCreateElementPresentSpec);
let step1Hint = constructHintMessage(1, `Try starting by calling document.createElement — this will create and return a new DOM element (the card) that you can store in a variable.`, RESOURCES.createElement);
// Check step 2 heuristics.
let classListAddPresentSpec =
functionSpec(createNewCard)
.contains("classList.add")
.andThen("card")
let classNameEqualsPresentSpec =
functionSpec(appendNewCard)
.contains("className")
.andThen("card");
let passedStep2Heuristics =
checkFunctionSpec(classListAddPresentSpec) ||
checkFunctionSpec(classNameEqualsPresentSpec);
let step2Hint = constructHintMessage(2, `Remember that you can access and manipulate an element's classes using cardElement.classList. Try checking out the docs for classList.add().`, RESOURCES.classListAdd);
let usesInnerHtml =
functionSpec(createNewCard)
.contains(".innerHTML");
let passedStep3Heuristics =
checkFunctionSpec(usesInnerHtml);
let step3Hint = constructHintMessage(3, `Try using innerHTML on your card element to define the two new divs with JavaScript template literals (using the backticks). You can define the divs with the same HTML syntax you use in your index.html!`, RESOURCES.innerHTML);
// Run user function.
let card;
let exception = callUserCode(() => {
card = createNewCard();
});
if (card == undefined) {
if (!passedStep1Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step1Hint);
} else if (!passedStep2Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2Hint);
} else if (!passedStep3Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step3Hint);
} else {
console.log(constructErrorMessage(TEST_NAME, 4, `We don't see a return value. Remember to return cardElement!`));
}
return false;
}
if (!(card instanceof Element)) {
console.log(constructErrorMessage(TEST_NAME, 4, `This function should return a DOM element, but that's not what we got.`));
return false;
}
if (card.tagName.toLowerCase() != "div") {
console.log(constructErrorMessage(TEST_NAME, 1, `The card should be a 'div' element but we got something else. Remember to use a 'div'!`));
console.log("\nHere's what the HTML looks like:\n" +
serialize(card) + "\n");
console.log(step1Hint);
}
if (!card.classList.contains("card")) {
console.log(constructErrorMessage(TEST_NAME, 2, `The card div should have a class named 'card'.`));
console.log("\nHere's what the HTML looks like:\n" +
serialize(card) + "\n");
console.log(step2Hint);
}
if (card.children.length !== 2) {
console.log(constructErrorMessage(TEST_NAME, 3, `You should be adding exactly 2 children to the innerHTML of the card, but we see ${card.children.length}.`));
console.log("\nHere's what the HTML looks like:\n" +
serialize(card) + "\n");
console.log(step3Hint);
return false;
}
let cardDown = card.children[0];
let cardUp = card.children[1];
if (!cardDown.classList.contains("card-down")) {
console.log(constructErrorMessage(TEST_NAME, 3, `The first child of the card should be a div with the class 'card-down'.`));
console.log("\nHere's what the HTML looks like:\n" +
serialize(card) + "\n");
console.log(step3Hint);
return false;
}
if (!cardUp.classList.contains("card-up")) {
console.log(constructErrorMessage(TEST_NAME, 3, `The second child of the card should be a div with the class 'card-up'.`));
console.log("\nHere's what the HTML looks like:\n" +
serialize(card) + "\n");
console.log(step3Hint);
return false;
}
outputPassMessage(TEST_NAME);
return true;
}
function appendNewCardTest() {
const TEST_NAME = "appendNewCardTest";
// Check step 1 heuristics.
let variableAndCreateCardPresentSpec =
functionSpec(appendNewCard)
.contains("let")
.or("var")
.or("const")
.andThen("createNewCard");
let passedStep1Heuristics =
checkFunctionSpec(variableAndCreateCardPresentSpec);
let step1Hint = constructHintMessage(1, `You should be starting by calling 'createNewCard' and storing the result in a variable.`, RESOURCES.createElement);
let usesAppendChild =
functionSpec(appendNewCard)
.contains(".appendChild");
let passedStep2Heuristics =
checkFunctionSpec(usesAppendChild);
let step2Hint = constructHintMessage(2, `Try using the appendChild method on the parentElement and pass in your new card element as the argument.`, RESOURCES.appendChild);
// Run user function.
let returnValue;
let parent = document.createElement("div");
parent.setAttribute("id", "card-container");
let exception = callUserCode(() => {
returnValue = appendNewCard(parent);
});
if (parent.children.length !== 1) {
if (!passedStep1Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step1Hint);
} else if (!passedStep2Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2Hint);
} else {
console.log(constructErrorMessage(TEST_NAME, 4, `The 'parentElement' does not have any children. Remember to append the new card to 'parentElement'.`));
console.log(step4Hint)
console.log("\nHere's what the HTML looks like:\n\n" + serialize(parent) + "\n\n");
}
return false;
}
let card = parent.children[0];
if (!card.classList.contains("card")) {
console.log(constructErrorMessage(TEST_NAME, 2, `The child of parentElement should be a card. Remember to add the 'card' class to this element.`));
console.log(step2Hint);
console.log("\nHere's what the HTML looks like:\n\n" + serialize(parent) + "\n\n");
}
if (returnValue !== card) {
console.log(constructErrorMessage(TEST_NAME, 3, `The return value of this function should be the card but that's not what we got.`));
console.log(constructHintMessage(3, "Remember to return the cardElement you just made!"));
return false;
}
if (exception != undefined) {
console.error(constructErrorMessage(TEST_NAME, "?", `We encountered an error running your function`));
return false;
}
outputPassMessage(TEST_NAME);
return true;
}
function shuffleCardImageClassesTest() {
const TEST_NAME = "shuffleCardImageClassesTest";
// Check step 1 heuristics.
let variableDeclarationAndClassesPresentSpec =
functionSpec(shuffleCardImageClasses)
.contains("let")
.or("var")
.or("const")
.andThen("[")
.andThen("image-1")
.andThen("image-1")
.andThen("image-2")
.andThen("image-2")
.andThen("image-3")
.andThen("image-3")
.andThen("image-4")
.andThen("image-4")
.andThen("image-5")
.andThen("image-5")
.andThen("image-6")
.andThen("image-6")
.andThen("]");
let passedStep1Heuristics =
checkFunctionSpec(variableDeclarationAndClassesPresentSpec);
let step1Hint = constructHintMessage(1, `Try starting by declaring a variable that holds an array of strings in the form ["image-1", "image-1", "image-2", "image-2", "image-3", ... , "image-6", "image-6"]`, RESOURCES.arrays);
let step2HintLoadUnderscore = constructHintMessage(2, `The CDN for underscore must be included in your script tags above all other scripts, like this: ${COLOR_CODE.cyan}<script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script>${COLOR_CODE.reset}`)
// Check step 3 heuristics.
let underScoreAndShuffleUsed =
functionSpec(shuffleCardImageClasses)
.contains("_")
.andThen(".shuffle");
let passedStep3Heuristics =
checkFunctionSpec(underScoreAndShuffleUsed);
let step3Hint = constructHintMessage(3, `We did not find use of _.shuffle. Your return needs to use _.shuffle using your image classes as the argument.`, RESOURCES.underscore);
// Check for underscore availability and exceptions.
let exception = callUserCode(() => {
shuffleCardImageClasses();
});
if (exception != undefined) {
if (!passedStep1Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 2));
console.log(step1Hint);
} else if (exception.toString().includes('_ is not defined')) {
console.log(constructErrorMessage(TEST_NAME, 2, "JavaScript does not understand the _ (underscore) in your code, meaning that the underscore.js library was not properly loaded."));
console.log(step2HintLoadUnderscore);
} else {
console.error(constructErrorMessage(TEST_NAME, "?", `We encountered an error running your function`));
return false;
}
return false;
}
let imageArray1;
let imageArray2;
let imageArray3;
let imageArray4;
exception = callUserCode(() => {
imageArray1 = shuffleCardImageClasses();
imageArray2 = shuffleCardImageClasses();
imageArray3 = shuffleCardImageClasses();
imageArray4 = shuffleCardImageClasses();
});
if (exception != undefined) {
console.error(constructErrorMessage(TEST_NAME, "?", `We encountered an error running your function`));
return false;
}
// Check for objects.
if (typeof imageArray1 != "object" ||
typeof imageArray2 != "object" ||
typeof imageArray3 != "object" ||
typeof imageArray4 != "object") {
if (!passedStep1Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 3));
console.log(step1Hint);
} else if (!passedStep3Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 3));
console.log(step3Hint);
} else {
console.log(constructErrorMessage(TEST_NAME, 3, "Your function should be returning an array but it's not."))
console.log(constructHintMessage(3, "Remember to write a return statement!"));
}
return false;
}
let allStrings = imageArray1.every(
el => (typeof el === "string"));
if (!allStrings) {
console.error(constructErrorMessage(TEST_NAME, 1, 'Your function should return an array of all strings but array elements were not all strings.'));
console.log(constructHintMessage(3, "Remeber to wrap your strings inside double or single quotes."));
return false;
}
let allGoodClassNames = imageArray1.every(
el => {
return el.startsWith('image-') &&
el.length == 7 &&
(el[6] >= 1 && el[6] <= 6);
});
if (!allGoodClassNames) {
console.log(constructErrorMessage(TEST_NAME, 1, "It looks like one or more of the string elements in your array have been misnamed. Please stick to 2 sets of 'image-1' through 'image-6', in string format."));
return false;
}
countHash = {};
for (let i = 1; i <= 6; i++) {
countHash[String(i)] = 0;
}
imageArray1.forEach(el => {
countHash[el[6]]++;
});
for (let i = 1; i <= 6; i++) {
if (countHash[String(i)] != 2) {
console.log(constructErrorMessage(TEST_NAME, 1, "You need to have exactly 2 of each image class (image-1 to image-6) in your array. It looks like that's not the case."));
return false;
}
}
let allSame = true;
for (let i = 0; i < imageArray1.length; i++) {
if (imageArray1[i] != imageArray2[i] ||
imageArray1[i] != imageArray3[i] ||
imageArray1[i] != imageArray4[i]) {
allSame = false;
break;
}
}
if (allSame) {
console.log(constructErrorMessage(TEST_NAME, 2, ` Function should return a random array of class names but 4 comparison calls returned the same array.`));
console.log(constructHintMessage(2, `Make sure to shuffle by calling _.shuffle using your array as the argument!`, RESOURCES.underscore));
return false;
}
outputPassMessage(TEST_NAME);
return true;
}
function createCardsTest() {
const TEST_NAME = "createCardsTest";
// Check step 1 heuristics.
let variableAndEmptyArrayPresentSpec =
functionSpec(createCards)
.contains("let")
.or("var")
.or("const")
.andThen("[]");
let passedStep1Heuristics =
checkFunctionSpec(variableAndEmptyArrayPresentSpec);
let step1Hint = constructHintMessage(1, `Try starting by creating a variable that holds an empty array: [].`, RESOURCES.arrays);
// Check step 2 heuristics.
let forLoopPresentSpec =
functionSpec(createCards)
.contains("for")
.andThen("12")
.andThen("++");
let passedStep2Heuristics =
checkFunctionSpec(forLoopPresentSpec);
let step2Hint = constructHintMessage(2, `Try checking that you have a for loop iterating 12 times.`, RESOURCES.forLoops);
// Check step 2a heuristics.
let variableappendNewCardPresentSpec =
functionSpec(createCards)
.contains("let")
.or("var")
.or("const")
.andThen("appendNewCard");
let passedStep2aHeuristics =
checkFunctionSpec(variableappendNewCardPresentSpec);
let step2aHint = constructHintMessage("2a", `Try declaring a variable that stores the result of calling appendNewCard with the argument 'parentElement'.`);
// Check step 2b heuristics.
let classListAddPresentSpec =
functionSpec(createCards)
.contains("classList.add")
.andThen("shuffledImageClasses");
let passedStep2bHeuristics =
checkFunctionSpec(classListAddPresentSpec);
let step2bHint = constructHintMessage("2b", `Try calling classList.add on your new card from step 2a.`, RESOURCES.classListAdd);
// Check step 2c index heuristics.
let cardObjectspec =
functionSpec(createCards)
.contains("index")
.andThen("element")
.andThen("imageClass")
let passedStep2cHeuristics =
checkFunctionSpec(cardObjectspec);
let step2cHint = constructHintMessage("2c", `Try checking that your object has 3 "key-value" pairs. Something like:
{
index: i, <-- the key is "index", value is loop iteration
element: newElement,
imageClass: shuffledImageClasses[i],
}`, RESOURCES.objects);
let imageClasses = [
"image-1", "image-1",
"image-2", "image-2",
"image-3", "image-3",
"image-4", "image-4",
"image-5", "image-5",
"image-6", "image-6",
];
let parent = document.createElement("div");
let exception = callUserCode(()=> {
return cards = createCards(parent, imageClasses);
});
if (parent.children.length != 12) {
if (!passedStep1Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step1Hint);
} else if (!passedStep2Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2Hint);
} else if (!passedStep2aHeuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2aHint);
}
else if (!passedStep2bHeuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2bHint);
}
else if (!passedStep2cHeuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2cHint);
} else {
console.error(constructErrorMessage(`Should create 12 card objects as children but got ${parent.children.length}. Make sure you are adding the right number of cards to the card-grid-container!`));
}
return false;
}
if (parent.children[0].classList[1] == undefined) {
console.log(constructErrorMessage(TEST_NAME, 2, `The classList for your new element should include an image class. We tested for classes and got: ${parent.children[0].classList}`));
console.log(step2bHint);
return false
}
if (!parent.children[0].classList[1].includes("image")) {
console.log(constructErrorMessage(TEST_NAME, 2, `The classList for your new element should include the "card" class and an image class. Your we tested for classes and got: ${parent.children[0].classList}`));
console.log(step2bHint);
return false
}
if (typeof(cards) !== "object" || cards.length == "undefined") {
console.error(constructErrorMessage(TEST_NAME, 3, `Should return an array of objects but returned ${typeof(cards)}.`));
console.log(constructHintMessage(3, `Remember to return the card object array you just made! The return value of this function should be the array of 12 card objects but that's not what we got.` ));
return false;
}
if (cards.length !== 12) {
if (!passedStep2cHeuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 4));
console.log(step2cHint);
} else {
console.error(`${ERROR}should return 12 card objects as children but got ${parent.children.length}. Make sure you are pushing 12 cards onto your cards array!`);
}
return false;
}
let badObject = null;
cards.forEach((card) => {
if (!card.hasOwnProperty("index") || !card.hasOwnProperty("element") || !card.hasOwnProperty("imageClass")) {
badObject = card;
return false;
}
});
if (badObject !== null) {
console.error(constructErrorMessage(TEST_NAME, "2c", `Card objects should each have index, element, and imageClass properties but got...`));
console.log(badObject);
console.log(step2cHint);
return false;
}
outputPassMessage(TEST_NAME);
return true;
}
function doCardsMatchTest() {
const TEST_NAME = "doCardsMatchTest";
let cardA = {
index: 5,
element: document.createElement("div"),
imageClass: "image-2"
};
let cardB = {
index: 7,
element: document.createElement("div"),
imageClass: "image-2"
}
let cardC = {
index: 9,
element: document.createElement("div"),
imageClass: "image-5"
}
let step1Hint = constructHintMessage(1, `Try comparing the imageClass property on each card element. You can do this by returning the result of a camparison between two parameters (e.g. parm1.property == param2.property)."`, RESOURCES.equality);
if (!doCardsMatch(cardA, cardB)) {
console.log(constructErrorMessage(TEST_NAME, 1, `We supplied cards with the same imageClass for cardObject1 and cardObject2 but the function returned 'false'.`));
console.log(step1Hint)
return false;
}
if (doCardsMatch(cardA, cardC)) {
console.log(constructErrorMessage(TEST_NAME, 1, `We supplied cards with different a imageClass for cardObject1 and cardObject2 but the function returned 'true'.`));
console.log(step1Hint)
return false;
}
outputPassMessage(TEST_NAME);
return true;
}
function incrementCounterTest() {
const TEST_NAME = "incrementCounterTest";
let counterNameAtZero =
functionSpec(incrementCounter)
.contains("if")
.andThen("counters")
.andThen("undefined");
let passedStep1Heuristics =
checkFunctionSpec(counterNameAtZero);
let step1Hint = constructHintMessage(1, `Try writing an 'if statement' that compares counters[counterName] and undefined`, RESOURCES._undefined);
let counterNameIncrement =
functionSpec(incrementCounter)
.contains("counters[counterName]++;")
.or("counters[counterName] += 1")
.or("counters[counterName] = counters[counterName] + 1")
let passedStep2Heuristics =
checkFunctionSpec(counterNameIncrement);
let step2Hint = constructHintMessage(2, `Make sure you're adding 1 to the counters[counterName]. The simplest way to achieve that is with the JavaScript increment operator`, RESOURCES.increment);
let innerHtmlSet =
functionSpec(incrementCounter)
.contains(".innerHTML")
.andThen("counters")
.andThen("[counterName]")
let passedStep3Heuristics =
checkFunctionSpec(innerHtmlSet);
let step3Hint = constructHintMessage(3, `Try using innerHTML on parentElement and set it to the new counter value.`, RESOURCES.innerHTML);
// Clear global counters.
try {
counters = {};
} catch(err) {}
let parentElement = document.createElement("div");
let string1;
let value1;
let string2;
let value2;
let exception = callUserCode(() => {
incrementCounter("counter1", parentElement);
string1 = parentElement.innerHTML;
value1 = Number(parentElement.innerHTML);
incrementCounter("counter1", parentElement);
string2 = parentElement.innerHTML;
value2 = Number(parentElement.innerHTML);
});
if (value1 !== 1) {
if (!passedStep1Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 3))
console.log(step1Hint);
} else if (!passedStep2Heuristics) {
console.log(constructLateErrorMessage(TEST_NAME, 3))
console.log(step2Hint)
} else if (!passedStep3Heuristics) {
console.log(constructErrorMessage(TEST_NAME, 3, `This function should place '1' in parentElement (counter should increase to 1) after first call but got ${string1}`));
console.log(step3Hint)
} else {
console.log(constructErrorMessage(TEST_NAME, 3, `This function should place '1' in parent (counter should increase to 1) after first call but got '${string1}'`));
}
return false;
}
if ((value2 - value1) !== 1) {
console.error(constructErrorMessage(TEST_NAME, 2, `This function should increment value in parent by 1 but consecutive calls to the same counter but got '${string1}' and '${string2}'`));
console.log(step2Hint);
return false;
}
let parentElement2 = document.createElement("div");
let string3;
let value3;
callUserCode(() => {
incrementCounter("newCounter", parentElement2);
string3 = parentElement2.innerHTML;
value3 = Number(parentElement2.innerHTML);
});
if (value3 !== 1) {
console.error(constructErrorMessage(TEST_NAME, 2, `This function should place '1' in parent after first call with new counterName but got '${string3}'`));
return false;
}
outputPassMessage(TEST_NAME);
return true;
}
function runAllTests() {
let tests = [
createNewCardTest,
appendNewCardTest,
shuffleCardImageClassesTest,
createCardsTest,
doCardsMatchTest,
incrementCounterTest];
let passed = true;
tests.forEach((test) => {
passed &= test();
});
if (passed) {
console.log("ALL TESTS PASSES!!!!");
} else {
console.log("TEST RUN FAILED");
}
}