open-design/apps/web/tests/components/design-system-group-order.test.ts
Chris Seifert 0afaf3bb7e
feat: pin custom design systems to top and read swatches from color tables (#2817)
* feat: pin custom design systems to top and read swatches from color tables

Two changes to Settings -> Design Systems.

Custom (user-created) systems now sort to the top of the list instead of
sitting under the built-in catalog. A small pure helper
(orderDesignSystemGroups) floats any group that holds an editable system
above the rest; everything else keeps its order.

Swatches now show for systems whose DESIGN.md keeps colors in a markdown
table. extractSwatches only understood inline forms before, so table
palettes came back empty and the cards showed no color squares. Added a
table-row pass that reads the first hex in a row as the value and the
first plain text cell as the name. Inline forms still win when a file
mixes both.

* Sort editable systems first within a category group

The group-level sort floated any category holding a user system to the top,
but items inside a group rendered in their incoming (alphabetized) order. A
user system that shares a category with built-ins (its DESIGN.md can set any
category) still landed below Apple/Airbnb in that group, which misses the
point of pinning custom systems to the top.

orderDesignSystemGroups now also sorts items editable-first within each
group, stable so built-ins keep their alphabetical order. The display order
comes from the helper output, so this covers the import path re-alphabetizing
before grouping without touching it.
2026-05-24 14:25:19 +00:00

74 lines
2.5 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import type { DesignSystemSummary } from '@open-design/contracts';
import { orderDesignSystemGroups } from '../../src/components/design-system-group-order';
function ds(id: string, partial: Partial<DesignSystemSummary> = {}): DesignSystemSummary {
return {
id,
title: id,
category: 'Misc',
summary: '',
surface: 'web',
source: 'built-in',
status: 'published',
isEditable: false,
...partial,
} as DesignSystemSummary;
}
type Entry = [string, DesignSystemSummary[]];
describe('orderDesignSystemGroups (issue #2813)', () => {
it('pins a group with editable systems above built-in groups', () => {
const entries: Entry[] = [
['Productivity', [ds('airbnb')]],
['Custom', [ds('user:acme', { source: 'user', isEditable: true })]],
];
expect(orderDesignSystemGroups(entries).map(([cat]) => cat)).toEqual([
'Custom',
'Productivity',
]);
});
it('keeps the built-in groups in their original order (stable sort)', () => {
const entries: Entry[] = [
['B', [ds('b')]],
['A', [ds('a')]],
['Custom', [ds('user:x', { isEditable: true })]],
];
expect(orderDesignSystemGroups(entries).map(([cat]) => cat)).toEqual(['Custom', 'B', 'A']);
});
it('treats source "user" as editable even without isEditable', () => {
const entries: Entry[] = [
['Built', [ds('x')]],
['Mine', [ds('y', { source: 'user' })]],
];
expect(orderDesignSystemGroups(entries).map(([cat]) => cat)).toEqual(['Mine', 'Built']);
});
it('leaves an all-built-in list unchanged', () => {
const entries: Entry[] = [
['A', [ds('a')]],
['B', [ds('b')]],
];
expect(orderDesignSystemGroups(entries).map(([cat]) => cat)).toEqual(['A', 'B']);
});
it('floats an editable system above built-ins inside a shared category', () => {
const entries: Entry[] = [
['Productivity', [ds('apple'), ds('airbnb'), ds('user:acme', { source: 'user', isEditable: true })]],
];
const items = orderDesignSystemGroups(entries)[0]![1];
expect(items.map((system) => system.id)).toEqual(['user:acme', 'apple', 'airbnb']);
});
it('keeps built-ins in their incoming order within a group (stable item sort)', () => {
const entries: Entry[] = [
['Productivity', [ds('b'), ds('user:x', { isEditable: true }), ds('a')]],
];
const items = orderDesignSystemGroups(entries)[0]![1];
expect(items.map((system) => system.id)).toEqual(['user:x', 'b', 'a']);
});
});