Skip to content

Elyses Destructured Enchantments: Prevent not following the instructions #2665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 11, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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 };
}
Original file line number Diff line number Diff line change
@@ -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 };
}
Original file line number Diff line number Diff line change
@@ -8,88 +8,134 @@ 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);
});
});

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,