Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: chrome/browser/resources/google_now/background_unittest.gtestjs

Issue 21985002: Add Finch Checks to the State Machine (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@SMLog
Patch Set: Make Strings Const Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * Test fixture for background.js. 6 * Test fixture for background.js.
7 * @constructor 7 * @constructor
8 * @extends {testing.Test} 8 * @extends {testing.Test}
9 */ 9 */
10 function GoogleNowBackgroundUnitTest () { 10 function GoogleNowBackgroundUnitTest () {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false); 48 testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
49 }); 49 });
50 50
51 /** 51 /**
52 * Mocks global functions and APIs that initialize() depends upon. 52 * Mocks global functions and APIs that initialize() depends upon.
53 * @param {Test} fixture Test fixture. 53 * @param {Test} fixture Test fixture.
54 */ 54 */
55 function mockInitializeDependencies(fixture) { 55 function mockInitializeDependencies(fixture) {
56 fixture.makeAndRegisterMockGlobals([ 56 fixture.makeAndRegisterMockGlobals([
57 'recordEvent', 57 'recordEvent',
58 'setBackgroundEnable',
58 'showWelcomeToast', 59 'showWelcomeToast',
59 'startPollingCards' 60 'startPollingCards'
60 ]); 61 ]);
61 fixture.makeAndRegisterMockApis([ 62 fixture.makeAndRegisterMockApis([
62 'authenticationManager.isSignedIn', 63 'authenticationManager.isSignedIn',
63 'chrome.location.clearWatch', 64 'chrome.location.clearWatch',
64 'chrome.storage.local.set', 65 'chrome.storage.local.set',
66 'instrumented.metricsPrivate.getFieldTrial',
65 'instrumented.notifications.getAll', 67 'instrumented.notifications.getAll',
66 'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get', 68 'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get',
67 'instrumented.storage.local.get', 69 'instrumented.storage.local.get',
68 'tasks.add', 70 'tasks.add',
69 'updateCardsAttempts.isRunning', 71 'updateCardsAttempts.isRunning',
70 'updateCardsAttempts.stop' 72 'updateCardsAttempts.stop'
71 ]); 73 ]);
72 } 74 }
73 75
74 /** 76 /**
75 * Sets up the test to expect the state machine calls and send 77 * Sets up the test to expect the state machine calls and send
76 * the specified state machine state. Currently used to test initialize(). 78 * the specified state machine state. Currently used to test initialize().
77 * Note that this CAN NOT be used if any of the methods below are called 79 * Note that this CAN NOT be used if any of the methods below are called
78 * outside of this context with the same argument matchers. 80 * outside of this context with the same argument matchers.
79 * expects() calls cannot be chained with the same argument matchers. 81 * expects() calls cannot be chained with the same argument matchers.
80 * @param {object} mockApisObj Mock APIs Object. 82 * @param {object} fixture Test fixture.
81 * @param {string} testIdentityToken getAuthToken callback token. 83 * @param {string} testIdentityToken getAuthToken callback token.
82 * @param {boolean} testGeolocationPref Geolocation Preference callback value. 84 * @param {boolean} testGeolocationPref Geolocation Preference callback value.
83 * @param {boolean} testUserRespondedToToast User Response to toast 85 * @param {boolean} testUserRespondedToToast User Response to toast
84 & callback value. 86 & callback value.
85 */ 87 */
86 function expectStateMachineCalls( 88 function expectStateMachineCalls(
87 mockApisObj, 89 fixture,
88 testIdentityToken, 90 testIdentityToken,
89 testGeolocationPref, 91 testGeolocationPref,
90 testUserRespondedToToast) { 92 testUserRespondedToToast,
93 testExperimentResponse) {
91 var authenticationManagerIsSignedInSavedArgs = new SaveMockArguments(); 94 var authenticationManagerIsSignedInSavedArgs = new SaveMockArguments();
92 mockApisObj.expects(once()). 95 fixture.mockApis.expects(once()).
93 authenticationManager_isSignedIn( 96 authenticationManager_isSignedIn(
94 authenticationManagerIsSignedInSavedArgs.match(ANYTHING)). 97 authenticationManagerIsSignedInSavedArgs.match(ANYTHING)).
95 will(invokeCallback( 98 will(invokeCallback(
96 authenticationManagerIsSignedInSavedArgs, 99 authenticationManagerIsSignedInSavedArgs,
97 0, 100 0,
98 testIdentityToken)); 101 testIdentityToken));
99 102
103 var getFieldTrialSavedArgs = new SaveMockArguments();
104 fixture.mockApis.expects(once()).
105 instrumented_metricsPrivate_getFieldTrial(
106 getFieldTrialSavedArgs.match(ANYTHING),
107 getFieldTrialSavedArgs.match(ANYTHING)).
108 will(invokeCallback(
109 getFieldTrialSavedArgs, 1, testExperimentResponse));
110
100 var googleGeolocationPrefGetSavedArgs = new SaveMockArguments(); 111 var googleGeolocationPrefGetSavedArgs = new SaveMockArguments();
101 mockApisObj.expects(once()). 112 fixture.mockApis.expects(once()).
102 instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get( 113 instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get(
103 googleGeolocationPrefGetSavedArgs.match(eqJSON({})), 114 googleGeolocationPrefGetSavedArgs.match(eqJSON({})),
104 googleGeolocationPrefGetSavedArgs.match(ANYTHING)). 115 googleGeolocationPrefGetSavedArgs.match(ANYTHING)).
105 will(invokeCallback( 116 will(invokeCallback(
106 googleGeolocationPrefGetSavedArgs, 1, {value: testGeolocationPref})); 117 googleGeolocationPrefGetSavedArgs, 1, {value: testGeolocationPref}));
107 118
108 var storageGetSavedArgs = new SaveMockArguments(); 119 var storageGetSavedArgs = new SaveMockArguments();
109 mockApisObj.expects(once()). 120 fixture.mockApis.expects(once()).
110 instrumented_storage_local_get( 121 instrumented_storage_local_get(
111 storageGetSavedArgs.match(eq('userRespondedToToast')), 122 storageGetSavedArgs.match(eq('userRespondedToToast')),
112 storageGetSavedArgs.match(ANYTHING)). 123 storageGetSavedArgs.match(ANYTHING)).
113 will(invokeCallback(storageGetSavedArgs, 1, testUserRespondedToToast)); 124 will(invokeCallback(storageGetSavedArgs, 1, testUserRespondedToToast));
125
126 var setBackgroundEnableSavedArgs = new SaveMockArguments();
127 fixture.mockGlobals.expects(once()).
128 setBackgroundEnable(
129 setBackgroundEnableSavedArgs.match(ANYTHING),
130 setBackgroundEnableSavedArgs.match(ANYTHING)).
131 will(invokeCallback(
132 setBackgroundEnableSavedArgs, 1, {}));
114 } 133 }
115 134
116 /** 135 /**
117 * Sets up the test to expect the initialization calls that 136 * Sets up the test to expect the initialization calls that
118 * initialize() invokes. 137 * initialize() invokes.
119 * Note that this CAN NOT be used if any of the methods below are called 138 * Note that this CAN NOT be used if any of the methods below are called
120 * outside of this context with the same argument matchers. 139 * outside of this context with the same argument matchers.
121 * expects() calls cannot be chained with the same argument matchers. 140 * expects() calls cannot be chained with the same argument matchers.
122 */ 141 */
123 function expectInitialization(mockApisObj) { 142 function expectInitialization(mockApisObj) {
(...skipping 24 matching lines...) Expand all
148 function() { 167 function() {
149 // Tests the case when the user isn't signed in and NOTIFICATION_CARDS_URL 168 // Tests the case when the user isn't signed in and NOTIFICATION_CARDS_URL
150 // is not set. Since NOTIFICATION_CARDS_URL is empty, 169 // is not set. Since NOTIFICATION_CARDS_URL is empty,
151 // nothing should start. 170 // nothing should start.
152 171
153 // Setup and expectations. 172 // Setup and expectations.
154 NOTIFICATION_CARDS_URL = undefined; 173 NOTIFICATION_CARDS_URL = undefined;
155 var testIdentityToken = undefined; 174 var testIdentityToken = undefined;
156 var testGeolocationPref = false; 175 var testGeolocationPref = false;
157 var testUserRespondedToToast = {}; 176 var testUserRespondedToToast = {};
177 var testExperimentResponse = '';
158 178
159 mockInitializeDependencies(this); 179 mockInitializeDependencies(this);
160 180
161 this.mockGlobals.expects(once()).recordEvent( 181 this.mockGlobals.expects(once()).recordEvent(
162 GoogleNowEvent.EXTENSION_START); 182 GoogleNowEvent.EXTENSION_START);
163 183
164 this.mockGlobals.expects(once()).recordEvent( 184 this.mockGlobals.expects(once()).recordEvent(
165 GoogleNowEvent.STOPPED); 185 GoogleNowEvent.STOPPED);
166 186
167 expectInitialization(this.mockApis); 187 expectInitialization(this.mockApis);
168 188
169 expectStateMachineCalls( 189 expectStateMachineCalls(
170 this.mockApis, 190 this,
171 testIdentityToken, 191 testIdentityToken,
172 testGeolocationPref, 192 testGeolocationPref,
173 testUserRespondedToToast); 193 testUserRespondedToToast,
194 testExperimentResponse);
174 195
175 var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); 196 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
176 this.mockApis.expects(exactly(2)). 197 this.mockApis.expects(exactly(2)).
177 instrumented_notifications_getAll( 198 instrumented_notifications_getAll(
178 chromeNotificationGetAllSavedArgs.match(ANYTHING)). 199 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
179 will( 200 will(
180 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), 201 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
181 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); 202 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
182 203
183 // TODO(robliao,vadimt): Determine the granularity of testing to perform. 204 // TODO(robliao,vadimt): Determine the granularity of testing to perform.
184 205
185 // Invoking the tested function. 206 // Invoking the tested function.
186 initialize(); 207 initialize();
187 }); 208 });
188 209
189 TEST_F( 210 TEST_F(
190 'GoogleNowBackgroundUnitTest', 211 'GoogleNowBackgroundUnitTest',
191 'Initialize_ToastStateEmpty2', 212 'Initialize_ToastStateEmpty2',
192 function() { 213 function() {
193 // Tests the case when NOTIFICATION_CARDS_URL is but getAuthToken fails 214 // Tests the case when NOTIFICATION_CARDS_URL is but getAuthToken fails
194 // most likely because the user is not signed in. In this case, the 215 // most likely because the user is not signed in. In this case, the
195 // function should quietly exit after finding out that getAuthToken fails. 216 // function should quietly exit after finding out that getAuthToken fails.
196 217
197 // Setup and expectations. 218 // Setup and expectations.
198 NOTIFICATION_CARDS_URL = 'https://some.server.url.com'; 219 NOTIFICATION_CARDS_URL = 'https://some.server.url.com';
199 var testIdentityToken = undefined; 220 var testIdentityToken = undefined;
200 var testGeolocationPref = false; 221 var testGeolocationPref = false;
201 var testUserRespondedToToast = {}; 222 var testUserRespondedToToast = {};
223 var testExperimentResponse = '';
202 224
203 mockInitializeDependencies(this); 225 mockInitializeDependencies(this);
204 226
205 this.mockGlobals.expects(once()).recordEvent( 227 this.mockGlobals.expects(once()).recordEvent(
206 GoogleNowEvent.EXTENSION_START); 228 GoogleNowEvent.EXTENSION_START);
207 229
208 this.mockGlobals.expects(once()).recordEvent( 230 this.mockGlobals.expects(once()).recordEvent(
209 GoogleNowEvent.STOPPED); 231 GoogleNowEvent.STOPPED);
210 232
211 expectInitialization(this.mockApis); 233 expectInitialization(this.mockApis);
212 234
213 expectStateMachineCalls( 235 expectStateMachineCalls(
214 this.mockApis, 236 this,
215 testIdentityToken, 237 testIdentityToken,
216 testGeolocationPref, 238 testGeolocationPref,
217 testUserRespondedToToast); 239 testUserRespondedToToast,
240 testExperimentResponse);
218 241
219 var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); 242 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
220 this.mockApis.expects(exactly(2)). 243 this.mockApis.expects(exactly(2)).
221 instrumented_notifications_getAll( 244 instrumented_notifications_getAll(
222 chromeNotificationGetAllSavedArgs.match(ANYTHING)). 245 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
223 will( 246 will(
224 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), 247 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
225 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); 248 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
226 249
227 // Invoking the tested function. 250 // Invoking the tested function.
228 initialize(); 251 initialize();
229 }); 252 });
230 253
231 TEST_F( 254 TEST_F(
232 'GoogleNowBackgroundUnitTest', 255 'GoogleNowBackgroundUnitTest',
233 'Initialize_ToastStateEmpty3', 256 'Initialize_ToastStateEmpty3',
234 function() { 257 function() {
235 // Tests the case when NOTIFICATION_CARDS_URL is set, getAuthToken 258 // Tests the case when NOTIFICATION_CARDS_URL is set, getAuthToken
236 // succeeds, and the user has never responded to the toast. 259 // succeeds, and the user has never responded to the toast.
237 // In this case, the function should invoke showWelcomeToast(). 260 // In this case, the function should invoke showWelcomeToast().
238 261
239 // Setup and expectations. 262 // Setup and expectations.
240 NOTIFICATION_CARDS_URL = 'https://some.server.url.com'; 263 NOTIFICATION_CARDS_URL = 'https://some.server.url.com';
241 var testIdentityToken = 'some identity token'; 264 var testIdentityToken = 'some identity token';
242 var testGeolocationPref = false; 265 var testGeolocationPref = false;
243 var testUserRespondedToToast = {}; 266 var testUserRespondedToToast = {};
267 var testExperimentResponse = '';
244 268
245 mockInitializeDependencies(this); 269 mockInitializeDependencies(this);
246 270
247 this.mockGlobals.expects(once()).recordEvent( 271 this.mockGlobals.expects(once()).recordEvent(
248 GoogleNowEvent.EXTENSION_START); 272 GoogleNowEvent.EXTENSION_START);
249 273
250 expectInitialization(this.mockApis); 274 expectInitialization(this.mockApis);
251 275
252 expectStateMachineCalls( 276 expectStateMachineCalls(
253 this.mockApis, 277 this,
254 testIdentityToken, 278 testIdentityToken,
255 testGeolocationPref, 279 testGeolocationPref,
256 testUserRespondedToToast); 280 testUserRespondedToToast,
281 testExperimentResponse);
257 282
258 var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); 283 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
259 this.mockApis.expects(exactly(2)). 284 this.mockApis.expects(exactly(2)).
260 instrumented_notifications_getAll( 285 instrumented_notifications_getAll(
261 chromeNotificationGetAllSavedArgs.match(ANYTHING)). 286 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
262 will( 287 will(
263 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), 288 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
264 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); 289 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
265 290
266 this.mockGlobals.expects(once()).showWelcomeToast(); 291 this.mockGlobals.expects(once()).showWelcomeToast();
267 292
268 // Invoking the tested function. 293 // Invoking the tested function.
269 initialize(); 294 initialize();
270 }); 295 });
271 296
272 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_RunGoogleNow', function() { 297 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_RunGoogleNow', function() {
273 // Tests if Google Now will invoke startPollingCards when all 298 // Tests if Google Now will invoke startPollingCards when all
274 // of the required state is fulfilled. 299 // of the required state is fulfilled.
275 300
276 // Setup and expectations. 301 // Setup and expectations.
277 NOTIFICATION_CARDS_URL = 'https://some.server.url.com'; 302 NOTIFICATION_CARDS_URL = 'https://some.server.url.com';
278 var testIdentityToken = 'some identity token'; 303 var testIdentityToken = 'some identity token';
279 var testGeolocationPref = true; 304 var testGeolocationPref = true;
280 var testUserRespondedToToast = {userRespondedToToast: true}; 305 var testUserRespondedToToast = {userRespondedToToast: true};
306 var testExperimentResponse = '';
281 307
282 mockInitializeDependencies(this); 308 mockInitializeDependencies(this);
283 309
284 this.mockGlobals.expects(once()).recordEvent( 310 this.mockGlobals.expects(once()).recordEvent(
285 GoogleNowEvent.EXTENSION_START); 311 GoogleNowEvent.EXTENSION_START);
286 312
287 expectInitialization(this.mockApis); 313 expectInitialization(this.mockApis);
288 314
289 expectStateMachineCalls( 315 expectStateMachineCalls(
290 this.mockApis, 316 this,
291 testIdentityToken, 317 testIdentityToken,
292 testGeolocationPref, 318 testGeolocationPref,
293 testUserRespondedToToast); 319 testUserRespondedToToast,
320 testExperimentResponse);
294 321
295 var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); 322 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
296 this.mockApis.expects(exactly(2)). 323 this.mockApis.expects(exactly(2)).
297 instrumented_notifications_getAll( 324 instrumented_notifications_getAll(
298 chromeNotificationGetAllSavedArgs.match(ANYTHING)). 325 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
299 will( 326 will(
300 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), 327 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
301 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); 328 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
302 329
303 this.mockGlobals.expects(once()).startPollingCards(); 330 this.mockGlobals.expects(once()).startPollingCards();
304 331
305 // Invoking the tested function. 332 // Invoking the tested function.
306 initialize(); 333 initialize();
307 }); 334 });
308 335
309 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_NoGeolocation', function() { 336 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_NoGeolocation', function() {
310 // Tests the case where everything is in place except for the 337 // Tests the case where everything is in place except for the
311 // Geolocation Preference after the user responded to the toast. 338 // Geolocation Preference after the user responded to the toast.
312 339
313 // Setup and expectations. 340 // Setup and expectations.
314 NOTIFICATION_CARDS_URL = 'https://some.server.url.com'; 341 NOTIFICATION_CARDS_URL = 'https://some.server.url.com';
315 var testIdentityToken = 'some identity token'; 342 var testIdentityToken = 'some identity token';
316 var testGeolocationPref = false; 343 var testGeolocationPref = false;
317 var testUserRespondedToToast = {userRespondedToToast: true}; 344 var testUserRespondedToToast = {userRespondedToToast: true};
345 var testExperimentResponse = '';
318 346
319 mockInitializeDependencies(this); 347 mockInitializeDependencies(this);
320 348
321 this.mockGlobals.expects(once()).recordEvent( 349 this.mockGlobals.expects(once()).recordEvent(
322 GoogleNowEvent.EXTENSION_START); 350 GoogleNowEvent.EXTENSION_START);
323 351
324 this.mockGlobals.expects(once()).recordEvent( 352 this.mockGlobals.expects(once()).recordEvent(
325 GoogleNowEvent.USER_SUPPRESSED); 353 GoogleNowEvent.USER_SUPPRESSED);
326 354
327 expectInitialization(this.mockApis); 355 expectInitialization(this.mockApis);
328 356
329 expectStateMachineCalls( 357 expectStateMachineCalls(
330 this.mockApis, 358 this,
331 testIdentityToken, 359 testIdentityToken,
332 testGeolocationPref, 360 testGeolocationPref,
333 testUserRespondedToToast); 361 testUserRespondedToToast,
362 testExperimentResponse);
334 363
335 var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); 364 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
336 this.mockApis.expects(exactly(2)). 365 this.mockApis.expects(exactly(2)).
337 instrumented_notifications_getAll( 366 instrumented_notifications_getAll(
338 chromeNotificationGetAllSavedArgs.match(ANYTHING)). 367 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
339 will( 368 will(
340 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), 369 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
341 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); 370 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
342 371
343 // Invoking the tested function. 372 // Invoking the tested function.
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})), 545 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
517 chromeTabsCreateSavedArgs.match(ANYTHING)). 546 chromeTabsCreateSavedArgs.match(ANYTHING)).
518 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab)); 547 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
519 this.mockApis.expects(once()).chrome_windows_create( 548 this.mockApis.expects(once()).chrome_windows_create(
520 eqJSON({url: testActionUrl})); 549 eqJSON({url: testActionUrl}));
521 550
522 // Invoking the tested function. 551 // Invoking the tested function.
523 onNotificationClicked( 552 onNotificationClicked(
524 testNotificationId, this.mockLocalFunctions.functions().selector); 553 testNotificationId, this.mockLocalFunctions.functions().selector);
525 }); 554 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/google_now/background.js ('k') | chrome/browser/resources/google_now/manifest.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698