refactor: Format root-level dirs (no-changelog) (#4938)

🎨 Format root-level dirs
This commit is contained in:
Iván Ovejero 2022-12-15 16:39:59 +01:00 committed by GitHub
parent d7b3d649d6
commit 3028ad3c61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 612 additions and 513 deletions

View file

@ -1,158 +1,135 @@
## [0.207.1](https://github.com/n8n-io/n8n/compare/n8n@0.207.0...n8n@0.207.1) (2022-12-13) ## [0.207.1](https://github.com/n8n-io/n8n/compare/n8n@0.207.0...n8n@0.207.1) (2022-12-13)
### Bug Fixes ### Bug Fixes
* **editor:** Fix undo on Windows and Linux ([#4898](https://github.com/n8n-io/n8n/issues/4898)) ([3fc2d7c](https://github.com/n8n-io/n8n/commit/3fc2d7cc5af54f826a8f0c27cb7860448f92bb77)) - **editor:** Fix undo on Windows and Linux ([#4898](https://github.com/n8n-io/n8n/issues/4898)) ([3fc2d7c](https://github.com/n8n-io/n8n/commit/3fc2d7cc5af54f826a8f0c27cb7860448f92bb77))
* **editor:** Schema view render empty data ([#4902](https://github.com/n8n-io/n8n/issues/4902)) ([0b6d470](https://github.com/n8n-io/n8n/commit/0b6d47086a27117ceb0a1da107e5fcfbe11e0cd4)) - **editor:** Schema view render empty data ([#4902](https://github.com/n8n-io/n8n/issues/4902)) ([0b6d470](https://github.com/n8n-io/n8n/commit/0b6d47086a27117ceb0a1da107e5fcfbe11e0cd4))
* Ensure parent directory exists before copying over the icons to generated static directory ([#4865](https://github.com/n8n-io/n8n/issues/4865)) ([91e9a88](https://github.com/n8n-io/n8n/commit/91e9a88e3a83530e1dce2e72b8796da24775dcf2)) - Ensure parent directory exists before copying over the icons to generated static directory ([#4865](https://github.com/n8n-io/n8n/issues/4865)) ([91e9a88](https://github.com/n8n-io/n8n/commit/91e9a88e3a83530e1dce2e72b8796da24775dcf2))
# [0.207.0](https://github.com/n8n-io/n8n/compare/n8n@0.206.1...n8n@0.207.0) (2022-12-12) # [0.207.0](https://github.com/n8n-io/n8n/compare/n8n@0.206.1...n8n@0.207.0) (2022-12-12)
### Bug Fixes ### Bug Fixes
* **core:** Remove `nodeGetter` checks ([#4883](https://github.com/n8n-io/n8n/issues/4883)) ([07b2f76](https://github.com/n8n-io/n8n/commit/07b2f7678cc409840328da8f2e0b6f064fab10d8)) - **core:** Remove `nodeGetter` checks ([#4883](https://github.com/n8n-io/n8n/issues/4883)) ([07b2f76](https://github.com/n8n-io/n8n/commit/07b2f7678cc409840328da8f2e0b6f064fab10d8))
* **editor:** Avoid adding manual trigger node when webhook node is added ([#4887](https://github.com/n8n-io/n8n/issues/4887)) ([b689d2d](https://github.com/n8n-io/n8n/commit/b689d2d7c28eb90c8979aba5bbc2f75867289505)) - **editor:** Avoid adding manual trigger node when webhook node is added ([#4887](https://github.com/n8n-io/n8n/issues/4887)) ([b689d2d](https://github.com/n8n-io/n8n/commit/b689d2d7c28eb90c8979aba5bbc2f75867289505))
* **editor:** Fix credential sharing issues handler when no matching id or name ([#4879](https://github.com/n8n-io/n8n/issues/4879)) ([1cce8ea](https://github.com/n8n-io/n8n/commit/1cce8eaf16a4394b4241572641427011287a7dc2)) - **editor:** Fix credential sharing issues handler when no matching id or name ([#4879](https://github.com/n8n-io/n8n/issues/4879)) ([1cce8ea](https://github.com/n8n-io/n8n/commit/1cce8eaf16a4394b4241572641427011287a7dc2))
* **editor:** Fix for broken tab navigation ([#4881](https://github.com/n8n-io/n8n/issues/4881)) ([983c544](https://github.com/n8n-io/n8n/commit/983c5447c512651db96fbc57f2934c019dd3bf20)) - **editor:** Fix for broken tab navigation ([#4881](https://github.com/n8n-io/n8n/issues/4881)) ([983c544](https://github.com/n8n-io/n8n/commit/983c5447c512651db96fbc57f2934c019dd3bf20))
* **editor:** Schema view shows checkbox in case of empty data ([#4889](https://github.com/n8n-io/n8n/issues/4889)) ([b0c158c](https://github.com/n8n-io/n8n/commit/b0c158c64fa7df7da7fefb6ee24223ce650318b2)) - **editor:** Schema view shows checkbox in case of empty data ([#4889](https://github.com/n8n-io/n8n/issues/4889)) ([b0c158c](https://github.com/n8n-io/n8n/commit/b0c158c64fa7df7da7fefb6ee24223ce650318b2))
* Increase workflow reactivation max timeout to 1 day ([#4869](https://github.com/n8n-io/n8n/issues/4869)) ([593354b](https://github.com/n8n-io/n8n/commit/593354b6d89b577182873ef621c2c86c5415ef48)) - Increase workflow reactivation max timeout to 1 day ([#4869](https://github.com/n8n-io/n8n/issues/4869)) ([593354b](https://github.com/n8n-io/n8n/commit/593354b6d89b577182873ef621c2c86c5415ef48))
* Issue listing executions with Postgres ([#4856](https://github.com/n8n-io/n8n/issues/4856)) ([5156328](https://github.com/n8n-io/n8n/commit/5156328c34f384e292e9cfaebe72ad0666b02af6)) - Issue listing executions with Postgres ([#4856](https://github.com/n8n-io/n8n/issues/4856)) ([5156328](https://github.com/n8n-io/n8n/commit/5156328c34f384e292e9cfaebe72ad0666b02af6))
* **Move Binary Data Node:** Stringify objects before encoding them in MoveBinaryData ([#4882](https://github.com/n8n-io/n8n/issues/4882)) ([3b969d2](https://github.com/n8n-io/n8n/commit/3b969d2cd11e2bff3402cdc5e8825b105b453630)) - **Move Binary Data Node:** Stringify objects before encoding them in MoveBinaryData ([#4882](https://github.com/n8n-io/n8n/issues/4882)) ([3b969d2](https://github.com/n8n-io/n8n/commit/3b969d2cd11e2bff3402cdc5e8825b105b453630))
* Remove foreign credentials when copying nodes or duplicating workflow ([#4880](https://github.com/n8n-io/n8n/issues/4880)) ([7d2e2ee](https://github.com/n8n-io/n8n/commit/7d2e2ee0f74fbe98c0e69ec1383e13af8b8cc035)) - Remove foreign credentials when copying nodes or duplicating workflow ([#4880](https://github.com/n8n-io/n8n/issues/4880)) ([7d2e2ee](https://github.com/n8n-io/n8n/commit/7d2e2ee0f74fbe98c0e69ec1383e13af8b8cc035))
* **Split In Batches Node:** Fix issue with pairedItem ([#4873](https://github.com/n8n-io/n8n/issues/4873)) ([38d7300](https://github.com/n8n-io/n8n/commit/38d7300d2a8168643a75f0c4fff108949f25ca15)) - **Split In Batches Node:** Fix issue with pairedItem ([#4873](https://github.com/n8n-io/n8n/issues/4873)) ([38d7300](https://github.com/n8n-io/n8n/commit/38d7300d2a8168643a75f0c4fff108949f25ca15))
* Stop returning `UNKNOWN ERROR` in the response if an actual error message is available ([#4859](https://github.com/n8n-io/n8n/issues/4859)) ([4cb4c5e](https://github.com/n8n-io/n8n/commit/4cb4c5e8188fd930312e3bf720472af35731a968)) - Stop returning `UNKNOWN ERROR` in the response if an actual error message is available ([#4859](https://github.com/n8n-io/n8n/issues/4859)) ([4cb4c5e](https://github.com/n8n-io/n8n/commit/4cb4c5e8188fd930312e3bf720472af35731a968))
* Update duplicate action ([#4858](https://github.com/n8n-io/n8n/issues/4858)) ([19e0e96](https://github.com/n8n-io/n8n/commit/19e0e962710070d4517b20b8c8b2b57392f2100a)) - Update duplicate action ([#4858](https://github.com/n8n-io/n8n/issues/4858)) ([19e0e96](https://github.com/n8n-io/n8n/commit/19e0e962710070d4517b20b8c8b2b57392f2100a))
* Upgrade sse-channel to mitigate CVE-2019-10744 ([#4835](https://github.com/n8n-io/n8n/issues/4835)) ([7e1a13f](https://github.com/n8n-io/n8n/commit/7e1a13f9b2cc110343f3dc1f26c9a0703eeee588)) - Upgrade sse-channel to mitigate CVE-2019-10744 ([#4835](https://github.com/n8n-io/n8n/issues/4835)) ([7e1a13f](https://github.com/n8n-io/n8n/commit/7e1a13f9b2cc110343f3dc1f26c9a0703eeee588))
* Use license-sdk v1.6.1 ([#4872](https://github.com/n8n-io/n8n/issues/4872)) ([ebad81a](https://github.com/n8n-io/n8n/commit/ebad81a68beb787cd0146e2439872ae369c81aa5)) - Use license-sdk v1.6.1 ([#4872](https://github.com/n8n-io/n8n/issues/4872)) ([ebad81a](https://github.com/n8n-io/n8n/commit/ebad81a68beb787cd0146e2439872ae369c81aa5))
### Features ### Features
* Add sharing permissions info for workflow sharees ([#4892](https://github.com/n8n-io/n8n/issues/4892)) ([c013245](https://github.com/n8n-io/n8n/commit/c013245db726bf7e2a880ac538631c53450a6471)) - Add sharing permissions info for workflow sharees ([#4892](https://github.com/n8n-io/n8n/issues/4892)) ([c013245](https://github.com/n8n-io/n8n/commit/c013245db726bf7e2a880ac538631c53450a6471))
* **editor:** Add undo/redo support for canvas actions ([#4787](https://github.com/n8n-io/n8n/issues/4787)) ([b2aba48](https://github.com/n8n-io/n8n/commit/b2aba48dfe441225c36ba1626aa6f8eb4f1a8173)) - **editor:** Add undo/redo support for canvas actions ([#4787](https://github.com/n8n-io/n8n/issues/4787)) ([b2aba48](https://github.com/n8n-io/n8n/commit/b2aba48dfe441225c36ba1626aa6f8eb4f1a8173))
* **editor:** Node creator actions ([#4696](https://github.com/n8n-io/n8n/issues/4696)) ([79fe57d](https://github.com/n8n-io/n8n/commit/79fe57dad8093b27651ce82164d6e7a0f08f9e43)) - **editor:** Node creator actions ([#4696](https://github.com/n8n-io/n8n/issues/4696)) ([79fe57d](https://github.com/n8n-io/n8n/commit/79fe57dad8093b27651ce82164d6e7a0f08f9e43))
* Handle sharing features when user skips owner setup ([#4850](https://github.com/n8n-io/n8n/issues/4850)) ([6f1b78d](https://github.com/n8n-io/n8n/commit/6f1b78df9877666212d9b01818155e30c2caba0f)) - Handle sharing features when user skips owner setup ([#4850](https://github.com/n8n-io/n8n/issues/4850)) ([6f1b78d](https://github.com/n8n-io/n8n/commit/6f1b78df9877666212d9b01818155e30c2caba0f))
* Update credential test error message for sharees ([#4864](https://github.com/n8n-io/n8n/issues/4864)) ([4765d76](https://github.com/n8n-io/n8n/commit/4765d767e361608a6349d08f7116dedc2a0e7e35)) - Update credential test error message for sharees ([#4864](https://github.com/n8n-io/n8n/issues/4864)) ([4765d76](https://github.com/n8n-io/n8n/commit/4765d767e361608a6349d08f7116dedc2a0e7e35))
## [0.206.1](https://github.com/n8n-io/n8n/compare/n8n@0.206.0...n8n@0.206.1) (2022-12-07) ## [0.206.1](https://github.com/n8n-io/n8n/compare/n8n@0.206.0...n8n@0.206.1) (2022-12-07)
### Bug Fixes ### Bug Fixes
* **core:** Make expression resolution improvements ([#4829](https://github.com/n8n-io/n8n/issues/4829)) ([0bd13c7](https://github.com/n8n-io/n8n/commit/0bd13c71739c4fb34feab4f7a169ee89bc77eee8)) - **core:** Make expression resolution improvements ([#4829](https://github.com/n8n-io/n8n/issues/4829)) ([0bd13c7](https://github.com/n8n-io/n8n/commit/0bd13c71739c4fb34feab4f7a169ee89bc77eee8))
* **editor:** Schema unit test stub fontawesome icon ([#4840](https://github.com/n8n-io/n8n/issues/4840)) ([1e4ca1f](https://github.com/n8n-io/n8n/commit/1e4ca1f0d0c89386470db7f6ce265a1339c79562)) - **editor:** Schema unit test stub fontawesome icon ([#4840](https://github.com/n8n-io/n8n/issues/4840)) ([1e4ca1f](https://github.com/n8n-io/n8n/commit/1e4ca1f0d0c89386470db7f6ce265a1339c79562))
* Remove unnecessary console message ([#4848](https://github.com/n8n-io/n8n/issues/4848)) ([2ad62bc](https://github.com/n8n-io/n8n/commit/2ad62bcd442c4595daef4d02119122d9c37ab43d)) - Remove unnecessary console message ([#4848](https://github.com/n8n-io/n8n/issues/4848)) ([2ad62bc](https://github.com/n8n-io/n8n/commit/2ad62bcd442c4595daef4d02119122d9c37ab43d))
# [0.206.0](https://github.com/n8n-io/n8n/compare/n8n@0.205.0...n8n@0.206.0) (2022-12-06) # [0.206.0](https://github.com/n8n-io/n8n/compare/n8n@0.205.0...n8n@0.206.0) (2022-12-06)
### Bug Fixes ### Bug Fixes
* **Code Node:** Restore `pairedItem` to required n8n item keys ([#4821](https://github.com/n8n-io/n8n/issues/4821)) ([915f144](https://github.com/n8n-io/n8n/commit/915f1445c26d834e3d43602f901a198931a107e1)) - **Code Node:** Restore `pairedItem` to required n8n item keys ([#4821](https://github.com/n8n-io/n8n/issues/4821)) ([915f144](https://github.com/n8n-io/n8n/commit/915f1445c26d834e3d43602f901a198931a107e1))
* **core:** Fix linter error ([#4808](https://github.com/n8n-io/n8n/issues/4808)) ([3bb3809](https://github.com/n8n-io/n8n/commit/3bb3809eecd1b660c0d05c26164b9ccc90a37008)) - **core:** Fix linter error ([#4808](https://github.com/n8n-io/n8n/issues/4808)) ([3bb3809](https://github.com/n8n-io/n8n/commit/3bb3809eecd1b660c0d05c26164b9ccc90a37008))
* **core:** Fix partial execution with pinned data on child node run ([#4764](https://github.com/n8n-io/n8n/issues/4764)) ([5d75e6c](https://github.com/n8n-io/n8n/commit/5d75e6ceb3bf7d88229b4e71dda3250086aceb05)) - **core:** Fix partial execution with pinned data on child node run ([#4764](https://github.com/n8n-io/n8n/issues/4764)) ([5d75e6c](https://github.com/n8n-io/n8n/commit/5d75e6ceb3bf7d88229b4e71dda3250086aceb05))
* **core:** OAuth2 scopes does not save ([7aefed4](https://github.com/n8n-io/n8n/commit/7aefed46dcdb5d795fe9755c9fc64f445136bc17)) - **core:** OAuth2 scopes does not save ([7aefed4](https://github.com/n8n-io/n8n/commit/7aefed46dcdb5d795fe9755c9fc64f445136bc17))
* Enable source-maps on WorkflowRunnerProcess in `own` mode ([#4832](https://github.com/n8n-io/n8n/issues/4832)) ([9485e2f](https://github.com/n8n-io/n8n/commit/9485e2f12a4131ec24f504591290246e24f1cd09)) - Enable source-maps on WorkflowRunnerProcess in `own` mode ([#4832](https://github.com/n8n-io/n8n/issues/4832)) ([9485e2f](https://github.com/n8n-io/n8n/commit/9485e2f12a4131ec24f504591290246e24f1cd09))
* **Execute Workflow Node:** Update Execute Workflow node info notice text ([#4809](https://github.com/n8n-io/n8n/issues/4809)) ([9e7a156](https://github.com/n8n-io/n8n/commit/9e7a156532293956e74103c66babd6c967bb062c)) - **Execute Workflow Node:** Update Execute Workflow node info notice text ([#4809](https://github.com/n8n-io/n8n/issues/4809)) ([9e7a156](https://github.com/n8n-io/n8n/commit/9e7a156532293956e74103c66babd6c967bb062c))
* **Gmail Trigger Node:** Trigger node missing some emails ([67aad63](https://github.com/n8n-io/n8n/commit/67aad6334358dfecd5ba3a6e8f085fca73bd40ad)) - **Gmail Trigger Node:** Trigger node missing some emails ([67aad63](https://github.com/n8n-io/n8n/commit/67aad6334358dfecd5ba3a6e8f085fca73bd40ad))
* Handle error when workflow does not exist or is inaccessible ([#4831](https://github.com/n8n-io/n8n/issues/4831)) ([b71295e](https://github.com/n8n-io/n8n/commit/b71295e4de658fb134b67eaa0b630704f858ce7e)) - Handle error when workflow does not exist or is inaccessible ([#4831](https://github.com/n8n-io/n8n/issues/4831)) ([b71295e](https://github.com/n8n-io/n8n/commit/b71295e4de658fb134b67eaa0b630704f858ce7e))
* **Local File Trigger Node:** Fix issue that causes a crash if the ignore field is empty ([#4824](https://github.com/n8n-io/n8n/issues/4824)) ([#4825](https://github.com/n8n-io/n8n/issues/4825)) ([c311424](https://github.com/n8n-io/n8n/commit/c3114241fdd399555666d2f5890815b6196ce1bf)) - **Local File Trigger Node:** Fix issue that causes a crash if the ignore field is empty ([#4824](https://github.com/n8n-io/n8n/issues/4824)) ([#4825](https://github.com/n8n-io/n8n/issues/4825)) ([c311424](https://github.com/n8n-io/n8n/commit/c3114241fdd399555666d2f5890815b6196ce1bf))
* Make `nodes.exclude` and `nodes.include` work with lazy-loaded nodes ([#4833](https://github.com/n8n-io/n8n/issues/4833)) ([85241fd](https://github.com/n8n-io/n8n/commit/85241fd230675691828c8d711f86aabb7e48dabe)) - Make `nodes.exclude` and `nodes.include` work with lazy-loaded nodes ([#4833](https://github.com/n8n-io/n8n/issues/4833)) ([85241fd](https://github.com/n8n-io/n8n/commit/85241fd230675691828c8d711f86aabb7e48dabe))
### Features ### Features
* Add message for readonly nodes. Improve foreign credentials handling ([#4759](https://github.com/n8n-io/n8n/issues/4759)) ([eb112ff](https://github.com/n8n-io/n8n/commit/eb112ffd23cec04f290d515917c227b628db2834)) - Add message for readonly nodes. Improve foreign credentials handling ([#4759](https://github.com/n8n-io/n8n/issues/4759)) ([eb112ff](https://github.com/n8n-io/n8n/commit/eb112ffd23cec04f290d515917c227b628db2834))
* Add prompt to overwrite changes when concurrent editing occurs ([#4817](https://github.com/n8n-io/n8n/issues/4817)) ([af6ac42](https://github.com/n8n-io/n8n/commit/af6ac42aa3ec6805a2a18b920128beafcb9a3cdc)) - Add prompt to overwrite changes when concurrent editing occurs ([#4817](https://github.com/n8n-io/n8n/issues/4817)) ([af6ac42](https://github.com/n8n-io/n8n/commit/af6ac42aa3ec6805a2a18b920128beafcb9a3cdc))
* **core:** Workflow Execution Statistics ([#4200](https://github.com/n8n-io/n8n/issues/4200)) ([1722c6b](https://github.com/n8n-io/n8n/commit/1722c6b0c5dde87d3389c328b611cbb611b2853e)) - **core:** Workflow Execution Statistics ([#4200](https://github.com/n8n-io/n8n/issues/4200)) ([1722c6b](https://github.com/n8n-io/n8n/commit/1722c6b0c5dde87d3389c328b611cbb611b2853e))
* **editor:** Alert design system component ([#4834](https://github.com/n8n-io/n8n/issues/4834)) ([9dbb3ea](https://github.com/n8n-io/n8n/commit/9dbb3ea182cba890781a89fe28eda2c7b50dbc65)) - **editor:** Alert design system component ([#4834](https://github.com/n8n-io/n8n/issues/4834)) ([9dbb3ea](https://github.com/n8n-io/n8n/commit/9dbb3ea182cba890781a89fe28eda2c7b50dbc65))
* **editor:** Schema view ([#4615](https://github.com/n8n-io/n8n/issues/4615)) ([4528f34](https://github.com/n8n-io/n8n/commit/4528f34462396b5faf550c5a58c4dd9163bdbc40)) - **editor:** Schema view ([#4615](https://github.com/n8n-io/n8n/issues/4615)) ([4528f34](https://github.com/n8n-io/n8n/commit/4528f34462396b5faf550c5a58c4dd9163bdbc40))
* Fix checkbox line height and make checkbox label clickable ([#4818](https://github.com/n8n-io/n8n/issues/4818)) ([1b7952a](https://github.com/n8n-io/n8n/commit/1b7952a516a5c5dfe1f79e25f811fc044a5e4962)) - Fix checkbox line height and make checkbox label clickable ([#4818](https://github.com/n8n-io/n8n/issues/4818)) ([1b7952a](https://github.com/n8n-io/n8n/commit/1b7952a516a5c5dfe1f79e25f811fc044a5e4962))
* **KoBoToolbox Node:** Add support for Media file API ([#4578](https://github.com/n8n-io/n8n/issues/4578)) ([37e580e](https://github.com/n8n-io/n8n/commit/37e580eb0628a651ecbc8faa3ad447cd0177d7cf)) - **KoBoToolbox Node:** Add support for Media file API ([#4578](https://github.com/n8n-io/n8n/issues/4578)) ([37e580e](https://github.com/n8n-io/n8n/commit/37e580eb0628a651ecbc8faa3ad447cd0177d7cf))
# [0.205.0](https://github.com/n8n-io/n8n/compare/n8n@0.204.0...n8n@0.205.0) (2022-12-02) # [0.205.0](https://github.com/n8n-io/n8n/compare/n8n@0.204.0...n8n@0.205.0) (2022-12-02)
### Bug Fixes ### Bug Fixes
* **AWS SNS Node:** Pagination Issue ([d96d161](https://github.com/n8n-io/n8n/commit/d96d1610ba921ba71e90677d379b025741c7c9c8)) - **AWS SNS Node:** Pagination Issue ([d96d161](https://github.com/n8n-io/n8n/commit/d96d1610ba921ba71e90677d379b025741c7c9c8))
* **core:** Ensure executions list is properly filtered for all users ([#4765](https://github.com/n8n-io/n8n/issues/4765)) ([ddf787c](https://github.com/n8n-io/n8n/commit/ddf787c087e523871891fd363f810075943b5e7b)) - **core:** Ensure executions list is properly filtered for all users ([#4765](https://github.com/n8n-io/n8n/issues/4765)) ([ddf787c](https://github.com/n8n-io/n8n/commit/ddf787c087e523871891fd363f810075943b5e7b))
* **core:** Fix `$items().length` in Execute Once mode ([#4755](https://github.com/n8n-io/n8n/issues/4755)) ([3d67df4](https://github.com/n8n-io/n8n/commit/3d67df490cad944704cd7da85c622feb418a2ea8)) - **core:** Fix `$items().length` in Execute Once mode ([#4755](https://github.com/n8n-io/n8n/issues/4755)) ([3d67df4](https://github.com/n8n-io/n8n/commit/3d67df490cad944704cd7da85c622feb418a2ea8))
* **core:** Mark binary data to be deleted when pruning executions ([#4713](https://github.com/n8n-io/n8n/issues/4713)) ([78c66f1](https://github.com/n8n-io/n8n/commit/78c66f16d6c4677a63be18d823866ad3d1414843)) - **core:** Mark binary data to be deleted when pruning executions ([#4713](https://github.com/n8n-io/n8n/issues/4713)) ([78c66f1](https://github.com/n8n-io/n8n/commit/78c66f16d6c4677a63be18d823866ad3d1414843))
* **core:** OAuth2 scope saved to DB fix ([7cb5dc2](https://github.com/n8n-io/n8n/commit/7cb5dc2aa5d15c574b0e07d0d7fa23dd9a9996ea)) - **core:** OAuth2 scope saved to DB fix ([7cb5dc2](https://github.com/n8n-io/n8n/commit/7cb5dc2aa5d15c574b0e07d0d7fa23dd9a9996ea))
* Credential overwrites should take precedence over credential default values ([#4782](https://github.com/n8n-io/n8n/issues/4782)) ([2ce6291](https://github.com/n8n-io/n8n/commit/2ce62917da514714b7198cab63dcfc0b1ebc0473)) - Credential overwrites should take precedence over credential default values ([#4782](https://github.com/n8n-io/n8n/issues/4782)) ([2ce6291](https://github.com/n8n-io/n8n/commit/2ce62917da514714b7198cab63dcfc0b1ebc0473))
* **editor:** Fix slots rendering of NodeCreator's NoResults component ([#4721](https://github.com/n8n-io/n8n/issues/4721)) ([d8c2dff](https://github.com/n8n-io/n8n/commit/d8c2dffc37155eb013a12d21cab6504264d16b8e)) - **editor:** Fix slots rendering of NodeCreator's NoResults component ([#4721](https://github.com/n8n-io/n8n/issues/4721)) ([d8c2dff](https://github.com/n8n-io/n8n/commit/d8c2dffc37155eb013a12d21cab6504264d16b8e))
* **editor:** JSON view values can be mapped like keys ([#4702](https://github.com/n8n-io/n8n/issues/4702)) ([6d4e959](https://github.com/n8n-io/n8n/commit/6d4e9598846c9c2eb128ce039d4aeae080178627)) - **editor:** JSON view values can be mapped like keys ([#4702](https://github.com/n8n-io/n8n/issues/4702)) ([6d4e959](https://github.com/n8n-io/n8n/commit/6d4e9598846c9c2eb128ce039d4aeae080178627))
* **Google Sheets Node:** Fix exception if no matching rows are found ([579f9c4](https://github.com/n8n-io/n8n/commit/579f9c4d4e5907a4ffba9a7ec6bcbb5d2faaefb9)) - **Google Sheets Node:** Fix exception if no matching rows are found ([579f9c4](https://github.com/n8n-io/n8n/commit/579f9c4d4e5907a4ffba9a7ec6bcbb5d2faaefb9))
* **Google Sheets Node:** Fix for append operation if no empty rows in sheet ([741c7da](https://github.com/n8n-io/n8n/commit/741c7da8b1a3f2824613d2a4c4880423c8be91cb)) - **Google Sheets Node:** Fix for append operation if no empty rows in sheet ([741c7da](https://github.com/n8n-io/n8n/commit/741c7da8b1a3f2824613d2a4c4880423c8be91cb))
* Lazy load nodes for credentials testing ([#4760](https://github.com/n8n-io/n8n/issues/4760)) ([0a7a2f3](https://github.com/n8n-io/n8n/commit/0a7a2f3e4179c6bd186547dd43a5c43400c18ff8)) - Lazy load nodes for credentials testing ([#4760](https://github.com/n8n-io/n8n/issues/4760)) ([0a7a2f3](https://github.com/n8n-io/n8n/commit/0a7a2f3e4179c6bd186547dd43a5c43400c18ff8))
* **Microsoft Outlook Node:** Fix binary attachment upload ([#4766](https://github.com/n8n-io/n8n/issues/4766)) ([528439c](https://github.com/n8n-io/n8n/commit/528439cb4d5ff3f61dddf75dea6377f508429155)) - **Microsoft Outlook Node:** Fix binary attachment upload ([#4766](https://github.com/n8n-io/n8n/issues/4766)) ([528439c](https://github.com/n8n-io/n8n/commit/528439cb4d5ff3f61dddf75dea6377f508429155))
* **Pipedrive Node:** Resolve properties not working ([c853b80](https://github.com/n8n-io/n8n/commit/c853b8078e66a671df448106956a0929c5b19b0a)) - **Pipedrive Node:** Resolve properties not working ([c853b80](https://github.com/n8n-io/n8n/commit/c853b8078e66a671df448106956a0929c5b19b0a))
* Remove background for resource ownership selector ([#4748](https://github.com/n8n-io/n8n/issues/4748)) ([30214f2](https://github.com/n8n-io/n8n/commit/30214f2bc20da18e16924e4047891a6ea8586593)) - Remove background for resource ownership selector ([#4748](https://github.com/n8n-io/n8n/issues/4748)) ([30214f2](https://github.com/n8n-io/n8n/commit/30214f2bc20da18e16924e4047891a6ea8586593))
* Update padding for resource filters dropdown ([#4751](https://github.com/n8n-io/n8n/issues/4751)) ([aff8cd9](https://github.com/n8n-io/n8n/commit/aff8cd9a2b376a429450661f108cdf8eb6e6d082)) - Update padding for resource filters dropdown ([#4751](https://github.com/n8n-io/n8n/issues/4751)) ([aff8cd9](https://github.com/n8n-io/n8n/commit/aff8cd9a2b376a429450661f108cdf8eb6e6d082))
* Update size of select components in filters dropdown ([#4747](https://github.com/n8n-io/n8n/issues/4747)) ([d6d442d](https://github.com/n8n-io/n8n/commit/d6d442d45882423661631ee40b732ed78543abfc)) - Update size of select components in filters dropdown ([#4747](https://github.com/n8n-io/n8n/issues/4747)) ([d6d442d](https://github.com/n8n-io/n8n/commit/d6d442d45882423661631ee40b732ed78543abfc))
* Update workflow save button type and design and share button type ([#4752](https://github.com/n8n-io/n8n/issues/4752)) ([b89301e](https://github.com/n8n-io/n8n/commit/b89301ec36fdbdc2a1d7c8996526b55930c20335)) - Update workflow save button type and design and share button type ([#4752](https://github.com/n8n-io/n8n/issues/4752)) ([b89301e](https://github.com/n8n-io/n8n/commit/b89301ec36fdbdc2a1d7c8996526b55930c20335))
### Features ### Features
* **editor:** Overhaul expression editor modal ([#4631](https://github.com/n8n-io/n8n/issues/4631)) ([59771c8](https://github.com/n8n-io/n8n/commit/59771c80ea6ccd1b0da4946f6d017e02b8016609)) - **editor:** Overhaul expression editor modal ([#4631](https://github.com/n8n-io/n8n/issues/4631)) ([59771c8](https://github.com/n8n-io/n8n/commit/59771c80ea6ccd1b0da4946f6d017e02b8016609))
* **Facebook Graph API Node:** Update to support api version 15 ([#4791](https://github.com/n8n-io/n8n/issues/4791)) ([2a85af1](https://github.com/n8n-io/n8n/commit/2a85af1bdb7098463085f1e5c96b25f820e19e15)) - **Facebook Graph API Node:** Update to support api version 15 ([#4791](https://github.com/n8n-io/n8n/issues/4791)) ([2a85af1](https://github.com/n8n-io/n8n/commit/2a85af1bdb7098463085f1e5c96b25f820e19e15))
* **Google Calendar Node:** Use resource locator component for calendar parameters ([#4410](https://github.com/n8n-io/n8n/issues/4410)) ([b319671](https://github.com/n8n-io/n8n/commit/b319671fd0f0488488788b472af140014bd7cc99)) - **Google Calendar Node:** Use resource locator component for calendar parameters ([#4410](https://github.com/n8n-io/n8n/issues/4410)) ([b319671](https://github.com/n8n-io/n8n/commit/b319671fd0f0488488788b472af140014bd7cc99))
* **Postmark Trigger Node:** Update credentials so they can be used with the HTTP Request Node ([#4790](https://github.com/n8n-io/n8n/issues/4790)) ([0c759dc](https://github.com/n8n-io/n8n/commit/0c759dc548c058372fde5d117ea34489f7a6a2d9)) - **Postmark Trigger Node:** Update credentials so they can be used with the HTTP Request Node ([#4790](https://github.com/n8n-io/n8n/issues/4790)) ([0c759dc](https://github.com/n8n-io/n8n/commit/0c759dc548c058372fde5d117ea34489f7a6a2d9))
* **Todoist Node:** Update to use latest api version ([#4650](https://github.com/n8n-io/n8n/issues/4650)) ([09a48c5](https://github.com/n8n-io/n8n/commit/09a48c51b64aaf31888e98b7f2711140e9818bed)) - **Todoist Node:** Update to use latest api version ([#4650](https://github.com/n8n-io/n8n/issues/4650)) ([09a48c5](https://github.com/n8n-io/n8n/commit/09a48c51b64aaf31888e98b7f2711140e9818bed))
# [0.204.0](https://github.com/n8n-io/n8n/compare/n8n@0.203.1...n8n@0.204.0) (2022-11-24) # [0.204.0](https://github.com/n8n-io/n8n/compare/n8n@0.203.1...n8n@0.204.0) (2022-11-24)
### Bug Fixes ### Bug Fixes
* **core:** Fix `$items().length` behavior in `executeOnce` mode ([#4694](https://github.com/n8n-io/n8n/issues/4694)) ([b87c122](https://github.com/n8n-io/n8n/commit/b87c12285fa2b339e726f81e271715e258b6a075)) - **core:** Fix `$items().length` behavior in `executeOnce` mode ([#4694](https://github.com/n8n-io/n8n/issues/4694)) ([b87c122](https://github.com/n8n-io/n8n/commit/b87c12285fa2b339e726f81e271715e258b6a075))
* **core:** Fix for unused imports ([a6df51b](https://github.com/n8n-io/n8n/commit/a6df51b6e83fa25dad962ab212123edb3c055cac)) - **core:** Fix for unused imports ([a6df51b](https://github.com/n8n-io/n8n/commit/a6df51b6e83fa25dad962ab212123edb3c055cac))
* **core:** Use CredentialsOverwrites when testing credentials ([#4675](https://github.com/n8n-io/n8n/issues/4675)) ([772ec78](https://github.com/n8n-io/n8n/commit/772ec78349b5b6877bf681f3262951e3a4e34fe4)) - **core:** Use CredentialsOverwrites when testing credentials ([#4675](https://github.com/n8n-io/n8n/issues/4675)) ([772ec78](https://github.com/n8n-io/n8n/commit/772ec78349b5b6877bf681f3262951e3a4e34fe4))
* Disable workflow locking due to issues ([#4708](https://github.com/n8n-io/n8n/issues/4708)) ([ee6ac5d](https://github.com/n8n-io/n8n/commit/ee6ac5d3417a2f308a7f4a3cda18c01fcec57faf)) - Disable workflow locking due to issues ([#4708](https://github.com/n8n-io/n8n/issues/4708)) ([ee6ac5d](https://github.com/n8n-io/n8n/commit/ee6ac5d3417a2f308a7f4a3cda18c01fcec57faf))
* **editor:** Fix for missing node connections in dev environment ([#4707](https://github.com/n8n-io/n8n/issues/4707)) ([b18ae18](https://github.com/n8n-io/n8n/commit/b18ae18a6b10fb125f3eed73103e33e3519cd82c)) - **editor:** Fix for missing node connections in dev environment ([#4707](https://github.com/n8n-io/n8n/issues/4707)) ([b18ae18](https://github.com/n8n-io/n8n/commit/b18ae18a6b10fb125f3eed73103e33e3519cd82c))
* **editor:** Fix missing resource locator component ([#4649](https://github.com/n8n-io/n8n/issues/4649)) ([44182f2](https://github.com/n8n-io/n8n/commit/44182f23a5e62c53209b3fa19edd1727586551ff)) - **editor:** Fix missing resource locator component ([#4649](https://github.com/n8n-io/n8n/issues/4649)) ([44182f2](https://github.com/n8n-io/n8n/commit/44182f23a5e62c53209b3fa19edd1727586551ff))
* **editor:** Prevent node-creator tabs from showing when toggled by CanvasAddButton ([#4661](https://github.com/n8n-io/n8n/issues/4661)) ([60746dc](https://github.com/n8n-io/n8n/commit/60746dc92ee1b6c33015e2a6a0d34bc981aa1dd5)) - **editor:** Prevent node-creator tabs from showing when toggled by CanvasAddButton ([#4661](https://github.com/n8n-io/n8n/issues/4661)) ([60746dc](https://github.com/n8n-io/n8n/commit/60746dc92ee1b6c33015e2a6a0d34bc981aa1dd5))
* **editor:** Table view column limit tooltip ([#4655](https://github.com/n8n-io/n8n/issues/4655)) ([3ac9ba3](https://github.com/n8n-io/n8n/commit/3ac9ba3491c0dc1de283bc4285a243e02747f971)) - **editor:** Table view column limit tooltip ([#4655](https://github.com/n8n-io/n8n/issues/4655)) ([3ac9ba3](https://github.com/n8n-io/n8n/commit/3ac9ba3491c0dc1de283bc4285a243e02747f971))
* Fix broken n8n-info-tip slots ([#4665](https://github.com/n8n-io/n8n/issues/4665)) ([6c99223](https://github.com/n8n-io/n8n/commit/6c992233a053db1ea235f785a52a754c1e694555)) - Fix broken n8n-info-tip slots ([#4665](https://github.com/n8n-io/n8n/issues/4665)) ([6c99223](https://github.com/n8n-io/n8n/commit/6c992233a053db1ea235f785a52a754c1e694555))
* **IF Node:** Fix "Is Empty" and "Is Not Empty" operation fails for date objects ([#4670](https://github.com/n8n-io/n8n/issues/4670)) ([753f4c9](https://github.com/n8n-io/n8n/commit/753f4c9a7d34c8d3329d4dc024fcf272f6f47ff3)) - **IF Node:** Fix "Is Empty" and "Is Not Empty" operation fails for date objects ([#4670](https://github.com/n8n-io/n8n/issues/4670)) ([753f4c9](https://github.com/n8n-io/n8n/commit/753f4c9a7d34c8d3329d4dc024fcf272f6f47ff3))
* Remove redundant await in node's api request functions without try/catch ([#4639](https://github.com/n8n-io/n8n/issues/4639)) ([67983e8](https://github.com/n8n-io/n8n/commit/67983e8f945397d3fb0be55fdeb47609be92b2cb)) - Remove redundant await in node's api request functions without try/catch ([#4639](https://github.com/n8n-io/n8n/issues/4639)) ([67983e8](https://github.com/n8n-io/n8n/commit/67983e8f945397d3fb0be55fdeb47609be92b2cb))
* **Schedule Trigger Node:** Fixes inconsitent behavior with cron and weekly intervals ([#4558](https://github.com/n8n-io/n8n/issues/4558)) ([2fb8ed8](https://github.com/n8n-io/n8n/commit/2fb8ed825b18118fc0783e95d1551ee2ce8c3a38)) - **Schedule Trigger Node:** Fixes inconsitent behavior with cron and weekly intervals ([#4558](https://github.com/n8n-io/n8n/issues/4558)) ([2fb8ed8](https://github.com/n8n-io/n8n/commit/2fb8ed825b18118fc0783e95d1551ee2ce8c3a38))
* Workflow activation should not crash if one of the credential is invalid ([#4671](https://github.com/n8n-io/n8n/issues/4671)) ([c0e13c2](https://github.com/n8n-io/n8n/commit/c0e13c2a8f9374e9c65aae3ce4102e37c993cf74)) - Workflow activation should not crash if one of the credential is invalid ([#4671](https://github.com/n8n-io/n8n/issues/4671)) ([c0e13c2](https://github.com/n8n-io/n8n/commit/c0e13c2a8f9374e9c65aae3ce4102e37c993cf74))
### Features ### Features
* Add credentials E2E test suite and page object ([#4596](https://github.com/n8n-io/n8n/issues/4596)) ([b5b44d1](https://github.com/n8n-io/n8n/commit/b5b44d1b598e67ef7e735d7cdfb5233ca72caca6)) - Add credentials E2E test suite and page object ([#4596](https://github.com/n8n-io/n8n/issues/4596)) ([b5b44d1](https://github.com/n8n-io/n8n/commit/b5b44d1b598e67ef7e735d7cdfb5233ca72caca6))
* Add save confirmation modal when leaving sharing modal ([#4683](https://github.com/n8n-io/n8n/issues/4683)) ([173badc](https://github.com/n8n-io/n8n/commit/173badc4e099ebb818686dc5a25c2192c138bcd9)) - Add save confirmation modal when leaving sharing modal ([#4683](https://github.com/n8n-io/n8n/issues/4683)) ([173badc](https://github.com/n8n-io/n8n/commit/173badc4e099ebb818686dc5a25c2192c138bcd9))
* Add share button to workflows list ([#4681](https://github.com/n8n-io/n8n/issues/4681)) ([a356d7b](https://github.com/n8n-io/n8n/commit/a356d7bdbadd5a4c69c61c5a5a30e75e9765e3d2)) - Add share button to workflows list ([#4681](https://github.com/n8n-io/n8n/issues/4681)) ([a356d7b](https://github.com/n8n-io/n8n/commit/a356d7bdbadd5a4c69c61c5a5a30e75e9765e3d2))
* **core:** Add license support to n8n ([#4566](https://github.com/n8n-io/n8n/issues/4566)) ([30e5d3d](https://github.com/n8n-io/n8n/commit/30e5d3d04c3457780875cc36637c8c1ea14ec783)) - **core:** Add license support to n8n ([#4566](https://github.com/n8n-io/n8n/issues/4566)) ([30e5d3d](https://github.com/n8n-io/n8n/commit/30e5d3d04c3457780875cc36637c8c1ea14ec783))
* **core:** Lazy-load nodes and credentials to reduce baseline memory usage ([#4577](https://github.com/n8n-io/n8n/issues/4577)) ([b6c57e1](https://github.com/n8n-io/n8n/commit/b6c57e19fc5683dd7fb9eabb60ec4e89359c59eb)) - **core:** Lazy-load nodes and credentials to reduce baseline memory usage ([#4577](https://github.com/n8n-io/n8n/issues/4577)) ([b6c57e1](https://github.com/n8n-io/n8n/commit/b6c57e19fc5683dd7fb9eabb60ec4e89359c59eb))
* **editor:** Add workflows list status filter ([#4690](https://github.com/n8n-io/n8n/issues/4690)) ([5364e7f](https://github.com/n8n-io/n8n/commit/5364e7fc9250421b799adc28b3e47dc75819ec7d)) - **editor:** Add workflows list status filter ([#4690](https://github.com/n8n-io/n8n/issues/4690)) ([5364e7f](https://github.com/n8n-io/n8n/commit/5364e7fc9250421b799adc28b3e47dc75819ec7d))
* Show delete button based on workflow permissions ([#4686](https://github.com/n8n-io/n8n/issues/4686)) ([4f64e26](https://github.com/n8n-io/n8n/commit/4f64e26a83c7e62c98d93c38bf3dcb6cdfaadb58)) - Show delete button based on workflow permissions ([#4686](https://github.com/n8n-io/n8n/issues/4686)) ([4f64e26](https://github.com/n8n-io/n8n/commit/4f64e26a83c7e62c98d93c38bf3dcb6cdfaadb58))
* Show toast when saving workflow sharing settings ([#4684](https://github.com/n8n-io/n8n/issues/4684)) ([6f8d0de](https://github.com/n8n-io/n8n/commit/6f8d0de55dc9c3c1cdb17329a8560ee8453c639a)) - Show toast when saving workflow sharing settings ([#4684](https://github.com/n8n-io/n8n/issues/4684)) ([6f8d0de](https://github.com/n8n-io/n8n/commit/6f8d0de55dc9c3c1cdb17329a8560ee8453c639a))
* Switch owner subview to all subview if has shared resources ([#4672](https://github.com/n8n-io/n8n/issues/4672)) ([e3e17e5](https://github.com/n8n-io/n8n/commit/e3e17e5dac685b1230e39bbef247312419b71f9b)) - Switch owner subview to all subview if has shared resources ([#4672](https://github.com/n8n-io/n8n/issues/4672)) ([e3e17e5](https://github.com/n8n-io/n8n/commit/e3e17e5dac685b1230e39bbef247312419b71f9b))
* Use longer stack-traces when error-reporting is enabled ([#4674](https://github.com/n8n-io/n8n/issues/4674)) ([de5b0b0](https://github.com/n8n-io/n8n/commit/de5b0b03fedede680f5a6e0f4dc73770b888bf46)) - Use longer stack-traces when error-reporting is enabled ([#4674](https://github.com/n8n-io/n8n/issues/4674)) ([de5b0b0](https://github.com/n8n-io/n8n/commit/de5b0b03fedede680f5a6e0f4dc73770b888bf46))
### Performance Improvements ### Performance Improvements
* **Code Node:** Improve n8n item key validation performance ([#4669](https://github.com/n8n-io/n8n/issues/4669)) ([740513b](https://github.com/n8n-io/n8n/commit/740513b42440b8760cd488659e92abe9951462b0)) - **Code Node:** Improve n8n item key validation performance ([#4669](https://github.com/n8n-io/n8n/issues/4669)) ([740513b](https://github.com/n8n-io/n8n/commit/740513b42440b8760cd488659e92abe9951462b0))
## [0.203.1](https://github.com/n8n-io/n8n/compare/n8n@0.203.0...n8n@0.203.1) (2022-11-18) ## [0.203.1](https://github.com/n8n-io/n8n/compare/n8n@0.203.0...n8n@0.203.1) (2022-11-18)

View file

@ -6,7 +6,7 @@ const BASE_URL = 'http://localhost:5678';
module.exports = defineConfig({ module.exports = defineConfig({
retries: { retries: {
openMode: 1, openMode: 1,
runMode: 3 runMode: 3,
}, },
e2e: { e2e: {
baseUrl: BASE_URL, baseUrl: BASE_URL,
@ -17,7 +17,7 @@ module.exports = defineConfig({
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
on('task', { on('task', {
'reset': () => fetch(BASE_URL + '/e2e/db/reset', { method: 'POST' }), reset: () => fetch(BASE_URL + '/e2e/db/reset', { method: 'POST' }),
'setup-owner': (payload) => 'setup-owner': (payload) =>
fetch(BASE_URL + '/e2e/db/setup-owner', { fetch(BASE_URL + '/e2e/db/setup-owner', {
method: 'POST', method: 'POST',

View file

@ -5,5 +5,5 @@ export const DEFAULT_USER_PASSWORD = 'CypressTest123';
export const MANUAL_TRIGGER_NODE_NAME = 'Manual Trigger'; export const MANUAL_TRIGGER_NODE_NAME = 'Manual Trigger';
export const SCHEDULE_TRIGGER_NODE_NAME = 'Schedule Trigger'; export const SCHEDULE_TRIGGER_NODE_NAME = 'Schedule Trigger';
export const CODE_NODE_NAME = 'Code' export const CODE_NODE_NAME = 'Code';
export const SET_NODE_NAME = 'Set' export const SET_NODE_NAME = 'Set';

View file

@ -1,5 +1,5 @@
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from "../constants"; import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
import { randFirstName, randLastName } from "@ngneat/falso"; import { randFirstName, randLastName } from '@ngneat/falso';
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows'; import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow'; import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
@ -22,7 +22,7 @@ describe('Workflows', () => {
expect(err.message).to.include('Not logged in'); expect(err.message).to.include('Not logged in');
return false; return false;
}) });
cy.signin({ email, password }); cy.signin({ email, password });
cy.visit(WorkflowsPage.url); cy.visit(WorkflowsPage.url);
@ -36,7 +36,7 @@ describe('Workflows', () => {
WorkflowPage.getters.workflowTags().should('contain.text', 'some-tag-1'); WorkflowPage.getters.workflowTags().should('contain.text', 'some-tag-1');
WorkflowPage.getters.workflowTags().should('contain.text', 'some-tag-2'); WorkflowPage.getters.workflowTags().should('contain.text', 'some-tag-2');
}) });
it('should create a new workflow using add workflow button', () => { it('should create a new workflow using add workflow button', () => {
WorkflowsPage.getters.newWorkflowButtonCard().should('not.exist'); WorkflowsPage.getters.newWorkflowButtonCard().should('not.exist');
@ -46,24 +46,28 @@ describe('Workflows', () => {
WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-1'); WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-1');
WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-2'); WorkflowPage.getters.workflowTags().should('contain.text', 'other-tag-2');
}) });
it('should search for a workflow', () => { it('should search for a workflow', () => {
WorkflowsPage.getters.searchBar().type('Empty State Card Workflow'); WorkflowsPage.getters.searchBar().type('Empty State Card Workflow');
WorkflowsPage.getters.workflowCards().should('have.length', 1); WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters.workflowCard('Empty State Card Workflow').should('contain.text', 'Empty State Card Workflow'); WorkflowsPage.getters
.workflowCard('Empty State Card Workflow')
.should('contain.text', 'Empty State Card Workflow');
WorkflowsPage.getters.searchBar().clear().type('Add Workflow Button Workflow'); WorkflowsPage.getters.searchBar().clear().type('Add Workflow Button Workflow');
WorkflowsPage.getters.workflowCards().should('have.length', 1); WorkflowsPage.getters.workflowCards().should('have.length', 1);
WorkflowsPage.getters.workflowCard('Add Workflow Button Workflow').should('contain.text', 'Add Workflow Button Workflow'); WorkflowsPage.getters
.workflowCard('Add Workflow Button Workflow')
.should('contain.text', 'Add Workflow Button Workflow');
WorkflowsPage.getters.searchBar().clear().type('Some non-existent workflow'); WorkflowsPage.getters.searchBar().clear().type('Some non-existent workflow');
WorkflowsPage.getters.workflowCards().should('not.exist'); WorkflowsPage.getters.workflowCards().should('not.exist');
cy.contains('No workflows found').should('be.visible'); cy.contains('No workflows found').should('be.visible');
}) });
it('should delete all the workflows', () => { it('should delete all the workflows', () => {
WorkflowsPage.getters.workflowCards().should('have.length', 2); WorkflowsPage.getters.workflowCards().should('have.length', 2);
@ -75,15 +79,14 @@ describe('Workflows', () => {
WorkflowsPage.getters.workflowDeleteButton().click(); WorkflowsPage.getters.workflowDeleteButton().click();
cy.get('button').contains('delete').click(); cy.get('button').contains('delete').click();
}) });
WorkflowsPage.getters.newWorkflowButtonCard().should('be.visible'); WorkflowsPage.getters.newWorkflowButtonCard().should('be.visible');
WorkflowsPage.getters.newWorkflowTemplateCard().should('be.visible'); WorkflowsPage.getters.newWorkflowTemplateCard().should('be.visible');
}) });
it('should contain empty state cards', () => { it('should contain empty state cards', () => {
WorkflowsPage.getters.newWorkflowButtonCard().should('be.visible'); WorkflowsPage.getters.newWorkflowButtonCard().should('be.visible');
WorkflowsPage.getters.newWorkflowTemplateCard().should('be.visible'); WorkflowsPage.getters.newWorkflowTemplateCard().should('be.visible');
}); });
}); });

View file

@ -53,8 +53,10 @@ describe('Undo/Redo', () => {
it('should undo/redo deleting node using delete button', () => { it('should undo/redo deleting node using delete button', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.canvasNodeByName(CODE_NODE_NAME). WorkflowPage.getters
find('[data-test-id=delete-node-button]').click({ force: true }); .canvasNodeByName(CODE_NODE_NAME)
.find('[data-test-id=delete-node-button]')
.click({ force: true });
WorkflowPage.getters.canvasNodes().should('have.have.length', 1); WorkflowPage.getters.canvasNodes().should('have.have.length', 1);
WorkflowPage.getters.nodeConnections().should('have.length', 0); WorkflowPage.getters.nodeConnections().should('have.length', 0);
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
@ -117,11 +119,20 @@ describe('Undo/Redo', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', 50, 150); cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', 50, 150);
WorkflowPage.getters.canvasNodes().last().should('have.attr', 'style', 'left: 740px; top: 360px;'); WorkflowPage.getters
.canvasNodes()
.last()
.should('have.attr', 'style', 'left: 740px; top: 360px;');
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
WorkflowPage.getters.canvasNodes().last().should('have.attr', 'style', 'left: 640px; top: 260px;'); WorkflowPage.getters
.canvasNodes()
.last()
.should('have.attr', 'style', 'left: 640px; top: 260px;');
WorkflowPage.actions.hitRedo(); WorkflowPage.actions.hitRedo();
WorkflowPage.getters.canvasNodes().last().should('have.attr', 'style', 'left: 740px; top: 360px;'); WorkflowPage.getters
.canvasNodes()
.last()
.should('have.attr', 'style', 'left: 740px; top: 360px;');
}); });
it('should undo/redo deleting a connection by pressing delete button', () => { it('should undo/redo deleting a connection by pressing delete button', () => {
@ -144,13 +155,17 @@ describe('Undo/Redo', () => {
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
WorkflowPage.getters.nodeConnections().should('have.length', 1); WorkflowPage.getters.nodeConnections().should('have.length', 1);
WorkflowPage.actions.hitRedo(); WorkflowPage.actions.hitRedo();
WorkflowPage.getters.nodeConnections().should('have.length', 0) WorkflowPage.getters.nodeConnections().should('have.length', 0);
}); });
it('should undo/redo disabling a node using disable button', () => { it('should undo/redo disabling a node using disable button', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.canvasNodes().last().find('[data-test-id="disable-node-button"]').click({ force: true }); WorkflowPage.getters
.canvasNodes()
.last()
.find('[data-test-id="disable-node-button"]')
.click({ force: true });
WorkflowPage.getters.disabledNodes().should('have.length', 1); WorkflowPage.getters.disabledNodes().should('have.length', 1);
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
WorkflowPage.getters.disabledNodes().should('have.length', 0); WorkflowPage.getters.disabledNodes().should('have.length', 0);
@ -207,7 +222,7 @@ describe('Undo/Redo', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.canvasNodes().last().click(); WorkflowPage.getters.canvasNodes().last().click();
cy.get('body').trigger("keydown", { key: "F2" }); cy.get('body').trigger('keydown', { key: 'F2' });
cy.get('.rename-prompt').should('be.visible'); cy.get('.rename-prompt').should('be.visible');
cy.get('body').type(CODE_NODE_NEW_NAME); cy.get('body').type(CODE_NODE_NEW_NAME);
cy.get('body').type('{enter}'); cy.get('body').type('{enter}');
@ -222,7 +237,11 @@ describe('Undo/Redo', () => {
it('should undo/redo duplicating a node', () => { it('should undo/redo duplicating a node', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.canvasNodes().last().find('[data-test-id="duplicate-node-button"]').click({ force: true }); WorkflowPage.getters
.canvasNodes()
.last()
.find('[data-test-id="duplicate-node-button"]')
.click({ force: true });
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
WorkflowPage.getters.canvasNodes().should('have.length', 2); WorkflowPage.getters.canvasNodes().should('have.length', 2);
WorkflowPage.actions.hitRedo(); WorkflowPage.actions.hitRedo();
@ -230,7 +249,7 @@ describe('Undo/Redo', () => {
}); });
it('should undo/redo pasting nodes', () => { it('should undo/redo pasting nodes', () => {
cy.fixture('Test_workflow-actions_paste-data.json').then(data => { cy.fixture('Test_workflow-actions_paste-data.json').then((data) => {
cy.get('body').paste(JSON.stringify(data)); cy.get('body').paste(JSON.stringify(data));
WorkflowPage.actions.zoomToFit(); WorkflowPage.actions.zoomToFit();
WorkflowPage.getters.canvasNodes().should('have.have.length', 2); WorkflowPage.getters.canvasNodes().should('have.have.length', 2);
@ -264,7 +283,10 @@ describe('Undo/Redo', () => {
WorkflowPage.getters.nodeConnections().should('have.length', 3); WorkflowPage.getters.nodeConnections().should('have.length', 3);
// Second undo: Should move first node to it's original position // Second undo: Should move first node to it's original position
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', 'left: 420px; top: 260px;'); WorkflowPage.getters
.canvasNodes()
.first()
.should('have.attr', 'style', 'left: 420px; top: 260px;');
// Third undo: Should enable last node // Third undo: Should enable last node
WorkflowPage.actions.hitUndo(); WorkflowPage.actions.hitUndo();
WorkflowPage.getters.disabledNodes().should('have.length', 0); WorkflowPage.getters.disabledNodes().should('have.length', 0);
@ -274,7 +296,10 @@ describe('Undo/Redo', () => {
WorkflowPage.getters.disabledNodes().should('have.length', 1); WorkflowPage.getters.disabledNodes().should('have.length', 1);
// Second redo: Should move the first node // Second redo: Should move the first node
WorkflowPage.actions.hitRedo(); WorkflowPage.actions.hitRedo();
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', 'left: 540px; top: 400px;'); WorkflowPage.getters
.canvasNodes()
.first()
.should('have.attr', 'style', 'left: 540px; top: 400px;');
// Third redo: Should delete the Set node // Third redo: Should delete the Set node
WorkflowPage.actions.hitRedo(); WorkflowPage.actions.hitRedo();
WorkflowPage.getters.canvasNodes().should('have.length', 3); WorkflowPage.getters.canvasNodes().should('have.length', 3);

View file

@ -1,5 +1,5 @@
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from "../constants"; import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
import { randFirstName, randLastName } from "@ngneat/falso"; import { randFirstName, randLastName } from '@ngneat/falso';
import { CredentialsPage, CredentialsModal } from '../pages'; import { CredentialsPage, CredentialsModal } from '../pages';
const email = DEFAULT_USER_EMAIL; const email = DEFAULT_USER_EMAIL;
@ -20,7 +20,7 @@ describe('Credentials', () => {
expect(err.message).to.include('Not logged in'); expect(err.message).to.include('Not logged in');
return false; return false;
}) });
cy.signin({ email, password }); cy.signin({ email, password });
cy.visit(credentialsPage.url); cy.visit(credentialsPage.url);

View file

@ -1,8 +1,16 @@
import { randFirstName, randLastName } from '@ngneat/falso'; import { randFirstName, randLastName } from '@ngneat/falso';
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants'; import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
import { SettingsUsersPage, SignupPage, WorkflowsPage, WorkflowPage, CredentialsPage, CredentialsModal, MessageBox } from '../pages'; import {
SettingsUsersPage,
SignupPage,
WorkflowsPage,
WorkflowPage,
CredentialsPage,
CredentialsModal,
MessageBox,
} from '../pages';
import { MainSidebar, SettingsSidebar } from "../pages/sidebar"; import { MainSidebar, SettingsSidebar } from '../pages/sidebar';
const mainSidebar = new MainSidebar(); const mainSidebar = new MainSidebar();
const settingsSidebar = new SettingsSidebar(); const settingsSidebar = new SettingsSidebar();
@ -29,7 +37,7 @@ describe('Default owner', () => {
}); });
beforeEach(() => { beforeEach(() => {
cy.visit('/'); cy.visit('/');
}) });
it('should skip owner setup', () => { it('should skip owner setup', () => {
cy.skipSetup(); cy.skipSetup();
@ -84,7 +92,7 @@ describe('Default owner', () => {
it('should be able to setup instance and migrate workflows and credentials', () => { it('should be able to setup instance and migrate workflows and credentials', () => {
cy.setup({ email, firstName, lastName, password }); cy.setup({ email, firstName, lastName, password });
messageBox.getters.content().should('contain.text', '1 existing workflow and 1 credential') messageBox.getters.content().should('contain.text', '1 existing workflow and 1 credential');
messageBox.actions.confirm(); messageBox.actions.confirm();
cy.url().should('include', settingsUsersPage.url); cy.url().should('include', settingsUsersPage.url);
@ -106,4 +114,3 @@ describe('Default owner', () => {
credentialsPage.getters.credentialCards().should('have.length', 1); credentialsPage.getters.credentialCards().should('have.length', 1);
}); });
}); });

View file

@ -1,8 +1,8 @@
import { NodeCreator } from '../pages/features/node-creator'; import { NodeCreator } from '../pages/features/node-creator';
import { INodeTypeDescription } from '../../packages/workflow'; import { INodeTypeDescription } from '../../packages/workflow';
import CustomNodeFixture from '../fixtures/Custom_node.json'; import CustomNodeFixture from '../fixtures/Custom_node.json';
import {DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD} from "../constants"; import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
import {randFirstName, randLastName} from "@ngneat/falso"; import { randFirstName, randLastName } from '@ngneat/falso';
const email = DEFAULT_USER_EMAIL; const email = DEFAULT_USER_EMAIL;
const password = DEFAULT_USER_PASSWORD; const password = DEFAULT_USER_PASSWORD;
@ -21,15 +21,16 @@ describe('Node Creator', () => {
cy.intercept('GET', '/types/nodes.json', (req) => { cy.intercept('GET', '/types/nodes.json', (req) => {
// Delete caching headers so that we can intercept the request // Delete caching headers so that we can intercept the request
['etag', 'if-none-match', 'if-modified-since'].forEach(header => {delete req.headers[header]}); ['etag', 'if-none-match', 'if-modified-since'].forEach((header) => {
delete req.headers[header];
});
req.continue((res) => { req.continue((res) => {
const nodes = res.body as INodeTypeDescription[]; const nodes = res.body as INodeTypeDescription[];
nodes.push(CustomNodeFixture as INodeTypeDescription); nodes.push(CustomNodeFixture as INodeTypeDescription);
res.send(nodes) res.send(nodes);
}) });
}).as('nodesIntercept'); }).as('nodesIntercept');
cy.visit(nodeCreatorFeature.url); cy.visit(nodeCreatorFeature.url);
@ -39,10 +40,13 @@ describe('Node Creator', () => {
it('should open node creator on trigger tab if no trigger is on canvas', () => { it('should open node creator on trigger tab if no trigger is on canvas', () => {
nodeCreatorFeature.getters.canvasAddButton().click(); nodeCreatorFeature.getters.canvasAddButton().click();
nodeCreatorFeature.getters.nodeCreator().contains('When should this workflow run?').should('be.visible'); nodeCreatorFeature.getters
.nodeCreator()
.contains('When should this workflow run?')
.should('be.visible');
nodeCreatorFeature.getters.nodeCreatorTabs().should('not.exist'); nodeCreatorFeature.getters.nodeCreatorTabs().should('not.exist');
}) });
it('should see all tabs when opening via plus button', () => { it('should see all tabs when opening via plus button', () => {
nodeCreatorFeature.actions.openNodeCreator(); nodeCreatorFeature.actions.openNodeCreator();
@ -55,9 +59,9 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.getCreatorItem('On App Event').click(); nodeCreatorFeature.getters.getCreatorItem('On App Event').click();
nodeCreatorFeature.getters.activeSubcategory().should('have.text', 'On App Event'); nodeCreatorFeature.getters.activeSubcategory().should('have.text', 'On App Event');
// Go back // Go back
nodeCreatorFeature.getters.activeSubcategory().find('button').click() nodeCreatorFeature.getters.activeSubcategory().find('button').click();
nodeCreatorFeature.getters.activeSubcategory().should('not.exist'); nodeCreatorFeature.getters.activeSubcategory().should('not.exist');
}) });
it('should search for nodes', () => { it('should search for nodes', () => {
nodeCreatorFeature.actions.openNodeCreator(); nodeCreatorFeature.actions.openNodeCreator();
@ -67,22 +71,28 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.creatorItem().should('have.length', 1); nodeCreatorFeature.getters.creatorItem().should('have.length', 1);
nodeCreatorFeature.getters.searchBar().find('input').clear().type('manual123'); nodeCreatorFeature.getters.searchBar().find('input').clear().type('manual123');
nodeCreatorFeature.getters.creatorItem().should('have.length', 0); nodeCreatorFeature.getters.creatorItem().should('have.length', 0);
nodeCreatorFeature.getters.noResults() nodeCreatorFeature.getters
.noResults()
.should('exist') .should('exist')
.should('contain.text', 'We didn\'t make that... yet'); .should('contain.text', "We didn't make that... yet");
nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image'); nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image');
nodeCreatorFeature.getters.creatorItem().should('have.length', 1); nodeCreatorFeature.getters.creatorItem().should('have.length', 1);
nodeCreatorFeature.getters.searchBar().find('input').clear().type('this node totally does not exist'); nodeCreatorFeature.getters
.searchBar()
.find('input')
.clear()
.type('this node totally does not exist');
nodeCreatorFeature.getters.creatorItem().should('have.length', 0); nodeCreatorFeature.getters.creatorItem().should('have.length', 0);
nodeCreatorFeature.getters.searchBar().find('input').clear() nodeCreatorFeature.getters.searchBar().find('input').clear();
nodeCreatorFeature.getters.getCreatorItem('On App Event').click(); nodeCreatorFeature.getters.getCreatorItem('On App Event').click();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image'); nodeCreatorFeature.getters.searchBar().find('input').clear().type('edit image');
nodeCreatorFeature.getters.creatorItem().should('have.length', 0); nodeCreatorFeature.getters.creatorItem().should('have.length', 0);
nodeCreatorFeature.getters.noResults() nodeCreatorFeature.getters
.noResults()
.should('exist') .should('exist')
.should('contain.text', 'To see all results, click here'); .should('contain.text', 'To see all results, click here');
@ -91,8 +101,8 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.getCreatorItem('Edit Image').should('exist'); nodeCreatorFeature.getters.getCreatorItem('Edit Image').should('exist');
nodeCreatorFeature.getters.selectedTab().should('have.text', 'All'); nodeCreatorFeature.getters.selectedTab().should('have.text', 'All');
nodeCreatorFeature.getters.searchBar().find('button').click(); nodeCreatorFeature.getters.searchBar().find('button').click();
nodeCreatorFeature.getters.searchBar().find('input').should('be.empty') nodeCreatorFeature.getters.searchBar().find('input').should('be.empty');
}) });
it('should add manual trigger node', () => { it('should add manual trigger node', () => {
nodeCreatorFeature.getters.canvasAddButton().click(); nodeCreatorFeature.getters.canvasAddButton().click();
@ -105,8 +115,8 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.nodeCreator().should('not.exist'); nodeCreatorFeature.getters.nodeCreator().should('not.exist');
// TODO: Replace once we have canvas feature utils // TODO: Replace once we have canvas feature utils
cy.get('div').contains("Add first step").should('exist'); cy.get('div').contains('Add first step').should('exist');
}) });
it('check if non-core nodes are rendered', () => { it('check if non-core nodes are rendered', () => {
cy.wait('@nodesIntercept').then((interception) => { cy.wait('@nodesIntercept').then((interception) => {
const nodes = interception.response?.body as INodeTypeDescription[]; const nodes = interception.response?.body as INodeTypeDescription[];
@ -118,29 +128,29 @@ describe('Node Creator', () => {
const categories = Object.keys(categorizedNodes); const categories = Object.keys(categorizedNodes);
categories.forEach((category: string) => { categories.forEach((category: string) => {
// Core Nodes contains subcategories which we'll test separately // Core Nodes contains subcategories which we'll test separately
if(category === 'Core Nodes') return; if (category === 'Core Nodes') return;
nodeCreatorFeature.actions.toggleCategory(category) nodeCreatorFeature.actions.toggleCategory(category);
// Check if all nodes are present // Check if all nodes are present
nodeCreatorFeature.getters.nodeItemName().then($elements => { nodeCreatorFeature.getters.nodeItemName().then(($elements) => {
const visibleNodes: string[] = []; const visibleNodes: string[] = [];
$elements.each((_, element) => { $elements.each((_, element) => {
visibleNodes.push(element.textContent?.trim() || ''); visibleNodes.push(element.textContent?.trim() || '');
}) });
const visibleCategoryNodes = (categorizedNodes[category] as INodeTypeDescription[]) const visibleCategoryNodes = (categorizedNodes[category] as INodeTypeDescription[])
.filter(node => !node.hidden) .filter((node) => !node.hidden)
.map(node => node.displayName?.trim()); .map((node) => node.displayName?.trim());
cy.wrap(visibleCategoryNodes).each((categoryNode: string) => { cy.wrap(visibleCategoryNodes).each((categoryNode: string) => {
expect(visibleNodes).to.include(categoryNode); expect(visibleNodes).to.include(categoryNode);
}); });
}) });
nodeCreatorFeature.actions.toggleCategory(category) nodeCreatorFeature.actions.toggleCategory(category);
}) });
}) });
}) });
it('should render and select community node', () => { it('should render and select community node', () => {
cy.wait('@nodesIntercept').then(() => { cy.wait('@nodesIntercept').then(() => {
@ -154,19 +164,25 @@ describe('Node Creator', () => {
nodeCreatorFeature.getters.getCreatorItem(customCategory).should('exist'); nodeCreatorFeature.getters.getCreatorItem(customCategory).should('exist');
nodeCreatorFeature.actions.toggleCategory(customCategory); nodeCreatorFeature.actions.toggleCategory(customCategory);
nodeCreatorFeature.getters.getCreatorItem(customNode).findChildByTestId('node-creator-item-tooltip').should('exist'); nodeCreatorFeature.getters
nodeCreatorFeature.getters.getCreatorItem(customNode).contains(customNodeDescription).should('exist'); .getCreatorItem(customNode)
.findChildByTestId('node-creator-item-tooltip')
.should('exist');
nodeCreatorFeature.getters
.getCreatorItem(customNode)
.contains(customNodeDescription)
.should('exist');
nodeCreatorFeature.actions.selectNode(customNode); nodeCreatorFeature.actions.selectNode(customNode);
// TODO: Replace once we have canvas feature utils // TODO: Replace once we have canvas feature utils
cy.get('.data-display .node-name').contains(customNode).should('exist'); cy.get('.data-display .node-name').contains(customNode).should('exist');
const nodeParameters = () => cy.getByTestId('node-parameters') const nodeParameters = () => cy.getByTestId('node-parameters');
const firstParameter = () => nodeParameters().find('.parameter-item').eq(0); const firstParameter = () => nodeParameters().find('.parameter-item').eq(0);
const secondParameter = () => nodeParameters().find('.parameter-item').eq(1); const secondParameter = () => nodeParameters().find('.parameter-item').eq(1);
// Check correct fields are rendered // Check correct fields are rendered
nodeParameters().should('exist') nodeParameters().should('exist');
// Test property text input // Test property text input
firstParameter().contains('Test property').should('exist'); firstParameter().contains('Test property').should('exist');
firstParameter().find('input.el-input__inner').should('have.value', 'Some default'); firstParameter().find('input.el-input__inner').should('have.value', 'Some default');
@ -174,11 +190,17 @@ describe('Node Creator', () => {
secondParameter().find('label').contains('Resource').should('exist'); secondParameter().find('label').contains('Resource').should('exist');
secondParameter().find('input.el-input__inner').should('have.value', 'option2'); secondParameter().find('input.el-input__inner').should('have.value', 'option2');
secondParameter().find('.el-select').click(); secondParameter().find('.el-select').click();
secondParameter().find('.el-select-dropdown__list').should('exist') secondParameter().find('.el-select-dropdown__list').should('exist');
// Check if all options are rendered and select the fourth one // 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().should('have.length', 4);
secondParameter().find('.el-select-dropdown__list').children().eq(3).contains('option4').should('exist').click(); secondParameter()
.find('.el-select-dropdown__list')
.children()
.eq(3)
.contains('option4')
.should('exist')
.click();
secondParameter().find('input.el-input__inner').should('have.value', 'option4'); secondParameter().find('input.el-input__inner').should('have.value', 'option4');
}) });
}) });
}); });

View file

@ -18,7 +18,7 @@ describe('NDV', () => {
workflowPage.actions.addInitialNodeToCanvas('Manual Trigger'); workflowPage.actions.addInitialNodeToCanvas('Manual Trigger');
workflowPage.getters.canvasNodes().first().dblclick(); workflowPage.getters.canvasNodes().first().dblclick();
ndv.getters.container().should('be.visible'); ndv.getters.container().should('be.visible');
ndv.getters.backToCanvas().click() ndv.getters.backToCanvas().click();
ndv.getters.container().should('not.be.visible'); ndv.getters.container().should('not.be.visible');
}); });
@ -31,13 +31,13 @@ describe('NDV', () => {
cy.grantBrowserPermissions('clipboardReadWrite', 'clipboardSanitizedWrite'); cy.grantBrowserPermissions('clipboardReadWrite', 'clipboardSanitizedWrite');
cy.readClipboard().then(url => { cy.readClipboard().then((url) => {
cy.request({ cy.request({
method: 'GET', method: 'GET',
url, url,
}).then((resp) => { }).then((resp) => {
expect(resp.status).to.eq(200) expect(resp.status).to.eq(200);
}) });
}); });
ndv.getters.runDataDisplayMode().should('have.length.at.least', 1).and('be.visible'); ndv.getters.runDataDisplayMode().should('have.length.at.least', 1).and('be.visible');

View file

@ -53,7 +53,10 @@ describe('Workflow Actions', () => {
WorkflowPage.actions.saveWorkflowOnButtonClick(); WorkflowPage.actions.saveWorkflowOnButtonClick();
WorkflowPage.actions.renameWorkflow(NEW_WORKFLOW_NAME); WorkflowPage.actions.renameWorkflow(NEW_WORKFLOW_NAME);
WorkflowPage.getters.isWorkflowSaved(); WorkflowPage.getters.isWorkflowSaved();
WorkflowPage.getters.workflowNameInputContainer().invoke('attr', 'title').should('eq', NEW_WORKFLOW_NAME); WorkflowPage.getters
.workflowNameInputContainer()
.invoke('attr', 'title')
.should('eq', NEW_WORKFLOW_NAME);
}); });
it('should add tags', () => { it('should add tags', () => {
@ -97,7 +100,7 @@ describe('Workflow Actions', () => {
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME); WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
WorkflowPage.getters.canvasNodes().should('have.have.length', 2); WorkflowPage.getters.canvasNodes().should('have.have.length', 2);
cy.get("#node-creator").should('not.exist'); cy.get('#node-creator').should('not.exist');
cy.get('body').type(metaKey, { delay: 500, release: false }).type('a'); cy.get('body').type(metaKey, { delay: 500, release: false }).type('a');
cy.get('.jtk-drag-selected').should('have.length', 2); cy.get('.jtk-drag-selected').should('have.length', 2);
cy.get('body').type(metaKey, { delay: 500, release: false }).type('c'); cy.get('body').type(metaKey, { delay: 500, release: false }).type('c');
@ -105,7 +108,7 @@ describe('Workflow Actions', () => {
}); });
it('should paste nodes', () => { it('should paste nodes', () => {
cy.fixture('Test_workflow-actions_paste-data.json').then(data => { cy.fixture('Test_workflow-actions_paste-data.json').then((data) => {
cy.get('body').paste(JSON.stringify(data)); cy.get('body').paste(JSON.stringify(data));
WorkflowPage.getters.canvasNodes().should('have.have.length', 2); WorkflowPage.getters.canvasNodes().should('have.have.length', 2);
}); });
@ -126,10 +129,9 @@ describe('Workflow Actions', () => {
}); });
it('should import workflow from file', () => { it('should import workflow from file', () => {
WorkflowPage.getters.workflowImportInput().selectFile( WorkflowPage.getters
'cypress/fixtures/Test_workflow-actions_paste-data.json', .workflowImportInput()
{ force: true } .selectFile('cypress/fixtures/Test_workflow-actions_paste-data.json', { force: true });
);
cy.waitForLoad(); cy.waitForLoad();
WorkflowPage.actions.zoomToFit(); WorkflowPage.actions.zoomToFit();
WorkflowPage.getters.canvasNodes().should('have.length', 2); WorkflowPage.getters.canvasNodes().should('have.length', 2);
@ -145,17 +147,49 @@ describe('Workflow Actions', () => {
WorkflowPage.getters.workflowMenuItemSettings().click(); WorkflowPage.getters.workflowMenuItemSettings().click();
// Change all settings // Change all settings
WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().find('li').should('have.length', 2); WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().find('li').should('have.length', 2);
WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().find('li').last().click({ force: true }); WorkflowPage.getters
.workflowSettingsErrorWorkflowSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').should('exist'); WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').should('exist');
WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').eq(1).click({ force: true }); WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').eq(1).click({ force: true });
WorkflowPage.getters.workflowSettingsSaveFiledExecutionsSelect().find('li').should('have.length', 3); WorkflowPage.getters
WorkflowPage.getters.workflowSettingsSaveFiledExecutionsSelect().find('li').last().click({ force: true }); .workflowSettingsSaveFiledExecutionsSelect()
WorkflowPage.getters.workflowSettingsSaveSuccessExecutionsSelect().find('li').should('have.length', 3); .find('li')
WorkflowPage.getters.workflowSettingsSaveSuccessExecutionsSelect().find('li').last().click({ force: true }); .should('have.length', 3);
WorkflowPage.getters.workflowSettingsSaveManualExecutionsSelect().find('li').should('have.length', 3); WorkflowPage.getters
WorkflowPage.getters.workflowSettingsSaveManualExecutionsSelect().find('li').last().click({ force: true }); .workflowSettingsSaveFiledExecutionsSelect()
WorkflowPage.getters.workflowSettingsSaveExecutionProgressSelect().find('li').should('have.length', 3); .find('li')
WorkflowPage.getters.workflowSettingsSaveExecutionProgressSelect().find('li').last().click({ force: true }); .last()
.click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveSuccessExecutionsSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveSuccessExecutionsSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveManualExecutionsSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveManualExecutionsSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveExecutionProgressSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveExecutionProgressSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters.workflowSettingsTimeoutWorkflowSwitch().click(); WorkflowPage.getters.workflowSettingsTimeoutWorkflowSwitch().click();
WorkflowPage.getters.workflowSettingsTimeoutForm().find('input').first().type('1'); WorkflowPage.getters.workflowSettingsTimeoutForm().find('input').first().type('1');
// Save settings // Save settings
@ -163,5 +197,4 @@ describe('Workflow Actions', () => {
WorkflowPage.getters.workflowSettingsModal().should('not.exist'); WorkflowPage.getters.workflowSettingsModal().should('not.exist');
WorkflowPage.getters.successToast().should('exist'); WorkflowPage.getters.successToast().should('exist');
}); });
}); });

View file

@ -1,5 +1,6 @@
{ {
"properties": [{ "properties": [
{
"displayName": "Test property", "displayName": "Test property",
"name": "testProp", "name": "testProp",
"type": "string", "type": "string",
@ -12,7 +13,8 @@
"name": "resource", "name": "resource",
"type": "options", "type": "options",
"noDataExpression": true, "noDataExpression": true,
"options": [{ "options": [
{
"name": "option1", "name": "option1",
"value": "option1" "value": "option1"
}, },
@ -34,9 +36,7 @@
], ],
"displayName": "E2E Node", "displayName": "E2E Node",
"name": "@e2e/n8n-nodes-e2e", "name": "@e2e/n8n-nodes-e2e",
"group": [ "group": ["transform"],
"transform"
],
"codex": { "codex": {
"categories": ["Custom Category"] "categories": ["Custom Category"]
}, },
@ -45,11 +45,7 @@
"defaults": { "defaults": {
"name": "E2E Node " "name": "E2E Node "
}, },
"inputs": [ "inputs": ["main"],
"main" "outputs": ["main"],
],
"outputs": [
"main"
],
"icon": "fa:network-wired" "icon": "fa:network-wired"
} }

View file

@ -7,10 +7,7 @@
"name": "On clicking 'execute'", "name": "On clicking 'execute'",
"type": "n8n-nodes-base.manualTrigger", "type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1, "typeVersion": 1,
"position": [ "position": [600, 580]
600,
580
]
}, },
{ {
"parameters": { "parameters": {
@ -20,10 +17,7 @@
"name": "Set", "name": "Set",
"type": "n8n-nodes-base.set", "type": "n8n-nodes-base.set",
"typeVersion": 1, "typeVersion": 1,
"position": [ "position": [820, 580]
820,
580
]
}, },
{ {
"parameters": { "parameters": {
@ -33,10 +27,7 @@
"name": "Set1", "name": "Set1",
"type": "n8n-nodes-base.set", "type": "n8n-nodes-base.set",
"typeVersion": 1, "typeVersion": 1,
"position": [ "position": [1040, 580]
1040,
580
]
} }
], ],
"pinData": { "pinData": {

View file

@ -2,7 +2,8 @@
"meta": { "meta": {
"instanceId": "1a30c82b98a30444ad25bce513655a5e02be772d361403542c23172be6062f04" "instanceId": "1a30c82b98a30444ad25bce513655a5e02be772d361403542c23172be6062f04"
}, },
"nodes": [{ "nodes": [
{
"parameters": { "parameters": {
"rule": { "rule": {
"interval": [{}] "interval": [{}]
@ -13,7 +14,8 @@
"type": "n8n-nodes-base.scheduleTrigger", "type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1, "typeVersion": 1,
"position": [420, 260] "position": [420, 260]
}, { },
{
"parameters": { "parameters": {
"options": {} "options": {}
}, },
@ -22,15 +24,18 @@
"type": "n8n-nodes-base.set", "type": "n8n-nodes-base.set",
"typeVersion": 1, "typeVersion": 1,
"position": [640, 260] "position": [640, 260]
}], }
],
"connections": { "connections": {
"Schedule Trigger": { "Schedule Trigger": {
"main": [ "main": [
[{ [
{
"node": "Set", "node": "Set",
"type": "main", "type": "main",
"index": 0 "index": 0
}] }
]
] ]
} }
} }

View file

@ -1,4 +1,4 @@
import { IE2ETestPage, IE2ETestPageElement } from "../types"; import { IE2ETestPage, IE2ETestPageElement } from '../types';
export class BasePage implements IE2ETestPage { export class BasePage implements IE2ETestPage {
getters: Record<string, IE2ETestPageElement> = {}; getters: Record<string, IE2ETestPageElement> = {};

View file

@ -1,4 +1,4 @@
import { BasePage } from "./base"; import { BasePage } from './base';
export class CredentialsPage extends BasePage { export class CredentialsPage extends BasePage {
url = '/credentials'; url = '/credentials';
@ -8,12 +8,15 @@ export class CredentialsPage extends BasePage {
searchInput: () => cy.getByTestId('resources-list-search'), searchInput: () => cy.getByTestId('resources-list-search'),
emptyList: () => cy.getByTestId('resources-list-empty'), emptyList: () => cy.getByTestId('resources-list-empty'),
credentialCards: () => cy.getByTestId('resources-list-item'), credentialCards: () => cy.getByTestId('resources-list-item'),
credentialCard: (credentialName: string) => this.getters.credentialCards() credentialCard: (credentialName: string) =>
this.getters
.credentialCards()
.contains(credentialName) .contains(credentialName)
.parents('[data-test-id="resources-list-item"]'), .parents('[data-test-id="resources-list-item"]'),
credentialCardActions: (credentialName: string) => this.getters.credentialCard(credentialName) credentialCardActions: (credentialName: string) =>
.findChildByTestId('credential-card-actions'), this.getters.credentialCard(credentialName).findChildByTestId('credential-card-actions'),
credentialDeleteButton: () => cy.getByTestId('action-toggle-dropdown').filter(':visible').contains('Delete'), credentialDeleteButton: () =>
cy.getByTestId('action-toggle-dropdown').filter(':visible').contains('Delete'),
sort: () => cy.getByTestId('resources-list-sort'), sort: () => cy.getByTestId('resources-list-sort'),
sortOption: (label: string) => this.getters.sort().contains(label).first(), sortOption: (label: string) => this.getters.sort().contains(label).first(),
filtersTrigger: () => cy.getByTestId('resources-list-filters-trigger'), filtersTrigger: () => cy.getByTestId('resources-list-filters-trigger'),

View file

@ -1,4 +1,4 @@
import { BasePage } from "../base"; import { BasePage } from '../base';
import { INodeTypeDescription } from '../../packages/workflow'; import { INodeTypeDescription } from '../../packages/workflow';
export class NodeCreator extends BasePage { export class NodeCreator extends BasePage {
@ -7,7 +7,8 @@ export class NodeCreator extends BasePage {
plusButton: () => cy.getByTestId('node-creator-plus-button'), plusButton: () => cy.getByTestId('node-creator-plus-button'),
canvasAddButton: () => cy.getByTestId('canvas-add-button'), canvasAddButton: () => cy.getByTestId('canvas-add-button'),
searchBar: () => cy.getByTestId('search-bar'), searchBar: () => cy.getByTestId('search-bar'),
getCreatorItem: (label: string) => this.getters.creatorItem().contains(label).parents('[data-test-id="item-iterator-item"]'), getCreatorItem: (label: string) =>
this.getters.creatorItem().contains(label).parents('[data-test-id="item-iterator-item"]'),
getNthCreatorItem: (n: number) => this.getters.creatorItem().eq(n), getNthCreatorItem: (n: number) => this.getters.creatorItem().eq(n),
nodeCreator: () => cy.getByTestId('node-creator'), nodeCreator: () => cy.getByTestId('node-creator'),
nodeCreatorTabs: () => cy.getByTestId('node-creator-type-selector'), nodeCreatorTabs: () => cy.getByTestId('node-creator-type-selector'),
@ -18,13 +19,14 @@ export class NodeCreator extends BasePage {
noResults: () => cy.getByTestId('categorized-no-results'), noResults: () => cy.getByTestId('categorized-no-results'),
nodeItemName: () => cy.getByTestId('node-creator-item-name'), nodeItemName: () => cy.getByTestId('node-creator-item-name'),
activeSubcategory: () => cy.getByTestId('categorized-items-subcategory'), activeSubcategory: () => cy.getByTestId('categorized-items-subcategory'),
expandedCategories: () => this.getters.creatorItem().find('>div').filter('.active').invoke('text'), expandedCategories: () =>
this.getters.creatorItem().find('>div').filter('.active').invoke('text'),
}; };
actions = { actions = {
openNodeCreator: () => { openNodeCreator: () => {
cy.waitForLoad(); cy.waitForLoad();
this.getters.plusButton().click(); this.getters.plusButton().click();
this.getters.nodeCreator().should('be.visible') this.getters.nodeCreator().should('be.visible');
}, },
selectNode: (displayName: string) => { selectNode: (displayName: string) => {
this.getters.getCreatorItem(displayName).click(); this.getters.getCreatorItem(displayName).click();
@ -33,15 +35,20 @@ export class NodeCreator extends BasePage {
this.getters.nodeCreatorTabs().contains(tab).click(); this.getters.nodeCreatorTabs().contains(tab).click();
}, },
toggleCategory: (category: string) => { toggleCategory: (category: string) => {
this.getters.getCreatorItem(category).click() this.getters.getCreatorItem(category).click();
}, },
categorizeNodes: (nodes: INodeTypeDescription[]) => { categorizeNodes: (nodes: INodeTypeDescription[]) => {
const categorizedNodes = nodes.reduce((acc, node) => { const categorizedNodes = nodes.reduce((acc, node) => {
const categories = (node?.codex?.categories || []).map((category: string) => category.trim()); const categories = (node?.codex?.categories || []).map((category: string) =>
category.trim(),
);
categories.forEach((category: {[key: string]: INodeTypeDescription[]}) => { categories.forEach((category: { [key: string]: INodeTypeDescription[] }) => {
// Node creator should show only the latest version of a node // Node creator should show only the latest version of a node
const newerVersion = nodes.find((n: INodeTypeDescription) => n.name === node.name && (n.version > node.version || Array.isArray(n.version))); const newerVersion = nodes.find(
(n: INodeTypeDescription) =>
n.name === node.name && (n.version > node.version || Array.isArray(n.version)),
);
if (acc[category] === undefined) { if (acc[category] === undefined) {
acc[category] = []; acc[category] = [];
@ -49,9 +56,9 @@ export class NodeCreator extends BasePage {
acc[category].push(newerVersion ?? node); acc[category].push(newerVersion ?? node);
}); });
return acc; return acc;
}, {}) }, {});
return categorizedNodes; return categorizedNodes;
} },
}; };
} }

View file

@ -1,14 +1,18 @@
import { BasePage } from "../base"; import { BasePage } from '../base';
export class CredentialsModal extends BasePage { export class CredentialsModal extends BasePage {
getters = { getters = {
newCredentialModal: () => cy.getByTestId('selectCredential-modal', { timeout: 5000 }), newCredentialModal: () => cy.getByTestId('selectCredential-modal', { timeout: 5000 }),
editCredentialModal: () => cy.getByTestId('editCredential-modal', { timeout: 5000 }), editCredentialModal: () => cy.getByTestId('editCredential-modal', { timeout: 5000 }),
newCredentialTypeSelect: () => cy.getByTestId('new-credential-type-select'), newCredentialTypeSelect: () => cy.getByTestId('new-credential-type-select'),
newCredentialTypeOption: (credentialType: string) => cy.getByTestId('new-credential-type-select-option').contains(credentialType), newCredentialTypeOption: (credentialType: string) =>
cy.getByTestId('new-credential-type-select-option').contains(credentialType),
newCredentialTypeButton: () => cy.getByTestId('new-credential-type-button'), newCredentialTypeButton: () => cy.getByTestId('new-credential-type-button'),
connectionParameters: () => cy.getByTestId('credential-connection-parameter'), connectionParameters: () => cy.getByTestId('credential-connection-parameter'),
connectionParameter: (fieldName: string) => this.getters.connectionParameters().contains(fieldName) connectionParameter: (fieldName: string) =>
this.getters
.connectionParameters()
.contains(fieldName)
.parents('[data-test-id="credential-connection-parameter"]') .parents('[data-test-id="credential-connection-parameter"]')
.find('.n8n-input input'), .find('.n8n-input input'),
name: () => cy.getByTestId('credential-name'), name: () => cy.getByTestId('credential-name'),
@ -24,14 +28,14 @@ export class CredentialsModal extends BasePage {
}, },
save: (test = false) => { save: (test = false) => {
cy.intercept('POST', '/rest/credentials').as('saveCredential'); cy.intercept('POST', '/rest/credentials').as('saveCredential');
if(test) { if (test) {
cy.intercept('POST', '/rest/credentials/test').as('testCredential'); cy.intercept('POST', '/rest/credentials/test').as('testCredential');
} }
this.getters.saveButton().click(); this.getters.saveButton().click();
cy.wait('@saveCredential'); cy.wait('@saveCredential');
if(test) cy.wait('@testCredential') if (test) cy.wait('@testCredential');
this.getters.saveButton().should('contain.text', 'Saved'); this.getters.saveButton().should('contain.text', 'Saved');
}, },
close: () => { close: () => {

View file

@ -1,4 +1,4 @@
import { BasePage } from "../base"; import { BasePage } from '../base';
export class MessageBox extends BasePage { export class MessageBox extends BasePage {
getters = { getters = {

View file

@ -1,4 +1,4 @@
import { BasePage } from "./base"; import { BasePage } from './base';
export class NDV extends BasePage { export class NDV extends BasePage {
getters = { getters = {
@ -12,5 +12,5 @@ export class NDV extends BasePage {
dataContainer: () => cy.getByTestId('ndv-data-container'), dataContainer: () => cy.getByTestId('ndv-data-container'),
runDataDisplayMode: () => cy.getByTestId('ndv-run-data-display-mode'), runDataDisplayMode: () => cy.getByTestId('ndv-run-data-display-mode'),
digital: () => cy.getByTestId('ndv-run-data-display-mode'), digital: () => cy.getByTestId('ndv-run-data-display-mode'),
} };
} }

View file

@ -1,11 +1,11 @@
import { BasePage } from "./base"; import { BasePage } from './base';
export class SettingsUsersPage extends BasePage { export class SettingsUsersPage extends BasePage {
url = '/settings/users'; url = '/settings/users';
getters = { getters = {
setUpOwnerButton: () => cy.getByTestId('action-box').find('button'), setUpOwnerButton: () => cy.getByTestId('action-box').find('button'),
} };
actions = { actions = {
goToOwnerSetup: () => this.getters.setUpOwnerButton().click(), goToOwnerSetup: () => this.getters.setUpOwnerButton().click(),
} };
} }

View file

@ -1,8 +1,9 @@
import { BasePage } from "../base"; import { BasePage } from '../base';
export class MainSidebar extends BasePage { export class MainSidebar extends BasePage {
getters = { getters = {
menuItem: (menuLabel: string) => cy.getByTestId('menu-item').filter(`:contains("${menuLabel}")`), menuItem: (menuLabel: string) =>
cy.getByTestId('menu-item').filter(`:contains("${menuLabel}")`),
settings: () => this.getters.menuItem('Settings'), settings: () => this.getters.menuItem('Settings'),
templates: () => this.getters.menuItem('Templates'), templates: () => this.getters.menuItem('Templates'),
workflows: () => this.getters.menuItem('Workflows'), workflows: () => this.getters.menuItem('Workflows'),
@ -19,7 +20,7 @@ export class MainSidebar extends BasePage {
goToCredentials: () => { goToCredentials: () => {
this.getters.credentials().should('be.visible'); this.getters.credentials().should('be.visible');
cy.get('[data-old-overflow]').should('not.exist'); cy.get('[data-old-overflow]').should('not.exist');
this.getters.credentials().click() this.getters.credentials().click();
}, },
}; };
} }

View file

@ -1,4 +1,4 @@
import { BasePage } from "../base"; import { BasePage } from '../base';
export class SettingsSidebar extends BasePage { export class SettingsSidebar extends BasePage {
getters = { getters = {

View file

@ -1,4 +1,4 @@
import { BasePage } from "./base"; import { BasePage } from './base';
export class SigninPage extends BasePage { export class SigninPage extends BasePage {
url = '/signin'; url = '/signin';
@ -7,5 +7,5 @@ export class SigninPage extends BasePage {
email: () => cy.getByTestId('email'), email: () => cy.getByTestId('email'),
password: () => cy.getByTestId('password'), password: () => cy.getByTestId('password'),
submit: () => cy.get('button'), submit: () => cy.get('button'),
} };
} }

View file

@ -1,4 +1,4 @@
import { BasePage } from "./base"; import { BasePage } from './base';
// todo rename to setup // todo rename to setup
export class SignupPage extends BasePage { export class SignupPage extends BasePage {
@ -11,5 +11,5 @@ export class SignupPage extends BasePage {
password: () => cy.getByTestId('password'), password: () => cy.getByTestId('password'),
submit: () => cy.get('button'), submit: () => cy.get('button'),
skip: () => cy.get('a'), skip: () => cy.get('a'),
} };
} }

View file

@ -4,13 +4,16 @@ export class WorkflowPage extends BasePage {
url = '/workflow/new'; url = '/workflow/new';
getters = { getters = {
workflowNameInputContainer: () => cy.getByTestId('workflow-name-input', { timeout: 5000 }), workflowNameInputContainer: () => cy.getByTestId('workflow-name-input', { timeout: 5000 }),
workflowNameInput: () => this.getters.workflowNameInputContainer().then(($el) => cy.wrap($el.find('input'))), workflowNameInput: () =>
this.getters.workflowNameInputContainer().then(($el) => cy.wrap($el.find('input'))),
workflowImportInput: () => cy.getByTestId('workflow-import-input'), workflowImportInput: () => cy.getByTestId('workflow-import-input'),
workflowTags: () => cy.getByTestId('workflow-tags'), workflowTags: () => cy.getByTestId('workflow-tags'),
workflowTagsContainer: () => cy.getByTestId('workflow-tags-container'), workflowTagsContainer: () => cy.getByTestId('workflow-tags-container'),
workflowTagsInput: () => this.getters.workflowTagsContainer().then(($el) => cy.wrap($el.find('input').first())), workflowTagsInput: () =>
this.getters.workflowTagsContainer().then(($el) => cy.wrap($el.find('input').first())),
workflowTagElements: () => cy.get('[data-test-id="workflow-tags-container"] span.tags > span'), workflowTagElements: () => cy.get('[data-test-id="workflow-tags-container"] span.tags > span'),
firstWorkflowTagElement: () => cy.get('[data-test-id="workflow-tags-container"] span.tags > span:nth-child(1)'), firstWorkflowTagElement: () =>
cy.get('[data-test-id="workflow-tags-container"] span.tags > span:nth-child(1)'),
workflowTagsDropdown: () => cy.getByTestId('workflow-tags-dropdown'), workflowTagsDropdown: () => cy.getByTestId('workflow-tags-dropdown'),
newTagLink: () => cy.getByTestId('new-tag-link'), newTagLink: () => cy.getByTestId('new-tag-link'),
saveButton: () => cy.getByTestId('workflow-save-button'), saveButton: () => cy.getByTestId('workflow-save-button'),
@ -18,7 +21,8 @@ export class WorkflowPage extends BasePage {
nodeCreatorPlusButton: () => cy.getByTestId('node-creator-plus-button'), nodeCreatorPlusButton: () => cy.getByTestId('node-creator-plus-button'),
canvasPlusButton: () => cy.getByTestId('canvas-plus-button'), canvasPlusButton: () => cy.getByTestId('canvas-plus-button'),
canvasNodes: () => cy.getByTestId('canvas-node'), canvasNodes: () => cy.getByTestId('canvas-node'),
canvasNodeByName: (nodeName: string) => this.getters.canvasNodes().filter(`:contains("${nodeName}")`), canvasNodeByName: (nodeName: string) =>
this.getters.canvasNodes().filter(`:contains("${nodeName}")`),
ndvParameterInput: (parameterName: string) => ndvParameterInput: (parameterName: string) =>
cy.getByTestId(`parameter-input-${parameterName}`), cy.getByTestId(`parameter-input-${parameterName}`),
ndvOutputPanel: () => cy.getByTestId('output-panel'), ndvOutputPanel: () => cy.getByTestId('output-panel'),
@ -51,13 +55,19 @@ export class WorkflowPage extends BasePage {
workflowSettingsModal: () => cy.getByTestId('workflow-settings-dialog'), workflowSettingsModal: () => cy.getByTestId('workflow-settings-dialog'),
workflowSettingsErrorWorkflowSelect: () => cy.getByTestId('workflow-settings-error-workflow'), workflowSettingsErrorWorkflowSelect: () => cy.getByTestId('workflow-settings-error-workflow'),
workflowSettingsTimezoneSelect: () => cy.getByTestId('workflow-settings-timezone'), workflowSettingsTimezoneSelect: () => cy.getByTestId('workflow-settings-timezone'),
workflowSettingsSaveFiledExecutionsSelect: () => cy.getByTestId('workflow-settings-save-failed-executions'), workflowSettingsSaveFiledExecutionsSelect: () =>
workflowSettingsSaveSuccessExecutionsSelect: () => cy.getByTestId('workflow-settings-save-success-executions'), cy.getByTestId('workflow-settings-save-failed-executions'),
workflowSettingsSaveManualExecutionsSelect: () => cy.getByTestId('workflow-settings-save-manual-executions'), workflowSettingsSaveSuccessExecutionsSelect: () =>
workflowSettingsSaveExecutionProgressSelect: () => cy.getByTestId('workflow-settings-save-execution-progress'), cy.getByTestId('workflow-settings-save-success-executions'),
workflowSettingsTimeoutWorkflowSwitch: () => cy.getByTestId('workflow-settings-timeout-workflow'), workflowSettingsSaveManualExecutionsSelect: () =>
cy.getByTestId('workflow-settings-save-manual-executions'),
workflowSettingsSaveExecutionProgressSelect: () =>
cy.getByTestId('workflow-settings-save-execution-progress'),
workflowSettingsTimeoutWorkflowSwitch: () =>
cy.getByTestId('workflow-settings-timeout-workflow'),
workflowSettingsTimeoutForm: () => cy.getByTestId('workflow-settings-timeout-form'), workflowSettingsTimeoutForm: () => cy.getByTestId('workflow-settings-timeout-form'),
workflowSettingsSaveButton: () => cy.getByTestId('workflow-settings-save-button').find('button'), workflowSettingsSaveButton: () =>
cy.getByTestId('workflow-settings-save-button').find('button'),
inlineExpressionEditorInput: () => cy.getByTestId('inline-expression-editor-input'), inlineExpressionEditorInput: () => cy.getByTestId('inline-expression-editor-input'),
inlineExpressionEditorOutput: () => cy.getByTestId('inline-expression-editor-output'), inlineExpressionEditorOutput: () => cy.getByTestId('inline-expression-editor-output'),
@ -124,7 +134,7 @@ export class WorkflowPage extends BasePage {
cy.get('body').type('{enter}'); cy.get('body').type('{enter}');
}, },
addTags: (tags: string[]) => { addTags: (tags: string[]) => {
tags.forEach(tag => { tags.forEach((tag) => {
this.getters.workflowTagsInput().type(tag); this.getters.workflowTagsInput().type(tag);
this.getters.workflowTagsInput().type('{enter}'); this.getters.workflowTagsInput().type('{enter}');
}); });
@ -142,10 +152,10 @@ export class WorkflowPage extends BasePage {
}, },
hitRedo: () => { hitRedo: () => {
const metaKey = Cypress.platform === 'darwin' ? '{meta}' : '{ctrl}'; const metaKey = Cypress.platform === 'darwin' ? '{meta}' : '{ctrl}';
cy.get('body'). cy.get('body')
type(metaKey, { delay: 500, release: false }). .type(metaKey, { delay: 500, release: false })
type('{shift}', { release: false }). .type('{shift}', { release: false })
type('z'); .type('z');
}, },
selectAll: () => { selectAll: () => {
const metaKey = Cypress.platform === 'darwin' ? '{meta}' : '{ctrl}'; const metaKey = Cypress.platform === 'darwin' ? '{meta}' : '{ctrl}';

View file

@ -1,4 +1,4 @@
import { BasePage } from "./base"; import { BasePage } from './base';
export class WorkflowsPage extends BasePage { export class WorkflowsPage extends BasePage {
url = '/workflows'; url = '/workflows';
@ -8,18 +8,21 @@ export class WorkflowsPage extends BasePage {
searchBar: () => cy.getByTestId('resources-list-search'), searchBar: () => cy.getByTestId('resources-list-search'),
createWorkflowButton: () => cy.getByTestId('resources-list-add'), createWorkflowButton: () => cy.getByTestId('resources-list-add'),
workflowCards: () => cy.getByTestId('resources-list-item'), workflowCards: () => cy.getByTestId('resources-list-item'),
workflowCard: (workflowName: string) => this.getters.workflowCards() workflowCard: (workflowName: string) =>
this.getters
.workflowCards()
.contains(workflowName) .contains(workflowName)
.parents('[data-test-id="resources-list-item"]'), .parents('[data-test-id="resources-list-item"]'),
workflowTags: (workflowName: string) => this.getters.workflowCard(workflowName) workflowTags: (workflowName: string) =>
.findChildByTestId('workflow-card-tags'), this.getters.workflowCard(workflowName).findChildByTestId('workflow-card-tags'),
workflowActivator: (workflowName: string) => this.getters.workflowCard(workflowName) workflowActivator: (workflowName: string) =>
.findChildByTestId('workflow-card-activator'), this.getters.workflowCard(workflowName).findChildByTestId('workflow-card-activator'),
workflowActivatorStatus: (workflowName: string) => this.getters.workflowActivator(workflowName) workflowActivatorStatus: (workflowName: string) =>
.findChildByTestId('workflow-activator-status'), this.getters.workflowActivator(workflowName).findChildByTestId('workflow-activator-status'),
workflowCardActions: (workflowName: string) => this.getters.workflowCard(workflowName) workflowCardActions: (workflowName: string) =>
.findChildByTestId('workflow-card-actions'), this.getters.workflowCard(workflowName).findChildByTestId('workflow-card-actions'),
workflowDeleteButton: () => cy.getByTestId('action-toggle-dropdown').filter(':visible').contains('Delete') workflowDeleteButton: () =>
cy.getByTestId('action-toggle-dropdown').filter(':visible').contains('Delete'),
// Not yet implemented // Not yet implemented
// myWorkflows: () => cy.getByTestId('my-workflows'), // myWorkflows: () => cy.getByTestId('my-workflows'),
// allWorkflows: () => cy.getByTestId('all-workflows'), // allWorkflows: () => cy.getByTestId('all-workflows'),
@ -35,6 +38,6 @@ export class WorkflowsPage extends BasePage {
this.getters.workflowDeleteButton().click(); this.getters.workflowDeleteButton().click();
cy.get('button').contains('delete').click(); cy.get('button').contains('delete').click();
} },
} };
} }

View file

@ -24,44 +24,50 @@
// -- This will overwrite an existing command -- // -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
import { WorkflowsPage, SigninPage, SignupPage } from "../pages"; import { WorkflowsPage, SigninPage, SignupPage } from '../pages';
import { N8N_AUTH_COOKIE } from "../constants"; import { N8N_AUTH_COOKIE } from '../constants';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow'; import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { MessageBox } from '../pages/modals/message-box'; import { MessageBox } from '../pages/modals/message-box';
Cypress.Commands.add('getByTestId', (selector, ...args) => { Cypress.Commands.add('getByTestId', (selector, ...args) => {
return cy.get(`[data-test-id="${selector}"]`, ...args) return cy.get(`[data-test-id="${selector}"]`, ...args);
}) });
Cypress.Commands.add('createFixtureWorkflow', (fixtureKey, workflowName) => { Cypress.Commands.add('createFixtureWorkflow', (fixtureKey, workflowName) => {
const WorkflowPage = new WorkflowPageClass() const WorkflowPage = new WorkflowPageClass();
// We need to force the click because the input is hidden // We need to force the click because the input is hidden
WorkflowPage.getters.workflowImportInput().selectFile(`cypress/fixtures/${fixtureKey}`, { force: true}); WorkflowPage.getters
.workflowImportInput()
.selectFile(`cypress/fixtures/${fixtureKey}`, { force: true });
WorkflowPage.getters.workflowNameInput().should('be.disabled'); WorkflowPage.getters.workflowNameInput().should('be.disabled');
WorkflowPage.getters.workflowNameInput().parent().click() WorkflowPage.getters.workflowNameInput().parent().click();
WorkflowPage.getters.workflowNameInput().should('be.enabled'); WorkflowPage.getters.workflowNameInput().should('be.enabled');
WorkflowPage.getters.workflowNameInput().clear().type(workflowName).type('{enter}'); WorkflowPage.getters.workflowNameInput().clear().type(workflowName).type('{enter}');
WorkflowPage.getters.saveButton().should('contain', 'Saved'); WorkflowPage.getters.saveButton().should('contain', 'Saved');
}) });
Cypress.Commands.add('findChildByTestId', { prevSubject: true }, (subject: Cypress.Chainable<JQuery<HTMLElement>>, childTestId) => { Cypress.Commands.add(
'findChildByTestId',
{ prevSubject: true },
(subject: Cypress.Chainable<JQuery<HTMLElement>>, childTestId) => {
return subject.find(`[data-test-id="${childTestId}"]`); return subject.find(`[data-test-id="${childTestId}"]`);
}) },
);
Cypress.Commands.add('waitForLoad', () => { Cypress.Commands.add('waitForLoad', () => {
cy.getByTestId('node-view-loader').should('not.exist', { timeout: 10000 }); cy.getByTestId('node-view-loader').should('not.exist', { timeout: 10000 });
cy.get('.el-loading-mask').should('not.exist', { timeout: 10000 }); cy.get('.el-loading-mask').should('not.exist', { timeout: 10000 });
}) });
Cypress.Commands.add( Cypress.Commands.add('signin', ({ email, password }) => {
'signin',
({ email, password }) => {
const signinPage = new SigninPage(); const signinPage = new SigninPage();
const workflowsPage = new WorkflowsPage(); const workflowsPage = new WorkflowsPage();
cy.session([email, password], () => { cy.session(
[email, password],
() => {
cy.visit(signinPage.url); cy.visit(signinPage.url);
signinPage.getters.form().within(() => { signinPage.getters.form().within(() => {
@ -77,7 +83,8 @@ Cypress.Commands.add(
validate() { validate() {
cy.getCookie(N8N_AUTH_COOKIE).should('exist'); cy.getCookie(N8N_AUTH_COOKIE).should('exist');
}, },
}); },
);
}); });
Cypress.Commands.add('setup', ({ email, firstName, lastName, password }) => { Cypress.Commands.add('setup', ({ email, firstName, lastName, password }) => {
@ -98,7 +105,7 @@ Cypress.Commands.add('setup', ({ email, firstName, lastName, password }) => {
} }
}); });
}); });
}) });
Cypress.Commands.add('skipSetup', () => { Cypress.Commands.add('skipSetup', () => {
const signupPage = new SignupPage(); const signupPage = new SignupPage();
@ -112,7 +119,6 @@ Cypress.Commands.add('skipSetup', () => {
if (url.endsWith(signupPage.url)) { if (url.endsWith(signupPage.url)) {
signupPage.getters.skip().click(); signupPage.getters.skip().click();
Confirmation.getters.header().should('contain.text', 'Skip owner account setup?'); Confirmation.getters.header().should('contain.text', 'Skip owner account setup?');
Confirmation.actions.confirm(); Confirmation.actions.confirm();
@ -123,7 +129,7 @@ Cypress.Commands.add('skipSetup', () => {
} }
}); });
}); });
}) });
Cypress.Commands.add('resetAll', () => { Cypress.Commands.add('resetAll', () => {
cy.task('reset'); cy.task('reset');
@ -135,25 +141,29 @@ Cypress.Commands.add('setupOwner', (payload) => {
}); });
Cypress.Commands.add('grantBrowserPermissions', (...permissions: string[]) => { Cypress.Commands.add('grantBrowserPermissions', (...permissions: string[]) => {
if(Cypress.isBrowser('chrome')) { if (Cypress.isBrowser('chrome')) {
cy.wrap(Cypress.automation('remote:debugger:protocol', { cy.wrap(
Cypress.automation('remote:debugger:protocol', {
command: 'Browser.grantPermissions', command: 'Browser.grantPermissions',
params: { params: {
permissions, permissions,
origin: window.location.origin, origin: window.location.origin,
}, },
})); }),
);
} }
}); });
Cypress.Commands.add('readClipboard', () => cy.window().its('navigator.clipboard').invoke('readText')); Cypress.Commands.add('readClipboard', () =>
cy.window().its('navigator.clipboard').invoke('readText'),
);
Cypress.Commands.add('paste', { prevSubject: true }, (selector, pastePayload) => { Cypress.Commands.add('paste', { prevSubject: true }, (selector, pastePayload) => {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event // https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event
cy.wrap(selector).then($destination => { cy.wrap(selector).then(($destination) => {
const pasteEvent = Object.assign(new Event('paste', { bubbles: true, cancelable: true }), { const pasteEvent = Object.assign(new Event('paste', { bubbles: true, cancelable: true }), {
clipboardData: { clipboardData: {
getData: () => pastePayload getData: () => pastePayload,
} },
}); });
$destination[0].dispatchEvent(pasteEvent); $destination[0].dispatchEvent(pasteEvent);
}); });

View file

@ -13,5 +13,4 @@
// https://on.cypress.io/configuration // https://on.cypress.io/configuration
// *********************************************************** // ***********************************************************
import './commands' import './commands';

View file

@ -16,8 +16,11 @@ interface SetupPayload {
declare global { declare global {
namespace Cypress { namespace Cypress {
interface Chainable { interface Chainable {
getByTestId(selector: string, ...args: (Partial<Loggable & Timeoutable & Withinable & Shadow> | undefined)[]): Chainable<JQuery<HTMLElement>> getByTestId(
findChildByTestId(childTestId: string): Chainable<JQuery<HTMLElement>> selector: string,
...args: (Partial<Loggable & Timeoutable & Withinable & Shadow> | undefined)[]
): Chainable<JQuery<HTMLElement>>;
findChildByTestId(childTestId: string): Chainable<JQuery<HTMLElement>>;
createFixtureWorkflow(fixtureKey: string, workflowName: string): void; createFixtureWorkflow(fixtureKey: string, workflowName: string): void;
signin(payload: SigninPayload): void; signin(payload: SigninPayload): void;
setup(payload: SetupPayload): void; setup(payload: SetupPayload): void;
@ -27,8 +30,8 @@ declare global {
waitForLoad(): void; waitForLoad(): void;
grantBrowserPermissions(...permissions: string[]): void; grantBrowserPermissions(...permissions: string[]): void;
readClipboard(): Chainable<string>; readClipboard(): Chainable<string>;
paste(pastePayload: string): void, paste(pastePayload: string): void;
drag(selector: string, xDiff: number, yDiff: number): void, drag(selector: string, xDiff: number, yDiff: number): void;
} }
} }
} }

View file

@ -1,4 +1,6 @@
export type IE2ETestPageElement = (...args: any[]) => export type IE2ETestPageElement = (
...args: any[]
) =>
| Cypress.Chainable<JQuery<HTMLElement>> | Cypress.Chainable<JQuery<HTMLElement>>
| Cypress.Chainable<JQuery<HTMLInputElement>> | Cypress.Chainable<JQuery<HTMLInputElement>>
| Cypress.Chainable<JQuery<HTMLButtonElement>>; | Cypress.Chainable<JQuery<HTMLButtonElement>>;

View file

@ -16,7 +16,7 @@ const config = path.resolve('.prettierrc.js');
const ignore = path.resolve('.prettierignore'); const ignore = path.resolve('.prettierignore');
const ROOT_DIRS_TO_SKIP = ['.git', 'node_modules', 'packages']; const ROOT_DIRS_TO_SKIP = ['.git', 'node_modules', 'packages'];
const EXTENSIONS_TO_FORMAT = ['.md', '.yml', '.js', '.json']; const EXTENSIONS_TO_FORMAT = ['.md', '.yml', '.js', '.json', '.ts'];
const isDir = (path) => fs.lstatSync(path).isDirectory(); const isDir = (path) => fs.lstatSync(path).isDirectory();

View file

@ -5,9 +5,7 @@
"cache": false "cache": false
}, },
"build": { "build": {
"dependsOn": [ "dependsOn": ["^build"]
"^build"
]
}, },
"typecheck": {}, "typecheck": {},
"format": {}, "format": {},