blob: d287babf5836b8d1a40f11e590b277ffbefe80ff [file] [log] [blame]
/*
* Copyright (C) 2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
import XCTest
import WebKit
final class JavaScriptToSwiftConversions : XCTestCase {
#if os(macOS)
let window = NSWindow()
#elseif os(iOS)
let window = UIWindow()
#endif
let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
override func setUp() {
#if os(macOS)
window.contentView?.addSubview(webView)
#else
window.isHidden = false
window.addSubview(webView)
#endif
webView.load(URLRequest(url: URL(string: "about:blank")!))
}
override func tearDown() {
#if os(macOS)
window.orderOut(nil)
#else
window.isHidden = true
#endif
}
func evaluateJavaScript<T : Equatable>(_ javaScript: String, andExpect expectedValue: T) {
let evaluationExpectation = self.expectation(description: "Evaluation of \(javaScript.debugDescription)")
webView.evaluateJavaScript(javaScript, in: nil, in: .defaultClient) { result in
do {
let actualValue = try result.get() as? T
XCTAssertEqual(actualValue, expectedValue)
evaluationExpectation.fulfill()
} catch {
XCTFail("Evaluating \(javaScript.debugDescription) failed with error: \(error)")
}
}
wait(for: [evaluationExpectation], timeout: 30)
}
func testNull() {
evaluateJavaScript("null", andExpect: NSNull())
}
func testInteger() {
evaluateJavaScript("12", andExpect: 12 as Int)
}
func testDecimal() {
evaluateJavaScript("12.0", andExpect: 12 as Float)
}
func testBoolean() {
evaluateJavaScript("true", andExpect: true)
evaluateJavaScript("false", andExpect: false)
}
func testString() {
evaluateJavaScript(#""Hello, world!""#, andExpect: "Hello, world!")
}
func testArray() {
// This uses [AnyHashable], instead of [Any], so we can perform an equality check for testing.
evaluateJavaScript(#"[ 1, 2, "cat" ]"#, andExpect: [1, 2, "cat"] as [AnyHashable])
}
func testDictionary() {
// This uses [AnyHashable:AnyHashable], instead of [AnyHashable:Any], so we can perform an
// equality check for testing. An object’s keys are always converted to strings, so even
// though we input `1:` we expect `"1":` back.
let result: [AnyHashable:AnyHashable] = ["1": 2, "cat": "dog"]
evaluateJavaScript(#"const value = { 1: 2, "cat": "dog" }; value"#, andExpect: result)
}
func testUndefined() {
let evaluationExpectation = self.expectation(description: "Evaluation of \"undefined\" using deprecated API")
webView.evaluateJavaScript("undefined", in: nil, in: .defaultClient) { (result: Result<Any, Error>) in
do {
let value = try result.get()
if let optionalValue = value as? Any?, optionalValue == nil {
evaluationExpectation.fulfill()
} else {
XCTFail("Value did not contain nil")
}
} catch {
XCTFail("Evaluating \"undefined\" failed with error: \(error)")
}
}
wait(for: [evaluationExpectation], timeout: 30)
}
#if swift(>=5.5)
@available(iOS 15.0, macOS 12.0, *)
func testUsingSwiftAsync() async throws {
guard let result = try await webView.evaluateJavaScript(#""Hello, world!""#) as? String else {
XCTFail("Unexpected result from evaluating JavaScript.")
return
}
XCTAssertEqual(result, "Hello, world!")
}
#endif
}