@wordpress/block-library
Version:
Block library for the WordPress editor.
163 lines (145 loc) • 5.16 kB
JavaScript
import { describe, expect, it } from 'vitest';
import { hasSortableImages, sortImageBlocks } from '../order-images';
const NEWEST_FIRST = { orderby: 'date', order: 'desc' };
const OLDEST_FIRST = { orderby: 'date', order: 'asc' };
const TITLE_A_TO_Z = { orderby: 'title', order: 'asc' };
const TITLE_Z_TO_A = { orderby: 'title', order: 'desc' };
/**
* Creates the minimal `core/image` block the helpers read: an attachment id
* and a client ID, which defaults from the id.
*
* @param {number|undefined} id Attachment id, or `undefined` for an external image.
* @param {string} clientId Block client ID.
*/
function createImageBlock( id, clientId = `block-${ id }` ) {
return { clientId, attributes: { id } };
}
/**
* Creates image blocks for the given attachment ids, in that order.
*
* @param {...number} ids Attachment ids.
*/
function createImageBlocks( ...ids ) {
return ids.map( ( id ) => createImageBlock( id ) );
}
/**
* Creates the minimal attachment record the helpers read.
*
* @param {number} id Attachment id.
* @param {string} title Attachment title.
* @param {string} date Upload date, ISO 8601.
*/
function createAttachment( id, title, date ) {
return { id, title: { raw: title, rendered: title }, date };
}
// Listed oldest to newest, so the date order reads top to bottom: 2, 3, 1, 4.
// The ids deliberately don't follow the dates, so a sort keyed on the id (or
// on the position in this list) can't pass the date tests by accident. The
// title order is different again: apple, Beach, IMG_2, IMG_10 (2, 1, 4, 3),
// which requires the compare to ignore case and treat numbers naturally.
const ATTACHMENTS = [
createAttachment( 2, 'apple', '2024-01-15T10:00:00' ),
createAttachment( 3, 'IMG_10', '2024-02-01T10:00:00' ),
createAttachment( 1, 'Beach', '2024-03-01T10:00:00' ),
createAttachment( 4, 'IMG_2', '2024-04-01T10:00:00' ),
];
const getImageIds = ( blocks ) =>
blocks.map( ( { attributes } ) => attributes.id );
describe( 'sortImageBlocks', () => {
it( 'sorts by date, newest first', () => {
const blocks = createImageBlocks( 1, 2, 3, 4 );
expect(
getImageIds( sortImageBlocks( blocks, ATTACHMENTS, NEWEST_FIRST ) )
).toEqual( [ 4, 1, 3, 2 ] );
} );
it( 'sorts by date, oldest first', () => {
const blocks = createImageBlocks( 1, 2, 3, 4 );
expect(
getImageIds( sortImageBlocks( blocks, ATTACHMENTS, OLDEST_FIRST ) )
).toEqual( [ 2, 3, 1, 4 ] );
} );
it( 'sorts by title ascending, ignoring case and comparing numbers naturally', () => {
const blocks = createImageBlocks( 1, 2, 3, 4 );
expect(
getImageIds( sortImageBlocks( blocks, ATTACHMENTS, TITLE_A_TO_Z ) )
).toEqual( [ 2, 1, 4, 3 ] );
} );
it( 'sorts by title descending', () => {
const blocks = createImageBlocks( 1, 2, 3, 4 );
expect(
getImageIds( sortImageBlocks( blocks, ATTACHMENTS, TITLE_Z_TO_A ) )
).toEqual( [ 3, 4, 1, 2 ] );
} );
it( 'returns a new array containing the same block objects', () => {
const blocks = createImageBlocks( 1, 2 );
const sorted = sortImageBlocks( blocks, ATTACHMENTS, OLDEST_FIRST );
expect( sorted ).not.toBe( blocks );
expect( sorted[ 0 ] ).toBe( blocks[ 1 ] );
expect( sorted[ 1 ] ).toBe( blocks[ 0 ] );
} );
it( 'moves images without an id or attachment record to the end, in their existing order', () => {
const blocks = [
createImageBlock( undefined, 'external-a' ),
createImageBlock( 1 ),
createImageBlock( 99 ),
createImageBlock( 2 ),
createImageBlock( undefined, 'external-b' ),
];
const sorted = sortImageBlocks( blocks, ATTACHMENTS, OLDEST_FIRST );
expect( sorted.map( ( { clientId } ) => clientId ) ).toEqual( [
'block-2',
'block-1',
'external-a',
'block-99',
'external-b',
] );
} );
it( 'keeps the existing order of images with equal keys', () => {
const media = [
createAttachment( 1, 'Same', '2024-01-01T00:00:00' ),
createAttachment( 2, 'Same', '2024-01-01T00:00:00' ),
];
const blocks = createImageBlocks( 2, 1 );
expect(
getImageIds( sortImageBlocks( blocks, media, NEWEST_FIRST ) )
).toEqual( [ 2, 1 ] );
expect(
getImageIds( sortImageBlocks( blocks, media, TITLE_A_TO_Z ) )
).toEqual( [ 2, 1 ] );
} );
it( 'falls back to the rendered title when there is no raw title', () => {
const media = [
{ id: 1, title: { rendered: 'b' }, date: '' },
{ id: 2, title: { rendered: 'a' }, date: '' },
];
expect(
getImageIds(
sortImageBlocks(
createImageBlocks( 1, 2 ),
media,
TITLE_A_TO_Z
)
)
).toEqual( [ 2, 1 ] );
} );
} );
describe( 'hasSortableImages', () => {
it( 'is true with two or more images that have an attachment record', () => {
expect(
hasSortableImages( createImageBlocks( 1, 2 ), ATTACHMENTS )
).toBe( true );
} );
it( 'is false while the attachment records have not resolved', () => {
expect( hasSortableImages( createImageBlocks( 1, 2 ), [] ) ).toBe(
false
);
} );
it( 'does not count images without an id or attachment record', () => {
expect(
hasSortableImages(
createImageBlocks( 1, undefined, 99 ),
ATTACHMENTS
)
).toBe( false );
} );
} );