From 2a704cb86d701abd2cef164a79442b46c0945934 Mon Sep 17 00:00:00 2001 From: Christian Glacet Date: Fri, 31 Aug 2018 17:57:26 +0200 Subject: [PATCH 1/3] Major version change on the zipper exercise. We added a an insertion method to the zipper class. The main goal is to be able to run to run test without using an intermediate tree structure. Now the test consists in creating a tree starting from an empty zipper using the the atomic operations left, right, up and insert/modify/read node values. In the old version there were no immutability check. Immutability will now be an important part of students goals. --- exercises/zipper/canonical-data.json | 1203 +++++++++++--------------- 1 file changed, 523 insertions(+), 680 deletions(-) diff --git a/exercises/zipper/canonical-data.json b/exercises/zipper/canonical-data.json index 02e40f1bf5..766ef2b6d0 100644 --- a/exercises/zipper/canonical-data.json +++ b/exercises/zipper/canonical-data.json @@ -1,697 +1,540 @@ { - "exercise": "zipper", - "version": "1.1.0", - "comments": [ - " The test cases for this exercise include an initial tree and a ", - " series of operations to perform on the initial tree. ", - " ", - " Trees are encoded as nested objects. Each node in the tree has ", - " three members: 'value', 'left', and 'right'. Each value is a ", - " number (for simplicity). Left and right are trees. An empty node ", - " is encoded as null. ", - " ", - " Each operation in the operations list is an object. The function ", - " name is listed under 'operation'. If the function requires ", - " arguments, the argument is listed under 'item'. Some functions ", - " require values (i.e. numbers), while others require trees. ", - " Comments are always optional and can be used almost anywhere. " - ], - "cases": [ - { - "description": "data is retained", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "to_tree" - } - ] - }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "left, right and value", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "right" - }, - { - "operation": "value" - } - ] + "exercise":"zipper", + "version":"2.0.0", + "comments":[ + " The test cases for this exercise verifies that a tree can be build ", + " from recursive applications of one of the following atomic ", + " operations: ", + " - cursor moving: left, right, up ", + " - node insertion/modification and reading ", + " ", + " A zipper binary tree, is a binary tree with a cursor placed on any ", + " of its nodes. ", + " ", + " Any zipper tree construction always start from an empty zipper: ", + " - an empty tree (not even a root node). ", + " - a cursor on the place where a root node coulb be inserted. ", + " ", + " The first part of the test consists in building a unique tree, ", + " checking at each steps that: ", + " - values inside the tree are correct, ", + " - and all operation are non mutating ", + " (reading is by definition non mutating, therefore we wont ", + " test this operation) ", + " ", + " The second part of the test for un-authorized moves operations, ", + " like inserting on non-empty spots, or going in a direction where ", + " cursor is not allowed to go (eg., up from the root) " + ], + "cases":[ + { + "description":"Zipper is empty.", + "property":"testEmpty", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + + ] + }, + "expected":{ + "error":"There is no value here, but you can insert a node here." + } }, - "expected": { - "type": "int", - "value": 3 - } - }, - { - "description": "dead end", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "left" - } - ] + { + "description":"Insert method shouldn't mutate the object.", + "property":"testInsertNonMutating", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":null, + "applyOn":"zipper", + "item":1 + } + ] + }, + "expected":{ + "error":"There is no value here, but you can insert a node here." + } }, - "expected": { - "type": "zipper", - "value": null - } - }, - { - "description": "tree from deep focus", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "right" - }, - { - "operation": "to_tree" - } - ] + { + "description":"Insert method actually set the right value at the right place.", + "property":"testInsertAndGetValue", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"value", + "affectTo":"actual" + } + ] + }, + "expected":{ + "type":"int", + "value":1 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "traversing up from top", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "up" - } - ] + { + "description":"Tests that left move arrives to a zipper that is empty support insertion.", + "property":"testLeft", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"left", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":2 + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "type":"int", + "value":2 + } }, - "expected": { - "type": "zipper", - "value": null - } - }, - { - "description": "left, right, and up", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "up" - }, - { - "operation": "right" - }, - { - "operation": "up" - }, - { - "operation": "left" - }, - { - "operation": "right" - }, - { - "operation": "value" - } - ] + { + "description":"Tests that right move arrives to a zipper that is empty support insertion.", + "property":"testLeft", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"right", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":3 + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "type":"int", + "value":3 + } }, - "expected": { - "type": "int", - "value": 3 - } - }, - { - "description": "set_value", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "set_value", - "item": 5 - }, - { - "operation": "to_tree" - } - ] + { + "description":"Tests that both left and right moves do not mutate the initialZipper.", + "property":"testLeftAndRightInsertNonMutating", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"left", + "affectTo":"tmp", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":null, + "applyOn":"tmp", + "item":2 + }, + { + "operation":"right", + "affectTo":"tmp", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":null, + "applyOn":"tmp", + "item":3 + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "type":"int", + "value":1 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 5, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "set_value after traversing up", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "right" - }, - { - "operation": "up" - }, - { - "operation": "set_value", - "item": 5 - }, - { - "operation": "to_tree" - } - ] + { + "description":"Tests that going left then up is equivalent to staying put.", + "property":"testLeftUpCancels", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"left", + "affectTo":"tmp", + "applyOn":"zipper" + }, + { + "operation":"up", + "affectTo":"tmp", + "applyOn":"tmp" + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"tmp" + } + ] + }, + "expected":{ + "type":"int", + "value":1 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 5, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "set_left with leaf", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "set_left", - "item": { - "value": 5, - "left": null, - "right": null - } - }, - { - "operation": "to_tree" - } - ] + { + "description":"Tests that going left then up is equivalent to staying put.", + "property":"testLeftUpCancels", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":2 + }, + { + "operation":"left", + "affectTo":"tmp", + "applyOn":"zipper" + }, + { + "operation":"up", + "affectTo":"tmp", + "applyOn":"tmp" + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"tmp" + } + ] + }, + "expected":{ + "type":"int", + "value":2 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 2, - "left": { - "value": 5, - "left": null, - "right": null + { + "description":"Tests that up moves do not mutate the initialZipper", + "property":"testUpNonMutating", + "input":{ + "initialZipper":{ + "name":"zipper" }, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "set_right with null", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "set_right", - "item": null - }, - { - "operation": "to_tree" - } - ] + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"left", + "affectTo":"tmp", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":2 + }, + { + "operation":"up", + "affectTo":null, + "applyOn":"zipper" + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "type":"int", + "value":2 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": null - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "set_right with subtree", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "set_right", - "item": { - "value": 6, - "left": { - "value": 7, - "left": null, - "right": null - }, - "right": { - "value": 8, - "left": null, - "right": null - } - } - }, - { - "operation": "to_tree" - } - ] + { + "description":"Test seting value (modifying an existing node)", + "property":"testSetValue", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"right", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":3 + }, + { + "operation":"up", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"left", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":2 + }, + { + "operation":"value", + "affectTo":"z_value", + "applyOn":"zipper" + }, + { + "operation":"multiply", + "affectTo":"tmp", + "applyOn":[ + "z_value", + 2 + ] + }, + { + "operation":"setValue", + "affectTo":"tmp", + "applyOn":"zipper", + "item":"tmp" + }, + { + "operation":"floorDivide", + "affectTo":"actual", + "applyOn":[ + "tmp", + "z_value" + ] + } + ] + }, + "expected":{ + "type":"int", + "value":2 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 6, - "left": { - "value": 7, - "left": null, - "right": null + { + "description":"Test that setValue do not mutate the initialZipper.", + "property":"testSetValueNonMutating", + "input":{ + "initialZipper":{ + "name":"zipper" }, - "right": { - "value": 8, - "left": null, - "right": null - } - } - } - } - }, - { - "description": "set_value on deep focus", - "property": "expectedValue", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "right" - }, - { - "operation": "set_value", - "item": 5 - }, - { - "operation": "to_tree" - } - ] + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":4 + }, + { + "operation":"setValue", + "affectTo":null, + "applyOn":"zipper", + "item":8 + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "type":"int", + "value":4 + } }, - "expected": { - "type": "tree", - "value": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 5, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - } - } - }, - { - "description": "different paths to same zipper", - "property": "sameResultFromOperations", - "input": { - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "left" - }, - { - "operation": "up" - }, - { - "operation": "right" - } - ] + { + "description":"Tests the root shortcut.", + "property":"testRoot", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"right", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":3 + }, + { + "operation":"left", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":5 + }, + { + "operation":"root", + "affectTo":"tmp", + "applyOn":"zipper" + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"tmp" + }, + ] + }, + "expected":{ + "type":"int", + "value":1 + } }, - "expected": { - "type": "zipper", - "initialTree": { - "value": 1, - "left": { - "value": 2, - "left": null, - "right": { - "value": 3, - "left": null, - "right": null - } - }, - "right": { - "value": 4, - "left": null, - "right": null - } - }, - "operations": [ - { - "operation": "right" - } - ] + { + "description":"Tests the root shortcut.", + "property":"testRoot", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"right", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":3 + }, + { + "operation":"left", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":5 + }, + { + "operation":"root", + "affectTo":null, + "applyOn":"zipper" + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + }, + ] + }, + "expected":{ + "type":"int", + "value":5 + } } - } - ] + ] } From 4aa07b4168a8e2c2842381a8f076df9e48f8be0e Mon Sep 17 00:00:00 2001 From: Christian Glacet Date: Fri, 31 Aug 2018 18:08:42 +0200 Subject: [PATCH 2/3] Major version change on the zipper exercise. We added a an insertion method to the zipper class. The main goal is to be able to run to run test without using an intermediate tree structure. Now the test consists in creating a tree starting from an empty zipper using the the atomic operations left, right, up and insert/modify/read node values. In the old version there were no immutability check. Immutability will now be an important part of students goals. --- exercises/zipper/canonical-data.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/zipper/canonical-data.json b/exercises/zipper/canonical-data.json index 766ef2b6d0..aa16397fbb 100644 --- a/exercises/zipper/canonical-data.json +++ b/exercises/zipper/canonical-data.json @@ -475,7 +475,7 @@ "operation":"value", "affectTo":"actual", "applyOn":"tmp" - }, + } ] }, "expected":{ @@ -528,7 +528,7 @@ "operation":"value", "affectTo":"actual", "applyOn":"zipper" - }, + } ] }, "expected":{ From 8d04a251f55140a321b31be188c3222ecdf61a8d Mon Sep 17 00:00:00 2001 From: Christian Glacet Date: Mon, 10 Sep 2018 18:13:44 +0200 Subject: [PATCH 3/3] 1) property names, 2) 'affectTo' and 'applyOn' explanation', 3) testing forbiden moves --- exercises/zipper/canonical-data.json | 232 ++++++++++++++++++++++----- 1 file changed, 194 insertions(+), 38 deletions(-) diff --git a/exercises/zipper/canonical-data.json b/exercises/zipper/canonical-data.json index aa16397fbb..2d08011d7d 100644 --- a/exercises/zipper/canonical-data.json +++ b/exercises/zipper/canonical-data.json @@ -2,9 +2,8 @@ "exercise":"zipper", "version":"2.0.0", "comments":[ - " The test cases for this exercise verifies that a tree can be build ", - " from recursive applications of one of the following atomic ", - " operations: ", + " Verifies that a tree can be build from recursive applications of ", + " one of the following atomic operations: ", " - cursor moving: left, right, up ", " - node insertion/modification and reading ", " ", @@ -24,12 +23,29 @@ " ", " The second part of the test for un-authorized moves operations, ", " like inserting on non-empty spots, or going in a direction where ", - " cursor is not allowed to go (eg., up from the root) " + " cursor is not allowed to go (eg., up from the root) ", + " ", + " Lets consider the following affectation: ", + " y <- f(x, value) ", + " The following notation will be used to represent this operation: ", + " { ", + " 'operation': 'f', ", + " 'affectTo': 'y', ", + " 'applyOn': 'x', ", + " 'item': 'value' ", + " } ", + " ", + " Each test should start with the initialisation of an empty zipper ", + " named 'zipper': ", + " 'initialZipper': { ", + " 'name': 'zipper' ", + " } ", + " " ], "cases":[ { "description":"Zipper is empty.", - "property":"testEmpty", + "property":"zipper", "input":{ "initialZipper":{ "name":"zipper" @@ -44,7 +60,7 @@ }, { "description":"Insert method shouldn't mutate the object.", - "property":"testInsertNonMutating", + "property":"insert", "input":{ "initialZipper":{ "name":"zipper" @@ -64,7 +80,7 @@ }, { "description":"Insert method actually set the right value at the right place.", - "property":"testInsertAndGetValue", + "property":"getValue", "input":{ "initialZipper":{ "name":"zipper" @@ -88,8 +104,8 @@ } }, { - "description":"Tests that left move arrives to a zipper that is empty support insertion.", - "property":"testLeft", + "description":"Left move and an empty spot insertion.", + "property":"left", "input":{ "initialZipper":{ "name":"zipper" @@ -125,8 +141,8 @@ } }, { - "description":"Tests that right move arrives to a zipper that is empty support insertion.", - "property":"testLeft", + "description":"Right move and an empty spot insertion.", + "property":"right", "input":{ "initialZipper":{ "name":"zipper" @@ -162,8 +178,8 @@ } }, { - "description":"Tests that both left and right moves do not mutate the initialZipper.", - "property":"testLeftAndRightInsertNonMutating", + "description":"Left move do not mutate initialZipper.", + "property":"left", "input":{ "initialZipper":{ "name":"zipper" @@ -180,23 +196,37 @@ "affectTo":"tmp", "applyOn":"zipper" }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "type":"int", + "value":1 + } + }, + { + "description":"Right move do not mutate initialZipper.", + "property":"right", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ { "operation":"insert", - "affectTo":null, - "applyOn":"tmp", - "item":2 + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 }, { "operation":"right", "affectTo":"tmp", "applyOn":"zipper" }, - { - "operation":"insert", - "affectTo":null, - "applyOn":"tmp", - "item":3 - }, { "operation":"value", "affectTo":"actual", @@ -210,8 +240,8 @@ } }, { - "description":"Tests that going left then up is equivalent to staying put.", - "property":"testLeftUpCancels", + "description":"Going left then up is equivalent to staying put.", + "property":"left", "input":{ "initialZipper":{ "name":"zipper" @@ -246,8 +276,8 @@ } }, { - "description":"Tests that going left then up is equivalent to staying put.", - "property":"testLeftUpCancels", + "description":"Going right then up is equivalent to staying put.", + "property":"right", "input":{ "initialZipper":{ "name":"zipper" @@ -260,7 +290,7 @@ "item":2 }, { - "operation":"left", + "operation":"right", "affectTo":"tmp", "applyOn":"zipper" }, @@ -282,8 +312,8 @@ } }, { - "description":"Tests that up moves do not mutate the initialZipper", - "property":"testUpNonMutating", + "description":"Moving up do not mutate initialZipper.", + "property":"up", "input":{ "initialZipper":{ "name":"zipper" @@ -324,8 +354,8 @@ } }, { - "description":"Test seting value (modifying an existing node)", - "property":"testSetValue", + "description":"Seting value (modifying an existing node)", + "property":"setValue", "input":{ "initialZipper":{ "name":"zipper" @@ -399,8 +429,8 @@ } }, { - "description":"Test that setValue do not mutate the initialZipper.", - "property":"testSetValueNonMutating", + "description":"Setting value do not mutate initialZipper.", + "property":"setValue", "input":{ "initialZipper":{ "name":"zipper" @@ -431,8 +461,8 @@ } }, { - "description":"Tests the root shortcut.", - "property":"testRoot", + "description":"Going back to root shortcut.", + "property":"root", "input":{ "initialZipper":{ "name":"zipper" @@ -484,8 +514,8 @@ } }, { - "description":"Tests the root shortcut.", - "property":"testRoot", + "description":"Going back to root shortcut.", + "property":"root", "input":{ "initialZipper":{ "name":"zipper" @@ -521,7 +551,7 @@ }, { "operation":"root", - "affectTo":null, + "affectTo": null, "applyOn":"zipper" }, { @@ -535,6 +565,132 @@ "type":"int", "value":5 } + }, + { + "description":"Inserting a zipper.", + "property":"insertZipper", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"right", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":3 + }, + { + "operation":"left", + "affectTo":"zipper", + "applyOn":"zipper" + }, + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":5 + }, + { + "operation":"createEmptyZipper", + "affectTo": "newZipper" + }, + { + "operation":"insertZipper", + "affectTo": "newZipper", + "applyOn":"newZipper", + "item":"zipper" + }, + { + "operation":"right", + "affectTo": "newZipper", + "applyOn":"newZipper" + }, + { + "operation":"value", + "affectTo":"actual", + "applyOn":"newZipper" + } + ] + }, + "expected":{ + "type":"int", + "value":3 + } + }, + { + "description":"Can't go left from empty location", + "property":"left", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"left", + "affectTo":"zipper", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "error":"Moving left is not allowed from this location." + } + }, + { + "description":"Can't go right from empty location", + "property":"right", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"right", + "affectTo":"zipper", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "error":"Moving right is not allowed from this location." + } + }, + { + "description":"Can't go top from root", + "property":"top", + "input":{ + "initialZipper":{ + "name":"zipper" + }, + "operations":[ + { + "operation":"insert", + "affectTo":"zipper", + "applyOn":"zipper", + "item":1 + }, + { + "operation":"top", + "affectTo":"zipper", + "applyOn":"zipper" + } + ] + }, + "expected":{ + "error":"There's nothing up here (current location is the root)." + } } ] }