Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions lua/flutter-tools/devices.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,17 @@ end
-----------------------------------------------------------------------------//

---@param job Job
local function handle_launch(job) ui.notify(utils.join(job:result())) end
local function notify_launch_error(job)
ui.notify(utils.join(job:stderr_result()), ui.ERROR, { timeout = 5000 })
end

-- `flutter emulators --launch` exits 0 even when the emulator dies during
-- startup, reporting the failure only on stderr.
---@param job Job
local function handle_launch(job)
if #job:stderr_result() > 0 then return notify_launch_error(job) end
ui.notify(utils.join(job:result()))
end

---@param emulator Device
---@param paths flutter.Paths
Expand All @@ -195,17 +205,13 @@ function M.launch_emulator(emulator)
local job
if spec then
job = Job:new({ command = spec.command, args = spec.args })
job:after_failure(
vim.schedule_wrap(
function(j) ui.notify(utils.join(j:stderr_result()), ui.ERROR, { timeout = 5000 }) end
)
)
else
local args = { "emulator", "--launch", emulator.id }
if emulator.cold_boot then table.insert(args, "--cold") end
job = Job:new({ command = paths.flutter_bin, args = args })
job:after_success(vim.schedule_wrap(handle_launch))
end
job:after_failure(vim.schedule_wrap(notify_launch_error))
job:start()
end)
end
Expand Down
52 changes: 49 additions & 3 deletions tests/devices_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -149,25 +149,42 @@ INFO | Storing crashdata in: /tmp/android-ts/emu-crash-34.2.14.db, detection
local devices
local config
local jobs
local notifications
local modules = {
"flutter-tools.devices",
"flutter-tools.config",
"flutter-tools.executable",
"flutter-tools.ui",
"plenary.job",
}
local paths = { flutter_bin = "/sdk/bin/flutter" }
local emulator = { id = "Pixel_8", name = "Pixel 8", system = "android", type = 1 }

local function finish(job, callback, stdout, stderr)
job.stdout, job.stderr = stdout or {}, stderr or {}
job.callbacks[callback](job)
vim.wait(100, function() return #notifications > 0 end)
end

before_each(function()
jobs = {}
notifications = {}
for _, name in ipairs(modules) do
package.loaded[name] = nil
end
package.loaded["flutter-tools.ui"] = {
ERROR = vim.log.levels.ERROR,
notify = function(msg, level)
if msg ~= "" then table.insert(notifications, { msg = msg, level = level }) end
end,
}
package.loaded["plenary.job"] = {
new = function(_, opts)
local job = { opts = opts, started = false }
function job:after_success() end
function job:after_failure() end
local job = { opts = opts, started = false, callbacks = {} }
function job:after_success(cb) self.callbacks.success = cb end
function job:after_failure(cb) self.callbacks.failure = cb end
function job:result() return self.stdout end
function job:stderr_result() return self.stderr end
function job:start() self.started = true end
table.insert(jobs, job)
return job
Expand Down Expand Up @@ -195,6 +212,35 @@ INFO | Storing crashdata in: /tmp/android-ts/emu-crash-34.2.14.db, detection
assert.is_true(jobs[1].started)
end)

it("should report a launch that exits cleanly but writes to stderr as an error", function()
devices.launch_emulator(emulator)

finish(jobs[1], "success", {}, { "The Android emulator exited with code 1 during startup" })

assert.same({
{
msg = "The Android emulator exited with code 1 during startup",
level = vim.log.levels.ERROR,
},
}, notifications)
end)

it("should show stdout of a clean launch", function()
devices.launch_emulator(emulator)

finish(jobs[1], "success", { "No emulator found that matches 'Pixel_8'." })

assert.same({ { msg = "No emulator found that matches 'Pixel_8'." } }, notifications)
end)

it("should report stderr when the flutter launch fails", function()
devices.launch_emulator(emulator)

finish(jobs[1], "failure", {}, { "boom" })

assert.same({ { msg = "boom", level = vim.log.levels.ERROR } }, notifications)
end)

it("should use the command returned by a custom launcher", function()
local received
config.set({
Expand Down
Loading