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   ¦ show-screen screen
137   ¦ loop +next-event
138   }
139 ]
140 
141 def find-click-in-sandbox-output env:&:environment, click-row:num -> sandbox:&:sandbox [
142   local-scope
143   load-ingredients
144   # assert click-row >= sandbox.starting-row-on-screen
145   sandbox:&:sandbox <- get *env, sandbox:offset
146   start:num <- get *sandbox, starting-row-on-screen:offset
147   clicked-on-sandboxes?:bool <- greater-or-equal click-row, start
148   assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
149   # while click-row < sandbox.next-sandbox.starting-row-on-screen
150   {
151   ¦ next-sandbox:&:sandbox <- get *sandbox, next-sandbox:offset
152   ¦ break-unless next-sandbox
153   ¦ next-start:num <- get *next-sandbox, starting-row-on-screen:offset
154   ¦ found?:bool <- lesser-than click-row, next-start
155   ¦ break-if found?
156   ¦ sandbox <- copy next-sandbox
157   ¦ loop
158   }
159   # return sandbox if click is in its output region
160   response-starting-row:num <- get *sandbox, response-starting-row-on-screen:offset
161   return-unless response-starting-row, 0/no-click-in-sandbox-output
162   click-in-response?:bool <- greater-or-equal click-row, response-starting-row
163   return-unless click-in-response?, 0/no-click-in-sandbox-output
164   return sandbox
165 ]
166 
167 def toggle-expected-response sandbox:&:sandbox -> sandbox:&:sandbox [
168   local-scope
169   load-ingredients
170   expected-response:text <- get *sandbox, expected-response:offset
171   {
172   ¦ # if expected-response is set, reset
173   ¦ break-unless expected-response
174   ¦ *sandbox <- put *sandbox, expected-response:offset, 0
175   }
176   {
177   ¦ # if not, set expected response to the current response
178   ¦ break-if expected-response
179   ¦ response:text <- get *sandbox, response:offset
180   ¦ *sandbox <- put *sandbox, expected-response:offset, response
181   }
182 ]
183 
184 # when rendering a sandbox, color it in red/green if expected response exists
185 after <render-sandbox-response> [
186   {
187   ¦ break-unless sandbox-response
188   ¦ *sandbox <- put *sandbox, response-starting-row-on-screen:offset, row
189   ¦ expected-response:text <- get *sandbox, expected-response:offset
190   ¦ break-unless expected-response  # fall-through to print in grey
191   ¦ response-is-expected?:bool <- equal expected-response, sandbox-response
192   ¦ {
193   ¦ ¦ break-if response-is-expected?:bool
194   ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 1/red, row
195   ¦ }
196   ¦ {
197   ¦ ¦ break-unless response-is-expected?:bool
198   ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 2/green, row
199   ¦ }
200   ¦ jump +render-sandbox-end
201   }
202 ]
203 
204 before <end-render-sandbox-reset-hidden> [
205   *sandbox <- put *sandbox, response-starting-row-on-screen:offset, 0
206 ]