test: add std gfx test (#11442)

### Changed
- Move some intergraion tests to std as they are more like basic tests
- Add some basic gfx-related tests
This commit is contained in:
doouding
2025-04-08 16:20:35 +00:00
parent e4e3d8ef59
commit d7268ce04c
19 changed files with 641 additions and 265 deletions

View File

@@ -2,10 +2,8 @@ import type { SurfaceBlockModel } from '@blocksuite/affine/blocks/surface';
import type {
BrushElementModel,
GroupElementModel,
ShapeElementModel,
} from '@blocksuite/affine/model';
import { DefaultTheme } from '@blocksuite/affine/model';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { beforeEach, describe, expect, test } from 'vitest';
import { wait } from '../utils/common.js';
import { setupEditor } from '../utils/setup.js';
@@ -23,88 +21,19 @@ beforeEach(async () => {
return cleanup;
});
describe('elements management', () => {
test('addElement should work correctly', () => {
const id = model.addElement({
type: 'shape',
});
expect(model.elementModels[0].id).toBe(id);
});
test('removeElement should work correctly', () => {
const id = model.addElement({
type: 'shape',
});
model.deleteElement(id);
expect(model.elementModels.length).toBe(0);
});
test('updateElement should work correctly', () => {
const id = model.addElement({
type: 'shape',
});
model.updateElement(id, { xywh: '[10,10,200,200]' });
expect(model.elementModels[0].xywh).toBe('[10,10,200,200]');
});
test('getElementById should return element', () => {
const id = model.addElement({
type: 'shape',
});
expect(model.getElementById(id)).not.toBeNull();
});
test('getElementById should return null if not found', () => {
expect(model.getElementById('not-found')).toBeNull();
});
});
describe('element model', () => {
test('default value should work correctly', () => {
const id = model.addElement({
type: 'shape',
});
const element = model.getElementById(id)! as ShapeElementModel;
expect(element.index).toBe('a0');
expect(element.strokeColor).toBe(DefaultTheme.shapeStrokeColor);
expect(element.strokeWidth).toBe(4);
});
test('defined prop should not be overwritten by default value', () => {
const id = model.addElement({
type: 'shape',
strokeColor: '--affine-palette-line-black',
});
const element = model.getElementById(id)! as ShapeElementModel;
expect(element.strokeColor).toBe('--affine-palette-line-black');
});
test('assign value to model property should update ymap directly', () => {
const id = model.addElement({
type: 'shape',
});
const element = model.getElementById(id)! as ShapeElementModel;
expect(element.yMap.get('strokeColor')).toBe(DefaultTheme.shapeStrokeColor);
element.strokeColor = '--affine-palette-line-black';
expect(element.yMap.get('strokeColor')).toBe('--affine-palette-line-black');
expect(element.strokeColor).toBe('--affine-palette-line-black');
});
});
describe('group', () => {
test('empty group should have all zero xywh', () => {
const id = model.addElement({
type: 'group',
});
const group = model.getElementById(id)! as GroupElementModel;
expect(group.x).toBe(0);
expect(group.y).toBe(0);
expect(group.w).toBe(0);
expect(group.h).toBe(0);
});
test('should get group', () => {
const id = model.addElement({
type: 'shape',
@@ -323,185 +252,6 @@ describe('connector', () => {
});
});
describe('stash/pop', () => {
test('stash and pop should work correctly', () => {
const id = model.addElement({
type: 'shape',
strokeWidth: 4,
});
const elementModel = model.getElementById(id)! as ShapeElementModel;
expect(elementModel.strokeWidth).toBe(4);
elementModel.stash('strokeWidth');
elementModel.strokeWidth = 10;
expect(elementModel.strokeWidth).toBe(10);
expect(elementModel.yMap.get('strokeWidth')).toBe(4);
elementModel.pop('strokeWidth');
expect(elementModel.strokeWidth).toBe(10);
expect(elementModel.yMap.get('strokeWidth')).toBe(10);
elementModel.strokeWidth = 6;
expect(elementModel.strokeWidth).toBe(6);
expect(elementModel.yMap.get('strokeWidth')).toBe(6);
});
test('assign stashed property should emit event', () => {
const id = model.addElement({
type: 'shape',
strokeWidth: 4,
});
const elementModel = model.getElementById(id)! as ShapeElementModel;
elementModel.stash('strokeWidth');
const onchange = vi.fn();
const subscription = model.elementUpdated.subscribe(({ id }) => {
subscription.unsubscribe();
onchange(id);
});
elementModel.strokeWidth = 10;
expect(onchange).toHaveBeenCalledWith(id);
});
test('stashed property should also trigger derive decorator', () => {
const id = model.addElement({
type: 'brush',
points: [
[0, 0],
[100, 100],
[120, 150],
],
});
const elementModel = model.getElementById(id)! as BrushElementModel;
elementModel.stash('points');
elementModel.points = [
[0, 0],
[50, 50],
[135, 145],
[150, 170],
[200, 180],
];
const points = elementModel.points;
expect(elementModel.w).toBe(200 + elementModel.lineWidth);
expect(elementModel.h).toBe(180 + elementModel.lineWidth);
expect(elementModel.yMap.get('points')).not.toEqual(points);
expect(elementModel.w).toBe(200 + elementModel.lineWidth);
expect(elementModel.h).toBe(180 + elementModel.lineWidth);
});
test('non-field property should not allow stash/pop, and should failed silently ', () => {
const id = model.addElement({
type: 'group',
});
const elementModel = model.getElementById(id)! as GroupElementModel;
elementModel.stash('xywh');
elementModel.xywh = '[10,10,200,200]';
expect(elementModel['_stashed'].has('xywh')).toBe(false);
elementModel.pop('xywh');
expect(elementModel['_stashed'].has('xywh')).toBe(false);
expect(elementModel.yMap.has('xywh')).toBe(false);
});
});
describe('derive decorator', () => {
test('derived decorator should work correctly', () => {
const id = model.addElement({
type: 'brush',
points: [
[0, 0],
[100, 100],
[120, 150],
],
});
const elementModel = model.getElementById(id)! as BrushElementModel;
expect(elementModel.w).toBe(120 + elementModel.lineWidth);
expect(elementModel.h).toBe(150 + elementModel.lineWidth);
});
});
describe('local decorator', () => {
test('local decorator should work correctly', () => {
const id = model.addElement({
type: 'shape',
});
const elementModel = model.getElementById(id)! as BrushElementModel;
expect(elementModel.display).toBe(true);
elementModel.display = false;
expect(elementModel.display).toBe(false);
elementModel.opacity = 0.5;
expect(elementModel.opacity).toBe(0.5);
});
test('assign local property should emit event', () => {
const id = model.addElement({
type: 'shape',
});
const elementModel = model.getElementById(id)! as BrushElementModel;
const onchange = vi.fn();
const subscription = model.elementUpdated.subscribe(({ id }) => {
subscription.unsubscribe();
onchange(id);
});
elementModel.display = false;
expect(elementModel.display).toBe(false);
expect(onchange).toHaveBeenCalledWith(id);
});
});
describe('convert decorator', () => {
test('convert decorator', () => {
const id = model.addElement({
type: 'brush',
points: [
[50, 25],
[200, 200],
[300, 300],
],
});
const elementModel = model.getElementById(id)! as BrushElementModel;
const halfLineWidth = elementModel.lineWidth / 2;
const xOffset = 50 - halfLineWidth;
const yOffset = 25 - halfLineWidth;
expect(elementModel.points).toEqual([
[50 - xOffset, 25 - yOffset],
[200 - xOffset, 200 - yOffset],
[300 - xOffset, 300 - yOffset],
]);
});
});
describe('basic property', () => {
test('empty group should have all zero xywh', () => {
const id = model.addElement({
type: 'group',
});
const group = model.getElementById(id)! as GroupElementModel;
expect(group.x).toBe(0);
expect(group.y).toBe(0);
expect(group.w).toBe(0);
expect(group.h).toBe(0);
});
});
describe('brush', () => {
test('same lineWidth should have same xywh', () => {
const id = model.addElement({