Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
A
Api
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Public iOS projects
Api
Commits
5946d7e4
Commit
5946d7e4
authored
Aug 14, 2016
by
Mauro E. Bender
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Close #2 - Create resource item
Add error handling.
parent
c1085960
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
157 additions
and
9 deletions
+157
-9
Api/Classes/Resource.swift
Api/Classes/Resource.swift
+41
-4
Api/Classes/Utils.swift
Api/Classes/Utils.swift
+15
-0
Example/Tests/Fixtures.swift
Example/Tests/Fixtures.swift
+12
-1
Example/Tests/Matchers.swift
Example/Tests/Matchers.swift
+52
-0
Example/Tests/ResourceTests.swift
Example/Tests/ResourceTests.swift
+37
-4
No files found.
Api/Classes/Resource.swift
View file @
5946d7e4
...
...
@@ -13,6 +13,12 @@ public protocol JSONSerializable {
func
toJSON
()
->
[
String
:
AnyObject
]
}
public
enum
ApiError
:
ErrorType
{
case
Network
(
error
:
NSError
,
response
:
NSURLResponse
)
case
JSONSerialization
(
error
:
NSError
)
case
Unknown
(
error
:
NSError
)
}
public
class
Resource
<
T
:
JSONSerializable
>
{
public
let
api
:
Api
public
let
path
:
String
...
...
@@ -23,13 +29,44 @@ public class Resource<T: JSONSerializable> {
}
public
func
item
(
id
:
AnyObject
,
parameters
:
[
String
:
String
]?
=
nil
,
headers
:
[
String
:
String
]?
=
nil
,
success
:
(
(
T
)
->
Void
)
)
headers
:
[
String
:
String
]?
=
nil
,
completion
:
(
(
T
?,
error
:
ApiError
?
)
->
Void
)
)
{
api
.
get
(
resourceMemberPath
(
id
),
parameters
:
parameters
,
headers
:
headers
)
{
response
in
if
let
json
=
response
.
result
.
value
{
success
(
T
(
fromJSON
:
json
as!
[
String
:
AnyObject
]
)
)
}
self
.
handleItemResult
(
response
,
handler
:
completion
)
}
}
public
func
create
(
item
:
T
,
parameters
:
[
String
:
String
]?
=
nil
,
headers
:
[
String
:
String
]?
=
nil
,
encoding
:
ParameterEncoding
=
.
JSON
,
completion
:
(
(
T
?,
error
:
ApiError
?
)
->
Void
)
)
{
var
requestParameters
=
item
.
toJSON
()
if
parameters
!=
nil
{
requestParameters
+=
parameters
!
}
api
.
post
(
path
,
parameters
:
requestParameters
,
encoding
:
encoding
,
headers
:
headers
)
{
response
in
self
.
handleItemResult
(
response
,
handler
:
completion
)
}
}
func
handleItemResult
(
response
:
Response
<
AnyObject
,
NSError
>
,
handler
:
(
T
?,
error
:
ApiError
?
)
->
Void
)
{
switch
(
response
.
result
)
{
case
.
Success
(
let
JSON
):
handler
(
T
(
fromJSON
:
JSON
as!
[
String
:
AnyObject
]
),
error
:
nil
)
case
.
Failure
(
let
error
):
handler
(
nil
,
error
:
handleError
(
response
)
)
}
}
func
handleError
(
response
:
Response
<
AnyObject
,
NSError
>
)
->
ApiError
{
let
error
=
response
.
result
.
error
!
if
let
statusCode
=
response
.
response
?
.
statusCode
where
!
(
200
...
299
)
.
contains
(
statusCode
)
{
return
.
Network
(
error
:
error
,
response
:
response
.
response
!
)
}
else
if
error
.
code
==
-
6006
{
return
.
JSONSerialization
(
error
:
error
)
}
return
.
Unknown
(
error
:
error
)
}
func
resourceMemberPath
(
memberId
:
AnyObject
)
->
String
{
...
...
Api/Classes/Utils.swift
0 → 100644
View file @
5946d7e4
//
// Utils.swift
// Pods
//
// Created by Mauro Bender on 14/8/16.
//
//
import
Foundation
func
+=
<
K
,
V
>
(
inout
left
:
[
K
:
V
],
right
:
[
K
:
V
])
{
for
(
k
,
v
)
in
right
{
left
.
updateValue
(
v
,
forKey
:
k
)
}
}
\ No newline at end of file
Example/Tests/Fixtures.swift
View file @
5946d7e4
...
...
@@ -20,6 +20,17 @@ extension Item: JSONSerializable {
}
func
toJSON
()
->
[
String
:
AnyObject
]
{
return
[
String
:
AnyObject
]()
var
json
=
[
String
:
AnyObject
]()
if
id
>
0
{
json
[
"id"
]
=
id
}
json
[
"name"
]
=
name
return
json
}
}
extension
Item
:
Equatable
{}
func
==
(
lhs
:
Item
,
rhs
:
Item
)
->
Bool
{
return
lhs
.
id
==
rhs
.
id
&&
lhs
.
name
==
rhs
.
name
}
\ No newline at end of file
Example/Tests/Matchers.swift
View file @
5946d7e4
...
...
@@ -10,6 +10,31 @@ import Api
import
Foundation
import
Mockingjay
// FIX HTTPBody being empty on matcher/builder
extension
NSInputStream
{
func
readFully
()
->
NSData
{
let
result
=
NSMutableData
()
self
.
open
()
readTo
(
result
)
self
.
close
()
return
result
}
private
func
readTo
(
data
:
NSMutableData
)
{
var
buffer
=
[
UInt8
](
count
:
4096
,
repeatedValue
:
0
)
var
amount
=
0
repeat
{
amount
=
self
.
read
(
&
buffer
,
maxLength
:
buffer
.
count
)
if
amount
>
0
{
data
.
appendBytes
(
buffer
,
length
:
amount
)
}
}
while
amount
>
0
}
}
let
baseURL
=
NSURL
(
string
:
"http://api.test.com"
)
!
let
apiPath
=
"1"
...
...
@@ -18,4 +43,31 @@ func matchApiPath( path: String, method: ApiMethod = .GET ) -> ( ( NSURLRequest
return
{
(
request
:
NSURLRequest
)
in
return
url
==
request
.
URL
&&
request
.
HTTPMethod
==
method
.
rawValue
}
}
func
buildItemFromRequest
(
id
:
Int
)
->
(
(
request
:
NSURLRequest
)
->
Response
)
{
return
{
(
request
:
NSURLRequest
)
in
let
response
=
NSHTTPURLResponse
(
URL
:
request
.
URL
!
,
statusCode
:
200
,
HTTPVersion
:
nil
,
headerFields
:
nil
)
!
return
.
Success
(
response
,
createItemWithIDFromRequest
(
id
,
request
:
request
)
)
}
}
func
createItemWithIDFromRequest
(
id
:
Int
,
request
:
NSURLRequest
)
->
NSData
?
{
var
json
=
jsonFromRequest
(
request
)
guard
json
!=
nil
else
{
return
nil
}
json
!
[
"id"
]
=
id
return
try
?
NSJSONSerialization
.
dataWithJSONObject
(
json
!
,
options
:
.
PrettyPrinted
)
}
func
jsonFromRequest
(
request
:
NSURLRequest
)
->
[
String
:
AnyObject
]?
{
guard
let
body
=
request
.
HTTPBodyStream
?
.
readFully
()
else
{
return
nil
}
let
json
=
try
?
NSJSONSerialization
.
JSONObjectWithData
(
body
,
options
:
.
AllowFragments
)
guard
json
!=
nil
else
{
return
nil
}
return
json
!
as?
[
String
:
AnyObject
]
}
\ No newline at end of file
Example/Tests/ResourceTests.swift
View file @
5946d7e4
...
...
@@ -17,6 +17,8 @@ class ResourceTests: QuickSpec {
// Register stubs
stub
(
matchApiPath
(
"items/1"
),
builder
:
json
(
[
"id"
:
1
,
"name"
:
"Item 1"
]
)
)
stub
(
matchApiPath
(
"items"
,
method
:
.
POST
),
builder
:
buildItemFromRequest
(
2
)
)
stub
(
matchApiPath
(
"failedItems"
,
method
:
.
POST
),
builder
:
http
(
422
)
)
}
override
func
spec
()
{
...
...
@@ -25,13 +27,44 @@ class ResourceTests: QuickSpec {
describe
(
"Resource"
)
{
let
resource
:
Resource
<
Item
>
=
api
.
resource
(
"items"
)
describe
(
"item
<T>
"
)
{
describe
(
"item"
)
{
context
(
"when the request is successful"
)
{
it
(
"should call the correct endpoint and return the item"
)
{
waitUntil
{
done
in
resource
.
item
(
1
)
{
(
item
:
Item
)
in
expect
(
item
.
id
)
==
1
expect
(
item
.
name
)
==
"Item 1"
resource
.
item
(
1
)
{
(
item
:
Item
?,
error
:
ApiError
?
)
in
expect
(
item
?
.
id
)
==
1
expect
(
item
?
.
name
)
==
"Item 1"
done
()
}
}
}
}
}
describe
(
"create"
)
{
context
(
"when the request is successful"
)
{
let
itemToCreate
=
Item
(
id
:
0
,
name
:
"Item 2"
)
it
(
"should call the correct endpoint and return the created item"
)
{
waitUntil
{
done
in
resource
.
create
(
itemToCreate
)
{
(
item
:
Item
?,
error
:
ApiError
?
)
in
expect
(
item
?
.
id
)
==
2
expect
(
item
?
.
name
)
==
"Item 2"
done
()
}
}
}
}
context
(
"when there's an error"
)
{
let
failResource
:
Resource
<
Item
>
=
api
.
resource
(
"failedItems"
)
let
itemToCreate
=
Item
(
id
:
0
,
name
:
"Item 2"
)
it
(
"should call the correct endpoint and return the created item"
)
{
waitUntil
{
done
in
failResource
.
create
(
itemToCreate
)
{
(
item
:
Item
?,
error
:
ApiError
?
)
in
expect
(
item
)
.
to
(
beNil
()
)
expect
(
error
)
.
toNot
(
beNil
()
)
done
()
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment