scratch-vm/test/unit/blocks_sensing.js
2018-04-30 20:19:21 -03:00

145 lines
4.6 KiB
JavaScript

const test = require('tap').test;
const Sensing = require('../../src/blocks/scratch3_sensing');
const Runtime = require('../../src/engine/runtime');
const Sprite = require('../../src/sprites/sprite');
const RenderedTarget = require('../../src/sprites/rendered-target');
test('getPrimitives', t => {
const rt = new Runtime();
const s = new Sensing(rt);
t.type(s.getPrimitives(), 'object');
t.end();
});
test('ask and answer with a hidden target', t => {
const rt = new Runtime();
const s = new Sensing(rt);
const util = {target: {visible: false}};
const expectedQuestion = 'a question';
const expectedAnswer = 'the answer';
// Test is written out of order because of promises, follow the (#) comments.
rt.addListener('QUESTION', question => {
// (2) Assert the question is correct, then emit the answer
t.strictEqual(question, expectedQuestion);
rt.emit('ANSWER', expectedAnswer);
});
// (1) Emit the question.
const promise = s.askAndWait({QUESTION: expectedQuestion}, util);
// (3) Ask block resolves after the answer is emitted.
promise.then(() => {
t.strictEqual(s.getAnswer(), expectedAnswer);
t.end();
});
});
test('ask and answer with a visible target', t => {
const rt = new Runtime();
const s = new Sensing(rt);
const util = {target: {visible: true}};
const expectedQuestion = 'a question';
const expectedAnswer = 'the answer';
rt.removeAllListeners('SAY'); // Prevent say blocks from executing
rt.addListener('SAY', (target, type, question) => {
// Should emit SAY with the question
t.strictEqual(question, expectedQuestion);
});
rt.addListener('QUESTION', question => {
// Question should be blank for a visible target
t.strictEqual(question, '');
// Remove the say listener and add a new one to assert bubble is cleared
// by setting say to empty string after answer is received.
rt.removeAllListeners('SAY');
rt.addListener('SAY', (target, type, text) => {
t.strictEqual(text, '');
t.end();
});
rt.emit('ANSWER', expectedAnswer);
});
s.askAndWait({QUESTION: expectedQuestion}, util);
});
test('set drag mode', t => {
const runtime = new Runtime();
runtime.requestTargetsUpdate = () => {}; // noop for testing
const sensing = new Sensing(runtime);
const s = new Sprite();
const rt = new RenderedTarget(s, runtime);
sensing.setDragMode({DRAG_MODE: 'not draggable'}, {target: rt});
t.strictEqual(rt.draggable, false);
sensing.setDragMode({DRAG_MODE: 'draggable'}, {target: rt});
t.strictEqual(rt.draggable, true);
t.end();
});
test('get loudness with caching', t => {
const rt = new Runtime();
const sensing = new Sensing(rt);
// It should report -1 when audio engine is not available.
t.strictEqual(sensing.getLoudness(), -1);
// Stub the audio engine with its getLoudness function, and set up different
// values to simulate it changing over time.
const firstLoudness = 1;
const secondLoudness = 2;
let simulatedLoudness = firstLoudness;
rt.audioEngine = {getLoudness: () => simulatedLoudness};
// It should report -1 when current step time is null.
t.strictEqual(sensing.getLoudness(), -1);
// Stub the current step time.
rt.currentStepTime = 1000 / 30;
// The first time it works, it should report the result from the stubbed audio engine.
t.strictEqual(sensing.getLoudness(), firstLoudness);
// Update the simulated loudness to a new value.
simulatedLoudness = secondLoudness;
// Simulate time passing by advancing the timer forward a little bit.
// After less than a step, it should still report cached loudness.
let simulatedTime = Date.now() + (rt.currentStepTime / 2);
sensing._timer = {time: () => simulatedTime};
t.strictEqual(sensing.getLoudness(), firstLoudness);
// Simulate more than a step passing. It should now request the value
// from the audio engine again.
simulatedTime += rt.currentStepTime;
t.strictEqual(sensing.getLoudness(), secondLoudness);
t.end();
});
test('loud? boolean', t => {
const rt = new Runtime();
const sensing = new Sensing(rt);
// The simplest way to test this is to actually override the getLoudness
// method, which isLoud uses.
let simulatedLoudness = 0;
sensing.getLoudness = () => simulatedLoudness;
t.false(sensing.isLoud());
// Check for GREATER than 10, not equal.
simulatedLoudness = 10;
t.false(sensing.isLoud());
simulatedLoudness = 11;
t.true(sensing.isLoud());
t.end();
});