RunKit + npm: jsverify-commands

node v8.17.0
version: 3.0.0
endpointsharetweet
Import modules
const assert = require('assert'); const jsc = require('jsverify'); const jscCommands = require('jsverify-commands');
Declare commands
play: - unavailable until at least one track has been added to the player - put the player in "play mode" pause: - put the player in "pause mode" next: - do not impact the mode: play keeps playing, pause keeps pausing - in case of multiple tracks switch to next track - otherwise keep playing the same track add track: - do not impact the mode: play keeps playing, pause keeps pausing - in case of empty player before the command, switch to added track - otherwise keep the same track
function PlayCommand() { this.check = model => model.num_tracks > 0; this.run = function(player, model) { model.is_playing = true; player.play(); return player.is_playing(); }; this.name = `Play`; } function PauseCommand() { this.check = model => true; this.run = function(player, model) { model.is_playing = false; player.pause(); return !player.is_playing(); }; this.name = `Pause`; } function NextCommand() { this.check = model => true; this.run = function(player, model) { const track_before = player.track_name(); player.next(); if (model.is_playing !== player.is_playing()) { return false; // should not change playing status } if (model.num_tracks <= 1) { return track_before === player.track_name(); // keep playing the same } else { return track_before !== player.track_name(); // go to another track } }; this.name = `Next`; } function AddTrackCommand(name, position) { this.check = model => !model.tracks_already_seen.hasOwnProperty(name); this.run = function(player, model) { ++model.num_tracks; model.tracks_already_seen[name] = undefined; const track_before = player.track_name(); player.add_track(name, position % model.num_tracks); if (model.is_playing !== player.is_playing()) { return false; // should not change playing status } if (model.num_tracks === 1) { return player.track_name() === name; } return track_before === player.track_name(); }; this.name = `AddTrack(${name}, ${position})`; }
Music player implementation
function MusicPlayer() { let tracks = []; let is_playing = false; let playing_idx = 0; this.is_playing = () => is_playing; this.track_name = () => tracks[playing_idx]; this.play = () => is_playing = true; this.pause = () => is_playing = false; this.add_track = (name, position) => { tracks = tracks.slice(0, position).concat(name).concat(tracks.slice(position)); if (tracks.length !== 1 && playing_idx >= position) { ++playing_idx; } }; this.next = () => { if (++playing_idx >= tracks.length) { playing_idx = 0; } }; }
Music player model implementation
function MusicPlayerModel() { this.is_playing = false this.num_tracks = 0; this.tracks_already_seen = {}; }
Fake mocha implementation (for RunKit purpose only)
const describe = (name, f) => f(); const it = async (name, f) => { try { await f(); console.log(`${name}: success`); } catch (err) { console.log(`${name}: failed with error`); console.log(err); } };
Your tests go there
describe('MusicPlayer', function() { it('should follow specifications', function() { const commands = jscCommands.commands( jscCommands.command(PlayCommand), jscCommands.command(PauseCommand), jscCommands.command(NextCommand), jscCommands.command(AddTrackCommand, jsc.string, jsc.nat)); const warmup = () => new Object({ state: new MusicPlayer(), model: new MusicPlayerModel() }); const teardown = () => {}; const settings = { metrics: true, verbose: true }; return jscCommands.assertForall(commands, warmup, teardown, settings); }); });
Created from: https://npm.runkit.com/jsverify-commands
Loading…

no comments

    sign in to comment