@learnpack/learnpack 2.1.26 → 2.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/lib/commands/start.js +15 -4
- package/lib/managers/file.d.ts +1 -0
- package/lib/managers/file.js +8 -1
- package/lib/managers/server/routes.js +48 -14
- package/lib/managers/session.d.ts +1 -1
- package/lib/managers/session.js +39 -12
- package/lib/managers/socket.d.ts +1 -1
- package/lib/managers/socket.js +57 -43
- package/lib/models/action.d.ts +1 -1
- package/lib/models/config.d.ts +1 -1
- package/lib/models/exercise-obj.d.ts +3 -0
- package/lib/models/session.d.ts +4 -1
- package/lib/models/socket.d.ts +7 -6
- package/lib/models/status.d.ts +1 -1
- package/lib/utils/api.d.ts +2 -0
- package/lib/utils/api.js +51 -6
- package/oclif.manifest.json +1 -1
- package/package.json +3 -1
- package/src/commands/audit.ts +113 -113
- package/src/commands/clean.ts +10 -10
- package/src/commands/download.ts +18 -18
- package/src/commands/init.ts +39 -39
- package/src/commands/login.ts +13 -13
- package/src/commands/logout.ts +9 -9
- package/src/commands/publish.ts +25 -25
- package/src/commands/start.ts +101 -75
- package/src/commands/test.ts +34 -34
- package/src/managers/config/allowed_files.ts +2 -2
- package/src/managers/config/defaults.ts +2 -2
- package/src/managers/config/exercise.ts +79 -79
- package/src/managers/config/index.ts +145 -145
- package/src/managers/file.ts +74 -65
- package/src/managers/server/index.ts +32 -31
- package/src/managers/server/routes.ts +139 -90
- package/src/managers/session.ts +53 -24
- package/src/managers/socket.ts +92 -79
- package/src/models/action.ts +8 -1
- package/src/models/config-manager.ts +2 -2
- package/src/models/config.ts +7 -2
- package/src/models/exercise-obj.ts +6 -3
- package/src/models/plugin-config.ts +2 -2
- package/src/models/session.ts +5 -2
- package/src/models/socket.ts +12 -6
- package/src/models/status.ts +15 -14
- package/src/plugin/command/compile.ts +10 -10
- package/src/plugin/command/test.ts +14 -14
- package/src/plugin/index.ts +5 -5
- package/src/plugin/plugin.ts +26 -26
- package/src/plugin/utils.ts +23 -23
- package/src/utils/BaseCommand.ts +16 -16
- package/src/utils/api.ts +143 -91
- package/src/utils/audit.ts +93 -96
- package/src/utils/exercisesQueue.ts +15 -15
- package/src/utils/fileQueue.ts +85 -85
- package/src/utils/watcher.ts +14 -14
    
        package/src/commands/start.ts
    CHANGED
    
    | @@ -1,19 +1,24 @@ | |
| 1 1 | 
             
            // import path from "path";
         | 
| 2 | 
            -
            import { flags } from "@oclif/command" | 
| 3 | 
            -
            import SessionCommand from "../utils/SessionCommand";
         | 
| 4 | 
            -
            import Console from "../utils/console";
         | 
| 5 | 
            -
            import socket from "../managers/socket";
         | 
| 6 | 
            -
            import queue from "../utils/fileQueue";
         | 
| 7 | 
            -
            import { decompress, downloadEditor } from "../managers/file";
         | 
| 8 | 
            -
            import { prioritizeHTMLFile } from "../utils/misc";
         | 
| 2 | 
            +
            import { flags } from "@oclif/command"
         | 
| 9 3 |  | 
| 10 | 
            -
            import  | 
| 4 | 
            +
            import SessionCommand from "../utils/SessionCommand"
         | 
| 5 | 
            +
            import Console from "../utils/console"
         | 
| 6 | 
            +
            import socket from "../managers/socket"
         | 
| 7 | 
            +
            import queue from "../utils/fileQueue"
         | 
| 8 | 
            +
            import {
         | 
| 9 | 
            +
              decompress,
         | 
| 10 | 
            +
              downloadEditor,
         | 
| 11 | 
            +
              checkIfDirectoryExists,
         | 
| 12 | 
            +
            } from "../managers/file"
         | 
| 13 | 
            +
            import { prioritizeHTMLFile } from "../utils/misc"
         | 
| 11 14 |  | 
| 12 | 
            -
            import  | 
| 13 | 
            -
             | 
| 15 | 
            +
            import createServer from "../managers/server"
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            import { IGitpodData } from "../models/gitpod-data"
         | 
| 18 | 
            +
            import { IExercise, IExerciseData } from "../models/exercise-obj"
         | 
| 14 19 |  | 
| 15 20 | 
             
            export default class StartCommand extends SessionCommand {
         | 
| 16 | 
            -
              static description = "Runs a small server with all the exercise instructions" | 
| 21 | 
            +
              static description = "Runs a small server with all the exercise instructions"
         | 
| 17 22 |  | 
| 18 23 | 
             
              static flags = {
         | 
| 19 24 | 
             
                ...SessionCommand.flags,
         | 
| @@ -50,25 +55,25 @@ export default class StartCommand extends SessionCommand { | |
| 50 55 | 
             
                  description: "debugger mode for more verbage",
         | 
| 51 56 | 
             
                  default: false,
         | 
| 52 57 | 
             
                }),
         | 
| 53 | 
            -
              } | 
| 58 | 
            +
              }
         | 
| 54 59 |  | 
| 55 60 | 
             
              // 🛑 IMPORTANT
         | 
| 56 61 | 
             
              // Every command that will use the configManager needs this init method
         | 
| 57 62 | 
             
              async init() {
         | 
| 58 | 
            -
                const { flags } = this.parse(StartCommand) | 
| 59 | 
            -
                await this.initSession(flags) | 
| 63 | 
            +
                const { flags } = this.parse(StartCommand)
         | 
| 64 | 
            +
                await this.initSession(flags)
         | 
| 60 65 | 
             
              }
         | 
| 61 66 |  | 
| 62 67 | 
             
              async run() {
         | 
| 63 68 | 
             
                // get configuration object
         | 
| 64 | 
            -
                const configObject = this.configManager?.get() | 
| 65 | 
            -
                const config = configObject?.config | 
| 69 | 
            +
                const configObject = this.configManager?.get()
         | 
| 70 | 
            +
                const config = configObject?.config
         | 
| 66 71 |  | 
| 67 72 | 
             
                if (configObject) {
         | 
| 68 | 
            -
                  const { config } = configObject | 
| 73 | 
            +
                  const { config } = configObject
         | 
| 69 74 |  | 
| 70 75 | 
             
                  // build exerises
         | 
| 71 | 
            -
                  this.configManager?.buildIndex() | 
| 76 | 
            +
                  this.configManager?.buildIndex()
         | 
| 72 77 |  | 
| 73 78 | 
             
                  Console.debug(
         | 
| 74 79 | 
             
                    `Grading: ${config?.grading} ${
         | 
| @@ -78,19 +83,25 @@ export default class StartCommand extends SessionCommand { | |
| 78 83 | 
             
                        configObject?.exercises.length :
         | 
| 79 84 | 
             
                        0
         | 
| 80 85 | 
             
                    } exercises found`
         | 
| 81 | 
            -
                  ) | 
| 86 | 
            +
                  )
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  const appAlreadyExists = checkIfDirectoryExists(
         | 
| 89 | 
            +
                    `${config?.dirPath}/_app`
         | 
| 90 | 
            +
                  )
         | 
| 82 91 |  | 
| 83 | 
            -
                   | 
| 84 | 
            -
             | 
| 85 | 
            -
                     | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 92 | 
            +
                  if (!appAlreadyExists) {
         | 
| 93 | 
            +
                    // download app and decompress
         | 
| 94 | 
            +
                    await downloadEditor(
         | 
| 95 | 
            +
                      config?.editor.version,
         | 
| 96 | 
            +
                      `${config?.dirPath}/app.tar.gz`
         | 
| 97 | 
            +
                    )
         | 
| 88 98 |  | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 99 | 
            +
                    Console.info("Decompressing LearnPack UI, this may take a minute...")
         | 
| 100 | 
            +
                    await decompress(
         | 
| 101 | 
            +
                      `${config?.dirPath}/app.tar.gz`,
         | 
| 102 | 
            +
                      `${config?.dirPath}/_app/`
         | 
| 103 | 
            +
                    )
         | 
| 104 | 
            +
                  }
         | 
| 94 105 |  | 
| 95 106 | 
             
                  // listen to socket commands
         | 
| 96 107 | 
             
                  if (config && this.configManager) {
         | 
| @@ -98,45 +109,51 @@ export default class StartCommand extends SessionCommand { | |
| 98 109 | 
             
                      configObject,
         | 
| 99 110 | 
             
                      this.configManager,
         | 
| 100 111 | 
             
                      process.env.NODE_ENV === "test"
         | 
| 101 | 
            -
                    ) | 
| 112 | 
            +
                    )
         | 
| 102 113 |  | 
| 103 114 | 
             
                    const dispatcher = queue.dispatcher({
         | 
| 104 115 | 
             
                      create: true,
         | 
| 105 116 | 
             
                      path: `${config.dirPath}/vscode_queue.json`,
         | 
| 106 | 
            -
                    }) | 
| 117 | 
            +
                    })
         | 
| 107 118 |  | 
| 108 | 
            -
                    socket.start(config, server, false) | 
| 119 | 
            +
                    socket.start(config, server, false)
         | 
| 109 120 |  | 
| 110 121 | 
             
                    socket.on("open", (data: IGitpodData) => {
         | 
| 111 | 
            -
                      Console.debug("Opening these files: ", data) | 
| 112 | 
            -
                       | 
| 113 | 
            -
             | 
| 114 | 
            -
                       | 
| 115 | 
            -
             | 
| 122 | 
            +
                      Console.debug("Opening these files: ", data)
         | 
| 123 | 
            +
                      console.log("Opening files", data)
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                      const files = prioritizeHTMLFile(data.files)
         | 
| 126 | 
            +
                      // console.log("files",files);
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                      dispatcher.enqueue(dispatcher.events.OPEN_FILES, files)
         | 
| 129 | 
            +
                      socket.ready("Ready to compile...")
         | 
| 130 | 
            +
                    })
         | 
| 116 131 |  | 
| 117 132 | 
             
                    socket.on("open_window", (data: IGitpodData) => {
         | 
| 118 | 
            -
                      Console.debug("Opening window: ", data) | 
| 119 | 
            -
                      dispatcher.enqueue(dispatcher.events.OPEN_WINDOW, data) | 
| 120 | 
            -
                       | 
| 121 | 
            -
             | 
| 133 | 
            +
                      Console.debug("Opening window: ", data)
         | 
| 134 | 
            +
                      dispatcher.enqueue(dispatcher.events.OPEN_WINDOW, data)
         | 
| 135 | 
            +
                      console.log(data)
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                      socket.ready("Ready to compile...")
         | 
| 138 | 
            +
                    })
         | 
| 122 139 |  | 
| 123 140 | 
             
                    socket.on("reset", (exercise: IExerciseData) => {
         | 
| 124 141 | 
             
                      try {
         | 
| 125 | 
            -
                        this.configManager?.reset(exercise.exerciseSlug) | 
| 142 | 
            +
                        this.configManager?.reset(exercise.exerciseSlug)
         | 
| 126 143 | 
             
                        dispatcher.enqueue(
         | 
| 127 144 | 
             
                          dispatcher.events.RESET_EXERCISE,
         | 
| 128 145 | 
             
                          exercise.exerciseSlug
         | 
| 129 | 
            -
                        ) | 
| 130 | 
            -
                        socket.ready("Ready to compile...") | 
| 146 | 
            +
                        )
         | 
| 147 | 
            +
                        socket.ready("Ready to compile...")
         | 
| 131 148 | 
             
                      } catch (error) {
         | 
| 132 149 | 
             
                        socket.error(
         | 
| 133 150 | 
             
                          "compiler-error",
         | 
| 134 151 | 
             
                          (error as TypeError).message ||
         | 
| 135 152 | 
             
                            "There was an error reseting the exercise"
         | 
| 136 | 
            -
                        ) | 
| 137 | 
            -
                        setTimeout(() => socket.ready("Ready to compile..."), 2000) | 
| 153 | 
            +
                        )
         | 
| 154 | 
            +
                        setTimeout(() => socket.ready("Ready to compile..."), 2000)
         | 
| 138 155 | 
             
                      }
         | 
| 139 | 
            -
                    }) | 
| 156 | 
            +
                    })
         | 
| 140 157 | 
             
                    // socket.on("preview", (data) => {
         | 
| 141 158 | 
             
                    //   Console.debug("Preview triggered, removing the 'preview' action ")
         | 
| 142 159 | 
             
                    //   socket.removeAllowed("preview")
         | 
| @@ -144,7 +161,7 @@ export default class StartCommand extends SessionCommand { | |
| 144 161 | 
             
                    // })
         | 
| 145 162 |  | 
| 146 163 | 
             
                    socket.on("build", async (data: IExerciseData) => {
         | 
| 147 | 
            -
                      const exercise = this.configManager?.getExercise(data.exerciseSlug) | 
| 164 | 
            +
                      const exercise = this.configManager?.getExercise(data.exerciseSlug)
         | 
| 148 165 |  | 
| 149 166 | 
             
                      if (!exercise?.language) {
         | 
| 150 167 | 
             
                        socket.error(
         | 
| @@ -152,8 +169,8 @@ export default class StartCommand extends SessionCommand { | |
| 152 169 | 
             
                          "Impossible to detect language to build for " +
         | 
| 153 170 | 
             
                            data.exerciseSlug +
         | 
| 154 171 | 
             
                            "..."
         | 
| 155 | 
            -
                        ) | 
| 156 | 
            -
                        return | 
| 172 | 
            +
                        )
         | 
| 173 | 
            +
                        return
         | 
| 157 174 | 
             
                      }
         | 
| 158 175 |  | 
| 159 176 | 
             
                      socket.log(
         | 
| @@ -163,17 +180,23 @@ export default class StartCommand extends SessionCommand { | |
| 163 180 | 
             
                          " with " +
         | 
| 164 181 | 
             
                          exercise.language +
         | 
| 165 182 | 
             
                          "..."
         | 
| 166 | 
            -
                      ) | 
| 183 | 
            +
                      )
         | 
| 167 184 | 
             
                      await this.config.runHook("action", {
         | 
| 168 185 | 
             
                        action: "compile",
         | 
| 169 186 | 
             
                        socket,
         | 
| 170 187 | 
             
                        configuration: config,
         | 
| 171 188 | 
             
                        exercise,
         | 
| 172 | 
            -
                      }) | 
| 173 | 
            -
                    }) | 
| 189 | 
            +
                      })
         | 
| 190 | 
            +
                    })
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                    socket.on("generate", async (data: IExerciseData) => {
         | 
| 193 | 
            +
                      console.log("data", data)
         | 
| 194 | 
            +
                    })
         | 
| 174 195 |  | 
| 175 196 | 
             
                    socket.on("test", async (data: IExerciseData) => {
         | 
| 176 | 
            -
                      const exercise = this.configManager?.getExercise(data.exerciseSlug) | 
| 197 | 
            +
                      const exercise = this.configManager?.getExercise(data.exerciseSlug)
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                      console.log("data", data)
         | 
| 177 200 |  | 
| 178 201 | 
             
                      if (!exercise?.language) {
         | 
| 179 202 | 
             
                        socket.error(
         | 
| @@ -181,57 +204,60 @@ export default class StartCommand extends SessionCommand { | |
| 181 204 | 
             
                          "Impossible to detect engine language for testing for " +
         | 
| 182 205 | 
             
                            data.exerciseSlug +
         | 
| 183 206 | 
             
                            "..."
         | 
| 184 | 
            -
                        ) | 
| 185 | 
            -
                        return | 
| 207 | 
            +
                        )
         | 
| 208 | 
            +
                        return
         | 
| 186 209 | 
             
                      }
         | 
| 187 210 |  | 
| 188 211 | 
             
                      if (
         | 
| 189 212 | 
             
                        config?.disabledActions!.includes("test") ||
         | 
| 190 213 | 
             
                        config?.disableGrading
         | 
| 191 214 | 
             
                      ) {
         | 
| 192 | 
            -
                        socket.ready("Grading is disabled on configuration") | 
| 193 | 
            -
                        return true | 
| 215 | 
            +
                        socket.ready("Grading is disabled on configuration")
         | 
| 216 | 
            +
                        return true
         | 
| 194 217 | 
             
                      }
         | 
| 195 218 |  | 
| 196 219 | 
             
                      socket.log(
         | 
| 197 220 | 
             
                        "testing",
         | 
| 198 221 | 
             
                        "Testing your exercise using the " + exercise.language + " engine."
         | 
| 199 | 
            -
                      ) | 
| 222 | 
            +
                      )
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                      console.log("About to call runHook")
         | 
| 200 225 |  | 
| 201 226 | 
             
                      await this.config.runHook("action", {
         | 
| 202 227 | 
             
                        action: "test",
         | 
| 203 228 | 
             
                        socket,
         | 
| 204 229 | 
             
                        configuration: config,
         | 
| 205 230 | 
             
                        exercise,
         | 
| 206 | 
            -
                      }) | 
| 207 | 
            -
             | 
| 231 | 
            +
                      })
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                      this.configManager?.save()
         | 
| 208 234 |  | 
| 209 | 
            -
                      return true | 
| 210 | 
            -
                    }) | 
| 235 | 
            +
                      return true
         | 
| 236 | 
            +
                    })
         | 
| 211 237 |  | 
| 212 238 | 
             
                    const terminate = () => {
         | 
| 213 | 
            -
                      Console.debug("Terminating Learnpack...") | 
| 239 | 
            +
                      Console.debug("Terminating Learnpack...")
         | 
| 214 240 | 
             
                      server.terminate(() => {
         | 
| 215 | 
            -
                        this.configManager?.noCurrentExercise() | 
| 216 | 
            -
                        dispatcher.enqueue(dispatcher.events.END) | 
| 217 | 
            -
                        process.exit() | 
| 218 | 
            -
                      }) | 
| 219 | 
            -
                    } | 
| 241 | 
            +
                        this.configManager?.noCurrentExercise()
         | 
| 242 | 
            +
                        dispatcher.enqueue(dispatcher.events.END)
         | 
| 243 | 
            +
                        process.exit()
         | 
| 244 | 
            +
                      })
         | 
| 245 | 
            +
                    }
         | 
| 220 246 |  | 
| 221 | 
            -
                    server.on("close", terminate) | 
| 222 | 
            -
                    process.on("SIGINT", terminate) | 
| 223 | 
            -
                    process.on("SIGTERM", terminate) | 
| 224 | 
            -
                    process.on("SIGHUP", terminate) | 
| 247 | 
            +
                    server.on("close", terminate)
         | 
| 248 | 
            +
                    process.on("SIGINT", terminate)
         | 
| 249 | 
            +
                    process.on("SIGTERM", terminate)
         | 
| 250 | 
            +
                    process.on("SIGHUP", terminate)
         | 
| 225 251 |  | 
| 226 252 | 
             
                    // finish the server startup
         | 
| 227 | 
            -
                    setTimeout(() => dispatcher.enqueue(dispatcher.events.RUNNING), 1000) | 
| 253 | 
            +
                    setTimeout(() => dispatcher.enqueue(dispatcher.events.RUNNING), 1000)
         | 
| 228 254 |  | 
| 229 255 | 
             
                    // start watching for file changes
         | 
| 230 256 |  | 
| 231 257 | 
             
                    if (StartCommand.flags.watch)
         | 
| 232 258 | 
             
                      this.configManager.watchIndex(_exercises =>
         | 
| 233 259 | 
             
                        socket.reload(null, _exercises)
         | 
| 234 | 
            -
                      ) | 
| 260 | 
            +
                      )
         | 
| 235 261 | 
             
                  }
         | 
| 236 262 | 
             
                }
         | 
| 237 263 | 
             
              }
         | 
    
        package/src/commands/test.ts
    CHANGED
    
    | @@ -1,77 +1,77 @@ | |
| 1 | 
            -
            import Console from "../utils/console" | 
| 2 | 
            -
            import SessionCommand from "../utils/SessionCommand" | 
| 3 | 
            -
            import socket from "../managers/socket" | 
| 1 | 
            +
            import Console from "../utils/console"
         | 
| 2 | 
            +
            import SessionCommand from "../utils/SessionCommand"
         | 
| 3 | 
            +
            import socket from "../managers/socket"
         | 
| 4 4 |  | 
| 5 | 
            -
            import createServer from "../managers/server" | 
| 6 | 
            -
            import ExercisesQueue from "../utils/exercisesQueue" | 
| 7 | 
            -
            import { IExercise } from "../models/exercise-obj" | 
| 5 | 
            +
            import createServer from "../managers/server"
         | 
| 6 | 
            +
            import ExercisesQueue from "../utils/exercisesQueue"
         | 
| 7 | 
            +
            import { IExercise } from "../models/exercise-obj"
         | 
| 8 8 |  | 
| 9 9 | 
             
            class TestCommand extends SessionCommand {
         | 
| 10 10 | 
             
              async init() {
         | 
| 11 | 
            -
                const { flags } = this.parse(TestCommand) | 
| 12 | 
            -
                await this.initSession(flags) | 
| 11 | 
            +
                const { flags } = this.parse(TestCommand)
         | 
| 12 | 
            +
                await this.initSession(flags)
         | 
| 13 13 | 
             
              }
         | 
| 14 14 |  | 
| 15 15 | 
             
              async run() {
         | 
| 16 16 | 
             
                const {
         | 
| 17 17 | 
             
                  args: { exerciseSlug },
         | 
| 18 | 
            -
                } = this.parse(TestCommand) | 
| 18 | 
            +
                } = this.parse(TestCommand)
         | 
| 19 19 |  | 
| 20 20 | 
             
                // Build exercises index
         | 
| 21 | 
            -
                this.configManager?.buildIndex() | 
| 21 | 
            +
                this.configManager?.buildIndex()
         | 
| 22 22 |  | 
| 23 | 
            -
                let exercises: IExercise[] | undefined = [] | 
| 23 | 
            +
                let exercises: IExercise[] | undefined = []
         | 
| 24 24 |  | 
| 25 25 | 
             
                // test all exercises
         | 
| 26 26 | 
             
                !exerciseSlug ?
         | 
| 27 27 | 
             
                  (exercises = this.configManager?.getAllExercises()) :
         | 
| 28 | 
            -
                  (exercises = [this.configManager!.getExercise(exerciseSlug)]) | 
| 28 | 
            +
                  (exercises = [this.configManager!.getExercise(exerciseSlug)])
         | 
| 29 29 |  | 
| 30 | 
            -
                const exercisesQueue = new ExercisesQueue(exercises) | 
| 30 | 
            +
                const exercisesQueue = new ExercisesQueue(exercises)
         | 
| 31 31 |  | 
| 32 | 
            -
                const configObject = this.configManager?.get() | 
| 32 | 
            +
                const configObject = this.configManager?.get()
         | 
| 33 33 |  | 
| 34 | 
            -
                let hasFailed = false | 
| 35 | 
            -
                let failedTestsCount = 0 | 
| 36 | 
            -
                let successTestsCount = 0 | 
| 37 | 
            -
                const testsToRunCount = exercisesQueue.size() | 
| 34 | 
            +
                let hasFailed = false
         | 
| 35 | 
            +
                let failedTestsCount = 0
         | 
| 36 | 
            +
                let successTestsCount = 0
         | 
| 37 | 
            +
                const testsToRunCount = exercisesQueue.size()
         | 
| 38 38 |  | 
| 39 39 | 
             
                configObject!.config!.testingFinishedCallback = ({ result }) => {
         | 
| 40 40 | 
             
                  if (result === "failed") {
         | 
| 41 | 
            -
                    hasFailed = true | 
| 42 | 
            -
                    failedTestsCount | 
| 41 | 
            +
                    hasFailed = true
         | 
| 42 | 
            +
                    failedTestsCount++
         | 
| 43 43 | 
             
                  } else {
         | 
| 44 | 
            -
                    successTestsCount | 
| 44 | 
            +
                    successTestsCount++
         | 
| 45 45 | 
             
                  }
         | 
| 46 46 |  | 
| 47 47 | 
             
                  if (exercisesQueue.isEmpty()) {
         | 
| 48 48 | 
             
                    Console.info(
         | 
| 49 49 | 
             
                      `${testsToRunCount} test${testsToRunCount > 1 ? "s" : ""} runned`
         | 
| 50 | 
            -
                    ) | 
| 50 | 
            +
                    )
         | 
| 51 51 | 
             
                    Console.success(
         | 
| 52 52 | 
             
                      `${successTestsCount} test${successTestsCount > 1 ? "s" : ""} passed`
         | 
| 53 | 
            -
                    ) | 
| 53 | 
            +
                    )
         | 
| 54 54 | 
             
                    Console.error(
         | 
| 55 55 | 
             
                      `${failedTestsCount} test${failedTestsCount > 1 ? "s" : ""} failed`
         | 
| 56 | 
            -
                    ) | 
| 56 | 
            +
                    )
         | 
| 57 57 |  | 
| 58 | 
            -
                    process.exit(hasFailed ? 1 : 0) | 
| 58 | 
            +
                    process.exit(hasFailed ? 1 : 0)
         | 
| 59 59 | 
             
                  } else {
         | 
| 60 | 
            -
                    exercisesQueue.pop()!.test!(this.config, config!, socket) | 
| 60 | 
            +
                    exercisesQueue.pop()!.test!(this.config, config!, socket)
         | 
| 61 61 | 
             
                  }
         | 
| 62 | 
            -
                } | 
| 62 | 
            +
                }
         | 
| 63 63 |  | 
| 64 | 
            -
                const config = configObject?.config | 
| 64 | 
            +
                const config = configObject?.config
         | 
| 65 65 |  | 
| 66 | 
            -
                const server = await createServer(configObject!, this.configManager!, true) | 
| 66 | 
            +
                const server = await createServer(configObject!, this.configManager!, true)
         | 
| 67 67 |  | 
| 68 | 
            -
                socket.start(config!, server, true) | 
| 68 | 
            +
                socket.start(config!, server, true)
         | 
| 69 69 |  | 
| 70 | 
            -
                exercisesQueue.pop()!.test!(this.config, config!, socket) | 
| 70 | 
            +
                exercisesQueue.pop()!.test!(this.config, config!, socket)
         | 
| 71 71 | 
             
              }
         | 
| 72 72 | 
             
            }
         | 
| 73 73 |  | 
| 74 | 
            -
            TestCommand.description = `Test exercises | 
| 74 | 
            +
            TestCommand.description = `Test exercises`
         | 
| 75 75 |  | 
| 76 76 | 
             
            TestCommand.args = [
         | 
| 77 77 | 
             
              {
         | 
| @@ -80,6 +80,6 @@ TestCommand.args = [ | |
| 80 80 | 
             
                description: "The name of the exercise to test",
         | 
| 81 81 | 
             
                hidden: false,
         | 
| 82 82 | 
             
              },
         | 
| 83 | 
            -
            ] | 
| 83 | 
            +
            ]
         | 
| 84 84 |  | 
| 85 | 
            -
            export default TestCommand | 
| 85 | 
            +
            export default TestCommand
         | 
| @@ -3,7 +3,7 @@ export default { | |
| 3 3 | 
             
                port: 3000,
         | 
| 4 4 | 
             
                editor: {
         | 
| 5 5 | 
             
                  mode: null, // [standalone, preview]
         | 
| 6 | 
            -
                  agent: null, // [vscode, gitpod, localhost]
         | 
| 6 | 
            +
                  agent: null, // [vscode, gitpod, localhost, codespaces] TODO: We need to check if we are in codespaces
         | 
| 7 7 | 
             
                  version: null,
         | 
| 8 8 | 
             
                },
         | 
| 9 9 | 
             
                dirPath: "./.learn",
         | 
| @@ -35,4 +35,4 @@ export default { | |
| 35 35 | 
             
              exercises: [],
         | 
| 36 36 | 
             
              bugsLink: null,
         | 
| 37 37 | 
             
              videoSolutions: false,
         | 
| 38 | 
            -
            } | 
| 38 | 
            +
            }
         |