mirror of
https://github.com/penpot/penpot.git
synced 2026-07-03 21:05:25 +00:00
🐛 Add test of fixes in the plugins api suite
This commit is contained in:
parent
1c9ab691e6
commit
f1426cb3bb
@ -4,9 +4,9 @@ import type { CommentThread, Page } from '@penpot/plugin-types';
|
||||
import type { TestContext } from '../framework/types';
|
||||
|
||||
// Comments.
|
||||
// Comment threads are created on the current page. Both thread removal APIs are
|
||||
// currently broken (see the dedicated red tests), so cleanup is best-effort to
|
||||
// keep the other assertions meaningful.
|
||||
// Comment threads are created on the current page. Thread/comment removal is
|
||||
// asynchronous (it resolves once the backend delete RPC completes), so callers
|
||||
// must await it; cleanup is best-effort and swallows errors.
|
||||
|
||||
function page(ctx: TestContext): Page {
|
||||
const p = ctx.penpot.currentPage;
|
||||
@ -124,7 +124,7 @@ describe.skipIfMocked('Comments', () => {
|
||||
x: 8,
|
||||
y: 8,
|
||||
});
|
||||
thread.remove();
|
||||
await thread.remove();
|
||||
const threads = await p.findCommentThreads();
|
||||
expect(threads.every((t) => t.seqNumber !== thread.seqNumber)).toBe(true);
|
||||
});
|
||||
|
||||
@ -83,6 +83,21 @@ describe('Interactions', () => {
|
||||
expect(interaction.action.type).toBe('open-overlay');
|
||||
});
|
||||
|
||||
// position is optional; when omitted the overlay defaults to 'center'.
|
||||
test('open-overlay without a position defaults to center', (ctx) => {
|
||||
const overlay = board(ctx);
|
||||
const r = rect(ctx);
|
||||
const interaction = r.addInteraction('click', {
|
||||
type: 'open-overlay',
|
||||
destination: overlay,
|
||||
});
|
||||
expect(interaction.action.type).toBe('open-overlay');
|
||||
if (interaction.action.type === 'open-overlay') {
|
||||
expect(interaction.action.destination.id).toBe(overlay.id);
|
||||
expect(interaction.action.position).toBe('center');
|
||||
}
|
||||
});
|
||||
|
||||
test('toggle-overlay interaction round-trips', (ctx) => {
|
||||
const overlay = board(ctx);
|
||||
const r = rect(ctx);
|
||||
@ -116,6 +131,23 @@ describe('Interactions', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// animation is optional on close-overlay; omitting it closes with no transition.
|
||||
test('close-overlay without an animation round-trips', (ctx) => {
|
||||
const overlay = board(ctx);
|
||||
const r = rect(ctx);
|
||||
const interaction = r.addInteraction('click', {
|
||||
type: 'close-overlay',
|
||||
destination: overlay,
|
||||
});
|
||||
expect(interaction.action.type).toBe('close-overlay');
|
||||
if (interaction.action.type === 'close-overlay') {
|
||||
expect(
|
||||
interaction.action.destination && interaction.action.destination.id,
|
||||
).toBe(overlay.id);
|
||||
expect(interaction.action.animation).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('previous-screen interaction round-trips', (ctx) => {
|
||||
const r = rect(ctx);
|
||||
const interaction = r.addInteraction('click', { type: 'previous-screen' });
|
||||
@ -134,6 +166,19 @@ describe('Interactions', () => {
|
||||
expect(interaction.delay).toBeCloseTo(1000, 0);
|
||||
});
|
||||
|
||||
// A zero delay is a valid value (fires immediately), not an error.
|
||||
test('after-delay accepts a zero delay', (ctx) => {
|
||||
const dest = board(ctx);
|
||||
const r = rect(ctx);
|
||||
const interaction = r.addInteraction(
|
||||
'after-delay',
|
||||
{ type: 'navigate-to', destination: dest },
|
||||
0,
|
||||
);
|
||||
expect(interaction.trigger).toBe('after-delay');
|
||||
expect(interaction.delay).toBeCloseTo(0, 0);
|
||||
});
|
||||
|
||||
test('mouse-leave trigger is recorded', (ctx) => {
|
||||
// click / mouse-enter / after-delay are covered above; mouse-leave is the
|
||||
// remaining trigger.
|
||||
@ -167,6 +212,20 @@ describe('Interactions', () => {
|
||||
expect(interaction.action.type).toBe('previous-screen');
|
||||
});
|
||||
|
||||
// The delay setter accepts zero (fires immediately) as a valid value.
|
||||
test('delay setter accepts a zero value', (ctx) => {
|
||||
const dest = board(ctx);
|
||||
const r = rect(ctx);
|
||||
const interaction = r.addInteraction(
|
||||
'after-delay',
|
||||
{ type: 'navigate-to', destination: dest },
|
||||
1000,
|
||||
);
|
||||
|
||||
interaction.delay = 0;
|
||||
expect(interaction.delay).toBeCloseTo(0, 0);
|
||||
});
|
||||
|
||||
describe('Animations', () => {
|
||||
test('dissolve animation round-trips', (ctx) => {
|
||||
const dest = board(ctx);
|
||||
|
||||
@ -65,6 +65,23 @@ describe('Layout', () => {
|
||||
expect(flex.leftPadding).toBeCloseTo(4, 0);
|
||||
});
|
||||
|
||||
// Gap and padding setters accept fractional numbers, not just integers.
|
||||
test('gaps and padding accept fractional values', (ctx) => {
|
||||
const flex = board(ctx).addFlexLayout();
|
||||
flex.rowGap = 5.5;
|
||||
flex.columnGap = 10.25;
|
||||
flex.topPadding = 1.5;
|
||||
flex.rightPadding = 2.25;
|
||||
flex.bottomPadding = 3.75;
|
||||
flex.leftPadding = 4.5;
|
||||
expect(flex.rowGap).toBeCloseTo(5.5, 2);
|
||||
expect(flex.columnGap).toBeCloseTo(10.25, 2);
|
||||
expect(flex.topPadding).toBeCloseTo(1.5, 2);
|
||||
expect(flex.rightPadding).toBeCloseTo(2.25, 2);
|
||||
expect(flex.bottomPadding).toBeCloseTo(3.75, 2);
|
||||
expect(flex.leftPadding).toBeCloseTo(4.5, 2);
|
||||
});
|
||||
|
||||
test('sizing round-trips', (ctx) => {
|
||||
const flex = board(ctx).addFlexLayout();
|
||||
flex.horizontalSizing = 'fix';
|
||||
@ -176,6 +193,23 @@ describe('Layout', () => {
|
||||
expect(grid.columnGap).toBeCloseTo(9, 0);
|
||||
});
|
||||
|
||||
// Gap and padding setters accept fractional numbers, not just integers.
|
||||
test('gaps and padding accept fractional values', (ctx) => {
|
||||
const grid = board(ctx).addGridLayout();
|
||||
grid.rowGap = 7.5;
|
||||
grid.columnGap = 9.25;
|
||||
grid.topPadding = 1.5;
|
||||
grid.rightPadding = 2.75;
|
||||
grid.bottomPadding = 3.25;
|
||||
grid.leftPadding = 4.5;
|
||||
expect(grid.rowGap).toBeCloseTo(7.5, 2);
|
||||
expect(grid.columnGap).toBeCloseTo(9.25, 2);
|
||||
expect(grid.topPadding).toBeCloseTo(1.5, 2);
|
||||
expect(grid.rightPadding).toBeCloseTo(2.75, 2);
|
||||
expect(grid.bottomPadding).toBeCloseTo(3.25, 2);
|
||||
expect(grid.leftPadding).toBeCloseTo(4.5, 2);
|
||||
});
|
||||
|
||||
// Index boundaries — invalid indices must be rejected.
|
||||
test('addRowAtIndex with a negative index throws', (ctx) => {
|
||||
const grid = board(ctx).addGridLayout();
|
||||
|
||||
@ -237,6 +237,21 @@ describe('Shapes', () => {
|
||||
expect(r.borderRadiusBottomRight).toBeCloseTo(3, 0);
|
||||
expect(r.borderRadiusBottomLeft).toBeCloseTo(4, 0);
|
||||
});
|
||||
|
||||
// Border radius setters accept fractional numbers, not just integers.
|
||||
test('border radius accepts fractional values', (ctx) => {
|
||||
const r = rect(ctx);
|
||||
r.borderRadius = 4.5;
|
||||
expect(r.borderRadius).toBeCloseTo(4.5, 2);
|
||||
r.borderRadiusTopLeft = 1.25;
|
||||
r.borderRadiusTopRight = 2.5;
|
||||
r.borderRadiusBottomRight = 3.75;
|
||||
r.borderRadiusBottomLeft = 0.5;
|
||||
expect(r.borderRadiusTopLeft).toBeCloseTo(1.25, 2);
|
||||
expect(r.borderRadiusTopRight).toBeCloseTo(2.5, 2);
|
||||
expect(r.borderRadiusBottomRight).toBeCloseTo(3.75, 2);
|
||||
expect(r.borderRadiusBottomLeft).toBeCloseTo(0.5, 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Ordering', () => {
|
||||
|
||||
@ -148,6 +148,19 @@ describe('Tokens', () => {
|
||||
theme.removeSet(set);
|
||||
});
|
||||
|
||||
// addSet/removeSet also accept a token set id (string), not just a TokenSet.
|
||||
test('addSet and removeSet accept a set id', async (ctx) => {
|
||||
const cat = catalog(ctx);
|
||||
const theme = cat.addTheme({ group: '', name: unique('theme') });
|
||||
const set = cat.addSet({ name: unique('set'), active: false });
|
||||
theme.addSet(set.id);
|
||||
await sleep(300);
|
||||
expect(theme.activeSets.length).toBeGreaterThan(0);
|
||||
theme.removeSet(set.id);
|
||||
await sleep(300);
|
||||
expect(theme.activeSets.length).toBe(0);
|
||||
});
|
||||
|
||||
test('duplicate and remove a theme', (ctx) => {
|
||||
const theme = catalog(ctx).addTheme({ group: '', name: unique('theme') });
|
||||
const dup = theme.duplicate();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user