Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,27 @@ The codebase is designed for fast, lightweight performance with an offline-first
## Theme & Styling

The app adopts the brand guidelines of Zync: Deep Slate background (`#060B14`), card layouts (`#0D1421`), and cyan/brand blue highlights (`#1A8FD1`).

## Testing Strategy

We implement a custom, decoupled unit testing framework integrated directly into the LÖVE lifecycle.

### Phased Testing Structure

1. **Persistence Phase**: Validates that filesystem utility methods correctly write and load structured JSON cache files.
- *Test file*: [test_file_manager.lua](file:///C:/Users/Chitkul%20Lakshya/.gemini/antigravity/brain/3be101ac-c6b9-4c2f-bf9e-330790a2d575/scratch/temp-lua-work/src/tests/test_file_manager.lua)
2. **API Mocking Phase**: Employs decoupling mocks ([mocks.lua](file:///C:/Users/Chitkul%20Lakshya/.gemini/antigravity/brain/3be101ac-c6b9-4c2f-bf9e-330790a2d575/scratch/temp-lua-work/src/tests/mocks.lua)) to inject a mock HTTP client, validating url endpoint binding, API parameters, and response caching.
- *Test file*: [test_project_manager.lua](file:///C:/Users/Chitkul%20Lakshya/.gemini/antigravity/brain/3be101ac-c6b9-4c2f-bf9e-330790a2d575/scratch/temp-lua-work/src/tests/test_project_manager.lua)
3. **Session Store Phase**: Validates authentication managers load and dump active token credentials cleanly.
- *Test file*: [test_auth_manager.lua](file:///C:/Users/Chitkul%20Lakshya/.gemini/antigravity/brain/3be101ac-c6b9-4c2f-bf9e-330790a2d575/scratch/temp-lua-work/src/tests/test_auth_manager.lua)
4. **Connectivity Check Phase**: Validates socket verification routing and exception handling.
- *Test file*: [test_connectivity_check.lua](file:///C:/Users/Chitkul%20Lakshya/.gemini/antigravity/brain/3be101ac-c6b9-4c2f-bf9e-330790a2d575/scratch/temp-lua-work/src/tests/test_connectivity_check.lua)

### Running Tests

To run the phased unit testing suite using the LÖVE CLI runner, pass the `--test` flag:
```bash
love src/ --test
```
All tests are managed by [runner.lua](file:///C:/Users/Chitkul%20Lakshya/.gemini/antigravity/brain/3be101ac-c6b9-4c2f-bf9e-330790a2d575/scratch/temp-lua-work/src/tests/runner.lua) which reports test run status and exit codes.

8 changes: 5 additions & 3 deletions src/api/project_manager.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
local http = require("api.http_client")
local default_http = require("api.http_client")
local file_manager = require("utils.file_manager")
local project_manager = {}
local project_manager = {
http = default_http
}

function project_manager.fetch_projects()
local response = http.request("https://zync-pd9r.onrender.com/api/projects", "GET")
local response = project_manager.http.request("https://zync-pd9r.onrender.com/api/projects", "GET")
if response.status == 200 then
file_manager.save_json("projects_cache.json", response.body)
return true
Expand Down
8 changes: 5 additions & 3 deletions src/api/task_manager.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
local http = require("api.http_client")
local default_http = require("api.http_client")
local file_manager = require("utils.file_manager")
local task_manager = {}
local task_manager = {
http = default_http
}

function task_manager.fetch_tasks(project_id)
local url = "https://zync-pd9r.onrender.com/api/tasks?projectId=" .. project_id
local response = http.request(url, "GET")
local response = task_manager.http.request(url, "GET")
if response.status == 200 then
file_manager.save_json("tasks_" .. project_id .. ".json", response.body)
return true
Expand Down
11 changes: 10 additions & 1 deletion src/main.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
function love.load()
function love.load(arg)
-- Check if testing flag is passed
if arg then
for _, val in ipairs(arg) do
if val == "--test" then
require("tests.runner")
return
end
end
end
print("ZYNC Desktop Loaded")
end
function love.draw()
Expand Down
23 changes: 23 additions & 0 deletions src/tests/mocks.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
local mocks = {}

function mocks.create_http_client()
local client = {
should_fail = false,
response_status = 200,
response_body = "{}",
calls = {}
}

function client.request(url, method, body, headers)
table.insert(client.calls, { url = url, method = method, body = body, headers = headers })
if client.should_fail then
return { status = 500, body = "Error" }
else
return { status = client.response_status, body = client.response_body }
end
end

return client
end

return mocks
47 changes: 47 additions & 0 deletions src/tests/runner.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
local test_file_manager = require("tests.test_file_manager")
local test_project_manager = require("tests.test_project_manager")
local test_auth_manager = require("tests.test_auth_manager")
local test_connectivity_check = require("tests.test_connectivity_check")

print("==================================================")
print("ZYNC Desktop (Lua) Phased Unit Tests Runner")
print("==================================================")

local suites = {
{ name = "FileManager persistence tests", suite = test_file_manager },
{ name = "ProjectManager API tests", suite = test_project_manager },
{ name = "AuthManager session tests", suite = test_auth_manager },
{ name = "ConnectivityCheck socket tests", suite = test_connectivity_check }
}

local passed = 0
local failed = 0

for _, item in ipairs(suites) do
print("Running Suite: " .. item.name .. "...")
local ok, err = pcall(item.suite.run)
if ok then
print("✓ " .. item.name .. " PASSED\n")
passed = passed + 1
else
print("❌ " .. item.name .. " FAILED")
print("Error: " .. tostring(err) .. "\n")
failed = failed + 1
end
end

print("==================================================")
print("Test Run Summary:")
print("Passed: " .. passed)
print("Failed: " .. failed)
print("==================================================")

-- Clean up any test files left
os.remove("test.json")
os.remove("projects_cache.json")

if failed > 0 then
os.exit(1)
else
os.exit(0)
end
20 changes: 20 additions & 0 deletions src/tests/test_auth_manager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
local auth_manager = require("api.auth_manager")

local function run_tests()
local test_token = "zync_test_session_token_12345"

-- Save token
local saved = auth_manager.save_token(test_token)
assert(saved == true, "Auth token save failed")

-- Load token
local loaded = auth_manager.get_token()
assert(loaded == test_token, "Auth token loaded mismatch")

-- Clean up session file
os.remove("session.json")

print("All auth_manager tests passed!")
end

return { run = run_tests }
18 changes: 18 additions & 0 deletions src/tests/test_connectivity_check.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local connectivity_check = require("utils.connectivity_check")

local function run_tests()
-- Check that the function exists
assert(type(connectivity_check.is_backend_online) == "function", "is_backend_online should be a function")

-- Wrap in pcall since luasocket might not be present in CLI test run environment
local status, result = pcall(connectivity_check.is_backend_online)
if status then
assert(type(result) == "boolean", "is_backend_online must return a boolean")
else
print("luasocket not available, skipped socket runtime check: " .. tostring(result))
end

print("All connectivity_check tests passed!")
end

return { run = run_tests }
32 changes: 32 additions & 0 deletions src/tests/test_project_manager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local project_manager = require("api.project_manager")
local mocks = require("tests.mocks")
local file_manager = require("utils.file_manager")

local function run_tests()
local mock_http = mocks.create_http_client()
project_manager.http = mock_http

-- Test case 1: Successful fetch
mock_http.response_body = '[{"id": "p1", "name": "Test project"}]'
mock_http.response_status = 200
mock_http.should_fail = false

local success = project_manager.fetch_projects()
assert(success == true, "Project fetch failed on successful mock request")
assert(#mock_http.calls == 1, "Expected exactly 1 HTTP call")
assert(mock_http.calls[1].method == "GET", "Expected GET request method")
assert(mock_http.calls[1].url == "https://zync-pd9r.onrender.com/api/projects", "Target URL mismatch")

-- Verify cache file was written
local cached = file_manager.load_json("projects_cache.json")
assert(cached ~= nil, "Cache JSON file was not written or loaded")

-- Test case 2: Server failure
mock_http.should_fail = true
local fail_success = project_manager.fetch_projects()
assert(fail_success == false, "Project fetch should return false on server error")

print("All project_manager tests passed!")
end

return { run = run_tests }
Loading