diff --git a/Sources/Expression.swift b/Sources/Expression.swift index 722f400..f063033 100644 --- a/Sources/Expression.swift +++ b/Sources/Expression.swift @@ -52,6 +52,8 @@ final class VariableExpression: Expression, CustomStringConvertible { truthy = !result.isEmpty } else if let result = result as? Bool { truthy = result + } else if let result = result as? String { + truthy = !result.isEmpty } else if let value = result, let result = toNumber(value: value) { truthy = result > 0 } else if result != nil { diff --git a/Tests/StencilTests/ExpressionSpec.swift b/Tests/StencilTests/ExpressionSpec.swift index 0ffc9b3..6dbb44e 100644 --- a/Tests/StencilTests/ExpressionSpec.swift +++ b/Tests/StencilTests/ExpressionSpec.swift @@ -45,6 +45,16 @@ func testExpressions() { try expect(try expression.evaluate(context: context)).to.beTrue() } + $0.it("evaluates to true with string") { + let context = Context(dictionary: ["value": "test"]) + try expect(try expression.evaluate(context: context)).to.beTrue() + } + + $0.it("evaluates to false when empty string") { + let context = Context(dictionary: ["value": ""]) + try expect(try expression.evaluate(context: context)).to.beFalse() + } + $0.it("evaluates to false when integer value is below 0 or below") { let context = Context(dictionary: ["value": 0]) try expect(try expression.evaluate(context: context)).to.beFalse() diff --git a/Tests/StencilTests/IfNodeSpec.swift b/Tests/StencilTests/IfNodeSpec.swift index ca3dc45..cfb6052 100644 --- a/Tests/StencilTests/IfNodeSpec.swift +++ b/Tests/StencilTests/IfNodeSpec.swift @@ -3,172 +3,6 @@ import Spectre func testIfNode() { - describe("Expression") { - $0.describe("VariableExpression") { - let expression = VariableExpression(variable: Variable("value")) - - $0.it("evaluates to true when value is not nil") { - let context = Context(dictionary: ["value": "known"]) - try expect(try expression.evaluate(context: context)).to.beTrue() - } - - $0.it("evaluates to false when value is unset") { - let context = Context() - try expect(try expression.evaluate(context: context)).to.beFalse() - } - - $0.it("evaluates to true when array variable is not empty") { - let items: [[String: Any]] = [["key":"key1","value":42],["key":"key2","value":1337]] - let context = Context(dictionary: ["value": [items]]) - try expect(try expression.evaluate(context: context)).to.beTrue() - } - - $0.it("evaluates to false when array value is empty") { - let emptyItems = [[String: Any]]() - let context = Context(dictionary: ["value": emptyItems]) - try expect(try expression.evaluate(context: context)).to.beFalse() - } - - $0.it("evaluates to false when dictionary value is empty") { - let emptyItems = [String:Any]() - let context = Context(dictionary: ["value": emptyItems]) - try expect(try expression.evaluate(context: context)).to.beFalse() - } - - $0.it("evaluates to false when Array value is empty") { - let context = Context(dictionary: ["value": ([] as [Any])]) - try expect(try expression.evaluate(context: context)).to.beFalse() - } - - $0.it("evaluates to true when integer value is above 0") { - let context = Context(dictionary: ["value": 1]) - try expect(try expression.evaluate(context: context)).to.beTrue() - } - - $0.it("evaluates to false when integer value is below 0 or below") { - let context = Context(dictionary: ["value": 0]) - try expect(try expression.evaluate(context: context)).to.beFalse() - - let negativeContext = Context(dictionary: ["value": 0]) - try expect(try expression.evaluate(context: negativeContext)).to.beFalse() - } - - $0.it("evaluates to true when float value is above 0") { - let context = Context(dictionary: ["value": Float(0.5)]) - try expect(try expression.evaluate(context: context)).to.beTrue() - } - - $0.it("evaluates to false when float is 0 or below") { - let context = Context(dictionary: ["value": Float(0)]) - try expect(try expression.evaluate(context: context)).to.beFalse() - } - - $0.it("evaluates to true when double value is above 0") { - let context = Context(dictionary: ["value": Double(0.5)]) - try expect(try expression.evaluate(context: context)).to.beTrue() - } - - $0.it("evaluates to false when double is 0 or below") { - let context = Context(dictionary: ["value": Double(0)]) - try expect(try expression.evaluate(context: context)).to.beFalse() - } - } - - $0.describe("NotExpression") { - $0.it("returns truthy for positive expressions") { - let expression = NotExpression(expression: StaticExpression(value: true)) - try expect(expression.evaluate(context: Context())).to.beFalse() - } - - $0.it("returns falsy for negative expressions") { - let expression = NotExpression(expression: StaticExpression(value: false)) - try expect(expression.evaluate(context: Context())).to.beTrue() - } - } - - $0.describe("expression parsing") { - $0.it("can parse a variable expression") { - let expression = try parseExpression(components: ["value"]) - try expect(expression.evaluate(context: Context())).to.beFalse() - try expect(expression.evaluate(context: Context(dictionary: ["value": true]))).to.beTrue() - } - - $0.it("can parse a not expression") { - let expression = try parseExpression(components: ["not", "value"]) - try expect(expression.evaluate(context: Context())).to.beTrue() - try expect(expression.evaluate(context: Context(dictionary: ["value": true]))).to.beFalse() - } - - $0.describe("and expression") { - let expression = try! parseExpression(components: ["lhs", "and", "rhs"]) - - $0.it("evaluates to false with lhs false") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": false, "rhs": true]))).to.beFalse() - } - - $0.it("evaluates to false with rhs false") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": false]))).to.beFalse() - } - - $0.it("evaluates to false with lhs and rhs false") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": false, "rhs": false]))).to.beFalse() - } - - $0.it("evaluates to true with lhs and rhs true") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": true]))).to.beTrue() - } - } - - $0.describe("or expression") { - let expression = try! parseExpression(components: ["lhs", "or", "rhs"]) - - $0.it("evaluates to true with lhs true") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": false]))).to.beTrue() - } - - $0.it("evaluates to true with rhs true") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": false, "rhs": true]))).to.beTrue() - } - - $0.it("evaluates to true with lhs and rhs true") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": true, "rhs": true]))).to.beTrue() - } - - $0.it("evaluates to false with lhs and rhs false") { - try expect(expression.evaluate(context: Context(dictionary: ["lhs": false, "rhs": false]))).to.beFalse() - } - } - - $0.describe("multiple expression") { - let expression = try! parseExpression(components: ["one", "or", "two", "and", "not", "three"]) - - $0.it("evaluates to true with one") { - try expect(expression.evaluate(context: Context(dictionary: ["one": true]))).to.beTrue() - } - - $0.it("evaluates to true with one and three") { - try expect(expression.evaluate(context: Context(dictionary: ["one": true, "three": true]))).to.beTrue() - } - - $0.it("evaluates to true with two") { - try expect(expression.evaluate(context: Context(dictionary: ["two": true]))).to.beTrue() - } - - $0.it("evaluates to false with two and three") { - try expect(expression.evaluate(context: Context(dictionary: ["two": true, "three": true]))).to.beFalse() - } - - $0.it("evaluates to false with two and three") { - try expect(expression.evaluate(context: Context(dictionary: ["two": true, "three": true]))).to.beFalse() - } - - $0.it("evaluates to false with nothing") { - try expect(expression.evaluate(context: Context())).to.beFalse() - } - } - } - } - describe("IfNode") { $0.describe("parsing") { $0.it("can parse an if block") { diff --git a/docs/builtins.rst b/docs/builtins.rst index f354bc9..34899b4 100644 --- a/docs/builtins.rst +++ b/docs/builtins.rst @@ -48,6 +48,7 @@ true the contents of the block are processed. Being true is defined as: * Being non-empty (dictionaries or arrays) * Not being a false boolean value * Not being a numerical value of 0 or below +* Not being an empty string .. code-block:: html+django