-
Notifications
You must be signed in to change notification settings - Fork 1
🐛 Support custom signature properties for TDD baseline variants #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When downloading baselines from the cloud, use the project's baseline_signature_properties to generate unique filenames for each variant. This fixes an issue where screenshots with the same name but different custom properties (e.g., mobile: true vs mobile: false) would overwrite each other on disk. Changes: - Update generateScreenshotSignature() to accept custom properties - Update signatureToFilename() to sanitize spaces and special chars - Extract signatureProperties from API response during download - Store signatureProperties in baseline metadata for persistence - Use signatureProperties consistently across all signature generation Fixes #96
Code ReviewI've reviewed this PR and it looks solid overall! The implementation correctly addresses the variant overwriting issue. Here are my findings: ✅ Strengths
🔍 Issues & Recommendations1. Missing Unit Tests for Core Logic (High Priority)The Recommendation: Add tests covering:
Example test structure: describe('generateScreenshotSignature', () => {
it('should generate signature with custom properties', () => {
const sig = generateScreenshotSignature(
'Login',
{ viewport_width: 1920, browser: 'chrome', mobile: false },
['mobile']
);
expect(sig).toBe('Login|1920|chrome|false');
});
it('should handle custom properties in nested metadata', () => {
const sig = generateScreenshotSignature(
'Login',
{
viewport_width: 1920,
metadata: { properties: { device: 'iPhone 15 Pro' } }
},
['device']
);
expect(sig).toBe('Login|1920||iPhone 15 Pro');
});
it('should sanitize special characters in filenames', () => {
const filename = signatureToFilename('Login|1920|chrome|iPhone 15 Pro');
expect(filename).toBe('Login_1920_chrome_iPhone_15_Pro');
});
});2. Integration Test Gap (Medium Priority)The existing test at Recommendation: Add an integration test: it('should download baselines with custom signature properties', async () => {
const mockBuildWithVariants = {
id: 'build123',
signatureProperties: ['mobile'],
screenshots: [
{
name: 'VCombobox_Showcase',
url: 'https://example.com/desktop.png',
metadata: { mobile: false },
// ... other fields
},
{
name: 'VCombobox_Showcase',
url: 'https://example.com/mobile.png',
metadata: { mobile: true },
// ... other fields
}
]
};
mockApiService.getBuild.mockResolvedValueOnce(mockBuildWithVariants);
// ... mock fetches ...
const result = await tddService.downloadBaselines('test', 'main', 'build123');
expect(writeFileSync).toHaveBeenCalledWith(
join(testDir, '.vizzly', 'baselines', 'VCombobox_Showcase_false.png'),
expect.any(Buffer)
);
expect(writeFileSync).toHaveBeenCalledWith(
join(testDir, '.vizzly', 'baselines', 'VCombobox_Showcase_true.png'),
expect.any(Buffer)
);
});3. API Response Validation (Low Priority)The code extracts Recommendation: Add validation: if (
apiResponse.signatureProperties &&
Array.isArray(apiResponse.signatureProperties) &&
apiResponse.signatureProperties.every(prop => typeof prop === 'string')
) {
this.signatureProperties = apiResponse.signatureProperties;
// ...
}4. Edge Case: Empty String Properties (Low Priority)When a custom property value is empty string, the signature includes it as Current behavior: generateScreenshotSignature('Login', { mobile: '' }, ['mobile'])
// Returns: 'Login||' (empty string for mobile)Recommendation: Add a comment explaining this is intentional or consider filtering empty values. 5. Filename Collision Risk (Very Low Priority)The 'A|B__C' → 'A_B__C' → 'A_B_C'
'A|B|C' → 'A_B_C' → 'A_B_C' // collision\!This is extremely unlikely in practice since signatures are controlled by the system, but worth noting. 📋 Test Plan CompletionThe PR description mentions:
Recommendation: Complete the manual testing or add automated tests covering these scenarios before merging. 🎯 SummaryThe implementation is sound and solves the reported issue. The main gap is test coverage for the new functionality. I'd recommend adding unit tests for the signature generation functions and at least one integration test demonstrating the variant handling before merging. Approval Status: Approve with suggestions for improved test coverage. src/services/tdd-service.js:60 - Line comment: The nested property lookup is thorough and well-documented |
Clarify the distinction between custom properties (variants) and baseline signature properties. Custom properties are for organizing and filtering in the dashboard, while baseline signature properties affect which baseline a screenshot matches.
…tion - Add 5 new tests for signatureProperties behavior: - Test that signatureProperties from API creates variant-aware signatures - Test that viewport/browser are included with custom properties - Test that only configured properties affect baseline matching - Test that empty signatureProperties works as expected - Fix property extraction in downloadBaselines methods: - Include viewport_width and browser from top-level screenshot fields - These are returned as top-level API fields, not inside metadata
Simplified wording and improved scannability.
89ab838 to
3c17e8b
Compare
Summary
When downloading baselines from the cloud, use the project's
baseline_signature_propertiesto generate unique filenames for each baseline variant. This fixes an issue where baseline screenshots with the same name but different custom properties would overwrite each other on disk.Important Distinction: Variants vs Baseline Variants
Variants are screenshots with the same name but different properties (browser, viewport, custom properties like
mobile,theme, etc.). They are used for organization and filtering in the Vizzly dashboard.Baseline variants are the specific variants you configure in Project Settings → Baseline Signature Properties to be used for baseline matching. Only these configured properties affect which screenshots are compared against each other.
For example, if you set
baseline_signature_properties: ['mobile']:mobile: truewill only match baselines withmobile: truemobile: falsewill only match baselines withmobile: falsetheme) are ignored for baseline matching (used for filtering only)The Problem
Previously both would be saved as
VCombobox_Showcase.png, with the second overwriting the first.The Solution
Now with
baseline_signature_properties: ['mobile']configured, they get unique filenames:VCombobox_Showcase_1280_chromium_false.pngVCombobox_Showcase_1280_chromium_true.pngChanges
generateScreenshotSignature()to accept custom properties arraysignatureToFilename()to sanitize spaces and special characterssignaturePropertiesfrom API response during baseline downloadsignaturePropertiesin baseline metadata for persistencesignaturePropertiesconsistently across all signature generation callsTest plan
baseline_signature_propertiesconfiguredFixes #96