Add more tests and fix failing ones

This commit is contained in:
Jorge Manrubia
2025-07-03 12:46:36 +02:00
parent 98e568482a
commit ca4628b457
34 changed files with 217406 additions and 13 deletions
+3 -1
View File
@@ -132,7 +132,7 @@ class Command::Ai::Translator
Do NOT infer unassigned just because an assignment follows.
* **Possessive “my” in front of “card” or “cards”***
→ assignee_ids: [ #{user.to_gid} ] — applies **even when other filters are present***
(e.g., “my cards closing soon”, “my stalled cards”, “my cards created yesterday”).
(e.g., “my cards closing soon”, “my stalled cards”, “my cards created yesterday”, "cards assigned to me").
* “Recent cards” (i.e., newly created) → indexed_by: "newest"
* “Cards with recent activity”, “recently updated cards” → indexed_by: "latest"
Only use "latest" if the user mentions activity, updates, or changes
@@ -157,6 +157,7 @@ class Command::Ai::Translator
* /consider → move card back to "considering" (reconsider)
* Unless a clear command applies, fallback to /search with the verbatim text.
* When searching for nouns (non-person), prefer /search over terms.
* When the person to pass to a command is "me" or "myself", use "#{user.to_gid}"
* Respect the spoken order of commands.
* "close as [reason]" or "close because [reason]" /close [reason]
Remove "as" or "because" from the actual command
@@ -193,6 +194,7 @@ class Command::Ai::Translator
* Never use names, tags, or stage names mentioned **inside commands** (like /assign, /tag, /stage) as filters.
* Never duplicate the assignee in both commands and context.
* Never add properties tied to UI view ("card", "list", etc.).
* When using infinitive verbs such as "assign" or "close", always use the corresponding command, NEVER a filter.
* To filter completed or closed cards, use "indexed_by: closed"; don't set a "closure" filter unless the user is asking for cards completed in a specific window of time.
* When you see a word with a # prefix, assume it refers to a tag (either a filter or a command argument, but don't search for it).
* All filters, including terms, must live **inside** context.
+2 -2
View File
@@ -40,7 +40,7 @@ class Command::Parser::Context
def find_workflow_stage(string)
candidate_stages.find do |stage|
stage.name.downcase.include?(combined_arguments.downcase)
stage.name.downcase.include?(string.downcase)
end
end
@@ -54,7 +54,7 @@ class Command::Parser::Context
end
def find_collection(string)
Collection.where("lower(name) like ?", "%#{name.downcase}%").first
Collection.where("lower(name) like ?", "%#{string.downcase}%").first
end
private
@@ -1,4 +1,4 @@
<lexical-prompt-item search="<%= "#{user.name} #{user.initials}" %>" sgid="<%= user.attachable_sgid %>">
<lexical-prompt-item search="<%= "#{user.name} #{user.initials} #{"me" if user == Current.user}" %>" sgid="<%= user.attachable_sgid %>">
<template type="menu">
<%= avatar_image_tag user %>
<%= user.name %>
@@ -0,0 +1,12 @@
require "test_helper"
class Prompts::CardsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
end
test "index" do
get prompts_cards_path
assert_response :success
end
end
@@ -0,0 +1,13 @@
require "test_helper"
class Prompts::Collections::UsersControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
@collection = collections(:writebook)
end
test "index" do
get prompts_collection_users_path(@collection)
assert_response :success
end
end
@@ -0,0 +1,12 @@
require "test_helper"
class Prompts::CommandsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
end
test "index" do
get prompts_commands_path
assert_response :success
end
end
@@ -0,0 +1,12 @@
require "test_helper"
class Prompts::TagsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
end
test "index" do
get prompts_tags_path
assert_response :success
end
end
@@ -0,0 +1,12 @@
require "test_helper"
class Prompts::UsersControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
end
test "index" do
get prompts_users_path
assert_response :success
end
end
+2 -3
View File
@@ -14,10 +14,9 @@ class Command::Ai::ParserTest < ActionDispatch::IntegrationTest
end
test "resolve filter string params as ids" do
result = parse_command "cards assigned to kevin, tagged with #web, in the collection writebook"
assert_equal 1, result.commands.size
command = parse_command "cards assigned to kevin, tagged with #web, in the collection writebook"
url = result.commands.first.url
url = command.url
query_string = URI.parse(url).query
params = Rack::Utils.parse_nested_query(query_string).with_indifferent_access
+4 -3
View File
@@ -3,6 +3,8 @@ require "test_helper"
class Command::Ai::TranslatorTest < ActionDispatch::IntegrationTest
include VcrTestHelper
vcr_record!
setup do
@user = users(:david)
end
@@ -89,7 +91,7 @@ class Command::Ai::TranslatorTest < ActionDispatch::IntegrationTest
test "combine commands and filters" do
assert_command(
{ context: { card_ids: [ 176, 170 ] }, commands: [ "/do", "/assign david", "/stage Investigating" ] },
{ context: { card_ids: [ 176, 170 ] }, commands: [ "/do", "/assign #{users(:david).to_gid}", "/stage Investigating" ] },
"Move 176 and 170 to doing, assign to me and set the stage to Investigating")
assert_command(
{ context: { assignee_ids: [ "jz" ], tag_ids: [ "design" ] }, commands: [ "/assign andy", "/tag #v2" ] },
@@ -129,8 +131,7 @@ class Command::Ai::TranslatorTest < ActionDispatch::IntegrationTest
test "closing soon and falling back soon" do
assert_command({ context: { indexed_by: "falling_back_soon" } }, "cards to be reconsidered soon")
assert_command({ context: { indexed_by: "falling_back_soon" } }, "cards to be reconsidered soon")
assert_command({ context: { assignee_ids: [ "david" ], indexed_by: "closing_soon" } }, "my cards that are going to be auto closed")
assert_command({ context: { assignee_ids: [ users(:david).to_gid.to_s ], indexed_by: "closing_soon" } }, "my cards that are going to be auto closed")
end
test "view users profiles" do
+2 -3
View File
@@ -18,10 +18,9 @@ class Command::GoToCardTest < ActionDispatch::IntegrationTest
test "result in a regular search if the card does not exist" do
command = parse_command "123"
visit_command = command.commands.first
assert visit_command.valid?
assert command.valid?
result = visit_command.execute
result = command.execute
assert_equal cards_path(terms: [ "123" ]), result.url
end
end
@@ -5,6 +5,7 @@ class Command::Parser::ContextTest < ActiveSupport::TestCase
setup do
@user = users(:david)
@context = Command::Parser::Context.new(@user, url: cards_path)
Card.find_each(&:reindex)
Comment.find_each(&:reindex)
@@ -49,4 +50,66 @@ class Command::Parser::ContextTest < ActiveSupport::TestCase
assert_empty context.cards
end
test "find_user by handle" do
assert_equal users(:david), @context.find_user("david")
assert_equal users(:david), @context.find_user("@david")
assert_equal users(:jz), @context.find_user("jz")
assert_equal users(:kevin), @context.find_user("kevin")
assert_nil @context.find_user("nonexistent")
end
test "find_user by GID" do
david_gid = users(:david).to_gid.to_s
assert_equal users(:david), @context.find_user(david_gid)
jz_gid = users(:jz).to_gid.to_s
assert_equal users(:jz), @context.find_user(jz_gid)
assert_nil @context.find_user("invalid-gid")
end
test "find_workflow_stage" do
card_context = Command::Parser::Context.new(@user, url: card_path(cards(:logo)))
assert_equal workflow_stages(:qa_triage), card_context.find_workflow_stage("triage")
assert_equal workflow_stages(:qa_in_progress), card_context.find_workflow_stage("in progress")
assert_equal workflow_stages(:qa_on_hold), card_context.find_workflow_stage("on hold")
assert_equal workflow_stages(:qa_review), card_context.find_workflow_stage("review")
assert_equal workflow_stages(:qa_in_progress), card_context.find_workflow_stage("progress")
assert_nil card_context.find_workflow_stage("nonexistent")
end
test "find_tag with title" do
assert_equal tags(:web), @context.find_tag("web")
assert_equal tags(:web), @context.find_tag("#web")
assert_equal tags(:mobile), @context.find_tag("mobile")
assert_nil @context.find_tag("nonexistent")
end
test "find_tag by GID" do
web_gid = tags(:web).to_gid.to_s
assert_equal tags(:web), @context.find_tag(web_gid)
mobile_gid = tags(:mobile).to_gid.to_s
assert_equal tags(:mobile), @context.find_tag(mobile_gid)
assert_nil @context.find_tag("invalid-gid")
end
test "find_collection" do
assert_equal collections(:writebook), @context.find_collection("Writebook")
assert_equal collections(:writebook), @context.find_collection("writebook")
assert_equal collections(:private), @context.find_collection("Private collection")
assert_equal collections(:private), @context.find_collection("private collection")
assert_equal collections(:writebook), @context.find_collection("write")
assert_equal collections(:private), @context.find_collection("private")
assert_nil @context.find_collection("nonexistent")
end
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff