Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests share table view controller #32

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions LineSDK/LineSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@
4BDD2C342133F32200DD563D /* LineSDKFlexSeparatorComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDD2C332133F32200DD563D /* LineSDKFlexSeparatorComponent.swift */; };
4BDD2C362133F32F00DD563D /* LineSDKSpacerComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDD2C352133F32F00DD563D /* LineSDKSpacerComponent.swift */; };
4BDD2C382133F34300DD563D /* LineSDKFlexBoxComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDD2C372133F34300DD563D /* LineSDKFlexBoxComponent.swift */; };
4BE4E0FC2251CEE10071FC60 /* ColumnDataStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE4E0FB2251CEE10071FC60 /* ColumnDataStoreTests.swift */; };
4BEB491A212B94BC00BA946A /* FlexImageComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEB4919212B94BC00BA946A /* FlexImageComponent.swift */; };
4BEB491C212B992B00BA946A /* FlexImageComponentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEB491B212B992B00BA946A /* FlexImageComponentTests.swift */; };
4BEB491E212B9E5500BA946A /* FlexFillerComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEB491D212B9E5500BA946A /* FlexFillerComponent.swift */; };
Expand Down Expand Up @@ -495,6 +496,7 @@
4BDD2C332133F32200DD563D /* LineSDKFlexSeparatorComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineSDKFlexSeparatorComponent.swift; sourceTree = "<group>"; };
4BDD2C352133F32F00DD563D /* LineSDKSpacerComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineSDKSpacerComponent.swift; sourceTree = "<group>"; };
4BDD2C372133F34300DD563D /* LineSDKFlexBoxComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineSDKFlexBoxComponent.swift; sourceTree = "<group>"; };
4BE4E0FB2251CEE10071FC60 /* ColumnDataStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColumnDataStoreTests.swift; sourceTree = "<group>"; };
4BEB4919212B94BC00BA946A /* FlexImageComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlexImageComponent.swift; sourceTree = "<group>"; };
4BEB491B212B992B00BA946A /* FlexImageComponentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlexImageComponentTests.swift; sourceTree = "<group>"; };
4BEB491D212B9E5500BA946A /* FlexFillerComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlexFillerComponent.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -824,6 +826,7 @@
4B90588521006E5D004D717F /* LineSDKTests */ = {
isa = PBXGroup;
children = (
4BE4E0FA2251C9090071FC60 /* Sharing */,
DB0AFF5F2247FB06002729AD /* UI */,
4B15EEF9211D5BE800866E6C /* Message */,
4B792FB421103CFD00EDDD1E /* API */,
Expand Down Expand Up @@ -1117,6 +1120,14 @@
path = Component;
sourceTree = "<group>";
};
4BE4E0FA2251C9090071FC60 /* Sharing */ = {
isa = PBXGroup;
children = (
4BE4E0FB2251CEE10071FC60 /* ColumnDataStoreTests.swift */,
);
path = Sharing;
sourceTree = "<group>";
};
4BF45A872137B27F00CCD28E /* Crypto */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1742,6 +1753,7 @@
4BEB491C212B992B00BA946A /* FlexImageComponentTests.swift in Sources */,
4B08F9C22119863500B140DF /* LineSDKErrorTests.swift in Sources */,
4B792FB121102D9200EDDD1E /* LoginProcessURLResponseTests.swift in Sources */,
4BE4E0FC2251CEE10071FC60 /* ColumnDataStoreTests.swift in Sources */,
4B5EE2E6212BD53E0009DF2E /* FlexBubbleContainerTests.swift in Sources */,
4BF45A8B2137B2C500CCD28E /* RSAKeyTests.swift in Sources */,
4BFC09F5213CF5B200F4594D /* GetDiscoveryDocumentRequestTests.swift in Sources */,
Expand Down
12 changes: 8 additions & 4 deletions LineSDK/LineSDK/SharingUI/ColumnDataStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ extension LineSDKNotificationKey {
class ColumnDataStore<T> {

struct ColumnIndex: Equatable {
let row: Int
let column: Int
let row: Int
}

struct AppendingIndexRange {
Expand Down Expand Up @@ -105,7 +105,7 @@ class ColumnDataStore<T> {
)
}

let targetIndex = ColumnIndex(row: rowIndex, column: columnIndex)
let targetIndex = ColumnIndex(column: columnIndex, row: rowIndex)
if let index = selected.firstIndex(of: targetIndex) {
selected.remove(at: index)
notifySelectingChange(selected: false, targetIndex: targetIndex)
Expand All @@ -120,11 +120,15 @@ class ColumnDataStore<T> {
return true
}

func indexes(atColumn column: Int, filtered: ((T) -> Bool)) -> [ColumnIndex] {
func indexes(atColumn column: Int, where filtered: ((T) -> Bool)) -> [ColumnIndex] {
return data(atColumn: column)
.enumerated()
.filter { _, elem in filtered(elem) }
.map { ColumnIndex(row: $0.offset, column: column) }
.map { ColumnIndex(column: column, row: $0.offset) }
}

func indexes(where filtered: ((T) -> Bool)) -> [[ColumnIndex]] {
return (0 ..< data.count).map { indexes(atColumn: $0, where: filtered) }
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ final class ShareTargetSearchResultViewController: UITableViewController, ShareT
var searchText: String = "" {
didSet {
guard searchText != oldValue else { return }
filteredIndexes = MessageShareTargetType.allCases.map {
store.indexes(atColumn: $0.rawValue) {
$0.displayName.localizedCaseInsensitiveContains(searchText)
}
filteredIndexes = store.indexes {
$0.displayName.localizedCaseInsensitiveContains(searchText)
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions LineSDK/LineSDK/SharingUI/ShareTargetSelectingTableCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ extension ShareTargetSelectingTableCell {

func placeholderUserImage(for name: String) -> UIImage? {
let value = name.count % 4 + 1
return UIImage(named: "unknown_user_small_0\(value)", in: Bundle.frameworkBundle, compatibleWith: nil)
return UIImage(named: "unknown_user_small_0\(value)", in: .frameworkBundle, compatibleWith: nil)
}

func setShareTarget(_ target: ShareTarget, selected: Bool, highlightText: String? = nil) {
Expand All @@ -144,8 +144,8 @@ extension ShareTargetSelectingTableCell {
currentImageDownloadToken = token

let selectedImage = selected ?
UIImage(named: "friend_check_on", in: Bundle.frameworkBundle, compatibleWith: nil) :
UIImage(named: "friend_check_off", in: Bundle.frameworkBundle, compatibleWith: nil)
UIImage(named: "friend_check_on", in: .frameworkBundle, compatibleWith: nil) :
UIImage(named: "friend_check_off", in: .frameworkBundle, compatibleWith: nil)
tickImageView.image = selectedImage
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ extension ShareTargetSelectingViewController {
withIdentifier: ShareTargetSelectingTableCell.reuseIdentifier,
for: indexPath) as! ShareTargetSelectingTableCell

let dataIndex = ColumnIndex(row: indexPath.row, column: columnIndex)
let dataIndex = ColumnIndex(column: columnIndex, row: indexPath.row)

let target = store.data(at: dataIndex)
let selected = store.isSelected(at: dataIndex)
Expand Down
4 changes: 2 additions & 2 deletions LineSDK/LineSDK/SharingUI/ShareViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ public protocol ShareViewControllerDelegate: AnyObject {
func shareViewController(
_ controller: ShareViewController,
didFailLoadingListType shareType: MessageShareTargetType,
withError: LineSDKError)
withError error: LineSDKError)
func shareViewControllerDidCancelSharing(_ controller: ShareViewController)
}

extension ShareViewControllerDelegate {
public func shareViewController(
_ controller: ShareViewController,
didFailLoadingListType shareType: MessageShareTargetType,
withError: LineSDKError) { }
withError error: LineSDKError) { }
public func shareViewControllerDidCancelSharing(_ controller: ShareViewController) { }
}

Expand Down
181 changes: 181 additions & 0 deletions LineSDK/LineSDKTests/Sharing/ColumnDataStoreTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
//
// ColumnDataStoreTests.swift
//
// Copyright (c) 2016-present, LINE Corporation. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by LINE Corporation.
//
// As with any software that integrates with the LINE Corporation platform, your use of this software
// is subject to the LINE Developers Agreement [http://terms2.line.me/LINE_Developers_Agreement].
// This copyright notice shall be included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

import XCTest
@testable import LineSDK

class ColumnDataStoreTests: XCTestCase {

var store: ColumnDataStore<Int>!
var token: NotificationToken!

override func setUp() {
super.setUp()
store = ColumnDataStore(columnCount: 3)
}

override func tearDown() {
store = nil
token = nil
super.tearDown()
}

func testAppendData() {
store.append(data: [1,2,3], to: 0)
store.append(data: [4,5,6], to: 1)
store.append(data: [7,8,9], to: 2)

XCTAssertEqual(store.data(atColumn: 0), [1, 2, 3])
XCTAssertEqual(store.data(atColumn: 1), [4, 5, 6])
XCTAssertEqual(store.data(atColumn: 2), [7, 8, 9])

store.append(data: [3,2,1], to: 0)
XCTAssertEqual(store.data(atColumn: 0), [1, 2, 3, 3, 2, 1])
}

func testGetData() {
store.append(data: [1,2,3], to: 0)
XCTAssertEqual(store.data(atColumn: 0), [1, 2, 3])
XCTAssertEqual(store.data(atColumn: 1), [])

XCTAssertEqual(store.data(atColumn: 0, row: 1), 2)

let index = ColumnDataStore<Int>.ColumnIndex(column: 0, row: 1)
XCTAssertEqual(store.data(at: index), 2)
}

func testSelectData() {
store.append(data: [1,2,3], to: 0)
XCTAssertTrue(store.selected.isEmpty)

let performed = store.toggleSelect(atColumn: 0, row: 1)
XCTAssertTrue(performed)

XCTAssertEqual(store.selected.count, 1)
XCTAssertTrue(store.isSelected(at: .init(column: 0, row: 1)))

let deselectPerformed = store.toggleSelect(atColumn: 0, row: 1)
XCTAssertTrue(deselectPerformed)
XCTAssertEqual(store.selected.count, 0)
XCTAssertFalse(store.isSelected(at: .init(column: 0, row: 1)))
}

func testMaximumSelection() {
store.maximumSelectedCount = 2
store.append(data: [1,2,3], to: 0)

// Select two elements.
XCTAssertTrue(store.toggleSelect(atColumn: 0, row: 0))
XCTAssertTrue(store.toggleSelect(atColumn: 0, row: 1))

// `maximumSelectedCount` count reached.
XCTAssertFalse(store.toggleSelect(atColumn: 0, row: 2))

// Unselect one.
XCTAssertTrue(store.toggleSelect(atColumn: 0, row: 1))
// Select the one failed again.
XCTAssertTrue(store.toggleSelect(atColumn: 0, row: 2))

// `maximumSelectedCount` count reached.
XCTAssertFalse(store.toggleSelect(atColumn: 0, row: 1))

XCTAssertTrue(store.isSelected(at: .init(column: 0, row: 0)))
XCTAssertFalse(store.isSelected(at: .init(column: 0, row: 1)))
XCTAssertTrue(store.isSelected(at: .init(column: 0, row: 2)))
}

func testFilterValues() {
store.append(data: [1,2,3], to: 0)
store.append(data: [4,5,6], to: 1)
store.append(data: [7,8,9], to: 2)

let result = store.indexes { $0 % 2 == 0 }
let values = result.map { indexes in indexes.map { store.data(at: $0) } }
XCTAssertEqual(values, [[2], [4, 6], [8]])
}

func testAppendingDataNotification() {
let expect = expectation(description: "\(#file)_\(#line)")

token = NotificationCenter.default.addObserver(
forName: .columnDataStoreDidAppendData,
object: nil,
queue: .main)
{
noti in
let range = noti.userInfo?[LineSDKNotificationKey.appendDataIndexRange]
as? ColumnDataStore<Int>.AppendingIndexRange
XCTAssertNotNil(range)
XCTAssertEqual(range!.column, 0)
XCTAssertEqual(range!.startIndex, 0)
XCTAssertEqual(range!.endIndex, 3)
expect.fulfill()
}

store.append(data: [1,2,3], to: 0)
waitForExpectations(timeout: 1, handler: nil)
}

func testSelectingDataNotification() {
let expect = expectation(description: "\(#file)_\(#line)")

token = NotificationCenter.default.addObserver(
forName: .columnDataStoreDidSelect,
object: nil,
queue: .main)
{
noti in
let index = noti.userInfo?[LineSDKNotificationKey.selectingIndex]
as? ColumnDataStore<Int>.ColumnIndex
XCTAssertNotNil(index)
XCTAssertEqual(index!.column, 0)
XCTAssertEqual(index!.row, 2)
expect.fulfill()
}

store.append(data: [1,2,3], to: 0)
_ = store.toggleSelect(atColumn: 0, row: 2)
waitForExpectations(timeout: 1, handler: nil)
}

func testDeselectingDataNotification() {
let expect = expectation(description: "\(#file)_\(#line)")

token = NotificationCenter.default.addObserver(
forName: .columnDataStoreDidDeselect,
object: nil,
queue: .main)
{
noti in
let index = noti.userInfo?[LineSDKNotificationKey.selectingIndex]
as? ColumnDataStore<Int>.ColumnIndex
XCTAssertNotNil(index)
XCTAssertEqual(index!.column, 0)
XCTAssertEqual(index!.row, 2)
expect.fulfill()
}

store.append(data: [1,2,3], to: 0)
_ = store.toggleSelect(atColumn: 0, row: 2)
_ = store.toggleSelect(atColumn: 0, row: 2)
waitForExpectations(timeout: 1, handler: nil)
}
}
43 changes: 42 additions & 1 deletion LineSDKSample/LineSDKSample/UI/SampleUIHomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,53 @@ class SampleUIHomeViewController: UITableViewController {

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == Cell.shareMessage.rawValue {
presentShareViewController()

let canSendToFriends = ShareViewController.authorizationStatusForSendingMessage(to: .friends)
let canSendToGroups = ShareViewController.authorizationStatusForSendingMessage(to: .groups)

switch (canSendToFriends, canSendToGroups) {
case (.authorized, .authorized):
presentShareViewController()
case (.lackOfPermissions(let p), _): fallthrough
case (_ , .lackOfPermissions(let p)):
UIAlertController.present(
in: self,
title: nil,
message: "Lack of permissions: \(p)",
actions: [.init(title: "OK", style: .cancel)]
)
case (.lackOfToken, _): fallthrough
case (_, .lackOfToken):
UIAlertController.present(
in: self,
title: nil,
message: "Please login first.",
actions: [.init(title: "OK", style: .cancel)]
)
}
}
}

private func presentShareViewController() {
let viewController = ShareViewController()
viewController.shareDelegate = self
present(viewController, animated: true)
}
}

extension SampleUIHomeViewController: ShareViewControllerDelegate {
func shareViewController(
_ controller: ShareViewController,
didFailLoadingListType shareType: MessageShareTargetType,
withError error: LineSDKError)
{
controller.dismiss(animated: true) {
UIAlertController.present(in: self, error: error)
}
}

func shareViewControllerDidCancelSharing(_ controller: ShareViewController) {
UIAlertController.present(
in: self, title: nil, message: "User Cancelled", actions: [.init(title: "OK", style: .cancel)])
}
}