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