Merge pull request #54 from kylef/kylef/linux

Make tests pass and run on Linux
This commit is contained in:
Kyle Fuller
2016-02-26 16:34:11 -05:00
9 changed files with 73 additions and 54 deletions

View File

@@ -1,8 +1,11 @@
os: os:
- osx - osx
- linux
language: generic
sudo: required
dist: trusty
osx_image: xcode7.2 osx_image: xcode7.2
install: install:
- curl -sL https://gist.github.com/kylef/5c0475ff02b7c7671d2a/raw/621ef9b29bbb852fdfd2e10ed147b321d792c1e4/swiftenv-install.sh | bash - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)"
script: script:
- . ~/.swiftenv/init
- make test - make test

View File

@@ -13,7 +13,9 @@ public class Namespace {
registerTag("for", parser: ForNode.parse) registerTag("for", parser: ForNode.parse)
registerTag("if", parser: IfNode.parse) registerTag("if", parser: IfNode.parse)
registerTag("ifnot", parser: IfNode.parse_ifnot) registerTag("ifnot", parser: IfNode.parse_ifnot)
#if !os(Linux)
registerTag("now", parser: NowNode.parse) registerTag("now", parser: NowNode.parse)
#endif
registerTag("include", parser: IncludeNode.parse) registerTag("include", parser: IncludeNode.parse)
registerTag("extends", parser: ExtendsNode.parse) registerTag("extends", parser: ExtendsNode.parse)
registerTag("block", parser: BlockNode.parse) registerTag("block", parser: BlockNode.parse)

View File

@@ -76,6 +76,8 @@ public class VariableNode : NodeType {
} }
} }
#if !os(Linux)
public class NowNode : NodeType { public class NowNode : NodeType {
public let format:Variable public let format:Variable
@@ -114,6 +116,8 @@ public class NowNode : NodeType {
return formatter!.stringFromDate(date) return formatter!.stringFromDate(date)
} }
} }
#endif
public class ForNode : NodeType { public class ForNode : NodeType {
let variable:Variable let variable:Variable

View File

@@ -56,11 +56,13 @@ public struct Variable : Equatable, Resolvable {
} }
for bit in lookup() { for bit in lookup() {
current = normalize(current)
if let context = current as? Context { if let context = current as? Context {
current = context[bit] current = context[bit]
} else if let dictionary = resolveDictionary(current) { } else if let dictionary = current as? [String: Any] {
current = dictionary[bit] current = dictionary[bit]
} else if let array = resolveArray(current) { } else if let array = current as? [Any] {
if let index = Int(bit) { if let index = Int(bit) {
current = array[index] current = array[index]
} else if bit == "first" { } else if bit == "first" {
@@ -90,50 +92,42 @@ public func ==(lhs: Variable, rhs: Variable) -> Bool {
} }
func resolveDictionary(current: Any?) -> [String: Any]? {
switch current {
case let dictionary as [String: Any]:
return dictionary
case let dictionary as [String: AnyObject]:
var result: [String: Any] = [:]
for (k, v) in dictionary {
result[k] = v as Any
}
return result
case let dictionary as NSDictionary:
var result: [String: Any] = [:]
for (k, v) in dictionary {
if let k = k as? String {
result[k] = v as Any
}
}
return result
default:
return nil
}
}
func resolveArray(current: Any?) -> [Any]? {
switch current {
case let array as [Any]:
return array
case let array as [AnyObject]:
return array.map { $0 as Any }
case let array as NSArray:
return array.map { $0 as Any }
default:
return nil
}
}
func normalize(current: Any?) -> Any? { func normalize(current: Any?) -> Any? {
if let array = resolveArray(current) { if let current = current as? Normalizable {
return array return current.normalize()
}
if let dictionary = resolveDictionary(current) {
return dictionary
} }
return current return current
} }
protocol Normalizable {
func normalize() -> Any?
}
extension Array : Normalizable {
func normalize() -> Any? {
return map { $0 as Any }
}
}
extension NSArray : Normalizable {
func normalize() -> Any? {
return map { $0 as Any }
}
}
extension Dictionary : Normalizable {
func normalize() -> Any? {
var dictionary: [String: Any] = [:]
for (key, value) in self {
if let key = key as? String {
dictionary[key] = Stencil.normalize(value)
} else if let key = key as? CustomStringConvertible {
dictionary[key.description] = Stencil.normalize(value)
}
}
return dictionary
}
}

View File

@@ -33,6 +33,7 @@ func testForNode() {
try expect(try node.render(any_context)) == "123" try expect(try node.render(any_context)) == "123"
} }
#if os(OSX)
$0.it("renders a context variable of type NSArray") { $0.it("renders a context variable of type NSArray") {
let nsarray_context = Context(dictionary: [ let nsarray_context = Context(dictionary: [
"items": NSArray(array: [1, 2, 3]) "items": NSArray(array: [1, 2, 3])
@@ -40,8 +41,9 @@ func testForNode() {
let nodes: [NodeType] = [VariableNode(variable: "item")] let nodes: [NodeType] = [VariableNode(variable: "item")]
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: []) let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
try expect(try node.render(nsarray_context)) == "123" try expect(try node.render(nsarray_context)) == "123"
} }
#endif
$0.it("renders the given nodes while providing if the item is first in the context") { $0.it("renders the given nodes while providing if the item is first in the context") {
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.first")] let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.first")]

View File

@@ -86,21 +86,21 @@ func testIfNode() {
} }
$0.it("renders the truth when array expression is not empty") { $0.it("renders the truth when array expression is not empty") {
let items: Array<[String:AnyObject]> = [["key":"key1","value":42],["key":"key2","value":1337]] let items: [[String: Any]] = [["key":"key1","value":42],["key":"key2","value":1337]]
let arrayContext = Context(dictionary: ["items": [items]]) let arrayContext = Context(dictionary: ["items": [items]])
let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")])
try expect(try node.render(arrayContext)) == "true" try expect(try node.render(arrayContext)) == "true"
} }
$0.it("renders the false when array expression is empty") { $0.it("renders the false when array expression is empty") {
let emptyItems = Array<[String:AnyObject]>() let emptyItems = [[String: Any]]()
let arrayContext = Context(dictionary: ["items": emptyItems]) let arrayContext = Context(dictionary: ["items": emptyItems])
let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")])
try expect(try node.render(arrayContext)) == "false" try expect(try node.render(arrayContext)) == "false"
} }
$0.it("renders the false when dictionary expression is empty") { $0.it("renders the false when dictionary expression is empty") {
let emptyItems = [String:AnyObject]() let emptyItems = [String:Any]()
let arrayContext = Context(dictionary: ["items": emptyItems]) let arrayContext = Context(dictionary: ["items": emptyItems])
let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")])
try expect(try node.render(arrayContext)) == "false" try expect(try node.render(arrayContext)) == "false"

View File

@@ -4,6 +4,7 @@ import Stencil
func testNowNode() { func testNowNode() {
#if !os(Linux)
describe("NowNode") { describe("NowNode") {
$0.describe("parsing") { $0.describe("parsing") {
$0.it("parses default format without any now arguments") { $0.it("parses default format without any now arguments") {
@@ -38,4 +39,5 @@ func testNowNode() {
} }
} }
} }
#endif
} }

View File

@@ -38,9 +38,14 @@ func testTokenParser() {
} }
$0.it("can parse a tag token") { $0.it("can parse a tag token") {
let namespace = Namespace()
namespace.registerSimpleTag("known") { _ in
return ""
}
let parser = TokenParser(tokens: [ let parser = TokenParser(tokens: [
Token.Block(value: "now"), Token.Block(value: "known"),
], namespace: Namespace()) ], namespace: namespace)
let nodes = try parser.parse() let nodes = try parser.parse()
try expect(nodes.count) == 1 try expect(nodes.count) == 1

View File

@@ -3,9 +3,11 @@ import Spectre
import Stencil import Stencil
#if os(OSX)
@objc class Object : NSObject { @objc class Object : NSObject {
let title = "Hello World" let title = "Hello World"
} }
#endif
func testVariable() { func testVariable() {
@@ -16,9 +18,12 @@ func testVariable() {
"profiles": [ "profiles": [
"github": "kylef", "github": "kylef",
], ],
"object": Object(),
]) ])
#if os(OSX)
context.push(["object": Object()])
#endif
$0.it("can resolve a string literal with double quotes") { $0.it("can resolve a string literal with double quotes") {
let variable = Variable("\"name\"") let variable = Variable("\"name\"")
let result = try variable.resolve(context) as? String let result = try variable.resolve(context) as? String
@@ -61,10 +66,12 @@ func testVariable() {
try expect(result) == "Carlton" try expect(result) == "Carlton"
} }
#if os(OSX)
$0.it("can resolve a value via KVO") { $0.it("can resolve a value via KVO") {
let variable = Variable("object.title") let variable = Variable("object.title")
let result = try variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "Hello World" try expect(result) == "Hello World"
} }
#endif
} }
} }