Skip to content

Commit

Permalink
Merge pull request #32 from line/tests/share-table-view-controller
Browse files Browse the repository at this point in the history
Tests share table view controller
  • Loading branch information
onevcat authored Apr 2, 2019
2 parents f1873f5 + 0d7becc commit 0030f3d
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 15 deletions.
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 @@ -126,7 +126,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 @@ -137,8 +137,8 @@ extension ShareTargetSelectingTableCell {
avatarImageView.setImage(target.avatarURL, placeholder: placeholderUserImage(for: target.displayName))

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)])
}
}

0 comments on commit 0030f3d

Please sign in to comment.