refactor(editor): getFirstContentBlock -> getFirstBlock & getLastContentBlock -> getLastBlock (#10809)

This commit is contained in:
yoyoyohamapi
2025-03-14 02:35:22 +00:00
parent d3aae962bc
commit e086fd2a43
10 changed files with 530 additions and 325 deletions
@@ -0,0 +1,230 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it } from 'vitest';
import { getFirstBlockCommand } from '../../../commands/block-crud/get-first-content-block';
import { affine } from '../../helpers/affine-template';
describe('commands/block-crud', () => {
describe('getFirstBlockCommand', () => {
it('should return null when root is not exists', () => {
const host = affine`<affine-page></affine-page>`;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: 'content',
root: undefined,
});
expect(firstBlock).toBeNull();
});
it('should return first block with content role when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-1-2">Second Paragraph</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2-2">Second Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: 'hub',
root: undefined,
});
expect(firstBlock?.id).toBe('note-1');
});
it('should return first block with any role in the array when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-1-2">Second Paragraph</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2-2">Second Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: ['hub', 'content'],
root: undefined,
});
expect(firstBlock?.id).toBe('note-1');
});
it('should return first block with specified flavour when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Paragraph</affine-paragraph>
<affine-list id="list-1">List Item</affine-list>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
flavour: 'affine:list',
root: note,
});
expect(firstBlock?.id).toBe('list-1');
});
it('should return first block with any flavour in the array when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Paragraph</affine-paragraph>
<affine-list id="list-1">List Item</affine-list>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
flavour: ['affine:list', 'affine:code'],
root: note,
});
expect(firstBlock?.id).toBe('list-1');
});
it('should return first block matching both role and flavour when both specified', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Content Paragraph</affine-paragraph>
<affine-list id="list-1">Content List</affine-list>
<affine-paragraph id="paragraph-2">hub Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: 'content',
flavour: 'affine:list',
root: note,
});
expect(firstBlock?.id).toBe('list-1');
});
it('should return first block with default roles when role not specified', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">hub Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Content Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-3">Hub Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
root: undefined,
});
expect(firstBlock?.id).toBe('note-1');
});
it('should return first block with specified role when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Content Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">hub Paragraph</affine-paragraph>
<affine-database id="database-1">Database</affine-database>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: 'hub',
root: note,
});
expect(firstBlock?.id).toBe('database-1');
});
it('should return null when no blocks with specified role are found in children', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Content Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Another Content Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: 'hub',
root: note,
});
expect(firstBlock).toBeNull();
});
it('should return null when no blocks with specified flavour are found in children', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Another Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
flavour: 'affine:list',
root: note,
});
expect(firstBlock).toBeNull();
});
it('should return first block with specified role within specified root subtree', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">1-1 Content</affine-paragraph>
<affine-paragraph id="paragraph-1-2">1-2 hub</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">2-1 hub</affine-paragraph>
<affine-paragraph id="paragraph-2-2">2-2 Content</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-2')?.model;
const [_, { firstBlock }] = host.command.exec(getFirstBlockCommand, {
role: 'content',
root: note,
});
expect(firstBlock?.id).toBe('paragraph-2-1');
});
});
});
@@ -1,89 +0,0 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it } from 'vitest';
import { getFirstContentBlockCommand } from '../../../commands/block-crud/get-first-content-block';
import { affine } from '../../helpers/affine-template';
describe('commands/block-crud', () => {
describe('getFirstContentBlockCommand', () => {
it('should return null when root is not provided and no note block exists', () => {
const host = affine`<affine-page></affine-page>`;
const [_, { firstBlock }] = host.command.exec(
getFirstContentBlockCommand,
{
root: undefined,
std: {
host,
} as any,
}
);
expect(firstBlock).toBeNull();
});
it('should return first content block when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Second Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { firstBlock }] = host.command.exec(
getFirstContentBlockCommand,
{
root: undefined,
}
);
expect(firstBlock?.id).toBe('paragraph-1');
});
it('should return null when no content blocks are found in children', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
</affine-note>
</affine-page>
`;
const [_, { firstBlock }] = host.command.exec(
getFirstContentBlockCommand,
{}
);
expect(firstBlock).toBeNull();
});
it('should return first content block within specified root subtree', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">1-1 Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-1-2">1-2 Paragraph</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">2-1 Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2-2">2-2 Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const noteBlock = host.doc.getBlock('note-2')?.model;
const [_, { firstBlock }] = host.command.exec(
getFirstContentBlockCommand,
{
root: noteBlock,
}
);
expect(firstBlock?.id).toBe('paragraph-2-1');
});
});
});
@@ -0,0 +1,230 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it } from 'vitest';
import { getLastBlockCommand } from '../../../commands/block-crud/get-last-content-block';
import { affine } from '../../helpers/affine-template';
describe('commands/block-crud', () => {
describe('getLastBlockCommand', () => {
it('should return null when root is not exists', () => {
const host = affine`<affine-page></affine-page>`;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: 'content',
root: undefined,
});
expect(lastBlock).toBeNull();
});
it('should return last block with content role when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-1-2">Second Paragraph</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2-2">Second Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: 'hub',
root: undefined,
});
expect(lastBlock?.id).toBe('note-2');
});
it('should return last block with any role in the array when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-1-2">Second Paragraph</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2-2">Second Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: ['hub', 'content'],
root: undefined,
});
expect(lastBlock?.id).toBe('note-2');
});
it('should return last block with specified flavour when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Paragraph</affine-paragraph>
<affine-list id="list-1">List Item</affine-list>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
flavour: 'affine:list',
root: note,
});
expect(lastBlock?.id).toBe('list-1');
});
it('should return last block with any flavour in the array when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Paragraph</affine-paragraph>
<affine-list id="list-1">List Item</affine-list>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
flavour: ['affine:list', 'affine:code'],
root: note,
});
expect(lastBlock?.id).toBe('list-1');
});
it('should return last block matching both role and flavour when both specified', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Content Paragraph</affine-paragraph>
<affine-list id="list-1">Content List</affine-list>
<affine-paragraph id="paragraph-2">hub Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: 'content',
flavour: 'affine:list',
root: note,
});
expect(lastBlock?.id).toBe('list-1');
});
it('should return last block with default roles when role not specified', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">hub Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Content Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-3">Hub Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
root: undefined,
});
expect(lastBlock?.id).toBe('note-1');
});
it('should return last block with specified role when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Content Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">hub Paragraph</affine-paragraph>
<affine-database id="database-1">Database</affine-database>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: 'hub',
root: note,
});
expect(lastBlock?.id).toBe('database-1');
});
it('should return null when no blocks with specified role are found in children', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Content Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Another Content Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: 'hub',
root: note,
});
expect(lastBlock).toBeNull();
});
it('should return null when no blocks with specified flavour are found in children', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Another Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-1')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
flavour: 'affine:list',
root: note,
});
expect(lastBlock).toBeNull();
});
it('should return last block with specified role within specified root subtree', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">1-1 Content</affine-paragraph>
<affine-paragraph id="paragraph-1-2">1-2 hub</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">2-1 hub</affine-paragraph>
<affine-paragraph id="paragraph-2-2">2-2 Content</affine-paragraph>
</affine-note>
</affine-page>
`;
const note = host.doc.getBlock('note-2')?.model;
const [_, { lastBlock }] = host.command.exec(getLastBlockCommand, {
role: 'content',
root: note,
});
expect(lastBlock?.id).toBe('paragraph-2-2');
});
});
});
@@ -1,80 +0,0 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it } from 'vitest';
import { getLastContentBlockCommand } from '../../../commands/block-crud/get-last-content-block';
import { affine } from '../../helpers/affine-template';
describe('commands/block-crud', () => {
describe('getLastContentBlockCommand', () => {
it('should return null when root is not provided and no note block exists', () => {
const host = affine`<affine-page></affine-page>`;
const [_, { lastBlock }] = host.command.exec(getLastContentBlockCommand, {
root: undefined,
std: {
host,
} as any,
});
expect(lastBlock).toBeNull();
});
it('should return last content block when found', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1">First Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2">Second Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const [_, { lastBlock }] = host.command.exec(getLastContentBlockCommand, {
root: undefined,
});
expect(lastBlock?.id).toBe('paragraph-2');
});
it('should return null when no content blocks are found in children', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
</affine-note>
</affine-page>
`;
const [_, { lastBlock }] = host.command.exec(
getLastContentBlockCommand,
{}
);
expect(lastBlock).toBeNull();
});
it('should return last content block within specified root subtree', () => {
const host = affine`
<affine-page>
<affine-note id="note-1">
<affine-paragraph id="paragraph-1-1">1-1 Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-1-2">1-2 Paragraph</affine-paragraph>
</affine-note>
<affine-note id="note-2">
<affine-paragraph id="paragraph-2-1">2-1 Paragraph</affine-paragraph>
<affine-paragraph id="paragraph-2-2">2-2 Paragraph</affine-paragraph>
</affine-note>
</affine-page>
`;
const noteBlock = host.doc.getBlock('note-2')?.model;
const [_, { lastBlock }] = host.command.exec(getLastContentBlockCommand, {
root: noteBlock,
});
expect(lastBlock?.id).toBe('paragraph-2-2');
});
});
});