Skip to content
Merged
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
78 changes: 78 additions & 0 deletions backend/test/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,83 @@ describe('Multi-farm support and data isolation', () => {
});
});

// ------------------------------------------------------------------ export

describe('Export', () => {
test('GET /farm/:id/export returns CSV by default', async () => {
const res = await get(`/farm/${farmId}/export`);
assert.equal(res.status, 200);
assert.ok(typeof res.body === 'string', 'CSV response should be a string');
assert.ok(res.body.includes('worker_name,shift_date,checked_in_at,amount_sats,payment_status'),
'CSV should contain header row');
});

test('GET /farm/:id/export?format=csv returns CSV with header', async () => {
const res = await get(`/farm/${farmId}/export?format=csv`);
assert.equal(res.status, 200);
assert.ok(typeof res.body === 'string');
const lines = res.body.trim().split('\r\n');
assert.ok(lines.length >= 1, 'Should have at least a header line');
assert.equal(lines[0], 'worker_name,shift_date,checked_in_at,amount_sats,payment_status');
});
});

});

test('GET /farm/:id/export?format=json returns JSON array', async () => {
const res = await get(`/farm/${farmId}/export?format=json`);
assert.equal(res.status, 200);
assert.ok(Array.isArray(res.body), 'JSON export should be an array');
if (res.body.length > 0) {
const row = res.body[0];
assert.ok('worker_name' in row);
assert.ok('shift_date' in row);
assert.ok('checked_in_at' in row);
assert.ok('amount_sats' in row);
assert.ok('payment_status' in row);
}
});

test('GET /farm/:id/export returns 404 for non-existent farm', async () => {
const res = await get('/farm/999999/export');
assert.equal(res.status, 404);
assert.equal(res.body.error, 'Farm not found');
});

test('GET /farm/:id/export?format=xml returns 400 for invalid format', async () => {
const res = await get(`/farm/${farmId}/export?format=xml`);
assert.equal(res.status, 400);
assert.ok(res.body.error.includes('Invalid format'));
});

test('GET /farm/:id/export?format=JSON is case-insensitive', async () => {
const res = await get(`/farm/${farmId}/export?format=JSON`);
assert.equal(res.status, 200);
assert.ok(Array.isArray(res.body), 'Uppercase JSON should work');
});

test('JSON export rows default to unpaid when no payment exists', async () => {
const res = await get(`/farm/${farmId}/export?format=json`);
assert.equal(res.status, 200);
if (res.body.length > 0) {
const unpaidRows = res.body.filter(r => r.payment_status === 'unpaid');
assert.ok(unpaidRows.length > 0, 'Checkins without payments should be unpaid');
}
});

test('CSV export for farm with no checkins returns header only', async () => {
const farmRes = await post('/farm', { name: 'Empty Export Farm', location: 'Nowhere', altitude_m: 500, owner_name: 'Nobody' });
assert.equal(farmRes.status, 201);
const emptyFarmId = farmRes.body.id;

const res = await get(`/farm/${emptyFarmId}/export`);
assert.equal(res.status, 200);
const lines = res.body.trim().split('\r\n');
assert.equal(lines.length, 1, 'Should only have header row for empty farm');
assert.equal(lines[0], 'worker_name,shift_date,checked_in_at,amount_sats,payment_status');
});
});

// ------------------------------------------------------------------ Feature: Lot route edge cases
describe('Lot edge cases', () => {
test('POST /lot returns 400 when required fields are missing', async () => {
Expand Down Expand Up @@ -1480,6 +1557,7 @@ describe('Lot edge cases', () => {
const res = await post('/lot/nonexistent-lot-id/transfer', { to_entity: 'Mill Corp', entity_type: 'wet_mill' });
assert.equal(res.status, 404);
assert.equal(res.body.error, 'Lot not found');

});
});

Loading