Revision control

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at */
import GCDWebServers
@testable import Client
import UIKit
import XCTest
class SearchTests: XCTestCase {
func testParsing() {
let parser = OpenSearchParser(pluginMode: true)
let file = Bundle.main.path(forResource: "google-b-m", ofType: "xml", inDirectory: "SearchPlugins/")
let engine: OpenSearchEngine! = parser.parse(file!, engineID: "google-b-m")
XCTAssertEqual(engine.shortName, "Google")
// Test regular search queries.
XCTAssertEqual(engine.searchURLForQuery("foobar")!.absoluteString, "")
// Test search suggestion queries.
XCTAssertEqual(engine.suggestURLForQuery("foobar")!.absoluteString, "")
func testURIFixup() {
// Check valid URLs. We can load these after some fixup.
checkValidURL("", afterFixup: "")
checkValidURL("about:", afterFixup: "about:")
checkValidURL("about:config", afterFixup: "about:config")
checkValidURL("about: config", afterFixup: "about:%20config")
checkValidURL("file:///f/o/o", afterFixup: "file:///f/o/o")
checkValidURL("", afterFixup: "")
checkValidURL("", afterFixup: "")
checkValidURL(" ", afterFixup: "")
checkValidURL("1.2.3", afterFixup: "http://1.2.3")
// Check invalid URLs. These are passed along to the default search engine.
checkInvalidURL("foo bar")
checkInvalidURL("mozilla. org")
checkInvalidURL("创业咖啡 中国")
checkInvalidURL("创业咖啡. 中国")
func testURIFixupPunyCode() {
checkValidURL("创业咖啡.中国", afterFixup: "http://xn--vhq70hq9bhxa.xn--fiqs8s")
checkValidURL(" 创业咖啡.中国 ", afterFixup: "http://xn--vhq70hq9bhxa.xn--fiqs8s")
fileprivate func checkValidURL(_ beforeFixup: String, afterFixup: String) {
XCTAssertEqual(URIFixup.getURL(beforeFixup)!.absoluteString, afterFixup)
fileprivate func checkInvalidURL(_ beforeFixup: String) {
func testSuggestClient() {
let webServerBase = startMockSuggestServer()
let engine = OpenSearchEngine(engineID: "mock", shortName: "Mock engine", image: UIImage(), searchTemplate: "", suggestTemplate: "\(webServerBase)?q={searchTerms}",
isCustomEngine: false)
let client = SearchSuggestClient(searchEngine: engine, userAgent: "Fx-testSuggestClient")
let query1 = self.expectation(description: "foo query")
client.query("foo", callback: { response, error in
withExtendedLifetime(client) {
if error != nil {
XCTFail("Error: \(error?.description ?? "nil")")
XCTAssertEqual(response![0], "foo")
XCTAssertEqual(response![1], "foo2")
XCTAssertEqual(response![2], "foo you")
waitForExpectations(timeout: 10, handler: nil)
let query2 = self.expectation(description: "foo bar query")
client.query("foo bar", callback: { response, error in
withExtendedLifetime(client) {
if error != nil {
XCTFail("Error: \(error?.description ?? "nil")")
XCTAssertEqual(response![0], "foo bar soap")
XCTAssertEqual(response![1], "foo barstool")
XCTAssertEqual(response![2], "foo bartender")
waitForExpectations(timeout: 10, handler: nil)
func testExtractingOfSearchTermsFromURL() {
let parser = OpenSearchParser(pluginMode: true)
var file = Bundle.main.path(forResource: "google-b-m", ofType: "xml", inDirectory: "SearchPlugins/")!
let googleEngine: OpenSearchEngine! = parser.parse(file, engineID: "google")
// create URL
let searchTerm = "Foo Bar"
let encodedSeachTerm = searchTerm.replacingOccurrences(of: " ", with: "+")
let duckDuckGoSearchURL = URL(string: "\(encodedSeachTerm)&ia=about")
let invalidSearchURL = URL(string: "")
let yaaniSearchURL = URL(string: "\(encodedSeachTerm)")
// check it correctly matches google search term given google config
XCTAssertEqual(searchTerm, googleEngine.queryForSearchURL(googleSearchURL))
// check it doesn't match when the URL is not a search URL
// check that it matches given a different configuration
file = Bundle.main.path(forResource: "duckduckgo", ofType: "xml", inDirectory: "SearchPlugins/")!
let duckDuckGoEngine: OpenSearchEngine! = parser.parse(file, engineID: "duckduckgo")
XCTAssertEqual(searchTerm, duckDuckGoEngine.queryForSearchURL(duckDuckGoSearchURL))
// check it doesn't match search URLs for different configurations
// check that if you pass in a nil URL that everything works
// check that if search engine that uses fragment matches search term
file = Bundle.main.path(forResource: "yaani", ofType: "xml", inDirectory: "SearchPlugins/")!
let yaaniEngine: OpenSearchEngine = parser.parse(file, engineID: "Yaani")!
XCTAssertEqual(searchTerm, yaaniEngine.queryForSearchURL(yaaniSearchURL))
fileprivate func startMockSuggestServer() -> String {
let webServer: GCDWebServer = GCDWebServer()
webServer.addHandler(forMethod: "GET", path: "/", request: GCDWebServerRequest.self) { (request) -> GCDWebServerResponse? in
var suggestions: [String]!
let query = request.query!["q"]!
switch query {
case "foo":
suggestions = ["foo", "foo2", "foo you"]
case "foo bar":
suggestions = ["foo bar soap", "foo barstool", "foo bartender"]
XCTFail("Unexpected query: \(query)")
return GCDWebServerDataResponse(jsonObject: [query, suggestions as Any])
if !webServer.start(withPort: 0, bonjourName: nil) {
XCTFail("Can't start the GCDWebServer")