Merge pull request #1631 from mzgoddard/stop-other-asks

Stop other asks
This commit is contained in:
Andrew Sliwinski 2018-10-15 13:16:49 -04:00 committed by GitHub
commit 23f6346045
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 0 deletions

View file

@ -42,6 +42,7 @@ class Scratch3SensingBlocks {
this.runtime.on('ANSWER', this._onAnswer.bind(this));
this.runtime.on('PROJECT_START', this._resetAnswer.bind(this));
this.runtime.on('PROJECT_STOP_ALL', this._clearAllQuestions.bind(this));
this.runtime.on('STOP_FOR_TARGET', this._clearTargetQuestions.bind(this));
}
/**
@ -134,6 +135,21 @@ class Scratch3SensingBlocks {
this.runtime.emit('QUESTION', null);
}
_clearTargetQuestions (stopTarget) {
const currentlyAsking = this._questionList.length > 0 && this._questionList[0][2] === stopTarget;
this._questionList = this._questionList.filter(question => (
question[2] !== stopTarget
));
if (currentlyAsking) {
if (this._questionList.length > 0) {
this._askNextQuestion();
} else {
this.runtime.emit('QUESTION', null);
}
}
}
askAndWait (args, util) {
const _target = util.target;
return new Promise(resolve => {

View file

@ -383,6 +383,15 @@ class Runtime extends EventEmitter {
return 'PROJECT_STOP_ALL';
}
/**
* Event name for target being stopped by a stop for target call.
* Used by blocks that need to stop individual targets.
* @const {string}
*/
static get STOP_FOR_TARGET () {
return 'STOP_FOR_TARGET';
}
/**
* Event name for visual value report.
* @const {string}
@ -1450,6 +1459,9 @@ class Runtime extends EventEmitter {
* @param {Thread=} optThreadException Optional thread to skip.
*/
stopForTarget (target, optThreadException) {
// Emit stop event to allow blocks to clean up any state.
this.emit(Runtime.STOP_FOR_TARGET, target, optThreadException);
// Stop any threads on the target.
for (let i = 0; i < this.threads.length; i++) {
if (this.threads[i] === optThreadException) {

View file

@ -37,6 +37,90 @@ test('ask and answer with a hidden target', t => {
});
});
test('ask and stop all dismisses question', t => {
const rt = new Runtime();
const s = new Sensing(rt);
const util = {target: {visible: false}};
const expectedQuestion = 'a question';
let call = 0;
rt.addListener('QUESTION', question => {
if (call === 0) {
// (2) Assert the question was passed.
t.strictEqual(question, expectedQuestion);
} else if (call === 1) {
// (4) Assert the question was dismissed.
t.strictEqual(question, null);
t.end();
}
call += 1;
});
// (1) Emit the question.
s.askAndWait({QUESTION: expectedQuestion}, util);
// (3) Emit the stop all event.
rt.stopAll();
});
test('ask and stop other scripts dismisses if it is the last question', t => {
const rt = new Runtime();
const s = new Sensing(rt);
const util = {target: {visible: false}, thread: {}};
const expectedQuestion = 'a question';
let call = 0;
rt.addListener('QUESTION', question => {
if (call === 0) {
// (2) Assert the question was passed.
t.strictEqual(question, expectedQuestion);
} else if (call === 1) {
// (4) Assert the question was dismissed.
t.strictEqual(question, null);
t.end();
}
call += 1;
});
// (1) Emit the questions.
s.askAndWait({QUESTION: expectedQuestion}, util);
// (3) Emit the stop for target event.
rt.stopForTarget(util.target, util.thread);
});
test('ask and stop other scripts asks next question', t => {
const rt = new Runtime();
const s = new Sensing(rt);
const util = {target: {visible: false}, thread: {}};
const util2 = {target: {visible: false}, thread: {}};
const expectedQuestion = 'a question';
const nextQuestion = 'a followup';
let call = 0;
rt.addListener('QUESTION', question => {
if (call === 0) {
// (2) Assert the question was passed.
t.strictEqual(question, expectedQuestion);
} else if (call === 1) {
// (4) Assert the next question was passed.
t.strictEqual(question, nextQuestion);
t.end();
}
call += 1;
});
// (1) Emit the questions.
s.askAndWait({QUESTION: expectedQuestion}, util);
s.askAndWait({QUESTION: nextQuestion}, util2);
// (3) Emit the stop for target event.
rt.stopForTarget(util.target, util.thread);
});
test('ask and answer with a visible target', t => {
const rt = new Runtime();
const s = new Sensing(rt);