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
34 changes: 25 additions & 9 deletions app/lib/linear_cli/cli/issue_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,28 @@ defmodule LinearCli.CLI.IssueHelpers do
:ok
end

@doc """
Moves `issue` to the already-resolved `project`, calling
`LinearCli.Linear.attach_issue_to_project/2` and printing a confirmation.

Unlike `attach_project/2`, this function takes a pre-resolved
`%LinearCli.Linear.Project{}` struct rather than a search string. Callers
that need to resolve a search string first should use `attach_project/2`,
which delegates here after resolution.
"""
@spec move_issue(%Linear.Issue{}, %Linear.Project{}) ::
{:ok, %Linear.Issue{}} | {:error, term()}
def move_issue(issue, project) do
case Linear.attach_issue_to_project(issue, project.id) do
{:ok, updated} ->
Prompt.ok("#{issue.identifier} was moved to #{project.name}")
{:ok, updated}

{:error, reason} ->
{:error, reason}
end
end

@doc """
Attaches `issue` to a project matched against `project_search` among its
team's projects (`LinearCli.CLI.Projects.project_for/2`, prompting to
Expand All @@ -291,22 +313,16 @@ defmodule LinearCli.CLI.IssueHelpers do
`project_search` matching nothing in an empty project list (`project_for`
returning `nil`) - the same faithfully-ported crash risk Ruby's own
`nil.id` would hit.

Resolves the project from the search string, then delegates to `move_issue/2`.
"""
@spec attach_project(%Linear.Issue{}, String.t() | nil) ::
{:ok, %Linear.Issue{}} | {:error, term()}
def attach_project(issue, project_search) do
with {:ok, projects} <-
Linear.projects_by_team(issue.team.id, %{search: project_search}) do
project = Projects.project_for(projects, project_search)

case Linear.attach_issue_to_project(issue, project.id) do
{:ok, updated} ->
Prompt.ok("#{issue.identifier} was attached to #{project.name}")
{:ok, updated}

{:error, reason} ->
{:error, reason}
end
move_issue(issue, project)
end
end

Expand Down
28 changes: 25 additions & 3 deletions app/test/linear_cli/cli/issue_helpers_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule LinearCli.CLI.IssueHelpersTest do
import ExUnit.CaptureIO

alias LinearCli.CLI.IssueHelpers
alias LinearCli.Linear.{Comment, Issue, Team, User, WorkflowState}
alias LinearCli.Linear.{Comment, Issue, Project, Team, User, WorkflowState}

# Every helper under test accepts an already-loaded resource struct (no
# data-layer fetch happens inside these functions themselves, mirroring
Expand Down Expand Up @@ -283,6 +283,28 @@ defmodule LinearCli.CLI.IssueHelpersTest do
end
end

describe "move_issue/2" do
test "moves the issue to the resolved project and prints a confirmation" do
stub_responses([{"issueUpdate", issue_updated()}])

project = %Project{id: "p1", name: "Manhattan Rollout"}

assert capture_io(fn ->
assert {:ok, %Issue{}} = IssueHelpers.move_issue(issue(), project)
end) =~ "CRY-1 was moved to Manhattan Rollout"
end

test "propagates an API error without printing confirmation" do
stub_responses([{"issueUpdate", %{"errors" => [%{"message" => "boom"}]}}])

project = %Project{id: "p1", name: "Manhattan Rollout"}

assert capture_io(fn ->
assert {:error, %Ash.Error.Invalid{}} = IssueHelpers.move_issue(issue(), project)
end) == ""
end
end

describe "attach_project/2 (Ruby: CLI::Issue#attach_project)" do
test "resolves the project by name against the team's projects and attaches it" do
stub_responses([
Expand All @@ -303,7 +325,7 @@ defmodule LinearCli.CLI.IssueHelpersTest do
assert capture_io(fn ->
assert {:ok, %Issue{}} =
IssueHelpers.attach_project(issue(), "Manhattan Rollout")
end) =~ "CRY-1 was attached to Manhattan Rollout"
end) =~ "CRY-1 was moved to Manhattan Rollout"
end
end

Expand Down Expand Up @@ -380,7 +402,7 @@ defmodule LinearCli.CLI.IssueHelpersTest do
assert :ok = IssueHelpers.update_issue(issue(), project: "Manhattan Rollout")
end)

assert output =~ "CRY-1 was attached to Manhattan Rollout"
assert output =~ "CRY-1 was moved to Manhattan Rollout"
end

test "with :description, updates the issue description" do
Expand Down