https://github.com/akkartik/mu/blob/master/edit/009-sandbox-test.mu

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