ci(editor): Run e2e tests in parallel and improve build caching (#5445)

* WIP: Cypress parallel CI run test

* Trigger action on branch push

* Change build artifacts path

* Make sure to checkout the repo for testing job

* Use Cypress action for installing

* Lock cypress action userd version

* Skip node install step since we're using cypress node16 container

* Let Cypress handle pnpm install

* Use setup-node action for caching pnpm

* Set CYPRESS_CACHE_FOLDER

* Set CYPRESS_CACHE_FOLDER

* Manually cache pnpm store

* Dont fix pnpm version

* Use caching action also in testing job

* Zip packages dist before uploading the artifacts and change caching key

* Use absolute build paths for zipping job

* Use zip command in action

* Use tar for zipping packages

* Debuggin directory ls

* Debugging caching of modules

* Attempt to fix permissions issue

* Porivde Cypress executable via `CYPRESS_RUN_BINARY`

* Cache /github/home

* Adjust caching keys

* Debug: search for cypress exec

* Debugging: List dirs

* Use pnpm install action to install node_modules

* Do not log /home/runner

* Use node_modules/.bin Cypress binary

* Use absolute path to nodue modules

* Run Cypress via custom command

* Try with patched cypress action

* Revert logging

* Manually specify cypress config file

* Use absolute paths

* Fix cypress config name

* Debug print cypress config

* Remove debugging, increase to 4 containers

* Increase amount of containers

* Add env-version matrix

* Replace node14 with node18 in testing matrix

* Remove debugging and add node 14

* Use just node14

* Use cypress:base and remove browser req

* Give more general timeouts

* Try with node16

* Change cache directive position

* Replace zip artifact upload with cache

* Cache full packages not just dist

* Test with variable inputs

* Add commit info message

* Remove wrongly commited code

* Allow WF API dispatch

* Try Chrome browser again for comparison

* Include Monaco in the build

* Make e2e workflow re-usable

* Comment out invalid reusable workflow args

* Use electron and add node 14 run

* Fix env arg

* Provide custom ci-build-id

* Refactor remaining e2e workflow to use reusable action

* Remove single matrix directive

* Refactor ci-pull-req

* Make lint job dependant on test jobs

* Disable debugging job

* Make containers dynamic

* Cleanup & install git for linting action

* Use regular buntu image for PR linting

* Debugging failing tests

* Remove fixed spec name

* Debug e2e env var

* Do not use realkeypress which crashes electron runner

* Debugging

* chore: remove console

* chore: remove console

* test: remove node 14 tests

* test: replace test branch with master

* test: use tests in current branch

* test: use relative path

* chore: clean up

* test: only trigger on approval

* ci: update test PR

* ci: use curr branch

* ci: only run 14 on schedule, not for slack command

* ci: only run test on approval

* ci: clean up branch, rename step

* ci: rename steps

* ci: clean up cancel

* ci: clean up env var

* ci: set var

* ci: use chromef

* ci: use electron

* chore: add console log

* chore: add console log

* ci: update to string

* ci: set all env options

* test: build

* ci: fix step issue

* Fix failing tests & upgrade to Cypress 12

* Allow WF dispatch of e2e reusable

* Fix wrong naming in e2e-tests workflow

* Redeploy

* Fix tests

* Fix NDV tests and remove skipping of webhooks execution tests

* Fix clipboard read command

* Fix execution failing tests

* Reset before each 15 and 3

* Fix flaky tests

* Cleanup and log envs

* Test fixes

* Default owner spec fixes

* Get rid of CYPRESS_RUN_ENV

* Increase amount of containers, cleanup and add mock for credentials test call

* Cleanup & fix PR tests unit tests

* Wait for WF to loade in sharing spec

* Do linting and unit tests first

* Use frozen lockfile

* Revert back ci pull request jobs order

* Refine credential input selector and move cy.waitForLoad to correct position in 15-scheduler spec

* test: build

* Wait for WF execution instead of arbitraty timeout in WF execution spec, change order of jobs for ci pull request

* Fix flaky 3-default owner spec and wait for execution list to load in 20-workflow-executions

* Use setup node action

* Remove caching for lint/unit tests

* Experiment with parallel test & lint on ci

* Provide cache key dynamically

* Run e2e in parallel on pr

* Only run node14 e2e on daily schedule

* Make sure to generate generate new ci-build-id on re-runs

* Remove debugging prints

* Address PR comments

* Rename custom onBeforeUnload handler

* Make sure 19-execution spec waits for wf to load properly before import fixtures

---------

Co-authored-by: Mutasem <mutdmour@gmail.com>
This commit is contained in:
OlegIvaniv 2023-03-02 16:50:21 +01:00 committed by GitHub
parent 5040fea93e
commit 0004dc7ee8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 528 additions and 356 deletions

View file

@ -1,27 +1,24 @@
name: Test Pull Requests
name: Build, unit/smoke test and lint branch
on: [pull_request]
jobs:
build:
install:
name: Install & Build
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
- uses: actions/checkout@v3
with:
repository: n8n-io/n8n
ref: ${{ inputs.branch }}
- uses: pnpm/action-setup@v2.2.4
- name: Use Node.js ${{ matrix.node-version }}
- name: Use Node.js 16
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
node-version: 16.x
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
@ -29,13 +26,74 @@ jobs:
- name: Build
run: pnpm build
- name: Cache build artifacts
uses: actions/cache@v3
with:
path: |
/github/home/.cache
/github/home/.pnpm-store
./node_modules
./packages
key: ${{ github.sha }}-base:16.18.1-test-lint
unit-test:
name: Unit tests
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v3
with:
repository: n8n-io/n8n
ref: ${{ inputs.branch }}
- name: Restore cached build artifacts
uses: actions/cache@v3
with:
path: |
/github/home/.cache
/github/home/.pnpm-store
./node_modules
./packages
key: ${{ github.sha }}-base:16.18.1-test-lint
- uses: pnpm/action-setup@v2.2.4
- name: Use Node.js 16
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: pnpm
- name: Test
run: pnpm test
- name: Test E2E
run: |
pnpm cypress:install
pnpm test:e2e:smoke
lint:
name: Lint changes
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v3
with:
repository: n8n-io/n8n
ref: ${{ inputs.branch }}
- name: Restore cached build artifacts
uses: actions/cache@v3
with:
path: |
/github/home/.cache
/github/home/.pnpm-store
./node_modules
./packages
key: ${{ github.sha }}-base:16.18.1-test-lint
- uses: pnpm/action-setup@v2.2.4
- name: Use Node.js 16
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: pnpm
- name: Fetch base branch for `git diff`
run: git fetch origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }}
@ -44,3 +102,18 @@ jobs:
env:
ESLINT_PLUGIN_DIFF_COMMIT: ${{ github.event.pull_request.base.ref }}
run: pnpm lint
smoke-test:
name: E2E [Electron/Node 16]
uses: ./.github/workflows/e2e-reusable.yml
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-e2e') }}
with:
branch: ${{ github.event.pull_request.base.ref }}
user: ${{ github.event.inputs.user || 'PR User' }}
spec: ${{ github.event.inputs.spec || 'e2e/0-smoke.cy.ts' }}
run-env: base:16.18.1
record: false
parallel: false
containers: '[1]'
secrets:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

150
.github/workflows/e2e-reusable.yml vendored Normal file
View file

@ -0,0 +1,150 @@
name: Reusable e2e workflow
on:
workflow_call:
inputs:
branch:
description: 'GitHub branch to test.'
required: false
type: string
default: 'master'
user:
description: 'User who kicked this off.'
required: false
type: string
default: 'schedule'
spec:
description: 'Specify specs.'
required: false
default: 'e2e/*'
type: string
run-env:
description: 'Node env version to run tests with.'
required: false
default: 'browsers:node16.18.0-chrome90-ff88'
type: string
cache-key:
description: 'Cache key for modules and build artifacts.'
required: false
default: ${{ github.sha }}-${{ inputs.run-env }}-e2e-modules
type: string
record:
description: 'Record test run.'
required: false
default: true
type: boolean
parallel:
description: 'Run tests in parallel.'
required: false
default: true
type: boolean
containers:
description: 'Number of containers to run tests in.'
required: false
default: '[1, 2, 3, 4, 5, 6, 7, 8]'
type: string
secrets:
CYPRESS_RECORD_KEY:
description: 'Cypress record key.'
required: true
jobs:
# single job that generates and outputs a common id
prepare:
runs-on: ubuntu-latest
outputs:
uuid: ${{ steps.uuid.outputs.value }}
steps:
- name: Generate unique ID 💎
id: uuid
# take the current commit + timestamp together
# the typical value would be something like
# "sha-5d3fe...35d3-time-1620841214"
run: echo "value=sha-$GITHUB_SHA-time-$(date +"%s")" >> $GITHUB_OUTPUT
install:
runs-on: ubuntu-latest
needs: ['prepare']
container:
image: cypress/${{ inputs.run-env }}
options: --user 1001
steps:
- uses: actions/checkout@v3
with:
repository: n8n-io/n8n
ref: ${{ inputs.branch }}
- name: Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
run_install: true
- name: Cache pnpm modules
uses: actions/cache@v3
with:
path: |
/github/home/.cache
/github/home/.pnpm-store
./node_modules
./packages
key: ${{ inputs.cache-key }}
- name: Cypress build
uses: cypress-io/github-action@v5
with:
# Disable running of tests within install job
runTests: false
install: false
build: pnpm build
- name: Cypress install
run: pnpm cypress:install
testing:
runs-on: ubuntu-latest
container:
image: cypress/${{ inputs.run-env }}
options: --user 1001
needs: ['prepare', 'install']
strategy:
fail-fast: false
matrix:
containers: ${{ fromJSON(inputs.containers) }}
steps:
- uses: actions/checkout@v3
with:
repository: n8n-io/n8n
ref: ${{ inputs.branch }}
- name: Setup pnpm
uses: pnpm/action-setup@v2.2.4
- name: Restore cached pnpm modules
uses: actions/cache@v3
with:
path: |
/github/home/.cache
/github/home/.pnpm-store
./node_modules
./packages
key: ${{ inputs.cache-key }}
- name: Cypress run
uses: cypress-io/github-action@v5
with:
install: false
start: pnpm start
wait-on: 'http://localhost:5678'
wait-on-timeout: 120 #
record: ${{ inputs.record }}
parallel: ${{ inputs.parallel }}
# We have to provide custom ci-build-id key to make sure that this workflow could be run multiple times
# in the same parent workflow
ci-build-id: ${{ needs.prepare.outputs.uuid }}
spec: "/__w/n8n/n8n/cypress/${{ inputs.spec }}"
config-file: /__w/n8n/n8n/cypress.config.js
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
E2E_TESTS: true
COMMIT_INFO_MESSAGE: 🌳 ${{ inputs.branch }} 🖥️ ${{ inputs.run-env }} 🤖 ${{ inputs.user }} 🗃️ ${{ inputs.spec }}

View file

@ -7,53 +7,28 @@ on:
- 'master'
jobs:
runTests:
name: 'Run E2E tests'
runs-on: ubuntu-latest
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-e2e') }}
# We disable this for now because cancelling runs makes the Cypress Cloud tests to hang.
# cancel-previous-runs:
# runs-on: ubuntu-latest
# name: 'Cancel previous e2e test runs'
# strategy:
# matrix:
# node-version: [16.x]
timeout-minutes: 30
# steps:
# - name: 'Cancel previous runs'
# uses: styfle/cancel-workflow-action@0.9.0
# with:
# access_token: ${{ github.token }}
strategy:
matrix:
node-version: [16.x]
steps:
- name: 'Cancel previous runs'
uses: styfle/cancel-workflow-action@0.9.0
with:
access_token: ${{ github.token }}
- name: 'Cancel if PR is not approved'
if: github.event.review.state != 'approved'
uses: andymckay/cancel-action@0.2
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Test E2E
run: |
pnpm cypress:install
pnpm test:e2e:all
- name: Upload artifacts
uses: actions/upload-artifact@v3
if: failure()
with:
name: cypress-screenshots
path: |
cypress/screenshots
retention-days: 1
run-e2e-tests:
name: E2E [Electron/Node 16]
uses: ./.github/workflows/e2e-reusable.yml
if: ${{ github.event.review.state == 'approved' && !contains(github.event.pull_request.labels.*.name, 'skip-e2e') }}
with:
branch: ${{ github.event.pull_request.head.ref }}
user: ${{ github.event.pull_request.user.login || 'PR User' }}
spec: 'e2e/*'
run-env: base:16.18.1
secrets:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

View file

@ -24,54 +24,46 @@ on:
default: ''
jobs:
build:
calls-start-url:
name: Calls start URL
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
node-version: [14.x, 16.x]
if: ${{ github.event.inputs.start-url != '' }}
steps:
- name: Call Start URL - optionally
- name: Calls start URL
run: |
[[ "${{github.event.inputs.start-url}}" != "" ]] && curl -v -X POST -d 'url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' ${{github.event.inputs.start-url}} || echo ""
shell: bash
- uses: actions/checkout@v3
with:
repository: ${{ github.event.inputs.repository || 'n8n-io/n8n' }}
ref: ${{ github.event.inputs.branch || 'master' }}
run-e2e-tests:
name: E2E [Electron/Node 16]
uses: ./.github/workflows/e2e-reusable.yml
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-e2e') }}
with:
branch: ${{ github.event.inputs.branch || 'master' }}
user: ${{ github.event.inputs.user || 'PR User' }}
spec: ${{ github.event.inputs.spec || 'e2e/*' }}
run-env: base:16.18.1
secrets:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
- uses: pnpm/action-setup@v2.2.4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Test E2E
run: |
pnpm cypress:install
pnpm test:e2e:all
- name: Upload artifacts
uses: actions/upload-artifact@v3
if: failure()
with:
name: cypress-screenshots
path: |
cypress/screenshots
retention-days: 1
run-e2e-tests-node-14:
name: E2E [Electron/Node 14]
uses: ./.github/workflows/e2e-reusable.yml
if: ${{ github.event_name == 'schedule' }}
with:
branch: ${{ github.event.inputs.branch || 'master' }}
user: ${{ github.event.inputs.user || 'schedule' }}
spec: ${{ github.event.inputs.spec || 'e2e/*' }}
run-env: base:14.21.1
secrets:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
calls-success-url-notify:
name: Calls success URL and notifies
runs-on: ubuntu-latest
needs: [run-e2e-tests, run-e2e-tests-node-14]
if: ${{ github.event.inputs.success-url != '' }}
steps:
- name: Notify Slack on failure
uses: act10ns/slack@v2.0.0
if: failure()

View file

@ -4,29 +4,39 @@ const { defineConfig } = require('cypress');
const BASE_URL = 'http://localhost:5678';
module.exports = defineConfig({
projectId: "5hbsdn",
retries: {
openMode: 0,
runMode: 3,
runMode: 2,
},
defaultCommandTimeout: 10000,
requestTimeout: 12000,
e2e: {
baseUrl: BASE_URL,
video: false,
video: true,
screenshotOnRunFailure: true,
experimentalSessionAndOrigin: true,
experimentalInteractiveRunEvents: true,
experimentalSessionAndOrigin: true,
setupNodeEvents(on, config) {
on('task', {
reset: () => fetch(BASE_URL + '/e2e/db/reset', { method: 'POST' }),
'setup-owner': (payload) =>
fetch(BASE_URL + '/e2e/db/setup-owner', {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' },
}),
'setup-owner': (payload) => {
try {
return fetch(BASE_URL + '/e2e/db/setup-owner', {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' },
})
} catch (error) {
console.error("setup-owner failed with: ", error)
return null
}
},
'enable-feature': (feature) =>
fetch(BASE_URL + `/e2e/enable-feature/${feature}`, { method: 'POST' }),
});
},
},
});

View file

@ -63,11 +63,9 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters
.getDestinationNameInput()
.click()
.clear()
.type('Destination 0');
settingsLogStreamingPage.getters.getDestinationNameInput().click()
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 0');
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
cy.wait(100);
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
@ -88,11 +86,8 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters
.getDestinationNameInput()
.click()
.clear()
.type('Destination 1');
settingsLogStreamingPage.getters.getDestinationNameInput().click()
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 1');
settingsLogStreamingPage.getters.getDestinationSaveButton().should('not.have.attr', 'disabled');
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
cy.wait(100);

View file

@ -17,6 +17,7 @@ describe('Inline expression editor', () => {
});
it('should resolve primitive resolvables', () => {
WorkflowPage.getters.inlineExpressionEditorInput().clear();
WorkflowPage.getters.inlineExpressionEditorInput().type('{{');
WorkflowPage.getters.inlineExpressionEditorInput().type('1 + 2');
WorkflowPage.getters.inlineExpressionEditorOutput().contains(/^3$/);
@ -35,6 +36,7 @@ describe('Inline expression editor', () => {
});
it('should resolve object resolvables', () => {
WorkflowPage.getters.inlineExpressionEditorInput().clear();
WorkflowPage.getters.inlineExpressionEditorInput().type('{{');
WorkflowPage.getters
.inlineExpressionEditorInput()

View file

@ -16,7 +16,7 @@ describe('Data transformation expressions', () => {
cy.window()
// @ts-ignore
.then(
(win) => win.onBeforeUnload && win.removeEventListener('beforeunload', win.onBeforeUnload),
(win) => win.onBeforeUnloadNodeView && win.removeEventListener('beforeunload', win.onBeforeUnloadNodeView),
);
});
@ -80,19 +80,18 @@ describe('Data transformation expressions', () => {
ndv.getters.outputDataContainer().contains(output);
});
it('$json + native array methods', () => {
it('$json + native array access', () => {
wf.actions.addInitialNodeToCanvas('Schedule Trigger', { keepNdvOpen: true });
ndv.actions.setPinnedData([{ myArr: [1, 2, 3] }]);
ndv.actions.close();
addSet();
const input = '{{$json.myArr.includes(1) + " " + $json.myArr.at(2)';
const input = '{{$json.myArr.includes(1) + " " + $json.myArr[2]';
const output = 'true 3';
ndv.getters.inlineExpressionEditorInput().clear().type(input);
ndv.actions.execute();
ndv.getters.outputDataContainer().should('be.visible');
ndv.getters.outputDataContainer().contains(output);
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist')
ndv.getters.outputDataContainer().find('[class*=value_]').should('contain', output);
});
it('$json + n8n array methods', () => {
@ -106,7 +105,8 @@ describe('Data transformation expressions', () => {
ndv.getters.inlineExpressionEditorInput().clear().type(input);
ndv.actions.execute();
ndv.getters.outputDataContainer().should('be.visible').contains(output);
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist')
ndv.getters.outputDataContainer().find('[class*=value_]').should('contain', output);
});
});

View file

@ -21,7 +21,7 @@ describe('Data mapping', () => {
cy.window()
// @ts-ignore
.then(
(win) => win.onBeforeUnload && win.removeEventListener('beforeunload', win.onBeforeUnload),
(win) => win.onBeforeUnloadNodeView && win.removeEventListener('beforeunload', win.onBeforeUnloadNodeView),
);
});

View file

@ -5,15 +5,15 @@ const workflowPage = new WorkflowPage();
const ndv = new NDV();
describe('Schedule Trigger node', async () => {
before(() => {
beforeEach(() => {
cy.resetAll();
cy.skipSetup();
cy.visit(workflowsPage.url);
});
it('should execute and return the execution timestamp', () => {
cy.visit(workflowsPage.url);
workflowsPage.actions.createWorkflowFromCard();
cy.waitForLoad();
workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger');
workflowPage.actions.openNode('Schedule Trigger');
ndv.actions.execute();
@ -22,9 +22,8 @@ describe('Schedule Trigger node', async () => {
});
it('should execute once per second when activated', () => {
cy.visit(workflowsPage.url);
workflowsPage.actions.createWorkflowFromCard();
cy.waitForLoad();
workflowPage.actions.renameWorkflow('Schedule Trigger Workflow');
workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger');
workflowPage.actions.openNode('Schedule Trigger');

View file

@ -103,7 +103,7 @@ describe('Webhook Trigger node', async () => {
cy.window()
// @ts-ignore
.then(
(win) => win.onBeforeUnload && win.removeEventListener('beforeunload', win.onBeforeUnload),
(win) => win.onBeforeUnloadNodeView && win.removeEventListener('beforeunload', win.onBeforeUnloadNodeView),
);
});

View file

@ -82,6 +82,7 @@ describe('Sharing', () => {
cy.visit(workflowsPage.url);
workflowsPage.getters.newWorkflowButtonCard().click();
cy.waitForLoad();
workflowPage.actions.setWorkflowName('Workflow W1');
workflowPage.actions.addInitialNodeToCanvas('Manual Trigger');
workflowPage.actions.addNodeToCanvas('Notion', true, true);

View file

@ -5,12 +5,9 @@ const wf = new WorkflowPage();
const TEST_TAGS = ['Tag 1', 'Tag 2', 'Tag 3'];
describe('Workflow tags', () => {
before(() => {
beforeEach(() => {
cy.resetAll();
cy.skipSetup();
});
beforeEach(() => {
wf.actions.visit();
cy.waitForLoad();
});

View file

@ -6,18 +6,15 @@ const workflowPage = new WorkflowPageClass();
const ndv = new NDV();
describe('Execution', () => {
before(() => {
beforeEach(() => {
cy.resetAll();
cy.skipSetup();
});
beforeEach(() => {
cy.visit('/');
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.waitForLoad();
});
it('should test manual workflow', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Manual_wait_set.json', `Manual wait set ${uuid()}`);
// Check workflow buttons
@ -40,14 +37,14 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
@ -58,15 +55,15 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
// Clear execution data
workflowPage.getters.clearExecutionDataButton().should('be.visible');
@ -78,8 +75,6 @@ describe('Execution', () => {
});
it('should test manual workflow stop', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Manual_wait_set.json', `Manual wait set ${uuid()}`);
// Check workflow buttons
@ -102,14 +97,14 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
@ -121,11 +116,11 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt').should('not.visible'));
@ -143,8 +138,6 @@ describe('Execution', () => {
});
it('should test webhook workflow', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Webhook_wait_set.json', `Webhook wait set ${uuid()}`);
// Check workflow buttons
@ -184,14 +177,14 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
@ -202,15 +195,15 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
// Clear execution data
workflowPage.getters.clearExecutionDataButton().should('be.visible');
@ -222,8 +215,6 @@ describe('Execution', () => {
});
it('should test webhook workflow stop', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Webhook_wait_set.json', `Webhook wait set ${uuid()}`);
// Check workflow buttons
@ -259,34 +250,33 @@ describe('Execution', () => {
});
});
workflowPage.getters.stopExecutionButton().click();
// Check canvas nodes after 1st step (workflow passed the manual trigger node
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
cy.wait(1000);
workflowPage.getters.stopExecutionWaitingForWebhookButton().click();
// Check canvas nodes after workflow stopped
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt').should('not.visible'));

View file

@ -32,6 +32,14 @@ describe('Credentials', () => {
before(() => {
cy.resetAll();
cy.setup({ email, firstName, lastName, password });
// Always intercept the request to test credentials and return a success
cy.intercept('POST', '/rest/credentials/test', {
statusCode: 200,
body: {
data: { status: 'success', message: 'Tested successfully' },
}
});
});
beforeEach(() => {
@ -53,7 +61,6 @@ describe('Credentials', () => {
credentialsModal.getters.newCredentialTypeOption('Notion API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.connectionParameter('API Key').type('1234567890');
credentialsModal.actions.setName('My awesome Notion account');
@ -71,7 +78,7 @@ describe('Credentials', () => {
credentialsModal.getters.newCredentialTypeOption('Airtable API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.editCredentialModal().should('be.visible');
credentialsModal.getters.connectionParameter('API Key').type('1234567890');
credentialsModal.actions.setName('Airtable Account');

View file

@ -19,7 +19,13 @@ describe('Current Workflow Executions', () => {
});
it('should render executions tab correctly', () => {
cy.waitForLoad();
cy.intercept('GET', '/rest/executions?filter=*').as('getExecutions');
cy.intercept('GET', '/rest/executions-current?filter=*').as('getCurrentExecutions');
executionsTab.actions.switchToExecutionsTab();
cy.wait(['@getExecutions', '@getCurrentExecutions']);
executionsTab.getters.executionListItems().should('have.length', 11);
executionsTab.getters.successfulExecutionListItems().should('have.length', 9);
executionsTab.getters.failedExecutionListItems().should('have.length', 2);
@ -40,6 +46,4 @@ const createMockExecutions = () => {
// Then add some more successful ones
executionsTab.actions.toggleNodeEnabled('Error');
executionsTab.actions.createManualExecutions(4);
executionsTab.actions.switchToExecutionsTab();
cy.waitForLoad();
};

View file

@ -34,26 +34,19 @@ const firstName = randFirstName();
const lastName = randLastName();
describe('Default owner', () => {
before(() => {
cy.resetAll();
});
beforeEach(() => {
cy.visit('/');
});
it('should skip owner setup', () => {
cy.skipSetup();
});
it('should be able to create workflows', () => {
cy.resetAll();
cy.skipSetup();
cy.visit('/');
workflowsPage.getters.newWorkflowButtonCard().should('be.visible');
workflowsPage.getters.newWorkflowButtonCard().click();
cy.waitForLoad();
cy.createFixtureWorkflow('Test_workflow_1.json', `Test workflow`);
// reload page, ensure owner still has access
cy.reload();
cy.waitForLoad();
workflowPage.getters.workflowNameInput().should('contain.value', 'Test workflow');
});
@ -82,6 +75,7 @@ describe('Default owner', () => {
});
it('should be able to setup UM from settings', () => {
cy.visit('/');
mainSidebar.getters.settings().should('be.visible');
mainSidebar.actions.goToSettings();
cy.url().should('include', settingsUsagePage.url);

View file

@ -1,13 +1,7 @@
import { NodeCreator } from '../pages/features/node-creator';
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
import { randFirstName, randLastName } from '@ngneat/falso';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV } from '../pages/ndv';
const email = DEFAULT_USER_EMAIL;
const password = DEFAULT_USER_PASSWORD;
const firstName = randFirstName();
const lastName = randLastName();
const nodeCreatorFeature = new NodeCreator();
const WorkflowPage = new WorkflowPageClass();
const NDVModal = new NDV();
@ -15,12 +9,10 @@ const NDVModal = new NDV();
describe('Node Creator', () => {
before(() => {
cy.resetAll();
cy.setup({ email, firstName, lastName, password });
cy.skipSetup();
});
beforeEach(() => {
cy.signin({ email, password });
cy.visit(nodeCreatorFeature.url);
cy.waitForLoad();
});
@ -105,58 +97,52 @@ describe('Node Creator', () => {
it('should search through actions and confirm added action', () => {
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('ftp');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{rightarrow}');
nodeCreatorFeature.getters.searchBar().find('input').type('{rightarrow}');
nodeCreatorFeature.getters.activeSubcategory().should('have.text', 'FTP');
nodeCreatorFeature.getters.searchBar().find('input').clear().type('file');
// Navigate to rename action which should be the 4th item
nodeCreatorFeature.getters.searchBar().find('input').realPress('{downarrow}');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{downarrow}');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{downarrow}');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{rightarrow}');
nodeCreatorFeature.getters.searchBar().find('input').type('{downarrow} {downarrow} {downarrow} {rightarrow}');
NDVModal.getters.parameterInput('operation').should('contain.text', 'Rename');
})
it('should render and select community node', () => {
cy.intercept('GET', '/types/nodes.json').as('nodesIntercept');
cy.wait('@nodesIntercept').then(() => {
const customNode = 'E2E Node';
const customNode = 'E2E Node';
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type(customNode);
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type(customNode);
nodeCreatorFeature.getters
.getCreatorItem(customNode)
.findChildByTestId('node-creator-item-tooltip')
.should('exist');
nodeCreatorFeature.actions.selectNode(customNode);
nodeCreatorFeature.getters
.getCreatorItem(customNode)
.findChildByTestId('node-creator-item-tooltip')
.should('exist');
nodeCreatorFeature.actions.selectNode(customNode);
// TODO: Replace once we have canvas feature utils
cy.get('.data-display .node-name').contains(customNode).should('exist');
// TODO: Replace once we have canvas feature utils
cy.get('.data-display .node-name').contains(customNode).should('exist');
const nodeParameters = () => cy.getByTestId('node-parameters');
const firstParameter = () => nodeParameters().find('.parameter-item').eq(0);
const secondParameter = () => nodeParameters().find('.parameter-item').eq(1);
const nodeParameters = () => cy.getByTestId('node-parameters');
const firstParameter = () => nodeParameters().find('.parameter-item').eq(0);
const secondParameter = () => nodeParameters().find('.parameter-item').eq(1);
// Check correct fields are rendered
nodeParameters().should('exist');
// Test property text input
firstParameter().contains('Test property').should('exist');
firstParameter().find('input.el-input__inner').should('have.value', 'Some default');
// Resource select input
secondParameter().find('label').contains('Resource').should('exist');
secondParameter().find('input.el-input__inner').should('have.value', 'option2');
secondParameter().find('.el-select').click();
secondParameter().find('.el-select-dropdown__list').should('exist');
// Check if all options are rendered and select the fourth one
secondParameter().find('.el-select-dropdown__list').children().should('have.length', 4);
secondParameter()
.find('.el-select-dropdown__list')
.children()
.eq(3)
.contains('option4')
.should('exist')
.click();
secondParameter().find('input.el-input__inner').should('have.value', 'option4');
});
// Check correct fields are rendered
nodeParameters().should('exist');
// Test property text input
firstParameter().contains('Test property').should('exist');
firstParameter().find('input.el-input__inner').should('have.value', 'Some default');
// Resource select input
secondParameter().find('label').contains('Resource').should('exist');
secondParameter().find('input.el-input__inner').should('have.value', 'option2');
secondParameter().find('.el-select').click();
secondParameter().find('.el-select-dropdown__list').should('exist');
// Check if all options are rendered and select the fourth one
secondParameter().find('.el-select-dropdown__list').children().should('have.length', 4);
secondParameter()
.find('.el-select-dropdown__list')
.children()
.eq(3)
.contains('option4')
.should('exist')
.click();
secondParameter().find('input.el-input__inner').should('have.value', 'option4');
});
});

View file

@ -1,22 +1,19 @@
import { WorkflowsPage, WorkflowPage, NDV } from '../pages';
import { WorkflowPage, NDV } from '../pages';
import { v4 as uuid } from 'uuid';
const workflowsPage = new WorkflowsPage();
const workflowPage = new WorkflowPage();
const ndv = new NDV();
describe('NDV', () => {
before(() => {
cy.resetAll();
cy.skipSetup();
});
beforeEach(() => {
workflowsPage.actions.createWorkflowFromCard();
cy.resetAll();
cy.skipSetup();
cy.visit(workflowPage.url)
cy.waitForLoad();
workflowPage.actions.renameWorkflow(uuid());
workflowPage.actions.saveWorkflowOnButtonClick();
});
it('should show up when double clicked on a node and close when Back to canvas clicked', () => {
workflowPage.actions.addInitialNodeToCanvas('Manual');
workflowPage.getters.canvasNodes().first().dblclick();
@ -52,11 +49,12 @@ describe('NDV', () => {
workflowPage.getters.canvasNodes().last().dblclick();
ndv.getters.inputSelect().click();
ndv.getters.inputOption().last().click();
ndv.getters.inputDataContainer().find('[class*=schema_]').should('exist')
ndv.getters.inputDataContainer().should('contain', 'start');
});
it('should show correct validation state for resource locator params', () => {
workflowPage.actions.addNodeToCanvas('Typeform', true, false);
workflowPage.actions.addNodeToCanvas('Typeform', true, true);
ndv.getters.container().should('be.visible');
cy.get('.has-issues').should('have.length', 0);
cy.get('[class*=hasIssues]').should('have.length', 0);

View file

@ -112,6 +112,9 @@ describe('Workflow Actions', () => {
});
it('should update workflow settings', () => {
cy.resetAll();
cy.skipSetup();
WorkflowPage.actions.visit();
// Open settings dialog
WorkflowPage.actions.saveWorkflowOnButtonClick();
WorkflowPage.getters.workflowMenu().should('be.visible');

View file

@ -5,7 +5,7 @@ export class CredentialsPage extends BasePage {
getters = {
emptyListCreateCredentialButton: () => cy.getByTestId('empty-resources-list').find('button'),
createCredentialButton: () => cy.getByTestId('resources-list-add'),
searchInput: () => cy.getByTestId('resources-list-search'),
searchInput: () => cy.getByTestId('resources-list-search').find('input'),
emptyList: () => cy.getByTestId('resources-list-empty'),
credentialCards: () => cy.getByTestId('resources-list-item'),
credentialCard: (credentialName: string) =>

View file

@ -12,9 +12,7 @@ export class CredentialsModal extends BasePage {
connectionParameter: (fieldName: string) =>
this.getters
.connectionParameters()
.contains(fieldName)
.parents('[data-test-id="credential-connection-parameter"]')
.find('.n8n-input input'),
.find(`:contains('${fieldName}') .n8n-input input`),
name: () => cy.getByTestId('credential-name'),
nameInput: () => cy.getByTestId('credential-name').find('input'),
// Saving of the credentials takes a while on the CI so we need to increase the timeout
@ -45,10 +43,6 @@ export class CredentialsModal extends BasePage {
},
save: (test = false) => {
cy.intercept('POST', '/rest/credentials').as('saveCredential');
if (test) {
cy.intercept('POST', '/rest/credentials/test').as('testCredential');
}
this.getters.saveButton().click();
cy.wait('@saveCredential');

View file

@ -26,8 +26,9 @@ export class WorkflowExecutionsTab extends BasePage {
},
createManualExecutions: (count: number) => {
for (let i=0; i<count; i++) {
cy.intercept('POST', '/rest/workflows/run').as('workflowExecution');
workflowPage.actions.executeWorkflow();
cy.wait(300);
cy.wait('@workflowExecution');
}
},
switchToExecutionsTab: () => {

View file

@ -44,7 +44,7 @@ export class WorkflowPage extends BasePage {
firstStepButton: () => cy.getByTestId('canvas-add-button'),
isWorkflowSaved: () => this.getters.saveButton().should('match', 'span'), // In Element UI, disabled button turn into spans 🤷‍♂️
isWorkflowActivated: () => this.getters.activatorSwitch().should('have.class', 'is-checked'),
expressionModalInput: () => cy.getByTestId('expression-modal-input'),
expressionModalInput: () => cy.getByTestId('expression-modal-input').find('[role=textbox]'),
expressionModalOutput: () => cy.getByTestId('expression-modal-output'),
nodeViewRoot: () => cy.getByTestId('node-view-root'),
@ -84,7 +84,7 @@ export class WorkflowPage extends BasePage {
duplicateWorkflowModal: () => cy.getByTestId('duplicate-modal'),
nodeViewBackground: () => cy.getByTestId('node-view-background'),
nodeView: () => cy.getByTestId('node-view'),
inlineExpressionEditorInput: () => cy.getByTestId('inline-expression-editor-input'),
inlineExpressionEditorInput: () => cy.getByTestId('inline-expression-editor-input').find('[role=textbox]'),
inlineExpressionEditorOutput: () => cy.getByTestId('inline-expression-editor-output'),
zoomInButton: () => cy.getByTestId('zoom-in-button'),
zoomOutButton: () => cy.getByTestId('zoom-out-button'),
@ -181,8 +181,10 @@ export class WorkflowPage extends BasePage {
this.getters.workflowNameInput().clear().type(name).type('{enter}');
},
activateWorkflow: () => {
cy.intercept('PATCH', '/rest/workflows/*').as('activateWorkflow');
this.getters.activatorSwitch().find('input').first().should('be.enabled');
this.getters.activatorSwitch().click();
cy.wait('@activateWorkflow');
cy.get('body').type('{esc}');
},
renameWorkflow: (newName: string) => {

View file

@ -5,7 +5,7 @@ export class WorkflowsPage extends BasePage {
getters = {
newWorkflowButtonCard: () => cy.getByTestId('new-workflow-card'),
newWorkflowTemplateCard: () => cy.getByTestId('new-workflow-template-card'),
searchBar: () => cy.getByTestId('resources-list-search'),
searchBar: () => cy.getByTestId('resources-list-search').find('input'),
createWorkflowButton: () => cy.getByTestId('resources-list-add'),
workflowCards: () => cy.getByTestId('resources-list-item'),
workflowCard: (workflowName: string) =>

View file

@ -206,9 +206,8 @@ Cypress.Commands.add('grantBrowserPermissions', (...permissions: string[]) => {
);
}
});
Cypress.Commands.add('readClipboard', () =>
cy.window().its('navigator.clipboard').invoke('readText'),
);
Cypress.Commands.add('readClipboard', () => cy.window().then(win => win.navigator.clipboard.readText()))
Cypress.Commands.add('paste', { prevSubject: true }, (selector, pastePayload) => {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event

View file

@ -42,7 +42,7 @@
"@types/jest": "^29.2.2",
"@types/supertest": "^2.0.12",
"cross-env": "^7.0.3",
"cypress": "^10.0.3",
"cypress": "^12.7.0",
"cypress-real-events": "^1.7.6",
"jest": "^29.4.2",
"jest-environment-jsdom": "^29.4.2",

View file

@ -12,6 +12,7 @@ export const inProduction = NODE_ENV === 'production';
export const inDevelopment = !NODE_ENV || NODE_ENV === 'development';
export const inTest = NODE_ENV === 'test';
export const inE2ETests = E2E_TESTS === 'true';
export const CUSTOM_API_CALL_NAME = 'Custom API Call';
export const CUSTOM_API_CALL_KEY = '__CUSTOM_API_CALL__';

View file

@ -447,7 +447,10 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
},
methods: {
setWidth() {
this.width = (this.$refs.container as HTMLElement).offsetWidth;
const containerRef = this.$refs.container as HTMLElement;
if (containerRef) {
this.width = containerRef?.offsetWidth;
}
},
getLinkAlt(entity: string) {
if (this.selectedMode === 'list' && entity) {

View file

@ -2594,7 +2594,7 @@ export default mixins(
// allow to be overriden in e2e tests
// @ts-ignore
window.onBeforeUnload = (e) => {
window.onBeforeUnloadNodeView = (e) => {
if (this.isDemo) {
return;
} else if (this.uiStore.stateIsDirty) {
@ -2608,7 +2608,7 @@ export default mixins(
return;
}
};
window.addEventListener('beforeunload', window.onBeforeUnload);
window.addEventListener('beforeunload', window.onBeforeUnloadNodeView);
},
getOutputEndpointUUID(nodeName: string, index: number): string | null {
const node = this.workflowsStore.getNodeByName(nodeName);

View file

@ -34,7 +34,7 @@ importers:
'@types/jest': ^29.2.2
'@types/supertest': ^2.0.12
cross-env: ^7.0.3
cypress: ^10.0.3
cypress: ^12.7.0
cypress-real-events: ^1.7.6
jest: ^29.4.2
jest-environment-jsdom: ^29.4.2
@ -60,12 +60,12 @@ importers:
'@types/jest': 29.2.2
'@types/supertest': 2.0.12
cross-env: 7.0.3
cypress: 10.11.0
cypress-real-events: 1.7.6_cypress@10.11.0
cypress: 12.7.0
cypress-real-events: 1.7.6_cypress@12.7.0
jest: 29.4.2
jest-environment-jsdom: 29.4.2
jest-mock: 29.4.2
jest-mock-extended: 3.0.1_47mstovy2thvxzoe7ouhdvjexm
jest-mock-extended: 3.0.1_gelezmms3va3pnkofxaadhcvma
nock: 13.2.9
node-fetch: 2.6.7
p-limit: 3.1.0
@ -74,8 +74,8 @@ importers:
run-script-os: 1.1.6
start-server-and-test: 1.14.0
supertest: 6.3.3
ts-jest: 29.0.5_pa4ebk5usulsg7iw3zwjv5figy
tsc-watch: 6.0.0_typescript@4.9.4
ts-jest: 29.0.5_zgilbyuumz7xbrerspmrtjuxsi
tsc-watch: 6.0.0_typescript@4.9.5
turbo: 1.7.4
packages/@n8n_io/eslint-config:
@ -95,9 +95,9 @@ importers:
eslint-plugin-vue: ~7.17
devDependencies:
'@types/eslint': 8.4.6
'@typescript-eslint/eslint-plugin': 5.45.0_wke4plxjew2ogjxrdwvzd2srfq
'@typescript-eslint/parser': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@vue/eslint-config-typescript': 8.0.0_foaxzhaputljbcoeiwudem25oq
'@typescript-eslint/eslint-plugin': 5.45.0_nasf2kpz3oxiofoztaiw65ixem
'@typescript-eslint/parser': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
'@vue/eslint-config-typescript': 8.0.0_tzuopv2z7r6hmaghrrdryxy3qq
eslint: 8.28.0
eslint-config-airbnb-typescript: 17.0.0_twozqnrpw2n42bn4rzkw5rgv4m
eslint-config-prettier: 8.5.0_eslint@8.28.0
@ -337,7 +337,7 @@ importers:
sse-channel: 4.0.0
swagger-ui-express: 4.5.0_express@4.18.2
syslog-client: 1.1.1
typedi: 0.10.0
typedi: 0.10.0_syy565ld7euwcedfbmx53j2qc4
typeorm: 0.3.12_pgelcv6ef3switkrteavpif3pq
uuid: 8.3.2
validator: 13.7.0
@ -391,7 +391,7 @@ importers:
mock-jwks: 1.0.9_nock@13.2.9
nodemon: 2.0.20
run-script-os: 1.1.6
ts-essentials: 7.0.3_typescript@4.9.4
ts-essentials: 7.0.3_typescript@4.9.5
tsc-alias: 1.8.2
tsconfig-paths: 4.1.2
@ -520,7 +520,7 @@ importers:
'@storybook/addon-links': 7.0.0-beta.46_6l5554ty5ajsajah6yazvrjhoe
'@storybook/addon-postcss': 3.0.0-alpha.1_webpack@5.75.0
'@storybook/vue': 7.0.0-beta.46_wp7tvu3eu4pbkovl2pyk3t6dzu
'@storybook/vue-webpack5': 7.0.0-beta.46_kqbjeyqrxfaciuxblodnlqbkgm
'@storybook/vue-webpack5': 7.0.0-beta.46_6qmhhfx7j6nt5tk6ratxcrskc4
'@testing-library/jest-dom': 5.16.5
'@testing-library/vue': 5.8.3_rhqkolmkwunxzlyyxxsuwaiuri
'@types/markdown-it': 12.2.3
@ -545,7 +545,7 @@ importers:
vue-loader: 15.10.1_eo5mtzohqv75mh6aooqyrh42dy
vue-property-decorator: 9.1.2_jtyyyychrtcflhl7vfprhmeb3y
vue-template-compiler: 2.7.14
vue-tsc: 1.0.24_typescript@4.9.4
vue-tsc: 1.0.24_typescript@4.9.5
packages/editor-ui:
specifiers:
@ -664,7 +664,7 @@ importers:
n8n-design-system: link:../design-system
n8n-workflow: link:../workflow
normalize-wheel: 1.0.1
pinia: 2.0.23_vj744rb3neneiaeb3oalctaenu
pinia: 2.0.23_hwpzsh6pnvsm3pjf2zi526hnzq
prettier: 2.8.3
prismjs: 1.29.0
stream-browserify: 3.0.0
@ -710,7 +710,7 @@ importers:
vite: 4.0.4_sass@1.55.0+terser@5.16.1
vite-plugin-monaco-editor: 1.1.0_monaco-editor@0.33.0
vitest: 0.28.4_sass@1.55.0+terser@5.16.1
vue-tsc: 1.0.24_typescript@4.9.4
vue-tsc: 1.0.24_typescript@4.9.5
packages/node-dev:
specifiers:
@ -1082,7 +1082,7 @@ importers:
'@types/tmp': 0.2.3
'@types/uuid': 8.3.4
'@types/xml2js': 0.4.11
eslint-plugin-n8n-nodes-base: 1.12.0_wy4udjehnvkneqnogzx5kughki
eslint-plugin-n8n-nodes-base: 1.12.0_pku7h6lsbnh7tcsfjudlqd5qce
gulp: 4.0.2
n8n-workflow: link:../workflow
@ -3983,7 +3983,7 @@ packages:
peerDependencies:
pinia: '>=2.0.19'
dependencies:
pinia: 2.0.23_vj744rb3neneiaeb3oalctaenu
pinia: 2.0.23_hwpzsh6pnvsm3pjf2zi526hnzq
vue-demi: 0.13.11_vue@2.7.14
transitivePeerDependencies:
- '@vue/composition-api'
@ -4557,7 +4557,7 @@ packages:
- supports-color
dev: true
/@storybook/builder-webpack5/7.0.0-beta.46_vsjsuvw2laeoxumlaes6yduxsu:
/@storybook/builder-webpack5/7.0.0-beta.46_lyfnfac7rmzfleuimsdvcn3dv4:
resolution: {integrity: sha512-1pvo9IDlz836hiDFmALVttQxw4ehSd3UEhE6Yz0B+TMl4cAQuSRWze8w2sI474tiHtGeKGRoIIWmH5hSVQvFrQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
@ -4595,7 +4595,7 @@ packages:
case-sensitive-paths-webpack-plugin: 2.4.0
css-loader: 6.7.3_webpack@5.75.0
express: 4.18.2
fork-ts-checker-webpack-plugin: 6.5.2_oidmngyddw6azfqg3taanyywde
fork-ts-checker-webpack-plugin: 6.5.2_3vu26w62dupooczhvlkrwvyfsa
fs-extra: 11.1.0
html-webpack-plugin: 5.5.0_webpack@5.75.0
path-browserify: 1.0.1
@ -4607,7 +4607,7 @@ packages:
style-loader: 3.3.1_webpack@5.75.0
terser-webpack-plugin: 5.3.6_htvmhiqynazf46fjrszipnqp7a
ts-dedent: 2.2.0
typescript: 4.9.4
typescript: 4.9.5
util: 0.12.5
util-deprecate: 1.0.2
webpack: 5.75.0_esbuild@0.16.17
@ -5012,7 +5012,7 @@ packages:
resolution: {integrity: sha512-tQ6hv57SPVxyOYPQzhlrhkuKs3Nk4Efa1DN9bzYg5jEzXbeZ9uK4jmV9TDQdWv0QeAvK81SD1YNI2OtzbLPVgA==}
dev: true
/@storybook/preset-vue-webpack/7.0.0-beta.46_saukmnhi62725vq7wtdfif6krm:
/@storybook/preset-vue-webpack/7.0.0-beta.46_hp247ej5z4ok6lxqqu3v2d7xta:
resolution: {integrity: sha512-X40UKuFlXV5lQuVrdP4jBEkPwf+9whXqJwNnBMlQICU/SEwC5oE2sqi7cFU5sZ8DBVzqDunxCE0rfYETeliyyw==}
engines: {node: '>=16.0.0'}
peerDependencies:
@ -5029,7 +5029,7 @@ packages:
'@types/node': 16.18.12
babel-loader: 9.1.2_la66t7xldg4uecmyawueag5wkm
css-loader: 6.7.3_webpack@5.75.0
ts-loader: 9.4.2_3fkjkrd3audxnith3e7fo4fnxi
ts-loader: 9.4.2_hhrrucqyg4eysmfpujvov2ym5u
vue: 2.7.14
vue-docgen-api: 4.56.4_vue@2.7.14
vue-docgen-loader: 1.5.1_yl6fzifju7igosbqtgzpjuylxi
@ -5177,7 +5177,7 @@ packages:
- supports-color
dev: true
/@storybook/vue-webpack5/7.0.0-beta.46_kqbjeyqrxfaciuxblodnlqbkgm:
/@storybook/vue-webpack5/7.0.0-beta.46_6qmhhfx7j6nt5tk6ratxcrskc4:
resolution: {integrity: sha512-PJJo/NGiWL1raOfHpJTb3X6LmLAC2TgI3EV2nDlkPigxj29O+zeMkyvfDky7eWpgOIbVqqtNVUYGH1GwbL7jqw==}
engines: {node: '>=16.0.0'}
peerDependencies:
@ -5191,9 +5191,9 @@ packages:
vue-template-compiler: ^2.6.8
dependencies:
'@babel/core': 7.20.12
'@storybook/builder-webpack5': 7.0.0-beta.46_vsjsuvw2laeoxumlaes6yduxsu
'@storybook/builder-webpack5': 7.0.0-beta.46_lyfnfac7rmzfleuimsdvcn3dv4
'@storybook/core-common': 7.0.0-beta.46
'@storybook/preset-vue-webpack': 7.0.0-beta.46_saukmnhi62725vq7wtdfif6krm
'@storybook/preset-vue-webpack': 7.0.0-beta.46_hp247ej5z4ok6lxqqu3v2d7xta
'@storybook/vue': 7.0.0-beta.46_wp7tvu3eu4pbkovl2pyk3t6dzu
'@types/node': 16.18.12
babel-loader: 9.1.2_la66t7xldg4uecmyawueag5wkm
@ -6391,7 +6391,7 @@ packages:
dev: true
optional: true
/@typescript-eslint/eslint-plugin/5.45.0_wke4plxjew2ogjxrdwvzd2srfq:
/@typescript-eslint/eslint-plugin/5.45.0_nasf2kpz3oxiofoztaiw65ixem:
resolution: {integrity: sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -6402,23 +6402,23 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/parser': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/parser': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
'@typescript-eslint/scope-manager': 5.45.0
'@typescript-eslint/type-utils': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/utils': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/type-utils': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
'@typescript-eslint/utils': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
debug: 4.3.4
eslint: 8.28.0
ignore: 5.2.0
natural-compare-lite: 1.4.0
regexpp: 3.2.0
semver: 7.3.8
tsutils: 3.21.0_typescript@4.9.4
typescript: 4.9.4
tsutils: 3.21.0_typescript@4.9.5
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/parser/5.45.0_wy4udjehnvkneqnogzx5kughki:
/@typescript-eslint/parser/5.45.0_pku7h6lsbnh7tcsfjudlqd5qce:
resolution: {integrity: sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -6430,10 +6430,10 @@ packages:
dependencies:
'@typescript-eslint/scope-manager': 5.45.0
'@typescript-eslint/types': 5.45.0
'@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.4
'@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.5
debug: 4.3.4
eslint: 8.28.0
typescript: 4.9.4
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
dev: true
@ -6446,7 +6446,7 @@ packages:
'@typescript-eslint/visitor-keys': 5.45.0
dev: true
/@typescript-eslint/type-utils/5.45.0_wy4udjehnvkneqnogzx5kughki:
/@typescript-eslint/type-utils/5.45.0_pku7h6lsbnh7tcsfjudlqd5qce:
resolution: {integrity: sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -6456,12 +6456,12 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.4
'@typescript-eslint/utils': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.5
'@typescript-eslint/utils': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
debug: 4.3.4
eslint: 8.28.0
tsutils: 3.21.0_typescript@4.9.4
typescript: 4.9.4
tsutils: 3.21.0_typescript@4.9.5
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
dev: true
@ -6471,7 +6471,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@typescript-eslint/typescript-estree/5.45.0_typescript@4.9.4:
/@typescript-eslint/typescript-estree/5.45.0_typescript@4.9.5:
resolution: {integrity: sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -6486,13 +6486,13 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.3.8
tsutils: 3.21.0_typescript@4.9.4
typescript: 4.9.4
tsutils: 3.21.0_typescript@4.9.5
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/utils/5.45.0_wy4udjehnvkneqnogzx5kughki:
/@typescript-eslint/utils/5.45.0_pku7h6lsbnh7tcsfjudlqd5qce:
resolution: {integrity: sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -6502,7 +6502,7 @@ packages:
'@types/semver': 7.3.13
'@typescript-eslint/scope-manager': 5.45.0
'@typescript-eslint/types': 5.45.0
'@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.4
'@typescript-eslint/typescript-estree': 5.45.0_typescript@4.9.5
eslint: 8.28.0
eslint-scope: 5.1.1
eslint-utils: 3.0.0_eslint@8.28.0
@ -6735,7 +6735,7 @@ packages:
/@vue/devtools-api/6.4.5:
resolution: {integrity: sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==}
/@vue/eslint-config-typescript/8.0.0_foaxzhaputljbcoeiwudem25oq:
/@vue/eslint-config-typescript/8.0.0_tzuopv2z7r6hmaghrrdryxy3qq:
resolution: {integrity: sha512-8u8Qpg4qfjJoNeRMdHlxif9BcGy4iYSSK4YYW5AFPPRtkBJiCqtoyT72l4F3ZeZII09ax2N6yQeHbQ0CXQi1bA==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
@ -6748,11 +6748,11 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/eslint-plugin': 5.45.0_wke4plxjew2ogjxrdwvzd2srfq
'@typescript-eslint/parser': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/eslint-plugin': 5.45.0_nasf2kpz3oxiofoztaiw65ixem
'@typescript-eslint/parser': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
eslint: 8.28.0
eslint-plugin-vue: 7.17.0_eslint@8.28.0
typescript: 4.9.4
typescript: 4.9.5
vue-eslint-parser: 7.11.0_eslint@8.28.0
transitivePeerDependencies:
- supports-color
@ -9436,17 +9436,17 @@ packages:
nub: 0.0.0
dev: false
/cypress-real-events/1.7.6_cypress@10.11.0:
/cypress-real-events/1.7.6_cypress@12.7.0:
resolution: {integrity: sha512-yP6GnRrbm6HK5q4DH6Nnupz37nOfZu/xn1xFYqsE2o4G73giPWQOdu6375QYpwfU1cvHNCgyD2bQ2hPH9D7NMw==}
peerDependencies:
cypress: ^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x || ^11.x || ^12.x
dependencies:
cypress: 10.11.0
cypress: 12.7.0
dev: true
/cypress/10.11.0:
resolution: {integrity: sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA==}
engines: {node: '>=12.0.0'}
/cypress/12.7.0:
resolution: {integrity: sha512-7rq+nmhzz0u6yabCFyPtADU2OOrYt6pvUau9qV7xyifJ/hnsaw/vkr0tnLlcuuQKUAOC1v1M1e4Z0zG7S0IAvA==}
engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
hasBin: true
dependencies:
'@cypress/request': 2.88.10
@ -10488,8 +10488,8 @@ packages:
eslint: ^7.32.0 || ^8.2.0
eslint-plugin-import: ^2.25.3
dependencies:
'@typescript-eslint/eslint-plugin': 5.45.0_wke4plxjew2ogjxrdwvzd2srfq
'@typescript-eslint/parser': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/eslint-plugin': 5.45.0_nasf2kpz3oxiofoztaiw65ixem
'@typescript-eslint/parser': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
eslint: 8.28.0
eslint-config-airbnb-base: 15.0.0_ktrec6dplf4now6nlbc6d67jee
eslint-plugin-import: 2.26.0_xmouedd5rhgbah4737x2hltudq
@ -10558,7 +10558,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/parser': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
debug: 3.2.7
eslint: 8.28.0
eslint-import-resolver-node: 0.3.6
@ -10586,7 +10586,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/parser': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
array-includes: 3.1.5
array.prototype.flat: 1.3.0
debug: 2.6.9
@ -10611,10 +10611,10 @@ packages:
resolution: {integrity: sha512-qe6sVFDP1Vj5eXlqZxYZpIjwYvhuqXlI0P8OfPyhiPOhMkFtr0TpFphD8/6WCzkm7LJCvG1eJEzURCtMIsFTAg==}
dev: true
/eslint-plugin-n8n-nodes-base/1.12.0_wy4udjehnvkneqnogzx5kughki:
/eslint-plugin-n8n-nodes-base/1.12.0_pku7h6lsbnh7tcsfjudlqd5qce:
resolution: {integrity: sha512-AotXR6IsxLNnxp4OxhD33xcmRFwVq7ZImBd0mTgpirV3VX8pCJDdiDlI2zCAICcICZxtOdbVtHOMhhnMjTh71A==}
dependencies:
'@typescript-eslint/utils': 5.45.0_wy4udjehnvkneqnogzx5kughki
'@typescript-eslint/utils': 5.45.0_pku7h6lsbnh7tcsfjudlqd5qce
camel-case: 4.1.2
indefinite: 2.4.1
pascal-case: 3.1.2
@ -11451,7 +11451,7 @@ packages:
/forever-agent/0.6.1:
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
/fork-ts-checker-webpack-plugin/6.5.2_oidmngyddw6azfqg3taanyywde:
/fork-ts-checker-webpack-plugin/6.5.2_3vu26w62dupooczhvlkrwvyfsa:
resolution: {integrity: sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==}
engines: {node: '>=10', yarn: '>=1.0.0'}
peerDependencies:
@ -11478,7 +11478,7 @@ packages:
schema-utils: 2.7.0
semver: 7.3.8
tapable: 1.1.3
typescript: 4.9.4
typescript: 4.9.5
vue-template-compiler: 2.7.14
webpack: 5.75.0_esbuild@0.16.17
dev: true
@ -13447,15 +13447,15 @@ packages:
stack-utils: 2.0.6
dev: true
/jest-mock-extended/3.0.1_47mstovy2thvxzoe7ouhdvjexm:
/jest-mock-extended/3.0.1_gelezmms3va3pnkofxaadhcvma:
resolution: {integrity: sha512-RF4Ow8pXvbRuEcCTj56oYHmig5311BSFvbEGxPNYL51wGKGu93MvVQgx0UpFmjqyBXIcElkZo2Rke88kR1iSKQ==}
peerDependencies:
jest: ^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0
typescript: ^3.0.0 || ^4.0.0
dependencies:
jest: 29.4.2
ts-essentials: 7.0.3_typescript@4.9.4
typescript: 4.9.4
ts-essentials: 7.0.3_typescript@4.9.5
typescript: 4.9.5
dev: true
/jest-mock/29.4.2:
@ -16509,7 +16509,7 @@ packages:
engines: {node: '>=6'}
dev: true
/pinia/2.0.23_vj744rb3neneiaeb3oalctaenu:
/pinia/2.0.23_hwpzsh6pnvsm3pjf2zi526hnzq:
resolution: {integrity: sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==}
peerDependencies:
'@vue/composition-api': ^1.4.0
@ -16522,7 +16522,7 @@ packages:
optional: true
dependencies:
'@vue/devtools-api': 6.4.5
typescript: 4.9.4
typescript: 4.9.5
vue: 2.7.14
vue-demi: 0.13.11_vue@2.7.14
@ -17165,11 +17165,6 @@ packages:
resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==}
dev: false
/punycode/2.1.1:
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
engines: {node: '>=6'}
dev: false
/punycode/2.2.0:
resolution: {integrity: sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==}
engines: {node: '>=6'}
@ -19643,7 +19638,7 @@ packages:
dependencies:
ip-regex: 2.1.0
psl: 1.9.0
punycode: 2.1.1
punycode: 2.2.0
dev: false
/tough-cookie/4.1.2:
@ -19690,19 +19685,19 @@ packages:
engines: {node: '>=6.10'}
dev: true
/ts-essentials/7.0.3_typescript@4.9.4:
/ts-essentials/7.0.3_typescript@4.9.5:
resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==}
peerDependencies:
typescript: '>=3.7.0'
dependencies:
typescript: 4.9.4
typescript: 4.9.5
dev: true
/ts-expect/1.3.0:
resolution: {integrity: sha512-e4g0EJtAjk64xgnFPD6kTBUtpnMVzDrMb12N1YZV0VvSlhnVT3SGxiYTLdGy8Q5cYHOIC/FAHmZ10eGrAguicQ==}
dev: false
/ts-jest/29.0.5_pa4ebk5usulsg7iw3zwjv5figy:
/ts-jest/29.0.5_zgilbyuumz7xbrerspmrtjuxsi:
resolution: {integrity: sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
@ -19732,11 +19727,11 @@ packages:
lodash.memoize: 4.1.2
make-error: 1.3.6
semver: 7.3.8
typescript: 4.9.4
typescript: 4.9.5
yargs-parser: 21.1.1
dev: true
/ts-loader/9.4.2_3fkjkrd3audxnith3e7fo4fnxi:
/ts-loader/9.4.2_hhrrucqyg4eysmfpujvov2ym5u:
resolution: {integrity: sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==}
engines: {node: '>=12.0.0'}
peerDependencies:
@ -19747,7 +19742,7 @@ packages:
enhanced-resolve: 5.10.0
micromatch: 4.0.5
semver: 7.3.8
typescript: 4.9.4
typescript: 4.9.5
webpack: 5.75.0_esbuild@0.16.17
dev: true
@ -19767,7 +19762,7 @@ packages:
plimit-lit: 1.4.1
dev: true
/tsc-watch/6.0.0_typescript@4.9.4:
/tsc-watch/6.0.0_typescript@4.9.5:
resolution: {integrity: sha512-zgpju+/z5z29/kK5V28Nz16CMkX2voFOUxkTlCim/R25hxzbyUqu2NfTnmJBQfESBSPbEQUGqDdB9A8opAcB4A==}
engines: {node: '>=12.12.0'}
hasBin: true
@ -19778,7 +19773,7 @@ packages:
node-cleanup: 2.1.2
ps-tree: 1.2.0
string-argv: 0.3.1
typescript: 4.9.4
typescript: 4.9.5
dev: true
/tsconfig-paths/3.14.1:
@ -19816,14 +19811,14 @@ packages:
engines: {node: '>=0.6.x'}
dev: false
/tsutils/3.21.0_typescript@4.9.4:
/tsutils/3.21.0_typescript@4.9.5:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
dependencies:
tslib: 1.14.1
typescript: 4.9.4
typescript: 4.9.5
dev: true
/tunnel-agent/0.6.0:
@ -19971,9 +19966,10 @@ packages:
/typedarray/0.0.6:
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
/typedi/0.10.0:
/typedi/0.10.0_syy565ld7euwcedfbmx53j2qc4:
resolution: {integrity: sha512-v3UJF8xm68BBj6AF4oQML3ikrfK2c9EmZUyLOfShpJuItAqVBHWP/KtpGinkSsIiP6EZyyb6Z3NXyW9dgS9X1w==}
dev: false
patched: true
/typeorm/0.3.12_pgelcv6ef3switkrteavpif3pq:
resolution: {integrity: sha512-sYSxBmCf1nJLLTcYtwqZ+lQIRtLPyUoO93rHTOKk9vJCyT4UfRtU7oRsJvfvKP3nnZTD1hzz2SEy2zwPEN6OyA==}
@ -20058,8 +20054,8 @@ packages:
- supports-color
dev: false
/typescript/4.9.4:
resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==}
/typescript/4.9.5:
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
engines: {node: '>=4.2.0'}
hasBin: true
@ -21112,7 +21108,7 @@ packages:
resolution: {integrity: sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==}
dev: true
/vue-tsc/1.0.24_typescript@4.9.4:
/vue-tsc/1.0.24_typescript@4.9.5:
resolution: {integrity: sha512-mmU1s5SAqE1nByQAiQnao9oU4vX+mSdsgI8H57SfKH6UVzq/jP9+Dbi2GaV+0b4Cn361d2ln8m6xeU60ApiEXg==}
hasBin: true
peerDependencies:
@ -21120,7 +21116,7 @@ packages:
dependencies:
'@volar/vue-language-core': 1.0.24
'@volar/vue-typescript': 1.0.24
typescript: 4.9.4
typescript: 4.9.5
dev: true
/vue-typed-mixins/0.2.0: