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