mirror of
https://github.com/indentlabs/notebook.git
synced 2025-10-26 11:19:22 +00:00
231 lines
7.4 KiB
Ruby
231 lines
7.4 KiB
Ruby
require 'test_helper'
|
|
|
|
class PinWorkflowTest < ActionDispatch::IntegrationTest
|
|
include Devise::Test::IntegrationHelpers
|
|
|
|
setup do
|
|
@user = users(:one)
|
|
@character = characters(:one)
|
|
|
|
# Create multiple images for testing
|
|
@image1 = ImageUpload.create!(
|
|
user: @user,
|
|
content_type: 'Character',
|
|
content_id: @character.id,
|
|
privacy: 'public',
|
|
pinned: false
|
|
)
|
|
|
|
@image2 = ImageUpload.create!(
|
|
user: @user,
|
|
content_type: 'Character',
|
|
content_id: @character.id,
|
|
privacy: 'public',
|
|
pinned: false
|
|
)
|
|
|
|
@basil1 = BasilCommission.create!(
|
|
user: @user,
|
|
entity: @character,
|
|
entity_type: 'Character',
|
|
prompt: 'Test basil 1',
|
|
job_id: 'basil_job_1',
|
|
pinned: false
|
|
)
|
|
|
|
@basil2 = BasilCommission.create!(
|
|
user: @user,
|
|
entity: @character,
|
|
entity_type: 'Character',
|
|
prompt: 'Test basil 2',
|
|
job_id: 'basil_job_2',
|
|
pinned: false
|
|
)
|
|
|
|
sign_in @user
|
|
end
|
|
|
|
test "complete pin workflow: pin, switch, unpin" do
|
|
# Step 1: Pin first image
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @image1.id, image_type: 'image_upload' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
assert JSON.parse(response.body)['pinned']
|
|
|
|
# Verify state
|
|
@image1.reload
|
|
assert @image1.pinned, "Image 1 should be pinned"
|
|
assert_not @image2.reload.pinned, "Image 2 should remain unpinned"
|
|
assert_not @basil1.reload.pinned, "Basil 1 should remain unpinned"
|
|
assert_not @basil2.reload.pinned, "Basil 2 should remain unpinned"
|
|
|
|
# Step 2: Pin second image (should unpin first)
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @image2.id, image_type: 'image_upload' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
assert JSON.parse(response.body)['pinned']
|
|
|
|
# Verify state
|
|
@image1.reload
|
|
@image2.reload
|
|
assert_not @image1.pinned, "Image 1 should be unpinned"
|
|
assert @image2.pinned, "Image 2 should be pinned"
|
|
assert_not @basil1.reload.pinned, "Basil 1 should remain unpinned"
|
|
assert_not @basil2.reload.pinned, "Basil 2 should remain unpinned"
|
|
|
|
# Step 3: Pin basil commission (should unpin image)
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @basil1.id, image_type: 'basil_commission' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
assert JSON.parse(response.body)['pinned']
|
|
|
|
# Verify state
|
|
assert_not @image1.reload.pinned, "Image 1 should remain unpinned"
|
|
assert_not @image2.reload.pinned, "Image 2 should be unpinned"
|
|
assert @basil1.reload.pinned, "Basil 1 should be pinned"
|
|
assert_not @basil2.reload.pinned, "Basil 2 should remain unpinned"
|
|
|
|
# Step 4: Pin second basil (should unpin first basil)
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @basil2.id, image_type: 'basil_commission' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
assert JSON.parse(response.body)['pinned']
|
|
|
|
# Verify state
|
|
assert_not @image1.reload.pinned, "Image 1 should remain unpinned"
|
|
assert_not @image2.reload.pinned, "Image 2 should remain unpinned"
|
|
assert_not @basil1.reload.pinned, "Basil 1 should be unpinned"
|
|
assert @basil2.reload.pinned, "Basil 2 should be pinned"
|
|
|
|
# Step 5: Unpin the currently pinned basil (go back to 0 pins)
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @basil2.id, image_type: 'basil_commission' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
assert_not JSON.parse(response.body)['pinned']
|
|
|
|
# Verify final state - nothing should be pinned
|
|
assert_not @image1.reload.pinned, "Image 1 should remain unpinned"
|
|
assert_not @image2.reload.pinned, "Image 2 should remain unpinned"
|
|
assert_not @basil1.reload.pinned, "Basil 1 should remain unpinned"
|
|
assert_not @basil2.reload.pinned, "Basil 2 should be unpinned"
|
|
end
|
|
|
|
test "pin workflow across different content types" do
|
|
# Create another character with images
|
|
character2 = Character.create!(
|
|
name: 'Test Character 2',
|
|
user: @user,
|
|
privacy: 'public'
|
|
)
|
|
|
|
image_char2 = ImageUpload.create!(
|
|
user: @user,
|
|
content_type: 'Character',
|
|
content_id: character2.id,
|
|
privacy: 'public',
|
|
pinned: false
|
|
)
|
|
|
|
# Pin image for character 1
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @image1.id, image_type: 'image_upload' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
assert @image1.reload.pinned, "Character 1 image should be pinned"
|
|
|
|
# Pin image for character 2 - should NOT affect character 1 pins
|
|
post toggle_image_pin_path,
|
|
params: { image_id: image_char2.id, image_type: 'image_upload' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
assert_response :success
|
|
|
|
# Both should remain pinned (different content)
|
|
assert @image1.reload.pinned, "Character 1 image should remain pinned"
|
|
assert image_char2.reload.pinned, "Character 2 image should be pinned"
|
|
assert_not @image2.reload.pinned, "Character 1 other image should remain unpinned"
|
|
end
|
|
|
|
test "pin workflow with rapid requests should handle gracefully" do
|
|
# Simulate rapid clicking by making multiple requests quickly
|
|
threads = []
|
|
results = []
|
|
|
|
5.times do |i|
|
|
threads << Thread.new do
|
|
post toggle_image_pin_path,
|
|
params: { image_id: @image1.id, image_type: 'image_upload' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
results << {
|
|
status: response.status,
|
|
body: response.body.present? ? JSON.parse(response.body) : nil
|
|
}
|
|
end
|
|
end
|
|
|
|
threads.each(&:join)
|
|
|
|
# At least one request should succeed
|
|
successful_requests = results.select { |r| r[:status] == 200 }
|
|
assert successful_requests.any?, "At least one request should succeed"
|
|
|
|
# Final state should be consistent
|
|
@image1.reload
|
|
assert [@image1.pinned, !@image1.pinned].include?(true), "Image should have a consistent final state"
|
|
end
|
|
|
|
test "database performance with many images" do
|
|
# Create many images to test performance
|
|
images = []
|
|
20.times do |i|
|
|
images << ImageUpload.create!(
|
|
user: @user,
|
|
content_type: 'Character',
|
|
content_id: @character.id,
|
|
privacy: 'public',
|
|
pinned: false
|
|
)
|
|
end
|
|
|
|
# Time the pin operation
|
|
start_time = Time.current
|
|
|
|
post toggle_image_pin_path,
|
|
params: { image_id: images.first.id, image_type: 'image_upload' },
|
|
headers: { 'Accept' => 'application/json' }
|
|
|
|
end_time = Time.current
|
|
duration = end_time - start_time
|
|
|
|
assert_response :success
|
|
assert duration < 1.0, "Pin operation should complete in under 1 second even with many images"
|
|
|
|
# Verify only one image is pinned
|
|
pinned_count = ImageUpload.where(
|
|
content_type: 'Character',
|
|
content_id: @character.id,
|
|
pinned: true
|
|
).count
|
|
|
|
assert_equal 1, pinned_count, "Only one image should be pinned"
|
|
end
|
|
|
|
# Ensure we're signed out after all tests to avoid affecting smoke tests
|
|
teardown do
|
|
sign_out :user if @user
|
|
end
|
|
|
|
# Using Devise::Test::IntegrationHelpers for sign_in
|
|
end |