Resolve Test Failures Post-Dev Merge (#1742)

* 🔧 (playwright.config.ts): set workers to 1 to avoid parallel tests on CI
✨ (chat_io.spec.ts): refactor code to wait for modal to appear before clicking on the new project button
✨ (codeAreaModalComponent.spec.ts): refactor code to wait for modal to appear before clicking on the new project button, update code assertions
✨ (curl_api_generation.spec.ts): refactor code to wait for modal to appear before clicking on the new project button
✨ (dragAndDrop.spec.ts): refactor code to handle the case when generic node is not present
✨ (dropdownComponent.spec.ts): refactor code to wait for modal to appear before clicking on the new project button

✨ (filterEdge.spec.ts): add support for dynamic waiting for modal to appear before interacting with it
🐛 (filterEdge.spec.ts): remove redundant clicks on buttons and improve code readability
♻️ (filterEdge.spec.ts): refactor code to use loop instead of repetitive code for zooming out and waiting for timeout
✅ (filterEdge.spec.ts): update assertions to match changes in the application UI

✨ (floatComponent.spec.ts): refactor floatComponent test to use getByTitle instead of complex locators for button clicks
✨ (flowPage.spec.ts): refactor flowPage test to use getByTitle instead of complex locators for button clicks
✨ (group.spec.ts): refactor group test to use getByTestId instead of complex locators for button clicks and add loop to handle modal loading
✨ (inputComponent.spec.ts): refactor inputComponent test to use getByTitle instead of complex locators for button clicks

✨ (inputListComponent.spec.ts): add support for dynamic modal count to handle asynchronous modal loading
🐛 (inputListComponent.spec.ts): fix search query in inputListComponent test
♻️ (inputListComponent.spec.ts): refactor repetitive code for zooming out in inputListComponent test
✨ (intComponent.spec.ts): add support for dynamic modal count to handle asynchronous modal loading
♻️ (intComponent.spec.ts): refactor repetitive code for zooming out in intComponent test

✨ (keyPairListComponent.spec.ts): add support for dynamic modal count to handle modal loading delay
✨ (keyPairListComponent.spec.ts): update search input value to "amazon bedrock" for more accurate search results
✨ (keyPairListComponent.spec.ts): update node locator to "model_specsAmazon Bedrock" for more accurate node selection
✨ (keyPairListComponent.spec.ts): update zoom out action to use "zoom out" title for better readability
✨ (keyPairListComponent.spec.ts): update keypair verification locator to "editNodekeypair0" for more accurate verification
✨ (keyPairListComponent.spec.ts): update showcache checkbox locator to "showcache" for better readability
✨ (keyPairListComponent.spec.ts): update showcredentials_profile_name checkbox locator to "showcredentials_profile_name" for better readability
✨ (keyPairListComponent.spec.ts): update elementCountNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocator variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocatorNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCountNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocator variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocatorNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCountNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocator variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocatorNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCountNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocator variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocatorNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCountNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocator variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plusButtonLocatorNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementCountNode variable to handle nullability
✨ (keyPairListComponent.spec.ts): update keyPairVerification variable to handle nullability
✨ (keyPairListComponent.spec.ts): update elementKeyCount variable to handle nullability
✨ (keyPairListComponent.spec.ts): update plus

✨ (promptModalComponent.spec.ts): add support for dynamic modal count to handle asynchronous modal rendering
✨ (python_api_generation.spec.ts): add support for dynamic modal count to handle asynchronous modal rendering
✨ (saveComponents.spec.ts): add support for dynamic modal count to handle asynchronous modal rendering
✨ (store.spec.ts): add support for dynamic icon count to handle asynchronous rendering
✨ (textAreaModalComponent.spec.ts): add support for dynamic modal count to handle asynchronous modal rendering

✨ (toggleComponent.spec.ts): add support for dynamic waiting for modal to appear before interacting with it
🐛 (toggleComponent.spec.ts): fix typo in element locator for dataDirectory
♻️ (toggleComponent.spec.ts): refactor repetitive code for zooming out
✅ (toggleComponent.spec.ts): add assertions for checking toggle state and button clicks
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggleComponent.spec.ts): refactor repetitive code for toggling and checking toggle state
♻️ (toggle

* 🔧 (frontend/package.json): add dotenv package as a dependency to enable environment variable configuration
🔧 (frontend/playwright.config.ts): add dotenv configuration to read environment variables from .env file
♻️ (frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx): refactor code to add data-testid attribute to span element for sender name to improve testability
✅ (frontend/tests/end-to-end/chatInputOutput.spec.ts): add end-to-end test for user interaction with chat input/output functionality
✅ (frontend/tests/end-to-end/chat_io_teste.spec.ts): add end-to-end test for chat input/output functionality with file upload

✅ (chat_io.spec.ts): remove chat_io.spec.ts test file as it is no longer needed
✨ (textInputOutput.spec.ts): add new test file textInputOutput.spec.ts to test the functionality of text input and output components in the application

* 📝 (typescript_test.yml): remove unnecessary comments and unused code related to Playwright browser binaries caching and installation
🔧 (typescript_test.yml): refactor setup of Python and Poetry versions to use a custom GitHub action for caching and setting up the environment efficiently

* ✨ (globalVariables.spec.ts): add end-to-end test for global variables functionality in the frontend
✨ (textInputOutput.spec.ts): rename test from "CodeAreaModalComponent" to "TextInputOutputComponent" to improve clarity and accuracy

* 📝 (chatInputOutput.spec.ts): update test URL to use relative path instead of absolute path for better test portability
📝 (filterEdge.spec.ts): update test URL to use relative path instead of absolute path for better test portability
📝 (inputListComponent.spec.ts): update test URL to use relative path instead of absolute path for better test portability
📝 (store.spec.ts): update test URL to use relative path instead of absolute path for better test portability
📝 (textAreaModalComponent.spec.ts): update test URL to use relative path instead of absolute path for better test portability

* 🚀 (typescript_test.yml): add uvicorn command to run the app with Playwright tests
🔧 (typescript_test.yml): configure uvicorn to use the langflow.main:create_app factory function, listen on all interfaces, use port 7860, enable auto-reload, read environment variables from .env file, and use asyncio event loop

* 🔧 (typescript_test.yml): fix path to .env file in the uvicorn command to correctly load environment variables

* 🔧 (typescript_test.yml): fix path to .env file in uvicorn command to correctly locate the file

* 🐛 (typescript_test.yml): remove unnecessary --env-file flag from uvicorn command to fix an issue with loading environment variables

* 🔧 (typescript_test.yml): run uvicorn command in the background and add a 2-second sleep to allow the server to start before running Playwright tests

* ✨ (typescript_test.yml): update Playwright test command to use a single worker (--workers=1) to avoid race conditions and improve stability during test execution

* ✨ (.github/workflows/typescript_test.yml): remove unnecessary flags from the Playwright test command to simplify the command and improve readability

* 🔧 (typescript_test.yml): add command to install Playwright dependencies before running Playwright tests to ensure all required dependencies are installed

* ⬆️ (typescript_test.yml): upgrade Playwright installation command to use 'npm install' instead of 'npx playwright install --with-deps' to simplify the installation process

* ✅ (typescript_test.yml): add npm start command before running the tests to ensure the frontend server is running during the tests

* 🔧 (typescript_test.yml): run 'npm start' command in the background to allow the next step to execute concurrently
✨ (typescript_test.yml): add step to upload blob report to GitHub Actions Artifacts for easier access and analysis

* ✨ (typescript_test.yml): update Playwright test command to include shard index and total for parallel test execution

* 🔧 (playwright.config.ts): add conditional dotenv configuration based on process.env.CI to prevent loading .env file in CI environment

* 🔧 (playwright.config.ts): update dotenv configuration to only load .env file when not running in a CI environment
📝 (playwright.config.ts): add comment explaining the purpose of the dotenv configuration and providing a link to the Playwright documentation for test configuration

* ♻️ (playwright.config.ts): comment out dotenv.config() calls to improve performance and remove unnecessary code

* 📝 (playwright.config.ts): comment out the forbidOnly and retries options to disable them
📝 (playwright.config.ts): change the reporter option to always use the "blob" reporter
📝 (playwright.config.ts): comment out the globalTeardown option to disable it
📝 (playwright.config.ts): set the reuseExistingServer option to always be true

* ♻️ (playwright.config.ts): refactor fullyParallel option to be set to false instead of true to disable running tests in parallel

* ✨ (.github/workflows/typescript_test.yml): remove shardIndex and shardTotal arguments from the Playwright test command to simplify the command and avoid unnecessary complexity

* 🐛 (playwright.config.ts): add --loop asyncio flag to uvicorn command to fix asyncio event loop issue

* 📝 (playwright.config.ts): add support for reading environment variables from a .env file
♻️ (playwright.config.ts): refactor code to use path module instead of importing it from @playwright/test
✅ (playwright.config.ts): enable forbidOnly option to fail the build on CI if test.only is accidentally left in the source code
✅ (playwright.config.ts): enable retries option to retry tests on CI 2 times
♻️ (playwright.config.ts): refactor code to use globalTeardown option to specify the path to globalTeardown.ts file

* 🔧 (typescript_test.yml): run Playwright tests in the background using the '&' operator to improve workflow efficiency
♻️ (playwright.config.ts): refactor workers configuration to use 10 workers on CI and 1 worker otherwise to optimize test execution
🐛 (darkStore.tsx): fix issue where stars and lastUpdated values were not being refreshed correctly on CI environment

* ♻️ (darkStore.tsx): remove unnecessary empty line to improve code readability

* 🔧 (typescript_test.yml): remove unnecessary ampersand (&) at the end of the 'npx playwright test' command to prevent running the command in the background

* 📝 (darkStore.tsx): set "githubStars" to "0" in localStorage when running in CI environment to ensure consistent test results
🐛 (filterEdge.spec.ts): update test assertions to match changes in the application UI

* 📝 (api.tsx): add condition to reject promise if error occurs during API request to GitHub to prevent auto-login flow
📝 (auto_login.spec.ts): update page.goto() URLs to use relative paths instead of absolute URLs
📝 (chatInputOutput.spec.ts): move dotenv.config() call after page.goto() to ensure proper environment variable loading
📝 (codeAreaModalComponent.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (curl_api_generation.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (dragAndDrop.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (dropdownComponent.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (floatComponent.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (flowPage.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (globalVariables.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (group.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (inputComponent.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (intComponent.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (keyPairListComponent.spec.ts): update page.goto() URL to use relative path instead of absolute URL
📝 (langflowShortcuts.spec.ts): update page.goto() URL to use relative path instead of absolute URL

📝 (nestedComponent.spec.ts): update page URL to use relative path instead of absolute path for better portability and flexibility
📝 (promptModalComponent.spec.ts): update page URL to use relative path instead of absolute path for better portability and flexibility
📝 (saveComponents.spec.ts): update page URL to use relative path instead of absolute path for better portability and flexibility
📝 (textInputOutput.spec.ts): update page URL to use relative path instead of absolute path for better portability and flexibility
📝 (toggleComponent.spec.ts): update page URL to use relative path instead of absolute path for better portability and flexibility

* 🔧 (playwright.config.ts): set workers to a fixed value of 10 to improve test performance and avoid parallel tests on CI
🐛 (group.spec.ts): move page.goto("/") inside the test function to ensure the page is properly loaded before running the test

* ✅ (chatInputOutput.spec.ts): add dotenv configuration to load environment variables before running the test
🐛 (chatInputOutput.spec.ts): fix issue where the test was not waiting for the page to load before interacting with it
✅ (curl_api_generation.spec.ts): add dotenv configuration to load environment variables before running the test
🐛 (curl_api_generation.spec.ts): fix issue where the test was not waiting for the page to load before interacting with it

* 🔧 (playwright.config.ts): update number of workers based on the value of the CI environment variable
🐛 (chatInputOutput.spec.ts): fix potential null reference error when getting modal count
🐛 (codeAreaModalComponent.spec.ts): fix potential null reference error when getting modal count
🐛 (curl_api_generation.spec.ts): fix potential null reference error when getting modal count
🐛 (dropdownComponent.spec.ts): fix potential null reference error when getting modal count
🐛 (filterEdge.spec.ts): fix potential null reference error when getting modal count
🐛 (globalVariables.spec.ts): fix potential null reference error when getting modal count
🐛 (group.spec.ts): fix potential null reference error when getting modal count
🐛 (inputComponent.spec.ts): fix potential null reference error when getting modal count
🐛 (inputListComponent.spec.ts): fix potential null reference error when getting modal count
🐛 (intComponent.spec.ts): fix potential null reference error when getting modal count
🐛 (keyPairListComponent.spec.ts): fix potential null reference error when getting modal count
🐛 (langflowShortcuts.spec.ts): fix potential null reference error when getting modal count
🐛 (nestedComponent.spec.ts): fix potential null reference error when getting modal count

🐛 (promptModalComponent.spec.ts): fix potential null pointer exception when accessing page object
🐛 (python_api_generation.spec.ts): fix potential null pointer exception when accessing page object
🐛 (saveComponents.spec.ts): fix potential null pointer exception when accessing page object
🐛 (textAreaModalComponent.spec.ts): fix potential null pointer exception when accessing page object
🐛 (textInputOutput.spec.ts): fix potential null pointer exception when accessing page object
🐛 (toggleComponent.spec.ts): fix potential null pointer exception when accessing page object
🐛 (tweaks_test.spec.ts): fix potential null pointer exception when accessing page object

* 🔧 (playwright.config.ts): update workers configuration to use 10 workers on CI and default to an empty value otherwise
🔧 (playwright.config.ts): update reporter configuration to use "blob" reporter on CI and "html" reporter otherwise

* 🔧 (playwright.config.ts): update workers configuration to use a default value of 5 when not running on CI environment, to improve test performance and resource usage

* ✨ (playwright.config.ts): enable fully parallel test execution to improve test performance
🐛 (chatInputOutput.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (codeAreaModalComponent.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (curl_api_generation.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (dragAndDrop.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (dropdownComponent.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (filterEdge.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (flowPage.spec.ts): handle potential error when counting modal titles to prevent test failures
🐛 (globalVariables.spec.ts): handle potential error when counting modal titles to prevent test failures

🐛 (group.spec.ts): Fix bug in group and ungroup updating values test where modalCount was not correctly initialized
🐛 (inputComponent.spec.ts): Fix bug in InputComponent test where modalCount was not correctly initialized
🐛 (inputListComponent.spec.ts): Fix bug in InputListComponent test where modalCount was not correctly initialized
🐛 (intComponent.spec.ts): Fix bug in IntComponent test where modalCount was not correctly initialized
🐛 (keyPairListComponent.spec.ts): Fix bug in KeypairListComponent test where modalCount was not correctly initialized
🐛 (langflowShortcuts.spec.ts): Fix bug in LangflowShortcuts test where modalCount was not correctly initialized
🐛 (nestedComponent.spec.ts): Fix bug in NestedComponent test where modalCount was not correctly initialized
🐛 (promptModalComponent.spec.ts): Fix bug in PromptTemplateComponent test where modalCount was not correctly initialized
🐛 (python_api_generation.spec.ts): Fix bug in python_api_generation test where modalCount was not correctly initialized
🐛 (saveComponents.spec.ts): Fix bug in save group component tests where modalCount was not correctly initialized
🐛 (textAreaModalComponent.spec.ts): Fix bug in TextAreaModalComponent test where modalCount was not correctly initialized

✅ (textInputOutput.spec.ts): handle error when getting modal title element and set modalCount to 0 in case of error
✅ (toggleComponent.spec.ts): handle error when getting modal title element and set modalCount to 0 in case of error
✅ (tweaks_test.spec.ts): handle error when getting modal title element and set modalCount to 0 in case of error

* ⬆️ (playwright.config.ts): downgrade the number of workers from 10 to 5 to reduce resource usage and improve test stability

* ⬆️ (playwright.config.ts): decrease the number of workers to 1 to avoid parallel tests on CI
📝 (playwright.config.ts): comment out the workers configuration and add a new line with a single worker to clarify the intention
✨ (playwright.config.ts): add a new file "temp" to the frontend directory

* 📝 (chatInputOutput.spec.ts): add support for loading environment variables from .env file for local development and CI/CD environments
📝 (textInputOutput.spec.ts): add support for loading environment variables from .env file for local development and CI/CD environments

* 🔧 (typescript_test.yml): add step to create .env file and populate it with secret environment variables
🚀 (typescript_test.yml): run Playwright tests after creating .env file to ensure tests have access to necessary environment variables

* ✅ (dragAndDrop.spec.ts): add a test to close the modal by clicking on the "Close" button

* 🔧 (typescript_test.yml): update Playwright test command to include shard index and total for distributed test execution
♻️ (playwright.config.ts): refactor workers configuration to use environment variable CI to determine the number of workers for parallel tests

* ⬆️ (playwright.config.ts): downgrade the number of workers to 1 to avoid parallel tests on CI environment

* 📝 (filterEdge.spec.ts): remove unnecessary click on element with id 'headlessui-disclosure-button-:rld:'
♻️ (filterEdge.spec.ts): remove redundant assertions for elements with ids 'saved_componentsBasic RAG' and 'saved_componentsGroup'
♻️ (floatComponent.spec.ts): refactor code to handle modal dynamically by checking for modal title element and waiting for it to appear before clicking on 'new-project-btn' element

* 🔧 (playwright.config.ts): update number of workers to 5 when running on CI to improve test parallelization
🐛 (filterEdge.spec.ts): add a 2-second delay before asserting visibility of tooltips to ensure they are fully rendered before checking visibility

* 📝 (index.tsx): add data-testid attribute to the flow name element for easier testing and querying
📝 (index.tsx): add data-testid attribute to the public checkbox for easier testing and querying
📝 (test_file.txt): add a test file for end-to-end testing purposes
📝 (fileUploadComponent.spec.ts): add end-to-end test for file upload functionality

✨ (flowSettings.spec.ts): add end-to-end test for flow settings functionality
✨ (store.spec.ts): add end-to-end test for sharing a component with the share button

* 🔧 (playwright.config.ts): set workers to 1 to avoid parallel tests execution and improve stability
📝 (test_file.txt): remove newline at the end of the file for consistency
♻️ (flowPage.spec.ts): refactor code to remove unnecessary lines and commented out code
♻️ (flowSettings.spec.ts): refactor code to generate a random flow name instead of hardcoding it

* 🔧 (typescript_test.yml): remove shardIndex and shardTotal arguments from the 'npx playwright test' command to simplify the command and remove unnecessary complexity
🐛 (textInputOutput.spec.ts): change 'textContent()' to 'inputValue()' to correctly retrieve the value of the input field

* ♻️ (typescript_test.yml): refactor test workflow to remove unnecessary matrix configuration for shardIndex and shardTotal
✅ (typescript_test.yml): update test workflow to run tests on a single shard instead of multiple shards for simplicity and efficiency

* 🔧 (playwright.config.ts): add clipboard permissions for chromium and firefox projects to enable clipboard read and write functionality
🔧 (curl_api_generation.spec.ts): remove unnecessary context permission grant for clipboard read and write
🔧 (python_api_generation.spec.ts): remove unnecessary context permission grant for clipboard read and write
🔧 (tweaks_test.spec.ts): remove unnecessary context permission grant for clipboard read and write

---------

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
This commit is contained in:
Cristhian Zanforlin Lousa 2024-04-19 09:11:30 -03:00 • committed by GitHub
commit 47aad8aa87
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 1175 additions and 523 deletions

View file

@ -19,8 +19,8 @@ jobs:
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
shardIndex: [1]
shardTotal: [1]
steps:
- name: Checkout code
uses: actions/checkout@v4
@ -38,27 +38,6 @@ jobs:
npm ci
if: ${{ steps.setup-node.outputs.cache-hit != 'true' }}
# Attempt to restore the correct Playwright browser binaries based on the
# currently installed version of Playwright (The browser binary versions
# may change with Playwright versions).
# Note: Playwright's cache directory is hard coded because that's what it
# says to do in the docs. There doesn't appear to be a command that prints
# it out for us.
# - uses: actions/cache@v4
# id: playwright-cache
# with:
# path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}
# key: "${{ runner.os }}-playwright-${{ hashFiles('src/frontend/package-lock.json') }}"
# # As a fallback, if the Playwright version has changed, try use the
# # most recently cached version. There's a good chance that at least one
# # of the browser binary versions haven't been updated, so Playwright can
# # skip installing that in the next step.
# # Note: When falling back to an old cache, `cache-hit` (used below)
# # will be `false`. This allows us to restore the potentially out of
# # date cache, but still let Playwright decide if it needs to download
# # new binaries or not.
# restore-keys: |
# ${{ runner.os }}-playwright-
- name: Cache playwright binaries
uses: actions/cache@v4
id: playwright-cache
@ -82,32 +61,26 @@ jobs:
npx playwright install-deps
if: steps.playwright-cache.outputs.cache-hit != 'true'
# If the Playwright browser binaries weren't able to be restored, we tell
# paywright to install everything for us.
# - name: Install Playwright's dependencies
# if: steps.playwright-cache.outputs.cache-hit != 'true'
# run: npx playwright install --with-deps
- name: Install Poetry
run: pipx install "poetry==${{ env.POETRY_VERSION }}"
- name: Set up Python
uses: actions/setup-python@v5
id: setup-python
- name: Set up Python ${{ env.PYTHON_VERSION }} + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_caching"
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: "poetry"
poetry-version: ${{ env.POETRY_VERSION }}
cache-key: ${{ runner.os }}-poetry-${{ env.POETRY_VERSION }}-${{ hashFiles('**/poetry.lock') }}
- name: Install Python dependencies
run: |
poetry env use ${{ env.PYTHON_VERSION }}
poetry install
if: ${{ steps.setup-python.outputs.cache-hit != 'true' }}
- name: create .env
run: |
touch .env
echo "${{ secrets.ENV_VARS }}" > .env
- name: Run Playwright Tests
run: |
cd src/frontend
npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
npx playwright test
- name: Upload blob report to GitHub Actions Artifacts
if: always()

View file

@ -38,6 +38,7 @@
"clsx": "^1.2.1",
"cmdk": "^1.0.0",
"dompurify": "^3.0.5",
"dotenv": "^16.4.5",
"esbuild": "^0.17.19",
"framer-motion": "^11.0.6",
"lodash": "^4.17.21",
@ -5671,6 +5672,17 @@
"tslib": "^2.0.3"
}
},
"node_modules/dotenv": {
"version": "16.4.5",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",

View file

@ -33,6 +33,7 @@
"clsx": "^1.2.1",
"cmdk": "^1.0.0",
"dompurify": "^3.0.5",
"dotenv": "^16.4.5",
"esbuild": "^0.17.19",
"framer-motion": "^11.0.6",
"lodash": "^4.17.21",

View file

@ -1,14 +1,17 @@
import { defineConfig, devices } from "@playwright/test";
import * as dotenv from "dotenv";
import path from "path";
dotenv.config();
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
@ -18,7 +21,7 @@ export default defineConfig({
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: 3,
workers: 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
timeout: 120 * 1000,
// reporter: [
@ -40,24 +43,32 @@ export default defineConfig({
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
use: {
...devices["Desktop Chrome"],
contextOptions: {
// chromium-specific permissions
permissions: ["clipboard-read", "clipboard-write"],
},
},
},
{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
use: {
...devices["Desktop Firefox"],
launchOptions: {
firefoxUserPrefs: {
"dom.events.asyncClipboard.readText": true,
"dom.events.testing.asyncClipboard": true,
},
},
},
},
// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },
],
/* Run your local dev server before starting the tests */
webServer: [
{
command:
"poetry run uvicorn --factory langflow.main:create_app --host 127.0.0.1 --port 7860",
"poetry run uvicorn --factory langflow.main:create_app --host 127.0.0.1 --port 7860 --loop asyncio",
port: 7860,
env: {
LANGFLOW_DATABASE_URL: "sqlite:///./temp",
@ -65,7 +76,7 @@ export default defineConfig({
},
stdout: "ignore",
reuseExistingServer: !process.env.CI,
reuseExistingServer: true,
timeout: 120 * 1000,
},
{

View file

@ -83,7 +83,9 @@ export const MenuBar = ({
<DropdownMenuTrigger asChild>
<Button asChild variant="primary" size="sm">
<div className="header-menu-bar-display">
<div className="header-menu-flow-name">{currentFlow.name}</div>
<div className="header-menu-flow-name" data-testid="flow_name">
{currentFlow.name}
</div>
<IconComponent name="ChevronDown" className="h-4 w-4" />
</div>
</Button>

View file

@ -24,6 +24,9 @@ function ApiInterceptor() {
async (error: AxiosError) => {
if (error.response?.status === 403 || error.response?.status === 401) {
if (!autoLogin) {
if (error?.config?.url?.includes("github")) {
return Promise.reject(error);
}
const stillRefresh = checkErrorCount();
if (!stillRefresh) {
return Promise.reject(error);

View file

@ -135,7 +135,12 @@ export default function ChatMessage({
alt={!chat.isSend ? "robot_image" : "male_technology"}
/>
</div>
<span className="max-w-24 truncate text-xs">
<span
className="max-w-24 truncate text-xs"
data-testid={
"sender_name_" + chat.sender_name?.toLocaleLowerCase()
}
>
{chat.sender_name}
</span>
</div>

View file

@ -237,6 +237,7 @@ export default function ShareModal({
onCheckedChange={(event: boolean) => {
setSharePublic(event);
}}
data-testid="public-checkbox"
/>
<label htmlFor="public" className="export-modal-save-api text-sm ">
Set {nameComponent} status to public

View file

@ -18,6 +18,11 @@ export const useDarkStore = create<DarkStoreType>((set, get) => ({
});
},
refreshStars: () => {
if (import.meta.env.CI) {
window.localStorage.setItem("githubStars", "0");
set(() => ({ stars: 0, lastUpdated: new Date() }));
return;
}
let lastUpdated = window.localStorage.getItem("githubStarsLastUpdated");
let diff = 0;
// check if lastUpdated actually exists

View file

@ -0,0 +1 @@
this is a test file

View file

@ -2,12 +2,12 @@ import { test } from "@playwright/test";
test.describe("Auto_login tests", () => {
test("auto_login sign in", async ({ page }) => {
await page.goto("http:localhost:3000/");
await page.goto("/");
await page.locator('//*[@id="new-project-btn"]').click();
});
test("auto_login block_admin", async ({ page }) => {
await page.goto("http:localhost:3000/");
await page.goto("/");
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);

View file

@ -0,0 +1,149 @@
import { expect, test } from "@playwright/test";
import * as dotenv from "dotenv";
import { readFileSync } from "fs";
import path from "path";
test("user must interact with chat with Input/Output", async ({ page }) => {
if (!process.env.CI) {
dotenv.config();
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
}
await page.goto("/");
await page.waitForTimeout(1000);
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.getByRole("heading", { name: "Basic Prompting" }).click();
await page.waitForTimeout(1000);
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
if (!process.env.OPENAI_API_KEY) {
//You must set the OPENAI_API_KEY on .env file to run this test
expect(false).toBe(true);
}
await page
.getByTestId("input-openai_api_key")
.fill(process.env.OPENAI_API_KEY ?? "");
await page.getByText("Run", { exact: true }).click();
await page.getByPlaceholder("Send a message...").fill("Hello, how are you?");
await page.getByTestId("icon-LucideSend").click();
let valueUser = await page.getByTestId("sender_name_user").textContent();
let valueAI = await page.getByTestId("sender_name_ai").textContent();
expect(valueUser).toBe("User");
expect(valueAI).toBe("AI");
await page.keyboard.press("Escape");
await page
.getByTestId("textarea-input_value")
.nth(1)
.fill(
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!"
);
await page.getByTestId("input-sender_name").nth(1).fill("TestSenderNameUser");
await page.getByTestId("input-sender_name").nth(0).fill("TestSenderNameAI");
await page.getByText("Run", { exact: true }).click();
await page.getByTestId("icon-LucideSend").click();
valueUser = await page
.getByTestId("sender_name_testsendernameuser")
.textContent();
valueAI = await page
.getByTestId("sender_name_testsendernameai")
.textContent();
expect(valueUser).toBe("TestSenderNameUser");
expect(valueAI).toBe("TestSenderNameAI");
expect(
await page
.getByText(
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!",
{ exact: true }
)
.isVisible()
);
});
test("chat_io_teste", async ({ page }) => {
await page.goto("/");
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/end-to-end/assets/ChatTest.json",
"utf-8"
);
await page.waitForTimeout(3000);
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(2000);
// Create the DataTransfer and File
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data], "ChatTest.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
// Now dispatch
await page.dispatchEvent(
'//*[@id="react-flow-id"]/div[1]/div[1]/div',
"drop",
{
dataTransfer,
}
);
await page.getByLabel("fit view").click();
await page.getByText("Run", { exact: true }).click();
await page.getByPlaceholder("Send a message...").click();
await page.getByPlaceholder("Send a message...").fill("teste");
await page.getByRole("button").nth(1).click();
const chat_output = page.getByTestId("chat-message-AI-teste");
const chat_input = page.getByTestId("chat-message-User-teste");
await expect(chat_output).toHaveText("teste");
await expect(chat_input).toHaveText("teste");
});

View file

@ -1,49 +0,0 @@
import { expect, test } from "@playwright/test";
import { readFileSync } from "fs";
test("chat_io_teste", async ({ page }) => {
await page.goto("/");
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
"tests/end-to-end/assets/ChatTest.json",
"utf-8"
);
await page.waitForTimeout(3000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.locator('//*[@id="new-project-btn"]').click();
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(2000);
// Create the DataTransfer and File
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data], "ChatTest.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
// Now dispatch
await page.dispatchEvent(
'//*[@id="react-flow-id"]/div[1]/div[1]/div',
"drop",
{
dataTransfer,
}
);
await page.getByLabel("fit view").click();
await page.getByText("Run", { exact: true }).click();
await page.getByPlaceholder("Send a message...").click();
await page.getByPlaceholder("Send a message...").fill("teste");
await page.getByRole("button").nth(1).click();
const chat_output = page.getByTestId("chat-message-AI-teste");
const chat_input = page.getByTestId("chat-message-User-teste");
await expect(chat_output).toHaveText("teste");
await expect(chat_input).toHaveText("teste");
});

View file

@ -1,49 +1,63 @@
import { expect, test } from "@playwright/test";
test("CodeAreaModalComponent", async ({ page }) => {
await page.goto("http:localhost:3000/");
await page.goto("/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.waitForTimeout(1000);
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(1000);
await page.getByTestId("extended-disclosure").click();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("pythonfunctiontool");
await page.getByPlaceholder("Search").fill("python function");
await page.waitForTimeout(1000);
await page
.getByTestId("toolsPythonFunctionTool")
.getByTestId("experimentalPython Function")
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTestId("div-generic-node").click();
await page.getByTestId("code-button-modal").click();
let value = await page.locator('//*[@id="codeValue"]').inputValue();
const code =
'def python_function(text: str) -> str:\n """This is a default python function that returns the input text"""\n return text';
const wCode =
'def python_function(text: str) -> st: """This is a default python function that returns the input text""" return text';
const assertCode =
'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text';
const customComponentCode = `from typing import Callable
from langflow.field_typing import Code
from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.custom.utils import get_function
class PythonFunctionComponent(CustomComponent):
def python_function(text: str) -> str:
"""This is a default python function that returns the input text"""
return text`;
await page
.locator("#CodeEditor div")
.filter({ hasText: "def python_function(text: str" })
.filter({ hasText: "PythonFunctionComponent" })
.nth(1)
.click();
await page.locator("textarea").press("Control+a");
@ -55,13 +69,14 @@ test("CodeAreaModalComponent", async ({ page }) => {
).toBeTruthy();
await page.locator("textarea").press("Control+a");
await page.locator("textarea").fill(wCode);
await page.locator("textarea").fill(code);
await page.locator("textarea").fill(customComponentCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await page.waitForTimeout(1000);
expect(await page.getByText("Code is ready to run").isVisible()).toBeTruthy();
await page.getByTestId("code-button-modal").click();
expect(await page.locator('//*[@id="codeValue"]').inputValue()).toBe(
assertCode
);
const inputCodeValue = await page
.locator('//*[@id="codeValue"]')
.inputValue();
expect(inputCodeValue).toContain("def python_function(text: str) -> str");
});

View file

@ -1,9 +1,22 @@
import { expect, test } from "@playwright/test";
test("curl_api_generation", async ({ page, context }) => {
await page.goto("http:localhost:3000/");
await page.locator('//*[@id="new-project-btn"]').click();
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
await page.goto("/");
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.getByRole("heading", { name: "Basic Prompting" }).click();
await page.waitForTimeout(2000);
await page.getByText("API", { exact: true }).click();

View file

@ -4,7 +4,25 @@ import { readFileSync } from "fs";
test.describe("drag and drop test", () => {
/// <reference lib="dom"/>
test("drop collection", async ({ page }) => {
await page.goto("http:localhost:3000/");
await page.goto("/");
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.locator("span").filter({ hasText: "Close" }).first().click();
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
// Read your file into a buffer.
const jsonContent = readFileSync(
@ -36,7 +54,7 @@ test.describe("drag and drop test", () => {
await page.waitForTimeout(1000);
const genericNoda = page.getByTestId("div-generic-node");
const elementCount = await genericNoda.count();
const elementCount = await genericNoda?.count();
if (elementCount > 0) {
expect(true).toBeTruthy();
}

View file

@ -1,10 +1,24 @@
import { expect, test } from "@playwright/test";
test("dropDownComponent", async ({ page }) => {
await page.goto("http:localhost:3000/");
await page.goto("/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.waitForTimeout(1000);
await page.getByTestId("blank-flow").click();
@ -22,17 +36,10 @@ test("dropDownComponent", async ({ page }) => {
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTestId("title-Amazon Bedrock").click();
await page.getByTestId("dropdown-model_id").click();

View file

@ -0,0 +1,88 @@
import { expect, test } from "@playwright/test";
import path from "path";
test("dropDownComponent", async ({ page }) => {
await page.goto("/");
await page.waitForTimeout(2000);
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.waitForTimeout(1000);
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(1000);
await page.getByTestId("extended-disclosure").click();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("file");
await page.waitForTimeout(1000);
await page
.getByTestId("dataFile")
.first()
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
const fileChooserPromise = page.waitForEvent("filechooser");
await page.getByTestId("icon-FileSearch2").click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(path.join(__dirname, "/assets/test_file.txt"));
await page.getByText("test_file.txt").isVisible();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("text output");
await page
.getByTestId("outputsText Output")
.first()
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
// Click and hold on the first element
await page
.locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div'
)
.hover();
await page.mouse.down();
// Move to the second element
await page
.locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div/div'
)
.hover();
// Release the mouse
await page.mouse.up();
await page.getByText("Run", { exact: true }).click();
await page.getByText("Run Flow", { exact: true }).click();
await page.waitForTimeout(3000);
const textOutput = await page.getByPlaceholder("Empty").first().inputValue();
expect(textOutput).toContain("this is a test file");
});

View file

@ -1,11 +1,24 @@
import { expect, test } from "@playwright/test";
test("LLMChain - Tooltip", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.goto("/");
await page.waitForTimeout(1000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(1000);
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(1000);
@ -20,18 +33,10 @@ test("LLMChain - Tooltip", async ({ page }) => {
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page
.locator(
@ -39,26 +44,20 @@ test("LLMChain - Tooltip", async ({ page }) => {
)
.hover()
.then(async () => {
await expect(
page.getByTestId("available-input-model_specs").first()
).toBeVisible();
await expect(page.getByTestId("tooltip-Chains").first()).toBeVisible();
await expect(page.getByTestId("tooltip-Models").first()).toBeVisible();
await expect(page.getByTestId("tooltip-Inputs").first()).toBeVisible();
await expect(
page.getByTestId("tooltip-AzureOpenAIModel").first()
).toBeVisible();
await expect(
page.getByTestId("tooltip-Model Specs").first()
).toBeVisible();
await expect(page.getByTestId("tooltip-Outputs").first()).toBeVisible();
await page.getByTestId("icon-X").click();
await page.waitForTimeout(500);
});
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
@ -66,18 +65,12 @@ test("LLMChain - Tooltip", async ({ page }) => {
.hover()
.then(async () => {
await expect(
page.getByTestId("available-input-memories").first()
page.getByTestId("tooltip-Model Specs").first()
).toBeVisible();
await page.waitForTimeout(2000);
await expect(page.getByTestId("tooltip-Memories").first()).toBeVisible();
await expect(page.getByTestId("tooltip-Models").first()).toBeVisible();
await expect(
page
.getByTestId(
"tooltip-ConversationBufferMemory, ConversationBufferWindowMemory, ConversationEntityMemory, ConversationKGMemory, ConversationSummaryMemory, MotorheadMemory, VectorStoreRetrieverMemory"
)
.first()
).toBeVisible();
await page.getByTestId("icon-Search").click();
await page.waitForTimeout(500);
@ -97,11 +90,29 @@ test("LLMChain - Tooltip", async ({ page }) => {
});
test("LLMChain - Filter", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.goto("/");
await page.waitForTimeout(2000);
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.waitForTimeout(1000);
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(1000);
await page.getByTestId(
"input-list-plus-btn-edit_metadata_indexing_include-2"
);
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(1000);
@ -115,43 +126,28 @@ test("LLMChain - Filter", async ({ page }) => {
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.waitForTimeout(500);
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div'
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
)
.click();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div'
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
)
.click();
await page.getByTestId("icon-Search").click();
await expect(page.getByTestId("disclosure-models")).toBeVisible();
await expect(page.getByTestId("disclosure-model specs")).toBeVisible();
await expect(page.getByTestId("modelsAzure OpenAI")).toBeVisible();
await expect(page.getByTestId("model_specsAnthropic").first()).toBeVisible();
await expect(page.getByTestId("model_specsAmazon Bedrock")).toBeVisible();
await expect(page.getByTestId("model_specsAnthropic")).toBeVisible();
await expect(page.getByTestId("model_specsAnthropicLLM")).toBeVisible();
await expect(page.getByTestId("model_specsAzureChatOpenAI")).toBeVisible();
await expect(page.getByTestId("model_specsChatAnthropic")).toBeVisible();
await expect(page.getByTestId("model_specsChatLiteLLM")).toBeVisible();
await expect(page.getByTestId("model_specsChatOllama")).toBeVisible();
await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible();
@ -176,8 +172,6 @@ test("LLMChain - Filter", async ({ page }) => {
await expect(page.getByTestId("model_specsCTransformers")).not.toBeVisible();
await expect(page.getByTestId("model_specsAmazon Bedrock")).not.toBeVisible();
await expect(page.getByTestId("modelsAzure OpenAI")).not.toBeVisible();
await expect(page.getByTestId("model_specsAnthropic")).not.toBeVisible();
await expect(page.getByTestId("model_specsAnthropicLLM")).not.toBeVisible();
await expect(
page.getByTestId("model_specsAzureChatOpenAI")
).not.toBeVisible();
@ -190,52 +184,19 @@ test("LLMChain - Filter", async ({ page }) => {
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div'
)
.click();
await page
.locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div'
)
.click();
await expect(page.getByTestId("disclosure-memories")).toBeVisible();
await expect(
page.getByTestId("memoriesConversationBufferMemory")
).toBeVisible();
await expect(
page.getByTestId("memoriesConversationBufferWindowMemory")
).toBeVisible();
await expect(
page.getByTestId("memoriesConversationEntityMemory")
).toBeVisible();
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
await expect(
page.getByTestId("memoriesConversationSummaryMemory")
).toBeVisible();
await expect(
page.getByTestId("memoriesVectorStoreRetrieverMemory")
).toBeVisible();
await page.getByTestId("rf__wrapper").click();
await expect(
page.getByTestId("memoriesConversationBufferMemory")
).toBeVisible();
await expect(
page.getByTestId("memoriesConversationBufferWindowMemory")
).toBeVisible();
await expect(
page.getByTestId("memoriesConversationEntityMemory")
).toBeVisible();
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
await expect(
page.getByTestId("memoriesConversationSummaryMemory")
).toBeVisible();
await expect(
page.getByTestId("memoriesVectorStoreRetrieverMemory")
).toBeVisible();
await expect(page.getByTestId("inputsChat Input")).toBeVisible();
await expect(page.getByTestId("outputsChat Output")).toBeVisible();
await expect(page.getByTestId("helpersID Generator")).toBeVisible();
await expect(page.getByTestId("vectorstoresChroma")).toBeVisible();
await expect(page.getByTestId("disclosure-vector stores")).toBeVisible();
});

View file

@ -1,10 +1,24 @@
import { expect, test } from "@playwright/test";
test("FloatComponent", async ({ page }) => {
await page.goto("http:localhost:3000/");
await page.goto("/");
await page.waitForTimeout(2000);
await page.locator('//*[@id="new-project-btn"]').click();
let modalCount = 0;
try {
const modalTitleElement = await page?.getByTestId("modal-title");
if (modalTitleElement) {
modalCount = await modalTitleElement.count();
}
} catch (error) {
modalCount = 0;
}
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.waitForTimeout(1000);
await page.getByTestId("blank-flow").click();
@ -20,28 +34,10 @@ test("FloatComponent", async ({ page }) => {
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
.click();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.locator('//*[@id="float-input"]').click();
await page.locator('//*[@id="float-input"]').fill("3");
@ -145,7 +141,7 @@ test("FloatComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="float-input"]');
const elementCount = await plusButtonLocator.count();
const elementCount = await plusButtonLocator?.count();
if (elementCount === 0) {
expect(true).toBeTruthy();

Some files were not shown because too many files have changed in this diff Show more