216 lines
6.8 KiB
Ruby
216 lines
6.8 KiB
Ruby
require "minitest/autorun"
|
|
require_relative "../lib/backlog"
|
|
|
|
# Minimal stand-ins for the planka-api gem's error hierarchy, so tests never
|
|
# require (or need) the real gem installed — only the shape our code
|
|
# rescues against.
|
|
module Planka
|
|
class Error < StandardError; end
|
|
class ValidationError < Error; end
|
|
end
|
|
|
|
module BacklogTestHelpers
|
|
# A hand-rolled fake of the subset of Planka::Client's resource surface
|
|
# BoardEnsurer touches: projects, boards, lists, labels. In-memory only,
|
|
# no network. Mirrors the gem's real return shapes (string-keyed hashes).
|
|
class FakePlankaClient
|
|
Project = Struct.new(:id, :name, :type, :ownerProjectManagerId, :managers, keyword_init: true)
|
|
Board = Struct.new(:id, :project_id, :name, keyword_init: true)
|
|
List = Struct.new(:id, :board_id, :name, :type, :position, keyword_init: true)
|
|
Label = Struct.new(:id, :board_id, :name, :color, keyword_init: true)
|
|
Card = Struct.new(:id, :list_id, :board_id, :name, :type, :position, :description, keyword_init: true)
|
|
|
|
attr_reader :projects, :boards, :lists, :labels, :cards
|
|
|
|
def initialize(reject_colors: [])
|
|
@next_id = 0
|
|
@projects_store = []
|
|
@boards_store = []
|
|
@lists_store = []
|
|
@labels_store = []
|
|
@cards_store = []
|
|
@card_labels_store = []
|
|
|
|
@projects = ProjectsResource.new(self)
|
|
@boards = BoardsResource.new(self)
|
|
@lists = ListsResource.new(self)
|
|
@labels = LabelsResource.new(self, reject_colors: reject_colors)
|
|
@cards = CardsResource.new(self)
|
|
@comments = CommentsResource.new(self)
|
|
end
|
|
|
|
attr_reader :comments
|
|
|
|
def next_id = (@next_id += 1).to_s
|
|
|
|
attr_reader :projects_store, :boards_store, :lists_store, :labels_store,
|
|
:cards_store, :card_labels_store
|
|
|
|
def attach_label(card_id, label_id)
|
|
@card_labels_store << { "id" => next_id, "cardId" => card_id, "labelId" => label_id }
|
|
end
|
|
|
|
class ProjectsResource
|
|
def initialize(client) = @client = client
|
|
|
|
def list = @client.projects_store.map { |p| stringify(p) }
|
|
|
|
def create(attrs)
|
|
project = FakePlankaClient::Project.new(
|
|
id: @client.next_id, name: attrs[:name], type: attrs[:type],
|
|
ownerProjectManagerId: @client.next_id, managers: []
|
|
)
|
|
@client.projects_store << project
|
|
stringify(project)
|
|
end
|
|
|
|
def update(id, attrs)
|
|
project = @client.projects_store.find { |p| p.id == id }
|
|
project.ownerProjectManagerId = attrs[:ownerProjectManagerId] if attrs.key?(:ownerProjectManagerId)
|
|
stringify(project)
|
|
end
|
|
|
|
def add_manager(project_id, user_id)
|
|
project = @client.projects_store.find { |p| p.id == project_id }
|
|
project.managers << user_id
|
|
{ "id" => @client.next_id, "projectId" => project_id, "userId" => user_id }
|
|
end
|
|
|
|
private
|
|
|
|
def stringify(p) = { "id" => p.id, "name" => p.name, "type" => p.type }
|
|
end
|
|
|
|
class BoardsResource
|
|
def initialize(client) = @client = client
|
|
|
|
def list(project_id)
|
|
@client.boards_store.select { |b| b.project_id == project_id }.map { |b| stringify(b) }
|
|
end
|
|
|
|
def create(project_id, attrs)
|
|
board = FakePlankaClient::Board.new(id: @client.next_id, project_id: project_id, name: attrs[:name])
|
|
@client.boards_store << board
|
|
stringify(board)
|
|
end
|
|
|
|
def update(id, attrs)
|
|
board = @client.boards_store.find { |b| b.id == id }
|
|
board.name = attrs[:name] if attrs.key?(:name)
|
|
stringify(board)
|
|
end
|
|
|
|
def get(id)
|
|
board = @client.boards_store.find { |b| b.id == id }
|
|
{
|
|
"item" => stringify(board),
|
|
"included" => {
|
|
"lists" => @client.lists.list(id),
|
|
"labels" => @client.labels.list(id),
|
|
"cards" => @client.cards.all_for_board(id),
|
|
"cardLabels" => @client.card_labels_store.dup
|
|
}
|
|
}
|
|
end
|
|
|
|
private
|
|
|
|
def stringify(b) = { "id" => b.id, "projectId" => b.project_id, "name" => b.name }
|
|
end
|
|
|
|
class ListsResource
|
|
def initialize(client) = @client = client
|
|
|
|
def list(board_id)
|
|
@client.lists_store.select { |l| l.board_id == board_id }.map { |l| stringify(l) }
|
|
end
|
|
|
|
def create(board_id, attrs)
|
|
raise ArgumentError, "list create requires type" unless attrs[:type]
|
|
|
|
list = FakePlankaClient::List.new(id: @client.next_id, board_id: board_id, name: attrs[:name],
|
|
type: attrs[:type], position: attrs[:position])
|
|
@client.lists_store << list
|
|
stringify(list)
|
|
end
|
|
|
|
private
|
|
|
|
def stringify(l)
|
|
{ "id" => l.id, "boardId" => l.board_id, "name" => l.name, "type" => l.type, "position" => l.position }
|
|
end
|
|
end
|
|
|
|
class CardsResource
|
|
def initialize(client) = @client = client
|
|
|
|
def create(list_id, attrs)
|
|
raise ArgumentError, "card create requires type" unless attrs[:type]
|
|
|
|
list = @client.lists_store.find { |l| l.id == list_id }
|
|
card = FakePlankaClient::Card.new(
|
|
id: @client.next_id, list_id: list_id, board_id: list.board_id,
|
|
name: attrs[:name], type: attrs[:type], position: attrs[:position],
|
|
description: attrs[:description]
|
|
)
|
|
@client.cards_store << card
|
|
stringify(card)
|
|
end
|
|
|
|
def all_for_board(board_id)
|
|
@client.cards_store.select { |c| c.board_id == board_id }.map { |c| stringify(c) }
|
|
end
|
|
|
|
private
|
|
|
|
def stringify(c)
|
|
{ "id" => c.id, "listId" => c.list_id, "boardId" => c.board_id, "name" => c.name,
|
|
"type" => c.type, "position" => c.position, "description" => c.description }
|
|
end
|
|
end
|
|
|
|
class LabelsResource
|
|
def initialize(client, reject_colors: [])
|
|
@client = client
|
|
@reject_colors = reject_colors
|
|
end
|
|
|
|
def list(board_id)
|
|
@client.labels_store.select { |l| l.board_id == board_id }.map { |l| stringify(l) }
|
|
end
|
|
|
|
def create(board_id, attrs)
|
|
raise Planka::ValidationError, "color #{attrs[:color]} rejected" if @reject_colors.include?(attrs[:color])
|
|
|
|
label = FakePlankaClient::Label.new(id: @client.next_id, board_id: board_id, name: attrs[:name], color: attrs[:color])
|
|
@client.labels_store << label
|
|
stringify(label)
|
|
end
|
|
|
|
def attach_to_card(card_id, label_id)
|
|
@client.attach_label(card_id, label_id)
|
|
@client.card_labels_store.last
|
|
end
|
|
|
|
private
|
|
|
|
def stringify(l) = { "id" => l.id, "boardId" => l.board_id, "name" => l.name, "color" => l.color }
|
|
end
|
|
|
|
class CommentsResource
|
|
def initialize(client)
|
|
@client = client
|
|
@store = []
|
|
end
|
|
|
|
attr_reader :store
|
|
|
|
def create(card_id, attrs)
|
|
comment = { "id" => @client.next_id, "cardId" => card_id, "text" => attrs[:text] }
|
|
@store << comment
|
|
comment
|
|
end
|
|
end
|
|
end
|
|
end
|