fix(data): preserve numeric zero values through normalization - #631
fix(data): preserve numeric zero values through normalization#631seonghobae wants to merge 1 commit into
Conversation
|
Warning Review limit reachedNext included review available in 27 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| budget: task.budget === 0 ? 0 : task.budget || defaults.budget || '', | ||
| actualCost: task.actualCost === 0 ? 0 : task.actualCost || defaults.actualCost || '', | ||
| sprint: task.sprint || defaults.sprint || '', | ||
| storyPoints: task.storyPoints || defaults.storyPoints || '' | ||
| storyPoints: task.storyPoints === 0 ? 0 : task.storyPoints || defaults.storyPoints || '' |
There was a problem hiding this comment.
🟡 Numeric zero fields appear empty
When imported fields contain numeric zeroes, renderEditorField displays them as blanks during editing. Users cannot distinguish preserved zeroes from missing values.
Prompt for agents
Numeric zero values introduced by createNormalizedExternalRecord remain numbers in state, but app.js renderEditorField initializes each input with value || '', so imported zero budget, actualCost, and storyPoints fields appear empty when edited. Initialize editor inputs without treating numeric zero as missing, while preserving the existing fallback for null, undefined, false, and empty strings as intended. Add regression coverage that opens each imported zero-valued task and verifies the corresponding editor input shows "0".
Was this helpful? React with 👍 or 👎 to provide feedback.
| test('preserves numeric zero values through seed normalization and persistence', async ({ page }) => { | ||
| await page.route('**/wbs.json', async (route) => route.fulfill({ | ||
| status: 200, | ||
| contentType: 'application/json', | ||
| body: JSON.stringify([ | ||
| { __id: 'zero-budget', __depth: '3', phase: 'P5000', activity: 'Data', task: 'Zero budget', budget: 0, actualCost: 100, storyPoints: 1 }, | ||
| { __id: 'zero-cost', __depth: '3', phase: 'P5000', activity: 'Data', task: 'Zero cost', budget: 100, actualCost: 0, storyPoints: 1 }, | ||
| { __id: 'zero-points', __depth: '3', phase: 'P5000', activity: 'Data', task: 'Zero points', budget: 100, actualCost: 100, storyPoints: 0 }, | ||
| { __id: 'all-zero', __depth: '3', phase: 'P5000', activity: 'Data', task: 'All zero', budget: 0, actualCost: 0, storyPoints: 0 }, | ||
| { __id: 'missing-values', __depth: '3', phase: 'P5000', activity: 'Data', task: 'Missing values' } | ||
| ]) | ||
| })); | ||
| await page.evaluate(() => localStorage.clear()); | ||
| await page.reload(); | ||
|
|
||
| await expect(page.locator('tbody tr[data-task-id]')).toHaveCount(5); | ||
| await page.getByTestId('project-name-input').fill('Zero preservation round trip'); | ||
| await expect.poll(() => page.evaluate(() => localStorage.getItem('scopeweave:planner-state:v1'))).not.toBeNull(); | ||
| const savedTasks = await page.evaluate(() => JSON.parse(localStorage.getItem('scopeweave:planner-state:v1')).tasks); | ||
| const valuesById = Object.fromEntries(savedTasks.map((task) => [task.id, { | ||
| budget: task.budget, | ||
| actualCost: task.actualCost, | ||
| storyPoints: task.storyPoints | ||
| }])); | ||
| expect(valuesById).toEqual({ | ||
| 'zero-budget': { budget: 0, actualCost: 100, storyPoints: 1 }, | ||
| 'zero-cost': { budget: 100, actualCost: 0, storyPoints: 1 }, | ||
| 'zero-points': { budget: 100, actualCost: 100, storyPoints: 0 }, | ||
| 'all-zero': { budget: 0, actualCost: 0, storyPoints: 0 }, | ||
| 'missing-values': { budget: '', actualCost: '', storyPoints: '' } | ||
| }); | ||
| }); |
|
Closing this lane as superseded by #610 after exact comparison against the same protected base #631 head #610 current head |
Closes #609
Summary
Verification