Skip to content

Commit 6ee8691

Browse files
committed
add tests for utils
1 parent a010efa commit 6ee8691

File tree

3 files changed

+130
-13
lines changed

3 files changed

+130
-13
lines changed

src/lib/utils.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import terminalImage from 'terminal-image';
22
import Table from 'cli-table';
33
import { got } from 'got';
4-
import { select } from '@inquirer/prompts';
54
import {
65
eightiesTrackIds,
76
jazzTrackIds
@@ -24,6 +23,7 @@ export function buildPlayQueue ({ tracks, currentTrack }) {
2423
* @description Prompt the user to choose which device to setup the playback
2524
*/
2625
export async function chooseSystemNode (system) {
26+
const { select } = await import('@inquirer/prompts');
2727
const discoveredNodes = await system.discoverNodes();
2828
const choices = discoveredNodes
2929
.map((node) => ({
@@ -49,6 +49,7 @@ export async function chooseSystemNode (system) {
4949
* 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
5050
*/
5151
export async function chooseVibe () {
52+
const { select } = await import('@inquirer/prompts');
5253
const choice = await select({
5354
message: 'Aw yea! What type of mood would you like to set?',
5455
choices: [
@@ -80,10 +81,8 @@ export function randomTrack (items) {
8081
}
8182

8283
export function camelize (str) {
83-
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
84-
return index === 0 ? word.toLowerCase() : word.toUpperCase();
85-
})
86-
.replace(/\s+/g, '')
87-
.replace(/'/g, '')
88-
.replace(/'/g, '');
84+
return str
85+
.replace(/[-\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '') // capitalize after dash/space
86+
.replace(/'/g, '') // remove apostrophes
87+
.replace(/^./, c => c.toLowerCase()); // lowercase first letter
8988
}

test/lib/sonos.test.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,9 @@ describe('sonos.js', () => {
9696
describe('getDevice', () => {
9797
beforeEach(async () => {
9898
await sonosInstance.discoverNodes();
99-
// Debug: print known nodes after discovery
100-
// eslint-disable-next-line no-console
101-
console.log('Known nodes after discovery:', sonosInstance.getKnownNodes());
10299
});
103100

104101
it('should return device for valid key', async () => {
105-
// Debug: print keys in _nodes
106-
// eslint-disable-next-line no-console
107-
console.log('Device for key livingRoom:', sonosInstance.getDevice({ key: 'livingRoom' }));
108102
const device = sonosInstance.getDevice({ key: 'livingRoom' });
109103
expect(device).toBeDefined();
110104
expect(device.name).toBe('Living Room');

test/lib/utils.test.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { jest } from '@jest/globals';
2+
import {
3+
buildPlayQueue,
4+
printNowPlaying,
5+
randomTrack,
6+
camelize
7+
} from '../../src/lib/utils.js';
8+
9+
// Mock external dependencies
10+
jest.mock('terminal-image');
11+
jest.mock('cli-table');
12+
jest.mock('got');
13+
14+
describe('Utility Functions', () => {
15+
beforeEach(() => {
16+
jest.clearAllMocks();
17+
});
18+
19+
describe('buildPlayQueue', () => {
20+
it('should filter out the current track from the queue', () => {
21+
const tracks = [
22+
{ uri: 'spotify:track:1', title: 'Track 1' },
23+
{ uri: 'spotify:track:2', title: 'Track 2' },
24+
{ uri: 'spotify:track:3', title: 'Track 3' }
25+
];
26+
const currentTrack = { uri: 'spotify:track:2', title: 'Track 2' };
27+
28+
const result = buildPlayQueue({ tracks, currentTrack });
29+
30+
expect(result).toHaveLength(2);
31+
expect(result).not.toContainEqual(currentTrack);
32+
});
33+
34+
it('should return all tracks if current track is not in the list', () => {
35+
const tracks = [
36+
{ uri: 'spotify:track:1', title: 'Track 1' },
37+
{ uri: 'spotify:track:2', title: 'Track 2' }
38+
];
39+
const currentTrack = { uri: 'spotify:track:3', title: 'Track 3' };
40+
41+
const result = buildPlayQueue({ tracks, currentTrack });
42+
43+
expect(result).toEqual(tracks);
44+
});
45+
46+
it('should return all tracks if remaining tracks is empty', () => {
47+
const tracks = [{ uri: 'spotify:track:1', title: 'Track 1' }];
48+
const currentTrack = { uri: 'spotify:track:1', title: 'Track 1' };
49+
50+
const result = buildPlayQueue({ tracks, currentTrack });
51+
52+
expect(result).toEqual(tracks);
53+
});
54+
});
55+
56+
describe('chooseSystemNode', () => {
57+
it('should return the selected node', async () => {
58+
const mockNode = { name: 'Test Node' };
59+
const mockSystem = {
60+
discoverNodes: jest.fn().mockResolvedValue([mockNode])
61+
};
62+
63+
await jest.resetModules();
64+
// ESM-compliant mocking
65+
await jest.unstable_mockModule('@inquirer/prompts', () => ({
66+
select: jest.fn().mockResolvedValue(mockNode)
67+
}));
68+
69+
// Dynamically import after the mock is set up
70+
const { chooseSystemNode } = await import('../../src/lib/utils.js');
71+
const result = await chooseSystemNode(mockSystem);
72+
73+
expect(result).toEqual(mockNode);
74+
});
75+
});
76+
77+
describe('chooseVibe', () => {
78+
it('should return the selected vibe', async () => {
79+
const mockVibe = ['track1', 'track2'];
80+
await jest.resetModules();
81+
// ESM-compliant mocking
82+
await jest.unstable_mockModule('@inquirer/prompts', () => ({
83+
select: jest.fn().mockResolvedValue(mockVibe)
84+
}));
85+
86+
// Dynamically import after the mock is set up
87+
const { chooseVibe } = await import('../../src/lib/utils.js');
88+
const result = await chooseVibe();
89+
90+
expect(result).toBe(mockVibe);
91+
// Optionally, check the prompt message and choices if needed
92+
});
93+
});
94+
95+
describe('randomTrack', () => {
96+
it('should return a random track from the array', () => {
97+
const items = ['track1', 'track2', 'track3'];
98+
const result = randomTrack(items);
99+
expect(items).toContain(result);
100+
});
101+
102+
it('should return undefined for empty array', () => {
103+
const result = randomTrack([]);
104+
expect(result).toBeUndefined();
105+
});
106+
});
107+
108+
describe('camelize', () => {
109+
it('should convert string to camelCase', () => {
110+
expect(camelize('hello world')).toBe('helloWorld');
111+
expect(camelize('Hello World')).toBe('helloWorld');
112+
expect(camelize('hello-world')).toBe('helloWorld');
113+
});
114+
115+
it('should handle special characters', () => {
116+
expect(camelize("don't stop")).toBe('dontStop');
117+
expect(camelize("it's working")).toBe('itsWorking');
118+
});
119+
120+
it('should handle already camelCase strings', () => {
121+
expect(camelize('helloWorld')).toBe('helloWorld');
122+
});
123+
});
124+
});

0 commit comments

Comments
 (0)