1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * TestFixture for kiosk app settings WebUI testing.
7 * @extends {testing.Test}
8 * @constructor
9 */
10function AppListStartPageWebUITest() {}
11
12/**
13 * Mock of audioContext.
14 * @constructor
15 */
16function mockAudioContext() {
17  this.sampleRate = 44100; /* some dummy number */
18}
19
20mockAudioContext.prototype = {
21  createMediaStreamSource: function(stream) {
22    return {connect: function(audioProc) {},
23            disconnect: function() {}};
24  },
25  createScriptProcessor: function(bufSize, in_channels, out_channels) {
26    return {connect: function(destination) {},
27            disconnect: function() {}};
28  }
29};
30
31AppListStartPageWebUITest.prototype = {
32  __proto__: testing.Test.prototype,
33
34  /**
35   * Browser to app launcher start page.
36   */
37  browsePreload: 'chrome://app-list/',
38
39  /**
40   * Recommend apps data.
41   * @private
42   */
43  recommendedApps_: [
44    {
45      'appId': 'app_id_1',
46      'textTitle': 'app 1',
47      'iconUrl': 'icon_url_1'
48    },
49    {
50      'appId': 'app_id_2',
51      'textTitle': 'app 2',
52      'iconUrl': 'icon_url_2'
53    }
54  ],
55
56  /**
57   * Placeholder for mock speech recognizer.
58   */
59  speechRecognizer: null,
60
61  /**
62   * Sends the speech recognition result.
63   *
64   * @param {string} result The testing result.
65   * @param {boolean} isFinal Whether the result is final or not.
66   */
67  sendSpeechResult: function(result, isFinal) {
68    var speechEvent = new Event('test');
69    // Each result contains a list of alternatives and 'isFinal' flag.
70    var speechResult = [{transcript: result}];
71    speechResult.isFinal = isFinal;
72    speechEvent.results = [speechResult];
73    this.speechRecognizer.onresult(speechEvent);
74  },
75
76  /**
77   * Registers the webkitSpeechRecognition mock for test.
78   * @private
79   */
80  registerMockSpeechRecognition_: function() {
81    var owner = this;
82    function mockSpeechRecognition() {
83      this.inSpeech_ = false;
84      owner.speechRecognizer = this;
85    }
86
87    mockSpeechRecognition.prototype = {
88      start: function() {
89        this.onstart();
90      },
91
92      abort: function() {
93        if (this.inSpeech_)
94          this.onspeechend();
95        this.onerror(new Error());
96        this.onend();
97      }
98    },
99
100    window.webkitSpeechRecognition = mockSpeechRecognition;
101  },
102
103  /**
104   * Mock of webkitGetUserMedia for start page.
105   *
106   * @private
107   * @param {object} constraint The constraint parameter.
108   * @param {Function} success The success callback.
109   * @param {Function} error The error callback.
110   */
111  mockGetUserMedia_: function(constraint, success, error) {
112    function getAudioTracks() {
113    }
114    assertTrue(constraint.audio);
115    assertNotEquals(null, error, 'error callback must not be null');
116    var audioTracks = [];
117    for (var i = 0; i < 2; ++i) {
118      audioTracks.push(this.audioTrackMocks[i].proxy());
119    }
120    success({getAudioTracks: function() { return audioTracks; }});
121  },
122
123  /** @override */
124  preLoad: function() {
125    this.makeAndRegisterMockHandler(['initialize',
126                                     'launchApp',
127                                     'setSpeechRecognitionState',
128                                     'speechResult']);
129    this.mockHandler.stubs().initialize().will(callFunction(function() {
130      appList.startPage.setRecommendedApps(this.recommendedApps_);
131    }.bind(this)));
132    this.mockHandler.stubs().launchApp(ANYTHING);
133
134    this.registerMockSpeechRecognition_();
135    window.AudioContext = mockAudioContext;
136    navigator.webkitGetUserMedia = this.mockGetUserMedia_.bind(this);
137    this.audioTrackMocks = [mock(MediaStreamTrack), mock(MediaStreamTrack)];
138  }
139};
140
141TEST_F('AppListStartPageWebUITest', 'Basic', function() {
142  assertEquals(this.browsePreload, document.location.href);
143
144  var recommendedApp = $('start-page').querySelector('.recommended-apps');
145  assertEquals(this.recommendedApps_.length, recommendedApp.childElementCount);
146  for (var i = 0; i < recommendedApp.childElementCount; ++i) {
147    assertEquals(this.recommendedApps_[i].appId,
148                 recommendedApp.children[i].appId);
149  }
150});
151
152TEST_F('AppListStartPageWebUITest', 'ClickToLaunch', function() {
153  var recommendedApp = $('start-page').querySelector('.recommended-apps');
154  for (var i = 0; i < recommendedApp.childElementCount; ++i) {
155    this.mockHandler.expects(once()).launchApp(
156        [this.recommendedApps_[i].appId]);
157    cr.dispatchSimpleEvent(recommendedApp.children[i], 'click');
158  }
159});
160
161TEST_F('AppListStartPageWebUITest', 'SpeechRecognitionState', function() {
162  this.mockHandler.expects(once()).setSpeechRecognitionState('READY');
163  appList.startPage.onAppListShown();
164  this.mockHandler.expects(once()).setSpeechRecognitionState('RECOGNIZING');
165  appList.startPage.toggleSpeechRecognition();
166  Mock4JS.verifyAllMocks();
167  Mock4JS.clearMocksToVerify();
168
169  this.mockHandler.expects(once()).setSpeechRecognitionState('READY');
170  for (var i = 0; i < this.audioTrackMocks.length; ++i) {
171    this.audioTrackMocks[i].expects(once()).stop();
172  }
173  appList.startPage.toggleSpeechRecognition();
174  Mock4JS.verifyAllMocks();
175  Mock4JS.clearMocksToVerify();
176
177  this.mockHandler.expects(once()).setSpeechRecognitionState('RECOGNIZING');
178  appList.startPage.toggleSpeechRecognition();
179  Mock4JS.verifyAllMocks();
180  Mock4JS.clearMocksToVerify();
181
182  this.mockHandler.expects(once()).setSpeechRecognitionState('STOPPING');
183  this.mockHandler.expects(once()).setSpeechRecognitionState('READY');
184  for (var i = 0; i < this.audioTrackMocks.length; ++i) {
185    this.audioTrackMocks[i].expects(once()).stop();
186  }
187  appList.startPage.onAppListHidden();
188});
189
190TEST_F('AppListStartPageWebUITest', 'SpeechRecognition', function() {
191  this.mockHandler.expects(once()).setSpeechRecognitionState('READY');
192  appList.startPage.onAppListShown();
193  this.mockHandler.expects(once()).setSpeechRecognitionState('RECOGNIZING');
194  appList.startPage.toggleSpeechRecognition();
195  Mock4JS.verifyAllMocks();
196  Mock4JS.clearMocksToVerify();
197
198  this.mockHandler.expects(once()).setSpeechRecognitionState('IN_SPEECH');
199  this.speechRecognizer.onspeechstart();
200  Mock4JS.verifyAllMocks();
201  Mock4JS.clearMocksToVerify();
202
203  this.mockHandler.expects(once()).speechResult('test,false');
204  this.sendSpeechResult('test', false);
205  Mock4JS.verifyAllMocks();
206  Mock4JS.clearMocksToVerify();
207
208  this.mockHandler.expects(once()).speechResult('test,true');
209  this.mockHandler.expects(once()).setSpeechRecognitionState('READY');
210  for (var i = 0; i < this.audioTrackMocks.length; ++i) {
211    this.audioTrackMocks[i].expects(once()).stop();
212  }
213  this.sendSpeechResult('test', true);
214});
215