/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * These tests unit test the functionality of UrlbarController by stubbing out the * model and providing stubs to be called. */ "use strict"; const TEST_URL = "http://example.com"; const MATCH = new UrlbarResult( UrlbarUtils.RESULT_TYPE.TAB_SWITCH, UrlbarUtils.RESULT_SOURCE.TABS, { url: TEST_URL } ); const TELEMETRY_1ST_RESULT = "PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS"; const TELEMETRY_6_FIRST_RESULTS = "PLACES_AUTOCOMPLETE_6_FIRST_RESULTS_TIME_MS"; let controller; let firstHistogram; let sixthHistogram; /** * A delayed test provider, allowing the query to be delayed for an amount of time. */ class DelayedProvider extends TestProvider { async startQuery(context, add) { Assert.ok(context, "context is passed-in"); Assert.equal(typeof add, "function", "add is a callback"); this._add = add; await new Promise(resolve => { this._resultsAdded = resolve; }); } async addResults(matches, finish = true) { // startQuery may have not been invoked yet, so wait for it await TestUtils.waitForCondition( () => !!this._add, "Waiting for the _add callback" ); for (const match of matches) { this._add(this, match); } if (finish) { this._add = null; this._resultsAdded(); } } } /** * Returns the number of reports sent recorded within the histogram results. * * @param {object} results a snapshot of histogram results to check. * @returns {number} The count of reports recorded in the histogram. */ function getHistogramReportsCount(results) { let sum = 0; for (let [, value] of Object.entries(results.values)) { sum += value; } return sum; } add_task(function setup() { controller = UrlbarTestUtils.newMockController(); firstHistogram = Services.telemetry.getHistogramById(TELEMETRY_1ST_RESULT); sixthHistogram = Services.telemetry.getHistogramById( TELEMETRY_6_FIRST_RESULTS ); }); add_task(async function test_n_autocomplete_cancel() { firstHistogram.clear(); sixthHistogram.clear(); let providerCanceledDeferred = PromiseUtils.defer(); let provider = new TestProvider({ results: [], onCancel: providerCanceledDeferred.resolve, }); UrlbarProvidersManager.registerProvider(provider); const context = createContext(TEST_URL, { providers: [provider.name] }); Assert.ok( !TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should not have started first result stopwatch" ); Assert.ok( !TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should not have started first 6 results stopwatch" ); controller.startQuery(context); Assert.ok( TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should have started first result stopwatch" ); Assert.ok( TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should have started first 6 results stopwatch" ); controller.cancelQuery(context); await providerCanceledDeferred.promise; Assert.ok( !TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should have canceled first result stopwatch" ); Assert.ok( !TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should have canceled first 6 results stopwatch" ); let results = firstHistogram.snapshot(); Assert.equal( results.sum, 0, "Should not have recorded any times (first result)" ); results = sixthHistogram.snapshot(); Assert.equal( results.sum, 0, "Should not have recorded any times (first 6 results)" ); }); add_task(async function test_n_autocomplete_results() { firstHistogram.clear(); sixthHistogram.clear(); let provider = new DelayedProvider(); UrlbarProvidersManager.registerProvider(provider); const context = createContext(TEST_URL, { providers: [provider.name] }); let resultsPromise = promiseControllerNotification( controller, "onQueryResults" ); Assert.ok( !TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should not have started first result stopwatch" ); Assert.ok( !TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should not have started first 6 results stopwatch" ); controller.startQuery(context); Assert.ok( TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should have started first result stopwatch" ); Assert.ok( TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should have started first 6 results stopwatch" ); await provider.addResults([MATCH], false); await resultsPromise; Assert.ok( !TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should have stopped the first stopwatch" ); Assert.ok( TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should have kept the first 6 results stopwatch running" ); let firstResults = firstHistogram.snapshot(); let first6Results = sixthHistogram.snapshot(); Assert.equal( getHistogramReportsCount(firstResults), 1, "Should have recorded one time for the first result" ); Assert.equal( getHistogramReportsCount(first6Results), 0, "Should not have recorded any times (first 6 results)" ); // Now add 5 more results, so that the first 6 results is triggered. for (let i = 0; i < 5; i++) { resultsPromise = promiseControllerNotification( controller, "onQueryResults" ); await provider.addResults( [ new UrlbarResult( UrlbarUtils.RESULT_TYPE.TAB_SWITCH, UrlbarUtils.RESULT_SOURCE.TABS, { url: TEST_URL + "/" + i } ), ], false ); await resultsPromise; } Assert.ok( !TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context), "Should have stopped the first stopwatch" ); Assert.ok( !TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context), "Should have stopped the first 6 results stopwatch" ); let updatedResults = firstHistogram.snapshot(); let updated6Results = sixthHistogram.snapshot(); Assert.deepEqual( updatedResults, firstResults, "Should not have changed the histogram for the first result" ); Assert.equal( getHistogramReportsCount(updated6Results), 1, "Should have recorded one time for the first 6 results" ); // Add one more, to check neither are updated. resultsPromise = promiseControllerNotification(controller, "onQueryResults"); await provider.addResults([ new UrlbarResult( UrlbarUtils.RESULT_TYPE.TAB_SWITCH, UrlbarUtils.RESULT_SOURCE.TABS, { url: TEST_URL + "/6" } ), ]); await resultsPromise; let secondUpdateResults = firstHistogram.snapshot(); let secondUpdate6Results = sixthHistogram.snapshot(); Assert.deepEqual( secondUpdateResults, firstResults, "Should not have changed the histogram for the first result" ); Assert.equal( getHistogramReportsCount(secondUpdate6Results), 1, "Should not have changed the histogram for the first 6 results" ); });