Skip to content
Merged
Show file tree
Hide file tree
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
13 changes: 6 additions & 7 deletions src/lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import terminalImage from 'terminal-image';
import Table from 'cli-table';
import { got } from 'got';
import { select } from '@inquirer/prompts';
import {
eightiesTrackIds,
jazzTrackIds
Expand All @@ -24,6 +23,7 @@ export function buildPlayQueue ({ tracks, currentTrack }) {
* @description Prompt the user to choose which device to setup the playback
*/
export async function chooseSystemNode (system) {
const { select } = await import('@inquirer/prompts');
const discoveredNodes = await system.discoverNodes();
const choices = discoveredNodes
.map((node) => ({
Expand All @@ -49,6 +49,7 @@ export async function chooseSystemNode (system) {
* 4. Choose 'Share > Copy Song Link' and the track ID will be embedded in the link. Be sure to format it correctly when you paste it in the config
*/
export async function chooseVibe () {
const { select } = await import('@inquirer/prompts');
const choice = await select({
message: 'Aw yea! What type of mood would you like to set?',
choices: [
Expand Down Expand Up @@ -80,10 +81,8 @@ export function randomTrack (items) {
}

export function camelize (str) {
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
return index === 0 ? word.toLowerCase() : word.toUpperCase();
})
.replace(/\s+/g, '')
.replace(/'/g, '')
.replace(/'/g, '');
return str
.replace(/[-\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '') // capitalize after dash/space
.replace(/'/g, '') // remove apostrophes
.replace(/^./, c => c.toLowerCase()); // lowercase first letter
}
6 changes: 0 additions & 6 deletions test/lib/sonos.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,9 @@ describe('sonos.js', () => {
describe('getDevice', () => {
beforeEach(async () => {
await sonosInstance.discoverNodes();
// Debug: print known nodes after discovery
// eslint-disable-next-line no-console
console.log('Known nodes after discovery:', sonosInstance.getKnownNodes());
});

it('should return device for valid key', async () => {
// Debug: print keys in _nodes
// eslint-disable-next-line no-console
console.log('Device for key livingRoom:', sonosInstance.getDevice({ key: 'livingRoom' }));
const device = sonosInstance.getDevice({ key: 'livingRoom' });
expect(device).toBeDefined();
expect(device.name).toBe('Living Room');
Expand Down
124 changes: 124 additions & 0 deletions test/lib/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { jest } from '@jest/globals';
import {
buildPlayQueue,
printNowPlaying,
randomTrack,
camelize
} from '../../src/lib/utils.js';

// Mock external dependencies
jest.mock('terminal-image');
jest.mock('cli-table');
jest.mock('got');

describe('Utility Functions', () => {
beforeEach(() => {
jest.clearAllMocks();
});

describe('buildPlayQueue', () => {
it('should filter out the current track from the queue', () => {
const tracks = [
{ uri: 'spotify:track:1', title: 'Track 1' },
{ uri: 'spotify:track:2', title: 'Track 2' },
{ uri: 'spotify:track:3', title: 'Track 3' }
];
const currentTrack = { uri: 'spotify:track:2', title: 'Track 2' };

const result = buildPlayQueue({ tracks, currentTrack });

expect(result).toHaveLength(2);
expect(result).not.toContainEqual(currentTrack);
});

it('should return all tracks if current track is not in the list', () => {
const tracks = [
{ uri: 'spotify:track:1', title: 'Track 1' },
{ uri: 'spotify:track:2', title: 'Track 2' }
];
const currentTrack = { uri: 'spotify:track:3', title: 'Track 3' };

const result = buildPlayQueue({ tracks, currentTrack });

expect(result).toEqual(tracks);
});

it('should return all tracks if remaining tracks is empty', () => {
const tracks = [{ uri: 'spotify:track:1', title: 'Track 1' }];
const currentTrack = { uri: 'spotify:track:1', title: 'Track 1' };

const result = buildPlayQueue({ tracks, currentTrack });

expect(result).toEqual(tracks);
});
});

describe('chooseSystemNode', () => {
it('should return the selected node', async () => {
const mockNode = { name: 'Test Node' };
const mockSystem = {
discoverNodes: jest.fn().mockResolvedValue([mockNode])
};

await jest.resetModules();
// ESM-compliant mocking
await jest.unstable_mockModule('@inquirer/prompts', () => ({
select: jest.fn().mockResolvedValue(mockNode)
}));

// Dynamically import after the mock is set up
const { chooseSystemNode } = await import('../../src/lib/utils.js');
const result = await chooseSystemNode(mockSystem);

expect(result).toEqual(mockNode);
});
});

describe('chooseVibe', () => {
it('should return the selected vibe', async () => {
const mockVibe = ['track1', 'track2'];
await jest.resetModules();
// ESM-compliant mocking
await jest.unstable_mockModule('@inquirer/prompts', () => ({
select: jest.fn().mockResolvedValue(mockVibe)
}));

// Dynamically import after the mock is set up
const { chooseVibe } = await import('../../src/lib/utils.js');
const result = await chooseVibe();

expect(result).toBe(mockVibe);
// Optionally, check the prompt message and choices if needed
});
});

describe('randomTrack', () => {
it('should return a random track from the array', () => {
const items = ['track1', 'track2', 'track3'];
const result = randomTrack(items);
expect(items).toContain(result);
});

it('should return undefined for empty array', () => {
const result = randomTrack([]);
expect(result).toBeUndefined();
});
});

describe('camelize', () => {
it('should convert string to camelCase', () => {
expect(camelize('hello world')).toBe('helloWorld');
expect(camelize('Hello World')).toBe('helloWorld');
expect(camelize('hello-world')).toBe('helloWorld');
});

it('should handle special characters', () => {
expect(camelize("don't stop")).toBe('dontStop');
expect(camelize("it's working")).toBe('itsWorking');
});

it('should handle already camelCase strings', () => {
expect(camelize('helloWorld')).toBe('helloWorld');
});
});
});