• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

super3 / lowerproptax / 19310965814

12 Nov 2025 08:29PM UTC coverage: 88.942% (-11.1%) from 100.0%
19310965814

push

github

super3
Fix all tests for browser-use integration

Test Updates:
- Update mock database to support assessments table and transactions
- Add connect() method to mock pool for transaction support
- Update admin controller tests for new assessments structure
- Fix property controller error test for transaction-based creation
- Skip scraper in test environment

Changes:
- Mock database now handles BEGIN, COMMIT, ROLLBACK
- Mock supports both properties and assessments tables
- Admin tests expect assessments instead of properties queries
- Property creation error test mocks pool.connect() properly
- Scraper only runs when NODE_ENV !== 'test' and API key exists

All 78 tests passing ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

44 of 46 branches covered (95.65%)

Branch coverage included in aggregate %.

1 of 2 new or added lines in 1 file covered. (50.0%)

1 existing line in 1 file now uncovered.

141 of 162 relevant lines covered (87.04%)

7.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.74
/src/controllers/propertyController.js
1
import pool from '../db/connection.js';
2
import { queueScraping } from '../services/propertyScraperService.js';
3

4
// Test helper to reset storage
5
export async function resetProperties() {
6
  await pool.query('DELETE FROM properties');
35✔
7
}
8

9
// Get all properties for the authenticated user
10
export async function getProperties(req, res) {
11
  try {
6✔
12
    const userId = req.user.id;
6✔
13
    const result = await pool.query(
6✔
14
      `SELECT id, user_id as "userId", address, city, state,
15
              zip_code as "zipCode", country, lat, lng,
16
              created_at as "createdAt", updated_at as "updatedAt"
17
       FROM properties WHERE user_id = $1 ORDER BY created_at DESC`,
18
      [userId]
19
    );
20
    res.json(result.rows);
5✔
21
  } catch (error) {
22
    console.error('Error getting properties:', error);
1✔
23
    res.status(500).json({ error: 'Failed to get properties' });
1✔
24
  }
25
}
26

27
// Get a single property by ID
28
export async function getProperty(req, res) {
29
  try {
9✔
30
    const { id } = req.params;
9✔
31
    const result = await pool.query(
9✔
32
      `SELECT id, user_id as "userId", address, city, state,
33
              zip_code as "zipCode", country, lat, lng,
34
              created_at as "createdAt", updated_at as "updatedAt"
35
       FROM properties WHERE id = $1`,
36
      [id]
37
    );
38

39
    if (result.rows.length === 0) {
8✔
40
      return res.status(404).json({ error: 'Property not found' });
4✔
41
    }
42

43
    const property = result.rows[0];
4✔
44

45
    // Ensure user owns this property
46
    if (property.userId !== req.user.id) {
4✔
47
      return res.status(403).json({ error: 'Access denied' });
2✔
48
    }
49

50
    res.json(property);
2✔
51
  } catch (error) {
52
    console.error('Error getting property:', error);
1✔
53
    res.status(500).json({ error: 'Failed to get property' });
1✔
54
  }
55
}
56

57
// Create a new property
58
export async function createProperty(req, res) {
59
  try {
27✔
60
    const { address, city, state, zipCode, country, lat, lng } = req.body;
27✔
61

62
    if (!address) {
27✔
63
      return res.status(400).json({ error: 'Address is required' });
2✔
64
    }
65

66
    const propertyId = `prop_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
25✔
67
    const assessmentId = `assess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
25✔
68
    const currentYear = new Date().getFullYear();
25✔
69

70
    // Create property and assessment in a transaction
71
    const client = await pool.connect();
25✔
72
    try {
25✔
73
      await client.query('BEGIN');
25✔
74

75
      // Create property
76
      const propertyResult = await client.query(
24✔
77
        `INSERT INTO properties (id, user_id, address, city, state, zip_code, country, lat, lng, created_at, updated_at)
78
         VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW())
79
         RETURNING id, user_id as "userId", address, city, state,
80
                   zip_code as "zipCode", country, lat, lng,
81
                   created_at as "createdAt", updated_at as "updatedAt"`,
82
        [
83
          propertyId,
84
          req.user.id,
85
          address,
86
          city || '',
36✔
87
          state || '',
37✔
88
          zipCode || '',
43✔
89
          country || '',
46✔
90
          lat || null,
46✔
91
          lng || null
46✔
92
        ]
93
      );
94

95
      // Create assessment for current year with status 'preparing'
96
      await client.query(
24✔
97
        `INSERT INTO assessments (id, property_id, year, status, created_at, updated_at)
98
         VALUES ($1, $2, $3, 'preparing', NOW(), NOW())`,
99
        [assessmentId, propertyId, currentYear]
100
      );
101

102
      await client.query('COMMIT');
24✔
103

104
      // Queue scraping task in background (non-blocking) - skip in test environment
105
      if (process.env.NODE_ENV !== 'test' && process.env.BROWSER_USE_API_KEY) {
24!
NEW
106
        queueScraping(assessmentId, address, currentYear);
×
107
      }
108

109
      res.status(201).json(propertyResult.rows[0]);
24✔
110
    } catch (err) {
111
      await client.query('ROLLBACK');
1✔
UNCOV
112
      throw err;
×
113
    } finally {
114
      client.release();
25✔
115
    }
116
  } catch (error) {
117
    console.error('Error creating property:', error);
1✔
118
    res.status(500).json({ error: 'Failed to create property' });
1✔
119
  }
120
}
121

122
// Update a property
123
export async function updateProperty(req, res) {
124
  try {
10✔
125
    const { id } = req.params;
10✔
126

127
    // First check if property exists and user owns it
128
    const checkResult = await pool.query(
10✔
129
      'SELECT user_id FROM properties WHERE id = $1',
130
      [id]
131
    );
132

133
    if (checkResult.rows.length === 0) {
9✔
134
      return res.status(404).json({ error: 'Property not found' });
1✔
135
    }
136

137
    const property = checkResult.rows[0];
8✔
138

139
    // Ensure user owns this property
140
    if (property.user_id !== req.user.id) {
8✔
141
      return res.status(403).json({ error: 'Access denied' });
2✔
142
    }
143

144
    const { address, city, state, zipCode, country, lat, lng } = req.body;
6✔
145

146
    const result = await pool.query(
6✔
147
      `UPDATE properties
148
       SET address = COALESCE($1, address),
149
           city = COALESCE($2, city),
150
           state = COALESCE($3, state),
151
           zip_code = COALESCE($4, zip_code),
152
           country = COALESCE($5, country),
153
           lat = COALESCE($6, lat),
154
           lng = COALESCE($7, lng),
155
           updated_at = NOW()
156
       WHERE id = $8
157
       RETURNING id, user_id as "userId", address, city, state,
158
                 zip_code as "zipCode", country, lat, lng,
159
                 created_at as "createdAt", updated_at as "updatedAt"`,
160
      [
161
        /* istanbul ignore next */ address !== undefined ? address : null,
162
        /* istanbul ignore next */ city !== undefined ? city : null,
163
        /* istanbul ignore next */ state !== undefined ? state : null,
164
        /* istanbul ignore next */ zipCode !== undefined ? zipCode : null,
165
        /* istanbul ignore next */ country !== undefined ? country : null,
166
        /* istanbul ignore next */ lat !== undefined ? lat : null,
167
        /* istanbul ignore next */ lng !== undefined ? lng : null,
168
        id
169
      ]
170
    );
171

172
    res.json(result.rows[0]);
6✔
173
  } catch (error) {
174
    console.error('Error updating property:', error);
1✔
175
    res.status(500).json({ error: 'Failed to update property' });
1✔
176
  }
177
}
178

179
// Delete a property
180
export async function deleteProperty(req, res) {
181
  try {
6✔
182
    const { id } = req.params;
6✔
183

184
    // First check if property exists and user owns it
185
    const checkResult = await pool.query(
6✔
186
      'SELECT user_id FROM properties WHERE id = $1',
187
      [id]
188
    );
189

190
    if (checkResult.rows.length === 0) {
5✔
191
      return res.status(404).json({ error: 'Property not found' });
1✔
192
    }
193

194
    const property = checkResult.rows[0];
4✔
195

196
    // Ensure user owns this property
197
    if (property.user_id !== req.user.id) {
4✔
198
      return res.status(403).json({ error: 'Access denied' });
2✔
199
    }
200

201
    await pool.query('DELETE FROM properties WHERE id = $1', [id]);
2✔
202
    res.json({ message: 'Property deleted successfully' });
2✔
203
  } catch (error) {
204
    console.error('Error deleting property:', error);
1✔
205
    res.status(500).json({ error: 'Failed to delete property' });
1✔
206
  }
207
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc