diff --git a/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js b/exercises/concept/elyses-destructured-enchantments/.meta/exemplar.js index 6d17a20971..d92e0aea61 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 write 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 write 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 11472da21b..c4d15a9ae3 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 LimitedDeck { + 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 LimitedDeck(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,