Rageshake Service (#70)

This commit is contained in:
ismailgulek
2022-06-06 12:38:07 +03:00
committed by GitHub
parent 1e7243fcf9
commit fa0721b160
57 changed files with 3010 additions and 32 deletions
@@ -0,0 +1,90 @@
//
// BugReportServiceTests.swift
// UnitTests
//
// Created by Ismail on 31.05.2022.
// Copyright © 2022 element.io. All rights reserved.
//
import Foundation
@testable import ElementX
import XCTest
class BugReportServiceTests: XCTestCase {
let bugReportService = MockBugReportService()
func testInitialStateWithMockService() {
XCTAssertFalse(bugReportService.crashedLastRun)
}
func testSubmitBugReportWithMockService() async throws {
let result = try await bugReportService.submitBugReport(text: "i cannot send message",
includeLogs: true,
includeCrashLog: true,
githubLabels: [],
files: [])
XCTAssertFalse(result.reportUrl.isEmpty)
}
func testInitialStateWithRealService() throws {
let service = try BugReportService(withBaseUrlString: "https://www.example.com",
sentryEndpoint: "mock_sentry_dsn",
applicationId: "mock_app_id",
session: .mock)
XCTAssertFalse(service.crashedLastRun)
}
@MainActor func testSubmitBugReportWithRealService() async throws {
let service = try BugReportService(withBaseUrlString: "https://www.example.com",
sentryEndpoint: "mock_sentry_dsn",
applicationId: "mock_app_id",
session: .mock)
let result = try await service.submitBugReport(text: "i cannot send message",
includeLogs: true,
includeCrashLog: true,
githubLabels: [],
files: [])
XCTAssertEqual(result.reportUrl, "https://example.com/123")
}
}
private class MockURLProtocol: URLProtocol {
override func startLoading() {
let response = "{\"report_url\":\"https://example.com/123\"}"
if let data = response.data(using: .utf8) {
let urlResponse = URLResponse()
client?.urlProtocol(self, didReceive: urlResponse, cacheStoragePolicy: .allowedInMemoryOnly)
client?.urlProtocol(self, didLoad: data)
client?.urlProtocolDidFinishLoading(self)
}
}
override func stopLoading() {
// no-op
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
override class func canInit(with request: URLRequest) -> Bool {
return true
}
}
private extension URLSession {
static var mock: URLSession {
let configuration = URLSessionConfiguration.default
configuration.protocolClasses = [MockURLProtocol.self] + (configuration.protocolClasses ?? [])
let result = URLSession(configuration: configuration)
return result
}
}
@@ -0,0 +1,50 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import XCTest
@testable import ElementX
@MainActor
class BugReportViewModelTests: XCTestCase {
func testInitialState() {
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: nil)
let context = viewModel.context
XCTAssertEqual(context.reportText, "")
XCTAssertNil(context.viewState.screenshot)
XCTAssertTrue(context.sendingLogsEnabled)
}
func testToggleSendingLogs() async throws {
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: nil)
let context = viewModel.context
context.send(viewAction: .toggleSendLogs)
await Task.yield()
XCTAssertFalse(context.sendingLogsEnabled)
}
func testClearScreenshot() async throws {
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: UIImage.actions)
let context = viewModel.context
context.send(viewAction: .removeScreenshot)
await Task.yield()
XCTAssertNil(context.viewState.screenshot)
}
}
@@ -19,11 +19,65 @@ import XCTest
@testable import ElementX
class HomeScreenViewModelTests: XCTestCase {
override func setUpWithError() throws {
var viewModel: HomeScreenViewModelProtocol!
var context: HomeScreenViewModelType.Context!
@MainActor override func setUpWithError() throws {
viewModel = HomeScreenViewModel(attributedStringBuilder: AttributedStringBuilder())
context = viewModel.context
}
func testInitialState() {
@MainActor func testLogout() async throws {
var correctResult = false
viewModel.callback = { result in
switch result {
case .logout:
correctResult = true
default:
break
}
}
context.send(viewAction: .logout)
await Task.yield()
XCTAssert(correctResult)
}
@MainActor func testSelectRoom() async throws {
let mockRoomId = "mock_room_id"
var correctResult = false
var selectedRoomId = ""
viewModel.callback = { result in
switch result {
case .selectRoom(let roomId):
correctResult = true
selectedRoomId = roomId
default:
break
}
}
context.send(viewAction: .selectRoom(roomIdentifier: mockRoomId))
await Task.yield()
XCTAssert(correctResult)
XCTAssertEqual(mockRoomId, selectedRoomId)
}
@MainActor func testTapUserAvatar() async throws {
var correctResult = false
viewModel.callback = { result in
switch result {
case .tapUserAvatar:
correctResult = true
default:
break
}
}
context.send(viewAction: .tapUserAvatar)
await Task.yield()
XCTAssert(correctResult)
}
}
@@ -0,0 +1,57 @@
//
// ImageExtensionTests.swift
// UnitTests
//
// Created by Ismail on 31.05.2022.
// Copyright © 2022 element.io. All rights reserved.
//
import XCTest
@testable import ElementX
enum ImageAnonymizerTestsError: String, Error {
case screenshotNotFound
}
class ImageAnonymizerTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func sampleScreenshot() throws -> UIImage {
let bundle = Bundle(for: self.classForCoder)
guard let path = bundle.path(forResource: "sample_screenshot", ofType: "png"),
let image = UIImage(contentsOfFile: path) else {
throw ImageAnonymizerTestsError.screenshotNotFound
}
return image
}
func testImageAnonymizationConfidenceLevel() async throws {
let image = try sampleScreenshot()
let anonymized5 = try await ImageAnonymizer.anonymizedImage(from: image)
let anonymized1 = try await ImageAnonymizer.anonymizedImage(from: image, confidenceLevel: 0.1)
// comparing colors is a complicated process, just compare images for now
XCTAssertNotEqual(image, anonymized5)
XCTAssertNotEqual(anonymized1, anonymized5)
}
func testImageAnonymizationFillColor() async throws {
let image = try sampleScreenshot()
let anonymizedRed = try await ImageAnonymizer.anonymizedImage(from: image)
let anonymizedBlue = try await ImageAnonymizer.anonymizedImage(from: image, fillColor: .blue)
// comparing colors is a complicated process, just compare images for now
XCTAssertNotEqual(image, anonymizedRed)
XCTAssertNotEqual(anonymizedBlue, anonymizedRed)
}
}
+96
View File
@@ -0,0 +1,96 @@
//
// LoggingTests.swift
// UnitTests
//
// Created by Ismail on 31.05.2022.
// Copyright © 2022 element.io. All rights reserved.
//
import XCTest
@testable import ElementX
class LoggingTests: XCTestCase {
private enum Constants {
static let genericFailure = "Test failed"
}
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testFileLogging() throws {
MXLogger.deleteLogFiles()
guard let logFiles = MXLogger.logFiles() else {
XCTFail(Constants.genericFailure)
return
}
XCTAssertTrue(logFiles.isEmpty)
let log = UUID().uuidString
let configuration = MXLogConfiguration()
configuration.redirectLogsToFiles = true
MXLog.configure(configuration)
MXLog.debug(log)
guard let logFile = MXLogger.logFiles().first else {
XCTFail(Constants.genericFailure)
return
}
let content = try String(contentsOfFile: logFile)
XCTAssert(content.contains(log))
}
func testLogLevels() throws {
MXLogger.deleteLogFiles()
guard let logFiles = MXLogger.logFiles() else {
XCTFail(Constants.genericFailure)
return
}
XCTAssert(logFiles.isEmpty)
let log = UUID().uuidString
let configuration = MXLogConfiguration()
configuration.logLevel = .error
configuration.redirectLogsToFiles = true
MXLog.configure(configuration)
MXLog.debug(log)
guard let logFile = MXLogger.logFiles().first else {
XCTFail(Constants.genericFailure)
return
}
let content = try String(contentsOfFile: logFile)
XCTAssertFalse(content.contains(log))
}
func testSubLogName() {
MXLogger.deleteLogFiles()
guard let logFiles = MXLogger.logFiles() else {
XCTFail(Constants.genericFailure)
return
}
XCTAssert(logFiles.isEmpty)
let subLogName = "nse"
let configuration = MXLogConfiguration()
configuration.subLogName = subLogName
configuration.redirectLogsToFiles = true
MXLog.configure(configuration)
MXLog.debug(UUID().uuidString)
guard let logFile = MXLogger.logFiles().first else {
XCTFail(Constants.genericFailure)
return
}
XCTAssertTrue(logFile.contains(subLogName))
}
}
@@ -0,0 +1,63 @@
//
// ScreenshotDetectorTests.swift
// UnitTests
//
// Created by Ismail on 31.05.2022.
// Copyright © 2022 element.io. All rights reserved.
//
import Foundation
@testable import ElementX
import XCTest
import Photos
class ScreenshotDetectorTests: XCTestCase {
@MainActor func testDetection() async {
async { expectation in
let detector = ScreenshotDetector()
// disable auto request authorization
detector.autoRequestPHAuthorization = false
detector.callback = { image, error in
if PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized {
// if Photos already authorized on the simulator
// we should get an image
XCTAssertNotNil(image)
// we should not get an error
XCTAssertNil(error)
} else {
// otherwise we should not get an image
XCTAssertNil(image)
// and get an error
guard let error = error else {
XCTFail("Should get an error")
return
}
switch error {
case ScreenshotDetectorError.notAuthorized:
break
default:
XCTFail("Unknown error")
}
}
expectation.fulfill()
}
NotificationCenter.default.post(name: UIApplication.userDidTakeScreenshotNotification, object: nil)
}
}
private func async(_ timeout: TimeInterval = 0.5, _ block: @escaping (XCTestExpectation) -> Void) {
let waiter = XCTWaiter()
let expectation = XCTestExpectation(description: "Async operation expectation")
block(expectation)
waiter.wait(for: [expectation], timeout: timeout)
}
}
@@ -0,0 +1,58 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import XCTest
@testable import ElementX
@MainActor
class SettingsViewModelTests: XCTestCase {
var viewModel: SettingsViewModelProtocol!
var context: SettingsViewModelType.Context!
@MainActor override func setUpWithError() throws {
viewModel = SettingsViewModel()
context = viewModel.context
}
func testInitialState() {
XCTAssert(context.viewState.crashButtonVisible)
}
func testReportBug() async throws {
var correctResult = false
viewModel.callback = { result in
correctResult = result == .reportBug
}
context.send(viewAction: .reportBug)
await Task.yield()
XCTAssert(correctResult)
}
func testCrash() async throws {
var correctResult = false
viewModel.callback = { result in
correctResult = result == .crash
}
context.send(viewAction: .crash)
await Task.yield()
XCTAssert(correctResult)
}
}