bemusic/bemuse

View on GitHub
packages/bmson/src/index.spec.ts

Summary

Maintainability
C
1 day
Test Coverage
import assert from 'assert'

import * as bmson from '.'
import { Note } from './types'

/* global describe, it */
describe('bmson v1.0.0', function () {
  describe('songInfoForBmson', function () {
    it('should return a song info', function () {
      const info = bmson.songInfoForBmson({
        version: '1.0.0',
        info: {
          title: 'Reminiscentia',
          artist: 'flicknote',
          genre: 'Dramatic Trance',
          init_bpm: 160,
        },
      } as any)
      assert(info.title === 'Reminiscentia')
      assert(info.artist === 'flicknote')
      assert(info.genre === 'Dramatic Trance')
    })
    it('should put chart_name into subtitles field', function () {
      const info = bmson.songInfoForBmson({
        version: '1.0.0',
        info: {
          chart_name: 'FOUR DIMENSIONS',
        },
      } as any)
      assert.deepEqual(info.subtitles, ['FOUR DIMENSIONS'])
    })
    it('should put each line of subtitle into subtitles field', function () {
      const info = bmson.songInfoForBmson({
        version: '1.0.0',
        info: {
          subtitle: 'First Episode\nreturn of the cat meow',
        },
      } as any)
      assert.deepEqual(info.subtitles, [
        'First Episode',
        'return of the cat meow',
      ])
    })
    it('should skip blank chart names and subtitle', function () {
      const info = bmson.songInfoForBmson({
        version: '1.0.0',
        info: {
          subtitle: '',
          chart_name: '',
        },
      } as any)
      assert.deepEqual(info.subtitles, [])
    })
    it('should have subartists', function () {
      const info = bmson.songInfoForBmson({
        version: '1.0.0',
        info: {
          title: 'Running Out 2015',
          subartists: ['music:flicknote', 'bga:5argon'],
        },
      } as any)
      assert.deepEqual(info.subartists, ['music:flicknote', 'bga:5argon'])
    })
  })

  describe('barLinesForBmson', function () {
    it('should return barlines in beat', function () {
      const beats = bmson.barLinesForBmson({
        version: '1.0.0',
        info: {
          resolution: 3,
        },
        lines: [{ y: 0 }, { y: 12 }, { y: 24 }],
      } as any)
      assert.deepEqual(beats, [0, 4, 8])
    })
  })

  describe('timingInfoForBmson', function () {
    it('should return timing of initial bpm', function () {
      const { initialBPM } = bmson.timingInfoForBmson({
        version: '1.0.0',
        info: {
          init_bpm: 180,
        },
      } as any)
      assert(initialBPM === 180)
    })

    it('supports BPM changes', function () {
      const { initialBPM, actions } = bmson.timingInfoForBmson({
        version: '1.0.0',
        info: { init_bpm: 120 },
        bpm_events: [{ y: 2880, bpm: 196 }],
      } as any)
      assert(initialBPM === 120)
      assert.deepEqual(actions, [{ type: 'bpm', beat: 12, bpm: 196 }])
    })

    it('supports stops', function () {
      const { initialBPM, actions } = bmson.timingInfoForBmson({
        version: '1.0.0',
        info: { init_bpm: 120, resolution: 8 },
        stop_events: [{ y: 96, duration: 42 }],
      } as any)
      assert(initialBPM === 120)
      assert.deepEqual(actions, [{ type: 'stop', beat: 12, stopBeats: 42 / 8 }])
    })
  })

  describe('musicalScoreForBmson', function () {
    function setup(notes: Note[]) {
      const data = {
        version: '1.0.0',
        info: {
          init_bpm: 100,
          resolution: 24,
        },
        sound_channels: [
          {
            name: 'piano.wav',
            notes: notes,
          },
        ],
      } as any
      return bmson.musicalScoreForBmson(data)
    }

    it('returns a timing', function () {
      const score = setup([])
      assert(typeof score.timing.beatToSeconds === 'function')
      assert(score.timing.beatToSeconds(1) === 60 / 100)
    })

    it('generates keysounds and notes', function () {
      const score = setup([{ x: 1, y: 24, l: 0, c: false }])
      assert.deepEqual(score.notes.all(), [
        {
          column: '1',
          beat: 1,
          endBeat: void 0,
          keysound: '0001',
          keysoundStart: 0,
          keysoundEnd: void 0,
        },
      ])
      assert(score.keysounds.get('0001') === 'piano.wav')
    })

    it('handles long notes', function () {
      const score = setup([{ x: 1, y: 24, l: 48, c: false }])
      assert.deepEqual(score.notes.all(), [
        {
          column: '1',
          beat: 1,
          endBeat: 3,
          keysound: '0001',
          keysoundStart: 0,
          keysoundEnd: void 0,
        },
      ])
    })

    it('handles keysound slices', function () {
      const score = setup([
        { x: 1, y: 24, l: 0, c: false },
        { x: 1, y: 48, l: 0, c: true },
      ])
      const notes = score.notes.all()
      assert(notes[0].keysoundStart === 0)
      assert(notes[0].keysoundEnd === 0.6)
      assert(notes[1].keysoundStart === 0.6)
      assert(notes[1].keysoundEnd === undefined)
    })
  })

  describe('hasScratch', function () {
    it('should return true if there is a scratch in 1P', function () {
      const data = {
        version: '1.0.0',
        sound_channels: [
          { notes: [{ x: 1 }] },
          { notes: [{ x: 3 }, { x: 8 }] },
        ],
      }
      assert(bmson.hasScratch(data as any))
    })
    it('should return true if there is a scratch in 2P', function () {
      const data = {
        version: '1.0.0',
        sound_channels: [
          { notes: [{ x: 1 }] },
          { notes: [{ x: 13 }, { x: 18 }] },
        ],
      }
      assert(bmson.hasScratch(data as any))
    })
    it('should return false if scratch not found', function () {
      const data = {
        version: '1.0.0',
        sound_channels: [
          { notes: [{ x: 1 }] },
          { notes: [{ x: 3 }, { x: 7 }] },
        ],
      }
      assert(!bmson.hasScratch(data as any))
    })
  })

  describe('keysForBmson', function () {
    function testcase(xs: number[], keys: string) {
      it('should work with ' + keys, function () {
        const actual = bmson.keysForBmson({
          version: '1.0',
          sound_channels: xs.map((x) => ({
            notes: [{ x }],
          })),
        } as any)
        assert(actual === keys)
      })
    }
    testcase([1, 3, 5, 7], '7K')
    testcase([1, 3, 5, 8], '5K')
    testcase([1, 3, 5, 8, 12, 14, 18], '10K')
    testcase([1, 3, 5, 8, 12, 14, 16, 18], '14K')
    testcase([], 'empty')
  })
})