1 ## clicking on sandbox results to 'fix' them and turn sandboxes into tests
  2 
  3 scenario sandbox-click-on-result-toggles-color-to-green [
  4   local-scope
  5   trace-until 100/app  # trace too long
  6   assume-screen 100/width, 10/height
  7   # basic recipe
  8   assume-resources [
  9     [lesson/recipes.mu] <- [
 10       |recipe foo [|
 11       |  reply 4|
 12       |]|
 13     ]
 14   ]
 15   env:&:environment <- new-programming-environment resources, screen, [foo]
 16   # run it
 17   assume-console [
 18     press F4
 19   ]
 20   event-loop screen, console, env, resources
 21   screen-should-contain [
 22     .                                                                                 run (F4)           .
 23     .recipe foo [                                      ╎                                                 .
 24     .  reply 4                                         ╎─────────────────────────────────────────────────.
 25     .]                                                 ╎0   edit          copy            delete         .
 26     .                                                  ╎foo                                              .
 27     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4                                                .
 28     .                                                  ╎─────────────────────────────────────────────────.
 29     .                                                  ╎                                                 .
 30   ]
 31   # click on the '4' in the result
 32   assume-console [
 33     left-click 5, 51
 34   ]
 35   run [
 36     event-loop screen, console, env, resources
 37   ]
 38   # color toggles to green
 39   screen-should-contain-in-color 2/green, [
 40     .                                                                                                    .
 41     .                                                                                                    .
 42     .                                                                                                    .
 43     .                                                                                                    .
 44     .                                                                                                    .
 45     .                                                   4                                                .
 46     .                                                                                                    .
 47     .                                                                                                    .
 48   ]
 49   # cursor should remain unmoved
 50   run [
 51     cursor:char <- copy 9251/␣
 52     print screen, cursor
 53   ]
 54   screen-should-contain [
 55     .                                                                                 run (F4)           .
 56     .␣ecipe foo [                                      ╎                                                 .
 57     .  reply 4                                         ╎─────────────────────────────────────────────────.
 58     .]                                                 ╎0   edit          copy            delete         .
 59     .                                                  ╎foo                                              .
 60     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4                                                .
 61     .                                                  ╎─────────────────────────────────────────────────.
 62     .                                                  ╎                                                 .
 63   ]
 64   # now change the result
 65   # then rerun
 66   assume-console [
 67     left-click 2, 11  # cursor to end of line
 68     press backspace
 69     type [3]
 70     press F4
 71   ]
 72   run [
 73     event-loop screen, console, env, resources
 74   ]
 75   # result turns red
 76   screen-should-contain-in-color 1/red, [
 77     .                                                                                                    .
 78     .                                                                                                    .
 79     .                                                                                                    .
 80     .                                                                                                    .
 81     .                                                                                                    .
 82     .                                                   3                                                .
 83     .                                                                                                    .
 84     .                                                                                                    .
 85   ]
 86 ]
 87 
 88 # this requires tracking a couple more things
 89 container sandbox [
 90   response-starting-row-on-screen:num
 91   expected-response:text
 92 ]
 93 
 94 # include expected response when saving or restoring a sandbox
 95 before <end-save-sandbox> [
 96   {
 97     expected-response:text <- get *curr, expected-response:offset
 98     break-unless expected-response
 99     filename <- append filename, [.out]
100     resources <- dump resources, filename, expected-response
101   }
102 ]
103 
104 before <end-restore-sandbox> [
105   {
106     filename <- append filename, [.out]
107     contents <- slurp resources, filename
108     break-unless contents
109     *curr <- put *curr, expected-response:offset, contents
110   }
111 ]
112 
113 # clicks on sandbox responses save it as 'expected'
114 after <global-touch> [
115   # check if it's inside the output of any sandbox
116   {
117     sandbox-left-margin:num <- get *current-sandbox, left:offset
118     click-column:num <- get t, column:offset
119     on-sandbox-side?:bool <- greater-or-equal click-column, sandbox-left-margin
120     break-unless on-sandbox-side?
121     first-sandbox:&:sandbox <- get *env, sandbox:offset
122     break-unless first-sandbox
123     first-sandbox-begins:num <- get *first-sandbox, starting-row-on-screen:offset
124     click-row:num <- get t, row:offset
125     below-sandbox-editor?:bool <- greater-or-equal click-row, first-sandbox-begins
126     break-unless below-sandbox-editor?
127     # identify the sandbox whose output is being clicked on
128     sandbox:&:sandbox <- find-click-in-sandbox-output env, click-row
129     break-unless sandbox
130     # toggle its expected-response, and save session
131     sandbox <- toggle-expected-response sandbox
132     save-sandboxes env, resources
133     hide-screen screen
134     screen <- render-sandbox-side screen, env, render
135     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
136     # no change in cursor
137     show-screen screen
138     loop +next-event
139   }
140 ]
141 
142 def find-click-in-sandbox-output env:&:environment, click-row:num -> sandbox:&:sandbox [
143   local-scope
144   load-ingredients
145   # assert click-row >= sandbox.starting-row-on-screen
146   sandbox:&:sandbox <- get *env, sandbox:offset
147   start:num <- get *sandbox, starting-row-on-screen:offset
148   clicked-on-sandboxes?:bool <- greater-or-equal click-row, start
149   assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
150   # while click-row < sandbox.next-sandbox.starting-row-on-screen
151   {
152     next-sandbox:&:sandbox <- get *sandbox, next-sandbox:offset
153     break-unless next-sandbox
154     next-start:num <- get *next-sandbox, starting-row-on-screen:offset
155     found?:bool <- lesser-than click-row, next-start
156     break-if found?
157     sandbox <- copy next-sandbox
158     loop
159   }
160   # return sandbox if click is in its output region
161   response-starting-row:num <- get *sandbox, response-starting-row-on-screen:offset
162   return-unless response-starting-row, 0/no-click-in-sandbox-output
163   click-in-response?:bool <- greater-or-equal click-row, response-starting-row
164   return-unless click-in-response?, 0/no-click-in-sandbox-output
165   return sandbox
166 ]
167 
168 def toggle-expected-response sandbox:&:sandbox -> sandbox:&:sandbox [
169   local-scope
170   load-ingredients
171   expected-response:text <- get *sandbox, expected-response:offset
172   {
173     # if expected-response is set, reset
174     break-unless expected-response
175     *sandbox <- put *sandbox, expected-response:offset, 0
176   }
177   {
178     # if not, set expected response to the current response
179     break-if expected-response
180     response:text <- get *sandbox, response:offset
181     *sandbox <- put *sandbox, expected-response:offset, response
182   }
183 ]
184 
185 # when rendering a sandbox, color it in red/green if expected response exists
186 after <render-sandbox-response> [
187   {
188     break-unless sandbox-response
189     *sandbox <- put *sandbox, response-starting-row-on-screen:offset, row
190     expected-response:text <- get *sandbox, expected-response:offset
191     break-unless expected-response  # fall-through to print in grey
192     response-is-expected?:bool <- equal expected-response, sandbox-response
193     {
194       break-if response-is-expected?:bool
195       row, screen <- render-text screen, sandbox-response, left, right, 1/red, row
196     }
197     {
198       break-unless response-is-expected?:bool
199       row, screen <- render-text screen, sandbox-response, left, right, 2/green, row
200     }
201     jump +render-sandbox-end
202   }
203 ]
204 
205 before <end-render-sandbox-reset-hidden> [
206   *sandbox <- put *sandbox, response-starting-row-on-screen:offset, 0
207 ]