Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions .github/workflows/update-snapshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ on:
default: 18
node:
type: number
description: 'Node.js version (default: 16)'
description: 'Node.js version (default: 20)'
skip-tools:
description: 'Skip tools build'
type: boolean
Expand All @@ -36,6 +36,10 @@ on:
description: 'Rete Kit (<name>@<version> or <owner>/<repo>#<version>)'
type: string
default: 'rete-kit@latest'
deps:
description: 'List of dependencies (<owner>/<repo>#<branch>, comma separated)'
type: string
default: ''
workflow_dispatch:
inputs:
name:
Expand All @@ -57,7 +61,7 @@ on:
default: 18
node:
type: number
description: 'Node.js version (default: 16)'
description: 'Node.js version (default: 20)'
branch:
description: 'Branch'
default: main
Expand All @@ -69,6 +73,10 @@ on:
description: 'Rete Kit (<name>@<version> or <owner>/<repo>#<version>)'
type: string
default: 'rete-kit@latest'
deps:
description: 'List of dependencies (<owner>/<repo>#<branch>, comma separated)'
type: string
default: ''


jobs:
Expand All @@ -81,11 +89,19 @@ jobs:
qa: ${{ inputs.qa }}
kit: ${{ inputs.kit }}

deps:
name: Prepare alias deps
if: inputs.deps
uses: ./.github/workflows/prepare-deps.yml
secrets: inherit
with:
repos: ${{ inputs.deps }}

update:
timeout-minutes: 30
runs-on: ubuntu-latest
if: ${{ always() }}
needs: tools
if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
needs: [tools, deps]
# TODO reuse steps from regression.yml
steps:
- name: Download artifact with Rete QA
Expand All @@ -100,6 +116,12 @@ jobs:
with:
name: ${{ needs.tools.outputs.kit-artifact || inputs.kit }}
path: .
- name: Download deps
uses: actions/download-artifact@v4
if: inputs.deps
with:
name: deps
path: .
- name: Install fonts
run: |
sudo apt-get -qqy update
Expand All @@ -117,13 +139,13 @@ jobs:
sudo apt-get -qyy clean
- uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node || 16 }}
node-version: ${{ inputs.node || 20 }}
- name: Install Rete QA
run: npm i -g ${{ inputs.qa-path || needs.tools.outputs.qa-path }} ${{ inputs.kit-path || needs.tools.outputs.kit-path }}
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Init application
run: rete-qa init -s ${{ inputs.name }} -sv ${{ inputs.version }}
run: rete-qa init -s ${{ inputs.name }} -sv ${{ inputs.version }} ${{ inputs.deps && '--deps-alias deps.json' || '' }}
env:
CI: ""
- name: Update snapshots
Expand Down
15 changes: 10 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
"globals": "^15.9.0",
"nodemon": "^2.0.20",
"rete-cli": "~2.0.1",
"rete-kit": "^1.20.0",
"rete-kit": "^1.21.0",
"typescript": "^4.9.5"
},
"peerDependencies": {
"rete-kit": "^1.20.0"
"rete-kit": "^1.21.0"
},
"dependencies": {
"@playwright/test": "1.61.1",
Expand Down
Binary file added snapshots/chromium/comment-frame-dragged.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comment-inline-drag-undone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comment-inline-dragged.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comment-inline-edit-redone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comment-inline-edit-undone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comment-inline-edited.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comment-membership-out.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/comments-initial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-connection-added.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-connection-removed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-add-redone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-add-undone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-added.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-delete-redone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-delete-undone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-deleted.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-redo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-translated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/chromium/history-node-undo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/firefox/comment-frame-dragged.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added snapshots/firefox/comment-inline-drag-undone.png
Binary file added snapshots/firefox/comment-inline-dragged.png
Binary file added snapshots/firefox/comment-inline-edit-undone.png
Binary file added snapshots/firefox/comment-inline-edited.png
Binary file added snapshots/firefox/comment-membership-out.png
Binary file added snapshots/firefox/comments-initial.png
Binary file added snapshots/firefox/history-connection-added.png
Binary file added snapshots/firefox/history-connection-removed.png
Binary file added snapshots/firefox/history-node-add-redone.png
Binary file added snapshots/firefox/history-node-add-undone.png
Binary file added snapshots/firefox/history-node-added.png
Binary file added snapshots/firefox/history-node-delete-redone.png
Binary file added snapshots/firefox/history-node-delete-undone.png
Binary file added snapshots/firefox/history-node-deleted.png
Binary file added snapshots/firefox/history-node-redo.png
Binary file added snapshots/firefox/history-node-translated.png
Binary file added snapshots/firefox/history-node-undo.png
Binary file added snapshots/webkit/comment-frame-dragged.png
Binary file added snapshots/webkit/comment-inline-drag-undone.png
Binary file added snapshots/webkit/comment-inline-dragged.png
Binary file added snapshots/webkit/comment-inline-edit-redone.png
Binary file added snapshots/webkit/comment-inline-edit-undone.png
Binary file added snapshots/webkit/comment-inline-edited.png
Binary file added snapshots/webkit/comment-membership-out.png
Binary file added snapshots/webkit/comments-initial.png
Binary file added snapshots/webkit/history-connection-added.png
Binary file added snapshots/webkit/history-connection-removed.png
Binary file added snapshots/webkit/history-node-add-redone.png
Binary file added snapshots/webkit/history-node-add-undone.png
Binary file added snapshots/webkit/history-node-added.png
Binary file added snapshots/webkit/history-node-delete-undone.png
Binary file added snapshots/webkit/history-node-deleted.png
Binary file added snapshots/webkit/history-node-redo.png
Binary file added snapshots/webkit/history-node-translated.png
Binary file added snapshots/webkit/history-node-undo.png
22 changes: 21 additions & 1 deletion src/commands/init/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
expect(baseFeatures).not.toContainEqual(expect.any(App.Features.Minimap))
expect(baseFeatures).not.toContainEqual(expect.any(App.Features.Reroute))
expect(baseFeatures).not.toContainEqual(expect.any(App.Features.Readonly))
expect(baseFeatures).not.toContainEqual(expect.any(App.Features.Comments))
expect(baseFeatures).not.toContainEqual(expect.any(App.Features.History))
})

it('puts minimap, reroute and readonly into features object', () => {
it('puts optional plugins into features object extras', () => {

Check warning on line 31 in src/commands/init/index.test.ts

View workflow job for this annotation

GitHub Actions / ci / ci

Arrow function has too many statements (22). Maximum allowed is 16
expect(Array.isArray(features)).toBe(false)
if (Array.isArray(features)) return

Expand All @@ -43,6 +45,24 @@
from: 'default',
features: expect.arrayContaining(['Readonly'])
})
expect(features.comments).toEqual({
from: 'default',
features: expect.arrayContaining(['Comments'])
})
expect(features.history).toEqual({
from: 'default',
features: expect.arrayContaining(['History', 'Context menu'])
})
expect(features['comments-history']).toEqual({
from: 'default',
features: expect.arrayContaining(['Comments', 'History'])
})
if (typeof features.comments === 'object' && !Array.isArray(features.comments)) {
expect(features.comments.features).not.toContain('History')
}
if (typeof features.history === 'object' && !Array.isArray(features.history)) {
expect(features.history.features).not.toContain('Comments')
}
if (typeof features.minimap === 'object' && !Array.isArray(features.minimap)) {
expect(features.minimap.features).not.toContain('Reroute')
expect(features.minimap.features).not.toContain('Readonly')
Expand Down Expand Up @@ -75,7 +95,7 @@
describe('Validation', () => {
it('rejects unknown stack names', () => {
const stacks = ['react', 'angular', 'unknown']
const stackVersions = null

Check warning on line 98 in src/commands/init/index.test.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The type of 'stackVersions' is 'any'

const result = validate(stacks, stackVersions)

Expand Down
13 changes: 13 additions & 0 deletions src/commands/init/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@

export function getBaseFeatures({ stack, version }: Pick<(typeof fixtures)[0], 'stack' | 'version'>, next: boolean) {
return [
stack === 'angular' && new App.Features.Angular(version as AngularInitVersion as never, next),

Check warning on line 26 in src/commands/init/index.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The 'version as AngularInitVersion' has unsafe 'as' type assertion

Check warning on line 26 in src/commands/init/index.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The 'version as AngularInitVersion as never' has unsafe 'as' type assertion
['react', 'react-vite'].includes(stack) && new App.Features.React(version, stack, next),
stack === 'vue' && new App.Features.Vue(version as 2 | 3, next),

Check warning on line 28 in src/commands/init/index.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The 'version as 2 | 3' has unsafe 'as' type assertion
stack === 'svelte' && new App.Features.Svelte(version as 3 | 4 | 5, next),

Check warning on line 29 in src/commands/init/index.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The 'version as 3 | 4 | 5' has unsafe 'as' type assertion
stack === 'lit-vite' && new App.Features.Lit(version as 3, next),

Check warning on line 30 in src/commands/init/index.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The 'version as 3' has unsafe 'as' type assertion
new App.Features.ZoomAt(),
new App.Features.OrderNodes(),
new App.Features.Dataflow(next),
Expand Down Expand Up @@ -56,12 +56,25 @@
readonly: {
from: 'default',
features: [...base, 'Readonly']
},
comments: {
from: 'default',
features: [...base, 'Comments']
},
history: {
from: 'default',
// Context menu provides Delete for nodes/connections in e2e
features: [...base, 'History', 'Context menu']
},
'comments-history': {
from: 'default',
features: [...base, 'Comments', 'History']
}
}
}

export function validate(stacks: string[], stackVersions: string[] | null): { error: string | null } {
const unknownStacks = stacks.filter(name => !stackNames.includes(name as App.AppStack))

Check warning on line 77 in src/commands/init/index.ts

View workflow job for this annotation

GitHub Actions / ci / ci

The 'name as App.AppStack' has unsafe 'as' type assertion

if (unknownStacks.length > 0) {
return { error: `Unknown stack names: ${unknownStacks.join(', ')}` }
Expand Down
15 changes: 11 additions & 4 deletions src/commands/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,24 @@ export async function validateTestRun(app: string, dist: string): Promise<{ erro
return { error: null }
}

const snapshotStack = 'react-vite'

export function validateSnapshotsUpdate(targetFixtures: typeof fixtures) {
const fixture = targetFixtures[0]
const numberOfFixtures = targetFixtures.length
const target = targets[0]
const target = targets.find(({ stack }) => stack === snapshotStack)

if (!target) {
return { error: `Snapshot stack "${snapshotStack}" is not configured` }
}

const latestVersion = target.versions[target.versions.length - 1]
const canUpdateSnashots = numberOfFixtures === 1
&& fixture.stack === target.stack
&& fixture.version === target.versions[target.versions.length - 1]
&& fixture.stack === snapshotStack
&& fixture.version === latestVersion

if (!canUpdateSnashots) {
return { error: 'You can update snapshots only for the latest version of React' }
return { error: `You can update snapshots only for the latest version of ${snapshotStack} (v${latestVersion})` }
}

return { error: null }
Expand Down
71 changes: 71 additions & 0 deletions src/tests/comments-history.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { expect, test } from '@playwright/test'

import {
editCommentViaContextMenu,
findInlineComment,
getCommentText,
move,
redo,
takeBeforeEach,
undo
} from './helper'

const INLINE_ORIGINAL = 'Inline comment — try Ctrl+Z after edit/delete'
const INLINE_UPDATED = 'Updated inline comment'

// Integration: Comments + History (comment actions in the undo stack)
test.describe('Comments + History', () => {
const { getContainer: _getContainer } = takeBeforeEach('?template=comments-history', 500, 500)

test('edit inline comment undo/redo', async ({ page }) => {
const inline = await findInlineComment(page)

expect(await getCommentText(inline)).toContain('Inline comment')

await editCommentViaContextMenu(page, inline, INLINE_UPDATED)
await page.waitForTimeout(300)

expect(await getCommentText(inline)).toBe(INLINE_UPDATED)
expect(await page.screenshot()).toMatchSnapshot('comment-inline-edited.png')

await undo(page)
await page.waitForTimeout(300)

expect(await getCommentText(inline)).toBe(INLINE_ORIGINAL)
expect(await page.screenshot()).toMatchSnapshot('comment-inline-edit-undone.png')

await redo(page)
await page.waitForTimeout(300)

expect(await getCommentText(inline)).toBe(INLINE_UPDATED)
expect(await page.screenshot()).toMatchSnapshot('comment-inline-edit-redone.png')
})

test('undo comment drag', async ({ page }) => {
const inline = await findInlineComment(page)
const before = await inline.boundingBox()

if (!before) throw new Error('inline comment box')

await move(page, inline, 60, 40)
await page.waitForTimeout(300)

const dragged = await inline.boundingBox()

if (!dragged) throw new Error('inline comment box after drag')

expect(dragged.x - before.x).toBeGreaterThan(40)
expect(await page.screenshot()).toMatchSnapshot('comment-inline-dragged-before-undo.png')

await undo(page)
await page.waitForTimeout(300)

const restored = await inline.boundingBox()

if (!restored) throw new Error('inline comment box after undo')

expect(restored.x).toBeCloseTo(before.x, 1)
expect(restored.y).toBeCloseTo(before.y, 1)
expect(await page.screenshot()).toMatchSnapshot('comment-inline-drag-undone.png')
})
})
81 changes: 81 additions & 0 deletions src/tests/comments.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { expect, test } from '@playwright/test'

import {
boundingBox,
findFrameComment,
findInlineComment,
getCommentText,
getGraphView,
isInside,
move,
takeBeforeEach,
toRect
} from './helper'

test.describe('Comments', () => {
const { getContainer } = takeBeforeEach('?template=comments', 500, 500)

test('seeded on load', async ({ page }) => {
const frame = await findFrameComment(page)
const inline = await findInlineComment(page)

expect(await getCommentText(frame)).toContain('Frame comment')
expect(await getCommentText(inline)).toContain('Inline comment')
expect(await page.locator('.frame-comment')).toHaveCount(1)

Check failure on line 24 in src/tests/comments.spec.ts

View workflow job for this annotation

GitHub Actions / ci / ci

Unexpected `await` of a non-Promise (non-"Thenable") value

Check failure on line 24 in src/tests/comments.spec.ts

View workflow job for this annotation

GitHub Actions / ci / ci

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
expect(await page.locator('.inline-comment')).toHaveCount(1)

Check failure on line 25 in src/tests/comments.spec.ts

View workflow job for this annotation

GitHub Actions / ci / ci

Unexpected `await` of a non-Promise (non-"Thenable") value

Check failure on line 25 in src/tests/comments.spec.ts

View workflow job for this annotation

GitHub Actions / ci / ci

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
expect(await page.screenshot()).toMatchSnapshot('comments-initial.png')
})

test('drag inline comment', async ({ page }) => {
const inline = await findInlineComment(page)
const { before, after } = await move(page, inline, 50, 30)

expect(after.x - before.x).toBeCloseTo(50, 1)
expect(after.y - before.y).toBeCloseTo(30, 1)
expect(await page.screenshot()).toMatchSnapshot('comment-inline-dragged.png')
})

test('drag frame comment moves linked nodes', async ({ page }) => {
const { findNodes } = await getGraphView(getContainer())
const [number1, number2] = await findNodes('Number')
const frame = await findFrameComment(page)
const dx = 40
const dy = 25

const before1 = await boundingBox(number1)
const before2 = await boundingBox(number2)

await move(page, frame, dx, dy)

const after1 = await boundingBox(number1)
const after2 = await boundingBox(number2)

expect(after1.x - before1.x).toBeCloseTo(dx, 5)
expect(after1.y - before1.y).toBeCloseTo(dy, 5)
expect(after2.x - before2.x).toBeCloseTo(dx, 5)
expect(after2.y - before2.y).toBeCloseTo(dy, 5)
expect(await page.screenshot()).toMatchSnapshot('comment-frame-dragged.png')
})

test('frame membership — drag node out of frame', async ({ page }) => {
const { findNodes } = await getGraphView(getContainer())
const frame = await findFrameComment(page)
const [numberNode] = await findNodes('Number')
const frameRect = toRect(await boundingBox(frame))
const nodeRectBefore = toRect(await boundingBox(numberNode))

expect(isInside(nodeRectBefore, frameRect)).toBe(true)

await move(page, numberNode, 250, 0, 'corner', {
async down() {
await page.mouse.down({ button: 'left' })
await page.waitForTimeout(1500)
}
})

const nodeRectAfter = toRect(await boundingBox(numberNode))

expect(isInside(nodeRectAfter, frameRect)).toBe(false)
expect(await page.screenshot()).toMatchSnapshot('comment-membership-out.png')
})
})
Loading
Loading