better input field keyboard handling
This commit is contained in:
438
testing/__tests__/34_password_mode_tests.lua
Normal file
438
testing/__tests__/34_password_mode_tests.lua
Normal file
@@ -0,0 +1,438 @@
|
||||
-- ====================
|
||||
-- Password Mode Tests
|
||||
-- ====================
|
||||
-- Test suite for password mode functionality in FlexLove input fields
|
||||
|
||||
local lu = require("testing.luaunit")
|
||||
local loveStub = require("testing.loveStub")
|
||||
|
||||
-- Setup LÖVE environment
|
||||
_G.love = loveStub
|
||||
|
||||
-- Load FlexLove after setting up love stub
|
||||
local FlexLove = require("FlexLove")
|
||||
|
||||
-- Test fixtures
|
||||
local testElement
|
||||
|
||||
TestPasswordMode = {}
|
||||
|
||||
function TestPasswordMode:setUp()
|
||||
-- Clear all keyboard modifier states at start of each test
|
||||
love.keyboard.setDown("lshift", false)
|
||||
love.keyboard.setDown("rshift", false)
|
||||
love.keyboard.setDown("lctrl", false)
|
||||
love.keyboard.setDown("rctrl", false)
|
||||
love.keyboard.setDown("lalt", false)
|
||||
love.keyboard.setDown("ralt", false)
|
||||
love.keyboard.setDown("lgui", false)
|
||||
love.keyboard.setDown("rgui", false)
|
||||
|
||||
-- Reset FlexLove state
|
||||
FlexLove.Gui.topElements = {}
|
||||
FlexLove.Gui._focusedElement = nil
|
||||
|
||||
-- Create a test password input element
|
||||
testElement = FlexLove.Element.new({
|
||||
x = 100,
|
||||
y = 100,
|
||||
width = 200,
|
||||
height = 40,
|
||||
editable = true,
|
||||
passwordMode = true,
|
||||
text = "",
|
||||
})
|
||||
end
|
||||
|
||||
function TestPasswordMode:tearDown()
|
||||
-- Clear all keyboard modifier states
|
||||
love.keyboard.setDown("lshift", false)
|
||||
love.keyboard.setDown("rshift", false)
|
||||
love.keyboard.setDown("lctrl", false)
|
||||
love.keyboard.setDown("rctrl", false)
|
||||
love.keyboard.setDown("lalt", false)
|
||||
love.keyboard.setDown("ralt", false)
|
||||
love.keyboard.setDown("lgui", false)
|
||||
love.keyboard.setDown("rgui", false)
|
||||
|
||||
testElement = nil
|
||||
FlexLove.Gui.topElements = {}
|
||||
FlexLove.Gui._focusedElement = nil
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Property Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testPasswordModePropertyExists()
|
||||
-- Test that passwordMode property exists and can be set
|
||||
lu.assertNotNil(testElement.passwordMode)
|
||||
lu.assertTrue(testElement.passwordMode)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeDefaultIsFalse()
|
||||
-- Test that passwordMode defaults to false
|
||||
local normalElement = FlexLove.Element.new({
|
||||
x = 100,
|
||||
y = 100,
|
||||
width = 200,
|
||||
height = 40,
|
||||
editable = true,
|
||||
text = "Normal text",
|
||||
})
|
||||
|
||||
lu.assertFalse(normalElement.passwordMode or false)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeIsSingleLineOnly()
|
||||
-- Password mode should only work with single-line inputs
|
||||
-- The constraint is enforced in Element.lua line 292-293
|
||||
local multilinePassword = FlexLove.Element.new({
|
||||
x = 100,
|
||||
y = 100,
|
||||
width = 200,
|
||||
height = 100,
|
||||
editable = true,
|
||||
multiline = true,
|
||||
passwordMode = true,
|
||||
text = "Password",
|
||||
})
|
||||
|
||||
-- Based on the constraint, multiline should be set to false
|
||||
lu.assertFalse(multilinePassword.multiline)
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Text Buffer Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testActualTextContentRemains()
|
||||
-- Insert text into password field
|
||||
testElement:focus()
|
||||
testElement:insertText("S")
|
||||
testElement:insertText("e")
|
||||
testElement:insertText("c")
|
||||
testElement:insertText("r")
|
||||
testElement:insertText("e")
|
||||
testElement:insertText("t")
|
||||
|
||||
-- Verify actual text buffer contains the real text
|
||||
lu.assertEquals(testElement._textBuffer, "Secret")
|
||||
lu.assertEquals(testElement:getText(), "Secret")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordTextIsNotModified()
|
||||
-- Set initial text
|
||||
testElement:setText("MyPassword123")
|
||||
|
||||
-- The actual buffer should contain the real password
|
||||
lu.assertEquals(testElement._textBuffer, "MyPassword123")
|
||||
lu.assertEquals(testElement:getText(), "MyPassword123")
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Cursor Position Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testCursorPositionWithPasswordMode()
|
||||
testElement:setText("test")
|
||||
testElement:focus()
|
||||
|
||||
-- Set cursor to end
|
||||
testElement:setCursorPosition(4)
|
||||
lu.assertEquals(testElement._cursorPosition, 4)
|
||||
|
||||
-- Move cursor to middle
|
||||
testElement:setCursorPosition(2)
|
||||
lu.assertEquals(testElement._cursorPosition, 2)
|
||||
|
||||
-- Move cursor to start
|
||||
testElement:setCursorPosition(0)
|
||||
lu.assertEquals(testElement._cursorPosition, 0)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testCursorMovementInPasswordField()
|
||||
testElement:setText("password")
|
||||
testElement:focus()
|
||||
testElement:setCursorPosition(0)
|
||||
|
||||
-- Move right
|
||||
testElement:moveCursorBy(1)
|
||||
lu.assertEquals(testElement._cursorPosition, 1)
|
||||
|
||||
-- Move right again
|
||||
testElement:moveCursorBy(1)
|
||||
lu.assertEquals(testElement._cursorPosition, 2)
|
||||
|
||||
-- Move left
|
||||
testElement:moveCursorBy(-1)
|
||||
lu.assertEquals(testElement._cursorPosition, 1)
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Text Editing Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testInsertTextInPasswordMode()
|
||||
testElement:focus()
|
||||
testElement:setCursorPosition(0)
|
||||
|
||||
testElement:insertText("a")
|
||||
lu.assertEquals(testElement._textBuffer, "a")
|
||||
|
||||
testElement:insertText("b")
|
||||
lu.assertEquals(testElement._textBuffer, "ab")
|
||||
|
||||
testElement:insertText("c")
|
||||
lu.assertEquals(testElement._textBuffer, "abc")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testBackspaceInPasswordMode()
|
||||
testElement:setText("password")
|
||||
testElement:focus()
|
||||
testElement:setCursorPosition(8) -- End of text
|
||||
|
||||
-- Delete last character
|
||||
testElement:keypressed("backspace", nil, false)
|
||||
lu.assertEquals(testElement._textBuffer, "passwor")
|
||||
|
||||
-- Delete another character
|
||||
testElement:keypressed("backspace", nil, false)
|
||||
lu.assertEquals(testElement._textBuffer, "passwo")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testDeleteInPasswordMode()
|
||||
testElement:setText("password")
|
||||
testElement:focus()
|
||||
testElement:setCursorPosition(0) -- Start of text
|
||||
|
||||
-- Delete first character
|
||||
testElement:keypressed("delete", nil, false)
|
||||
lu.assertEquals(testElement._textBuffer, "assword")
|
||||
|
||||
-- Delete another character
|
||||
testElement:keypressed("delete", nil, false)
|
||||
lu.assertEquals(testElement._textBuffer, "ssword")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testInsertTextAtPosition()
|
||||
testElement:setText("pass")
|
||||
testElement:focus()
|
||||
testElement:setCursorPosition(2) -- Between 'pa' and 'ss'
|
||||
|
||||
testElement:insertText("x")
|
||||
lu.assertEquals(testElement._textBuffer, "paxss")
|
||||
lu.assertEquals(testElement._cursorPosition, 3)
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Selection Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testTextSelectionInPasswordMode()
|
||||
testElement:setText("password")
|
||||
testElement:focus()
|
||||
|
||||
-- Select from position 2 to 5
|
||||
testElement:setSelection(2, 5)
|
||||
|
||||
local selStart, selEnd = testElement:getSelection()
|
||||
lu.assertEquals(selStart, 2)
|
||||
lu.assertEquals(selEnd, 5)
|
||||
lu.assertTrue(testElement:hasSelection())
|
||||
end
|
||||
|
||||
function TestPasswordMode:testDeleteSelectionInPasswordMode()
|
||||
testElement:setText("password")
|
||||
testElement:focus()
|
||||
|
||||
-- Select "sswo" (positions 2-6)
|
||||
testElement:setSelection(2, 6)
|
||||
|
||||
-- Delete selection
|
||||
testElement:deleteSelection()
|
||||
lu.assertEquals(testElement._textBuffer, "pard")
|
||||
lu.assertFalse(testElement:hasSelection())
|
||||
end
|
||||
|
||||
function TestPasswordMode:testReplaceSelectionInPasswordMode()
|
||||
testElement:setText("password")
|
||||
testElement:focus()
|
||||
|
||||
-- Select "sswo" (positions 2-6)
|
||||
testElement:setSelection(2, 6)
|
||||
|
||||
-- Type new text (should replace selection)
|
||||
testElement:textinput("X")
|
||||
lu.assertEquals(testElement._textBuffer, "paXrd")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testSelectAllInPasswordMode()
|
||||
testElement:setText("secret")
|
||||
testElement:focus()
|
||||
|
||||
testElement:selectAll()
|
||||
|
||||
local selStart, selEnd = testElement:getSelection()
|
||||
lu.assertEquals(selStart, 0)
|
||||
lu.assertEquals(selEnd, 6)
|
||||
lu.assertTrue(testElement:hasSelection())
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Integration Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testPasswordModeWithMaxLength()
|
||||
testElement.maxLength = 5
|
||||
testElement:focus()
|
||||
|
||||
testElement:insertText("1")
|
||||
testElement:insertText("2")
|
||||
testElement:insertText("3")
|
||||
testElement:insertText("4")
|
||||
testElement:insertText("5")
|
||||
testElement:insertText("6") -- Should be rejected
|
||||
|
||||
lu.assertEquals(testElement._textBuffer, "12345")
|
||||
lu.assertEquals(utf8.len(testElement._textBuffer), 5)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeWithPlaceholder()
|
||||
local passwordWithPlaceholder = FlexLove.Element.new({
|
||||
x = 100,
|
||||
y = 100,
|
||||
width = 200,
|
||||
height = 40,
|
||||
editable = true,
|
||||
passwordMode = true,
|
||||
placeholder = "Enter password",
|
||||
text = "",
|
||||
})
|
||||
|
||||
-- When empty and not focused, placeholder should be available
|
||||
lu.assertEquals(passwordWithPlaceholder.placeholder, "Enter password")
|
||||
lu.assertEquals(passwordWithPlaceholder._textBuffer, "")
|
||||
|
||||
-- When text is added, actual text should be stored
|
||||
passwordWithPlaceholder:focus()
|
||||
passwordWithPlaceholder:insertText("secret")
|
||||
lu.assertEquals(passwordWithPlaceholder._textBuffer, "secret")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeClearText()
|
||||
testElement:setText("password123")
|
||||
lu.assertEquals(testElement._textBuffer, "password123")
|
||||
|
||||
-- Clear text
|
||||
testElement:setText("")
|
||||
lu.assertEquals(testElement._textBuffer, "")
|
||||
lu.assertEquals(testElement:getText(), "")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeToggle()
|
||||
-- Start with password mode off
|
||||
local toggleElement = FlexLove.Element.new({
|
||||
x = 100,
|
||||
y = 100,
|
||||
width = 200,
|
||||
height = 40,
|
||||
editable = true,
|
||||
passwordMode = false,
|
||||
text = "visible",
|
||||
})
|
||||
|
||||
lu.assertEquals(toggleElement._textBuffer, "visible")
|
||||
lu.assertFalse(toggleElement.passwordMode)
|
||||
|
||||
-- Enable password mode
|
||||
toggleElement.passwordMode = true
|
||||
lu.assertTrue(toggleElement.passwordMode)
|
||||
|
||||
-- Text buffer should remain unchanged
|
||||
lu.assertEquals(toggleElement._textBuffer, "visible")
|
||||
|
||||
-- Disable password mode again
|
||||
toggleElement.passwordMode = false
|
||||
lu.assertFalse(toggleElement.passwordMode)
|
||||
lu.assertEquals(toggleElement._textBuffer, "visible")
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- UTF-8 Support Tests
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testPasswordModeWithUTF8Characters()
|
||||
testElement:focus()
|
||||
|
||||
-- Insert UTF-8 characters
|
||||
testElement:insertText("h")
|
||||
testElement:insertText("é")
|
||||
testElement:insertText("l")
|
||||
testElement:insertText("l")
|
||||
testElement:insertText("ö")
|
||||
|
||||
-- Text buffer should contain actual UTF-8 text
|
||||
lu.assertEquals(testElement._textBuffer, "héllö")
|
||||
lu.assertEquals(utf8.len(testElement._textBuffer), 5)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeCursorWithUTF8()
|
||||
testElement:setText("café")
|
||||
testElement:focus()
|
||||
|
||||
-- Move cursor through UTF-8 text
|
||||
testElement:setCursorPosition(0)
|
||||
lu.assertEquals(testElement._cursorPosition, 0)
|
||||
|
||||
testElement:moveCursorBy(1)
|
||||
lu.assertEquals(testElement._cursorPosition, 1)
|
||||
|
||||
testElement:moveCursorBy(1)
|
||||
lu.assertEquals(testElement._cursorPosition, 2)
|
||||
|
||||
testElement:setCursorPosition(4)
|
||||
lu.assertEquals(testElement._cursorPosition, 4)
|
||||
end
|
||||
|
||||
-- ====================
|
||||
-- Edge Cases
|
||||
-- ====================
|
||||
|
||||
function TestPasswordMode:testPasswordModeWithEmptyString()
|
||||
testElement:setText("")
|
||||
lu.assertEquals(testElement._textBuffer, "")
|
||||
lu.assertEquals(testElement:getText(), "")
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeWithSingleCharacter()
|
||||
testElement:setText("x")
|
||||
lu.assertEquals(testElement._textBuffer, "x")
|
||||
lu.assertEquals(utf8.len(testElement._textBuffer), 1)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeWithLongPassword()
|
||||
local longPassword = string.rep("a", 100)
|
||||
testElement:setText(longPassword)
|
||||
|
||||
lu.assertEquals(testElement._textBuffer, longPassword)
|
||||
lu.assertEquals(utf8.len(testElement._textBuffer), 100)
|
||||
end
|
||||
|
||||
function TestPasswordMode:testPasswordModeSetTextUpdatesBuffer()
|
||||
testElement:setText("initial")
|
||||
lu.assertEquals(testElement._textBuffer, "initial")
|
||||
|
||||
testElement:setText("updated")
|
||||
lu.assertEquals(testElement._textBuffer, "updated")
|
||||
|
||||
testElement:setText("")
|
||||
lu.assertEquals(testElement._textBuffer, "")
|
||||
end
|
||||
|
||||
-- Run tests if executed directly
|
||||
if arg and arg[0] and arg[0]:match("34_password_mode_tests%.lua$") then
|
||||
os.exit(lu.LuaUnit.run())
|
||||
end
|
||||
|
||||
return TestPasswordMode
|
||||
Reference in New Issue
Block a user