Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ theme/static
.netlify
.DS_Store
.node-version

# BackstopJS
backstop_data/bitmaps_test/
backstop_data/html_report/
backstop_data/ci_report/
215 changes: 215 additions & 0 deletions backstop-scenarios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/**
* BackstopJS Scenarios for Mozilla Protocol
*
* This file defines all component URLs for visual regression testing.
* Components are organized by category and include all variants.
*/

const BASE_URL = 'http://localhost:3000/components/preview';

/**
* Helper to create a scenario object
* @param {string} label - Descriptive name for the scenario
* @param {string} path - Component path (e.g., 'button' or 'button--secondary')
* @param {object} options - Additional scenario options
*/
function createScenario(label, path, options = {}) {
return {
label: label,
url: `${BASE_URL}/${path}`,
delay: 500,
misMatchThreshold: 0.1,
requireSameDimensions: false,
...options
};
}

const scenarios = [
// =========================================================================
// BUTTON
// =========================================================================
createScenario('Button - Primary', 'button'),
createScenario('Button - Using Link', 'button--using-link'),
createScenario('Button - Primary Dark', 'button--primary-dark'),
createScenario('Button - Secondary', 'button--secondary'),
createScenario('Button - Secondary Dark', 'button--secondary-dark'),
createScenario('Button - Product', 'button--product'),
createScenario('Button - Product Secondary', 'button--product-secondary'),
createScenario('Button - Product Secondary Dark', 'button--product-secondary-dark'),
createScenario('Button - Neutral', 'button--neutral'),
createScenario('Button - Neutral Dark', 'button--neutral-dark'),
createScenario('Button - Disabled', 'button--disabled'),

// =========================================================================
// CARD
// =========================================================================
createScenario('Card - Overview', 'card'),
createScenario('Card - Extra Small', 'card--extra-small'),
createScenario('Card - Small', 'card--small'),
createScenario('Card - Medium', 'card--medium'),
createScenario('Card - Large', 'card--large'),
createScenario('Card - Dark Theme', 'card--dark-theme'),

// =========================================================================
// CTA LINK
// =========================================================================
createScenario('CTA Link', 'cta-link'),

// =========================================================================
// SPLIT
// =========================================================================
createScenario('Split - Default', 'split'),
createScenario('Split - Reversed', 'split--reversed'),
createScenario('Split - Narrow Body', 'split--narrow-body'),
createScenario('Split - Wide Body', 'split--wide-body'),
createScenario('Split - Background', 'split--background'),
createScenario('Split - Media Overflow', 'split--media-overflow'),
createScenario('Split - Constrained Media', 'split--constrained-media'),
createScenario('Split - Pop-out Media', 'split--pop-out-media'),
createScenario('Split - Body Alignment', 'split--body-alignment'),
createScenario('Split - Media Alignment', 'split--media-alignment'),

// =========================================================================
// BRANDING
// =========================================================================
createScenario('Logo - Default', 'logo'),
createScenario('Logo - Centered', 'logo--centered'),
createScenario('Logo - Centered on Mobile', 'logo--centered-on-mobile'),
createScenario('Wordmark - Default', 'wordmark'),
createScenario('Wordmark - Centered', 'wordmark--centered'),
createScenario('Wordmark - Centered on Mobile', 'wordmark--centered-on-mobile'),
createScenario('Zap', 'zap'),

// =========================================================================
// NOTIFICATION BAR
// =========================================================================
createScenario('Notification Bar - Default', 'notification-bar'),
createScenario('Notification Bar - Success', 'notification-bar--success'),
createScenario('Notification Bar - Warning', 'notification-bar--warning'),
createScenario('Notification Bar - Error', 'notification-bar--error'),
createScenario('Notification Bar - Click', 'notification-bar--click'),

// =========================================================================
// NEWSLETTER
// =========================================================================
createScenario('Newsletter - Default', 'newsletter'),
createScenario('Newsletter - Errors', 'newsletter--errors'),
createScenario('Newsletter - Success', 'newsletter--success'),

// =========================================================================
// BILLBOARD
// =========================================================================
createScenario('Billboard', 'billboard'),

// =========================================================================
// CALLOUT
// =========================================================================
createScenario('Callout - Default', 'callout'),
createScenario('Callout - Dark Theme', 'callout--dark-theme'),
createScenario('Callout - Content Width', 'callout--content-width'),
createScenario('Callout - Compact', 'callout--compact'),

// =========================================================================
// NAVIGATION
// =========================================================================
createScenario('Navigation', 'navigation'),
createScenario('Menu Item', 'menu-item'),

// =========================================================================
// DOWNLOAD BUTTON
// =========================================================================
createScenario('Download Button - Default', 'download-button'),
createScenario('Download Button - Secondary', 'download-button--secondary'),

// =========================================================================
// SECTION HEADING
// =========================================================================
createScenario('Section Heading', 'section-heading'),

// =========================================================================
// MENU LIST
// =========================================================================
createScenario('Menu List - Default', 'menu-list'),
createScenario('Menu List - Download', 'menu-list--download'),

// =========================================================================
// PICTO
// =========================================================================
createScenario('Picto - Default', 'picto'),
createScenario('Picto - Centered', 'picto--centered'),
createScenario('Picto - Side', 'picto--side'),

// =========================================================================
// STICKY PROMO
// =========================================================================
createScenario('Sticky Promo - Default', 'sticky-promo'),
createScenario('Sticky Promo - Dark Theme', 'sticky-promo--dark-theme'),

// =========================================================================
// LAYOUT - CONTENT CONTAINER
// =========================================================================
createScenario('Content Container - Default', 'content-container'),
createScenario('Content Container - Small', 'content-container--small-container'),
createScenario('Content Container - Medium', 'content-container--medium-container'),
createScenario('Content Container - Large', 'content-container--large-container'),
createScenario('Content Container - Extra Large', 'content-container--extra-large-container'),

// =========================================================================
// LAYOUT - COLUMNS
// =========================================================================
createScenario('Columns - Overview', 'columns'),
createScenario('Columns - Two', 'columns--two'),
createScenario('Columns - Three', 'columns--three'),
createScenario('Columns - Four', 'columns--four'),

// =========================================================================
// LAYOUT - CARD LAYOUT
// =========================================================================
createScenario('Card Layout - Overview', 'card-layout'),
createScenario('Card Layout - Half', 'card-layout--half'),
createScenario('Card Layout - Third', 'card-layout--third'),
createScenario('Card Layout - Quarter', 'card-layout--quarter'),
createScenario('Card Layout - Hero', 'card-layout--hero'),

// =========================================================================
// LAYOUT - MAIN WITH SIDEBAR
// =========================================================================
createScenario('Main with Sidebar - Default', 'main-with-sidebar'),
createScenario('Main with Sidebar - Right', 'main-with-sidebar--sidebar-right'),
createScenario('Example Sidebar Menu', 'example-sidebar-menu'),

// =========================================================================
// FOOTER
// =========================================================================
createScenario('Footer', 'footer'),
createScenario('Footer Example', 'example-basic'),

// =========================================================================
// FORMS - INPUT
// =========================================================================
createScenario('Input - Text', 'input'),
createScenario('Input - Date', 'input--date'),
createScenario('Input - Email', 'input--email'),
createScenario('Input - Placeholder', 'input--placeholder'),
createScenario('Input - Password', 'input--password'),
createScenario('Input - File', 'input--file'),
createScenario('Input - Search', 'input--search'),
createScenario('Input - Disabled', 'input--disabled'),

// =========================================================================
// FORMS - SELECT
// =========================================================================
createScenario('Select - Default', 'select'),
createScenario('Select - Disabled', 'select--disabled'),

// =========================================================================
// FORMS - OTHER
// =========================================================================
createScenario('Form Header', 'form-header'),
createScenario('Button Container - Default', 'button-container'),
createScenario('Button Container - End Aligned', 'button-container--end-aligned'),
createScenario('Button Container - Center Aligned', 'button-container--center-aligned'),
createScenario('Button Container - Stretched', 'button-container--stretched'),
];

module.exports = scenarios;
83 changes: 83 additions & 0 deletions backstop.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* BackstopJS Configuration for Mozilla Protocol
*
* Visual regression testing configuration for all Protocol components.
*
* Usage:
* npm run visual:reference - Capture baseline screenshots
* npm run visual:test - Compare against baseline
* npm run visual:approve - Accept current screenshots as new baseline
* npm run visual:open - Open the HTML report
*
* Filtering (run a subset of tests):
* Use --filter with a regex pattern to test specific components:
*
* npx backstop test --config=backstop.config.js --filter="Button"
* npx backstop test --config=backstop.config.js --filter="Card"
* npx backstop test --config=backstop.config.js --filter="Split - Default"
* npx backstop reference --config=backstop.config.js --filter="Newsletter"
*
* Prerequisites:
* The Fractal dev server must be running on localhost:3000
* Start it with: npm start
*/

const scenarios = require('./backstop-scenarios');

module.exports = {
id: 'protocol',
viewports: [
{
label: 'mobile',
width: 360,
height: 640
},
{
label: 'tablet',
width: 768,
height: 1024
},
{
label: 'desktop-sm',
width: 1024,
height: 768
},
{
label: 'desktop-md',
width: 1280,
height: 800
},
{
label: 'desktop-lg',
width: 1366,
height: 768
},
{
label: 'desktop-xl',
width: 1440,
height: 900
},
{
label: 'desktop-xxl',
width: 1536,
height: 864
}
],
scenarios: scenarios,
paths: {
bitmaps_reference: 'backstop_data/bitmaps_reference',
bitmaps_test: 'backstop_data/bitmaps_test',
html_report: 'backstop_data/html_report',
ci_report: 'backstop_data/ci_report'
},
report: ['browser', 'CI'],
engine: 'puppeteer',
engineOptions: {
args: ['--no-sandbox']
},
asyncCaptureLimit: 5,
asyncCompareLimit: 50,
debug: false,
debugWindow: false,
misMatchThreshold: 0.1
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading