Page MenuHomePhabricator (Chris)

config_spec.lua
No OneTemporary

Authored By
Unknown
Size
12 KB
Referenced Files
None
Subscribers
None

config_spec.lua

--[[
Tests for src/core/config.lua
Config module: loading .env, get/set values, typed access (number, boolean, list).
]]
describe('core.config', function()
local config
local tmpfile
-- Write a temporary .env file for testing
local function write_env(content)
tmpfile = os.tmpname()
local f = io.open(tmpfile, 'w')
f:write(content)
f:close()
return tmpfile
end
before_each(function()
-- Clear the cached module so each test gets a fresh config
package.loaded['src.core.config'] = nil
config = require('src.core.config')
end)
after_each(function()
if tmpfile then
os.remove(tmpfile)
tmpfile = nil
end
end)
describe('load()', function()
it('should load a valid .env file', function()
local path = write_env('FOO=bar\nBAZ=qux\n')
config.load(path)
assert.are.equal('bar', config.get('FOO'))
assert.are.equal('qux', config.get('BAZ'))
end)
it('should not error on missing .env file', function()
assert.has_no.errors(function()
config.load('/tmp/nonexistent_env_file_' .. os.time())
end)
end)
it('should ignore empty lines', function()
local path = write_env('FOO=bar\n\n\nBAZ=qux\n')
config.load(path)
assert.are.equal('bar', config.get('FOO'))
assert.are.equal('qux', config.get('BAZ'))
end)
it('should ignore comment lines', function()
local path = write_env('# This is a comment\nFOO=bar\n# Another comment\n')
config.load(path)
assert.are.equal('bar', config.get('FOO'))
end)
it('should strip surrounding double quotes from values', function()
local path = write_env('FOO="hello world"\n')
config.load(path)
assert.are.equal('hello world', config.get('FOO'))
end)
it('should strip surrounding single quotes from values', function()
local path = write_env("FOO='hello world'\n")
config.load(path)
assert.are.equal('hello world', config.get('FOO'))
end)
it('should strip inline comments from unquoted values', function()
local path = write_env('FOO=bar # this is a comment\n')
config.load(path)
assert.are.equal('bar', config.get('FOO'))
end)
it('should handle values with equals signs', function()
local path = write_env('FOO=bar=baz\n')
config.load(path)
assert.are.equal('bar=baz', config.get('FOO'))
end)
it('should trim whitespace around keys and values', function()
local path = write_env(' FOO = bar \n')
config.load(path)
assert.are.equal('bar', config.get('FOO'))
end)
end)
describe('get()', function()
it('should return the value for a known key', function()
local path = write_env('MY_KEY=my_value\n')
config.load(path)
assert.are.equal('my_value', config.get('MY_KEY'))
end)
it('should return default when key is missing', function()
local path = write_env('OTHER_KEY=other\n')
config.load(path)
assert.are.equal('fallback', config.get('NONEXISTENT', 'fallback'))
end)
it('should return nil when key is missing and no default', function()
local path = write_env('')
config.load(path)
assert.is_nil(config.get('NONEXISTENT'))
end)
it('should fall back to os.getenv for empty .env values', function()
local path = write_env('EMPTY_KEY=\n')
config.load(path)
-- This will either return nil or whatever the OS env has
local result = config.get('EMPTY_KEY', 'default_val')
assert.is_not_nil(result)
end)
it('should auto-load .env if not explicitly loaded', function()
-- Just calling get() without load() should not error
assert.has_no.errors(function()
config.get('ANYTHING')
end)
end)
end)
describe('get_number()', function()
it('should return a number for numeric values', function()
local path = write_env('PORT=8080\n')
config.load(path)
assert.are.equal(8080, config.get_number('PORT'))
end)
it('should return default for non-numeric values', function()
local path = write_env('PORT=abc\n')
config.load(path)
assert.are.equal(3000, config.get_number('PORT', 3000))
end)
it('should return default when key is missing', function()
local path = write_env('')
config.load(path)
assert.are.equal(5432, config.get_number('DB_PORT', 5432))
end)
it('should return nil when key is missing and no default', function()
local path = write_env('')
config.load(path)
assert.is_nil(config.get_number('MISSING'))
end)
it('should handle float values', function()
local path = write_env('RATE=1.5\n')
config.load(path)
assert.are.equal(1.5, config.get_number('RATE'))
end)
it('should handle negative numbers', function()
local path = write_env('OFFSET=-10\n')
config.load(path)
assert.are.equal(-10, config.get_number('OFFSET'))
end)
end)
describe('is_enabled()', function()
it('should return true for "true"', function()
local path = write_env('FLAG=true\n')
config.load(path)
assert.is_true(config.is_enabled('FLAG'))
end)
it('should return true for "1"', function()
local path = write_env('FLAG=1\n')
config.load(path)
assert.is_true(config.is_enabled('FLAG'))
end)
it('should return true for "yes"', function()
local path = write_env('FLAG=yes\n')
config.load(path)
assert.is_true(config.is_enabled('FLAG'))
end)
it('should return true case-insensitively for "TRUE"', function()
local path = write_env('FLAG=TRUE\n')
config.load(path)
assert.is_true(config.is_enabled('FLAG'))
end)
it('should return true case-insensitively for "Yes"', function()
local path = write_env('FLAG=Yes\n')
config.load(path)
assert.is_true(config.is_enabled('FLAG'))
end)
it('should return false for "false"', function()
local path = write_env('FLAG=false\n')
config.load(path)
assert.is_false(config.is_enabled('FLAG'))
end)
it('should return false for "0"', function()
local path = write_env('FLAG=0\n')
config.load(path)
assert.is_false(config.is_enabled('FLAG'))
end)
it('should return false for "no"', function()
local path = write_env('FLAG=no\n')
config.load(path)
assert.is_false(config.is_enabled('FLAG'))
end)
it('should return false for missing key', function()
local path = write_env('')
config.load(path)
assert.is_false(config.is_enabled('MISSING'))
end)
it('should return false for arbitrary string', function()
local path = write_env('FLAG=maybe\n')
config.load(path)
assert.is_false(config.is_enabled('FLAG'))
end)
end)
describe('get_list()', function()
it('should split comma-separated values into a table', function()
local path = write_env('ITEMS=a,b,c\n')
config.load(path)
local list = config.get_list('ITEMS')
assert.are.equal(3, #list)
assert.are.equal('a', list[1])
assert.are.equal('b', list[2])
assert.are.equal('c', list[3])
end)
it('should trim whitespace around items', function()
local path = write_env('ITEMS= a , b , c \n')
config.load(path)
local list = config.get_list('ITEMS')
assert.are.equal(3, #list)
assert.are.equal('a', list[1])
assert.are.equal('b', list[2])
assert.are.equal('c', list[3])
end)
it('should convert numeric items to numbers', function()
local path = write_env('IDS=100,200,300\n')
config.load(path)
local list = config.get_list('IDS')
assert.are.equal(3, #list)
assert.are.equal(100, list[1])
assert.are.equal(200, list[2])
assert.are.equal(300, list[3])
end)
it('should return empty table for missing key', function()
local path = write_env('')
config.load(path)
local list = config.get_list('MISSING')
assert.are.same({}, list)
end)
it('should return empty table for empty value', function()
local path = write_env('ITEMS=\n')
config.load(path)
local list = config.get_list('ITEMS')
assert.are.same({}, list)
end)
it('should handle single-item list', function()
local path = write_env('ITEMS=only\n')
config.load(path)
local list = config.get_list('ITEMS')
assert.are.equal(1, #list)
assert.are.equal('only', list[1])
end)
it('should handle mixed numeric and string items', function()
local path = write_env('ITEMS=100,hello,300\n')
config.load(path)
local list = config.get_list('ITEMS')
assert.are.equal(100, list[1])
assert.are.equal('hello', list[2])
assert.are.equal(300, list[3])
end)
end)
describe('convenience accessors', function()
it('should return bot_token', function()
local path = write_env('BOT_TOKEN=12345:ABCDEF\n')
config.load(path)
assert.are.equal('12345:ABCDEF', config.bot_token())
end)
it('should return bot_admins as a list', function()
local path = write_env('BOT_ADMINS=221714512,123456\n')
config.load(path)
local admins = config.bot_admins()
assert.are.equal(2, #admins)
assert.are.equal(221714512, admins[1])
end)
it('should return bot_name with default', function()
local path = write_env('')
config.load(path)
assert.are.equal('mattata', config.bot_name())
end)
it('should return database config with defaults', function()
local path = write_env('')
config.load(path)
local db = config.database()
assert.are.equal('postgres', db.host)
assert.are.equal(5432, db.port)
assert.are.equal('mattata', db.database)
end)
it('should return redis config with defaults', function()
local path = write_env('')
config.load(path)
local rc = config.redis_config()
assert.are.equal('redis', rc.host)
assert.are.equal(6379, rc.port)
assert.are.equal(0, rc.db)
end)
it('should return polling config with defaults', function()
local path = write_env('')
config.load(path)
local p = config.polling()
assert.are.equal(60, p.timeout)
assert.are.equal(100, p.limit)
end)
it('should return webhook config', function()
local path = write_env('WEBHOOK_ENABLED=true\nWEBHOOK_URL=https://example.com\nWEBHOOK_PORT=8443\n')
config.load(path)
local wh = config.webhook()
assert.is_true(wh.enabled)
assert.are.equal('https://example.com', wh.url)
assert.are.equal(8443, wh.port)
end)
it('should return debug status', function()
local path = write_env('DEBUG=true\n')
config.load(path)
assert.is_true(config.debug())
end)
it('should return ai config with defaults', function()
local path = write_env('')
config.load(path)
local ai = config.ai()
assert.is_false(ai.enabled)
assert.are.equal('gpt-4o', ai.openai_model)
end)
end)
describe('VERSION', function()
it('should be 2.0', function()
assert.are.equal('2.0', config.VERSION)
end)
end)
end)

File Metadata

Mime Type
application/javascript
Expires
Sun, Nov 15, 3:02 AM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
140095
Default Alt Text
config_spec.lua (12 KB)

Event Timeline