From 2d66a5db2779035c9c413bea23b78254a016f8be Mon Sep 17 00:00:00 2001 From: Derk-Jan Karrenbeld Date: Wed, 11 Jun 2025 00:55:08 +0200 Subject: [PATCH 1/3] Prevent not following the instructions --- .../enchantments.spec.js | 92 ++++++++++++++----- 1 file changed, 69 insertions(+), 23 deletions(-) diff --git a/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js b/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js index 11472da21b..1823074214 100644 --- a/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js +++ b/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js @@ -8,79 +8,125 @@ import { swapNamedPile, } from './enchantments'; +const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom'); +const customLogSymbol = Symbol.for('exercism.javascript.util.log'); + +// Follow the instructions in case you are stuck on "list.method is not a function" +class LimitedArray { + constructor(values) { + this.values = values; + } + + // Enables rest syntax and spread operator, as wel as for of, etc. + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + // Log value in non-upgraded environments + toString() { + return this.values.toString(); + } + + // Overrides logging in node (ie. students working locally) + [customInspectSymbol](depth, inspectOptions, inspect) { + const inner = this.values[customInspectSymbol] + ? this.values[customInspectSymbol](depth, inspectOptions, inspect) + : this.values.toString(); + + return `List of (${inner})`; + } + + // Overrides log overrides in web environment (ie. students working in editor) + [customLogSymbol](depth, inspectOptions, inspect) { + const inner = this.values[customLogSymbol] + ? this.values[customLogSymbol](depth, inspectOptions, inspect) + : this.values.toString(); + + return `List of (${inner})`; + } +} + +function deck(...values) { + return new LimitedArray(values); +} + describe('getFirstCard', () => { test('from a deck with a single card', () => { - expect(getFirstCard([3])).toBe(3); + expect(getFirstCard(deck(3))).toBe(3); }); test('from a deck with many cards', () => { - expect(getFirstCard([8, 3, 9, 5])).toBe(8); + expect(getFirstCard(deck(8, 3, 9, 5))).toBe(8); }); test('from an empty deck', () => { - expect(getFirstCard([])).toBe(undefined); + expect(getFirstCard(deck())).toBe(undefined); }); }); describe('getSecondCard', () => { test('from a deck with two cards', () => { - expect(getSecondCard([10, 4])).toBe(4); + expect(getSecondCard(deck(10, 4))).toBe(4); }); test('from a deck with many cards', () => { - expect(getSecondCard([2, 5, 7, 6])).toBe(5); + expect(getSecondCard(deck(2, 5, 7, 6))).toBe(5); }); test('from an empty deck', () => { - expect(getSecondCard([])).toBe(undefined); + expect(getSecondCard(deck())).toBe(undefined); }); test('from a deck with one card', () => { - expect(getSecondCard([8])).toBe(undefined); + expect(getSecondCard(deck(8))).toBe(undefined); }); }); describe('swapTwoCards', () => { test('swapping two numbered cards', () => { - expect(swapTwoCards([3, 6])).toStrictEqual([6, 3]); + expect(swapTwoCards(deck(3, 6))).toStrictEqual([6, 3]); }); test('swapping a high card with a low card', () => { - expect(swapTwoCards([10, 2])).toStrictEqual([2, 10]); + expect(swapTwoCards(deck(10, 2))).toStrictEqual([2, 10]); }); test('swapping a face card with a low card', () => { - expect(swapTwoCards(['king', 3])).toStrictEqual([3, 'king']); + expect(swapTwoCards(deck('king', 3))).toStrictEqual([3, 'king']); }); }); describe('shiftThreeCardsAround', () => { test('consecutive numbers', () => { - expect(shiftThreeCardsAround([6, 4, 5])).toStrictEqual([4, 5, 6]); + expect(shiftThreeCardsAround(deck(6, 4, 5))).toStrictEqual([4, 5, 6]); }); test('drop the face card to the bottom', () => { - expect(shiftThreeCardsAround(['king', 5, 2])).toStrictEqual([5, 2, 'king']); + expect(shiftThreeCardsAround(deck('king', 5, 2))).toStrictEqual([ + 5, + 2, + 'king', + ]); }); }); describe('pickNamedPile', () => { test('keeps the chosen pile', () => { - const chosen = [3, 'jack', 'queen', 'king', 10, 7]; - const disregarded = [4, 5, 6, 8, 9]; + const chosen = deck(3, 'jack', 'queen', 'king', 10, 7); + const disregarded = deck(4, 5, 6, 8, 9); const piles = { chosen, disregarded }; expect(pickNamedPile(piles)).toStrictEqual(chosen); }); test('returns the actual pile without recreating it', () => { - const chosen = [3, 'jack', 'queen', 'king', 10, 7]; - const disregarded = [4, 5, 6, 8, 9]; + const chosen = deck(3, 'jack', 'queen', 'king', 10, 7); + const disregarded = deck(4, 5, 6, 8, 9); const piles = { chosen, disregarded }; const result = pickNamedPile(piles); - chosen.push('joker'); + chosen.values.push('joker'); expect(result).toStrictEqual(chosen); }); @@ -88,8 +134,8 @@ describe('pickNamedPile', () => { describe('swapNamedPile', () => { test('renames the piles', () => { - const face_pile = [3, 'jack', 'queen', 'king', 10, 7]; - const numbers_pile = [4, 5, 6, 8, 9]; + const face_pile = deck(3, 'jack', 'queen', 'king', 10, 7); + const numbers_pile = deck(4, 5, 6, 8, 9); const piles = { chosen: numbers_pile, disregarded: face_pile }; expect(swapNamedPile(piles)).toStrictEqual({ @@ -99,14 +145,14 @@ describe('swapNamedPile', () => { }); test('returns the actual piles without recreating them', () => { - const face_pile = [3, 'jack', 'queen', 'king', 10, 7]; - const numbers_pile = [4, 5, 6, 8, 9]; + const face_pile = deck(3, 'jack', 'queen', 'king', 10, 7); + const numbers_pile = deck(4, 5, 6, 8, 9); const piles = { chosen: numbers_pile, disregarded: face_pile }; const result = swapNamedPile(piles); - face_pile.push('joker'); - numbers_pile.push(2); + face_pile.values.push('joker'); + numbers_pile.values.push(2); expect(result).toStrictEqual({ chosen: face_pile, From d23cf03edcb5b14d2b1b963826a2a5520c5d7df8 Mon Sep 17 00:00:00 2001 From: Derk-Jan Karrenbeld Date: Wed, 11 Jun 2025 01:59:59 +0200 Subject: [PATCH 2/3] Add note to use destructuring --- .../elyses-destructured-enchantments/.meta/exemplar.js | 4 +++- .../concept/elyses-destructured-enchantments/enchantments.js | 4 +++- .../elyses-destructured-enchantments/enchantments.spec.js | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js b/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js index 6d17a20971..f66e199cef 100644 --- a/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js +++ b/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js @@ -53,6 +53,7 @@ export function shiftThreeCardsAround([a, b, c]) { * @returns {Card[]} the pile named chosen */ export function pickNamedPile({ chosen }) { + // 🚨 Do NOT use piles.chosen or piles.disregarded. return chosen; } @@ -64,6 +65,7 @@ export function pickNamedPile({ chosen }) { */ export function swapNamedPile({ chosen: disregarded, disregarded: chosen }) { // 🪄 Don't break the magic. - // Do NOT touch the next line or Elyse will accidentally reveal the trick. + // 🚨 Do NOT use piles.chosen or piles.disregarded. + // 🚨 Do NOT touch the next line or Elyse will accidentally reveal the trick. return { chosen, disregarded }; } diff --git a/exercises/concept/elyses-destructured-enchantments/enchantments.js b/exercises/concept/elyses-destructured-enchantments/enchantments.js index 563fea1eed..f88f487877 100644 --- a/exercises/concept/elyses-destructured-enchantments/enchantments.js +++ b/exercises/concept/elyses-destructured-enchantments/enchantments.js @@ -53,6 +53,7 @@ export function shiftThreeCardsAround(deck) { * @returns {Card[]} the pile named chosen */ export function pickNamedPile(piles) { + // 🚨 Do NOT use piles.chosen or piles.disregarded. throw new Error('Implement the pickNamedPile function'); } @@ -64,6 +65,7 @@ export function pickNamedPile(piles) { */ export function swapNamedPile(piles) { // 🪄 Don't break the magic. - // Do NOT touch the next line or Elyse will accidentally reveal the trick. + // 🚨 Do NOT use piles.chosen or piles.disregarded. + // 🚨 Do NOT touch the next line or Elyse will accidentally reveal the trick. return { chosen, disregarded }; } diff --git a/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js b/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js index 1823074214..c4d15a9ae3 100644 --- a/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js +++ b/exercises/concept/elyses-destructured-enchantments/enchantments.spec.js @@ -12,7 +12,7 @@ const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom'); const customLogSymbol = Symbol.for('exercism.javascript.util.log'); // Follow the instructions in case you are stuck on "list.method is not a function" -class LimitedArray { +class LimitedDeck { constructor(values) { this.values = values; } @@ -47,7 +47,7 @@ class LimitedArray { } function deck(...values) { - return new LimitedArray(values); + return new LimitedDeck(values); } describe('getFirstCard', () => { From 5c7f774f31216ca9f3baed8eb66426b7c08d4de7 Mon Sep 17 00:00:00 2001 From: Derk-Jan Karrenbeld Date: Wed, 11 Jun 2025 02:00:23 +0200 Subject: [PATCH 3/3] Reword note --- .../elyses-destructured-enchantments/.meta/exemplar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js b/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js index f66e199cef..d92e0aea61 100644 --- a/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js +++ b/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js @@ -53,7 +53,7 @@ export function shiftThreeCardsAround([a, b, c]) { * @returns {Card[]} the pile named chosen */ export function pickNamedPile({ chosen }) { - // 🚨 Do NOT use piles.chosen or piles.disregarded. + // 🚨 Do NOT write piles.chosen or piles.disregarded. return chosen; } @@ -65,7 +65,7 @@ export function pickNamedPile({ chosen }) { */ export function swapNamedPile({ chosen: disregarded, disregarded: chosen }) { // 🪄 Don't break the magic. - // 🚨 Do NOT use piles.chosen or piles.disregarded. + // 🚨 Do NOT write piles.chosen or piles.disregarded. // 🚨 Do NOT touch the next line or Elyse will accidentally reveal the trick. return { chosen, disregarded }; }