Skip to content

Commit

Permalink
Add a note parser
Browse files Browse the repository at this point in the history
  • Loading branch information
simonppg committed Jun 1, 2024
1 parent 3b9e207 commit 5a721bc
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
59 changes: 59 additions & 0 deletions __tests__/NoteParser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {NoteParser} from "../src/NoteParser";

describe("NoteParser", () => {
let noteParser: NoteParser;

beforeEach(() => {
noteParser = new NoteParser();
});

it("should parse valid note strings", () => {
expect(noteParser.parseNote("C#4")).toEqual({ name: "C", accidental: "#", octave: 4 });
expect(noteParser.parseNote("Db0")).toEqual({ name: "D", accidental: "b", octave: 0 });
});

it("should parse valid note strings", () => {
// Valid note strings with different accidentals and octaves
expect(noteParser.parseNote("C#4")).toEqual({ name: "C", accidental: "#", octave: 4 });
expect(noteParser.parseNote("Db0")).toEqual({ name: "D", accidental: "b", octave: 0 });
expect(noteParser.parseNote("F3")).toEqual({ name: "F", octave: 3 });
});

it("should throw an error for invalid note strings", () => {
// Test invalid note strings
expect(() => noteParser.parseNote("InvalidNote")).toThrowError("InvalidArgumentException");
expect(() => noteParser.parseNote("")).toThrowError("InvalidArgumentException");
expect(() => noteParser.parseNote("C#4#")).toThrowError("InvalidArgumentException");
expect(() => noteParser.parseNote("#4")).toThrowError("InvalidArgumentException");
});

it("should parse valid note strings", () => {
// Test valid note strings
expect(noteParser.parseNote("C#4")).toEqual({ name: "C", accidental: "#", octave: 4 });
expect(noteParser.parseNote("Db0")).toEqual({ name: "D", accidental: "b", octave: 0 });
expect(noteParser.parseNote("F")).toEqual({ name: "F", octave: 0 });
expect(noteParser.parseNote("F#")).toEqual({ name: "F", accidental: "#", octave: 0 });
expect(noteParser.parseNote("Ab4")).toEqual({ name: "A", accidental: "b", octave: 4 });
});

it("should handle lowercase note names", () => {
// Valid note strings with lowercase note names
expect(noteParser.parseNote("C#4")).toEqual({ name: "C", accidental: "#", octave: 4 });
expect(noteParser.parseNote("Db0")).toEqual({ name: "D", accidental: "b", octave: 0 });
expect(noteParser.parseNote("F3")).toEqual({ name: "F", octave: 3 });
});

it("should handle accidental without octave", () => {
// Valid note strings with accidentals but without octave
expect(noteParser.parseNote("C#")).toEqual({ name: "C", accidental: "#", octave: 0 });
expect(noteParser.parseNote("Db")).toEqual({ name: "D", accidental: "b", octave: 0 });
expect(noteParser.parseNote("F")).toEqual({ name: "F", octave: 0 });
});

it("should handle note without accidental", () => {
// Valid note strings without accidentals
expect(noteParser.parseNote("C4")).toEqual({ name: "C", octave: 4 });
expect(noteParser.parseNote("D0")).toEqual({ name: "D", octave: 0 });
expect(noteParser.parseNote("F#3")).toEqual({ name: "F", accidental: "#", octave: 3 });
});
});
5 changes: 5 additions & 0 deletions src/NoteDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type NoteDTO = {
name: string; // The name of the note (e.g., "C", "D", "E", etc.)
octave?: number; // The octave of the note (e.g., 4, 5, 6, etc.)
accidental?: string; // The accidental of the note (e.g., "#" or "b")
};
28 changes: 28 additions & 0 deletions src/NoteParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {NoteDTO} from "./NoteDTO";

export class NoteParser {
parseNote(noteString: string): NoteDTO {
// Regular expression to match note strings with optional accidental and octave
const regex = /^([A-G])([#b]?)(\d*)$/;

// Execute the regular expression on the input string
const match = regex.exec(noteString);

// If there's no match, throw an error
if (!match) {
throw new Error("InvalidArgumentException");
}

// Extract components from the matched groups
const name = match[1];
const accidental = match[2] || undefined; // Accidental may be empty
const octave = match[3] ? parseInt(match[3], 10) : 0; // Parse octave if present, otherwise set to 0

// Create and return the NoteDTO object
return {
name,
accidental,
octave
};
}
}

0 comments on commit 5a721bc

Please sign in to comment.