diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d4eaafb95..5ad948a3c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -32,12 +32,15 @@ jobs: pipx install poetry==$POETRY_VERSION - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 + id: setup-python with: python-version: ${{ matrix.python-version }} cache: poetry - - name: Install dependencies + - name: Install Python dependencies run: | + poetry env use ${{ matrix.python-version }} poetry install + if: ${{ steps.setup-python.outputs.cache-hit != 'true' }} - name: Analysing the code with our lint run: | make lint diff --git a/.github/workflows/test.yml b/.github/workflows/python_test.yml similarity index 76% rename from .github/workflows/test.yml rename to .github/workflows/python_test.yml index 10ab9b324..a04a208f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/python_test.yml @@ -15,7 +15,7 @@ on: - "src/backend/**" env: - POETRY_VERSION: "1.5.0" + POETRY_VERSION: "1.8.2" jobs: build: @@ -33,11 +33,15 @@ jobs: run: pipx install poetry==$POETRY_VERSION - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 + id: setup-python with: python-version: ${{ matrix.python-version }} cache: "poetry" - - name: Install dependencies - run: poetry install + - name: Install Python dependencies + run: | + poetry env use ${{ matrix.python-version }} + poetry install + if: ${{ steps.setup-python.outputs.cache-hit != 'true' }} - name: Run unit tests run: | make tests diff --git a/.github/workflows/typescript_test.yml b/.github/workflows/typescript_test.yml new file mode 100644 index 000000000..a75327785 --- /dev/null +++ b/.github/workflows/typescript_test.yml @@ -0,0 +1,149 @@ +name: Run Frontend Tests + +on: + pull_request: + paths: + - "src/frontend/**" + +env: + POETRY_VERSION: "1.8.2" + NODE_VERSION: "21" + PYTHON_VERSION: "3.10" + # Define the directory where Playwright browsers will be installed. + # Adjust if your project uses a different path. + PLAYWRIGHT_BROWSERS_PATH: "ms-playwright" + +jobs: + setup-and-test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + shardIndex: [1, 2, 3, 4] + shardTotal: [4] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + id: setup-node + with: + node-version: ${{ env.NODE_VERSION }} + cache: "npm" + + - name: Install Node.js dependencies + run: | + cd src/frontend + 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 + with: + path: | + ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-${{ hashFiles('src/frontend/package-lock.json') }} + - name: Install Frontend dependencies + run: | + cd src/frontend + npm ci + + - name: Install Playwright's browser binaries + run: | + cd src/frontend + npx playwright install --with-deps + if: steps.playwright-cache.outputs.cache-hit != 'true' + - name: Install Playwright's dependencies + run: | + cd src/frontend + 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 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: "poetry" + + - name: Install Python dependencies + run: | + poetry env use ${{ env.PYTHON_VERSION }} + poetry install + if: ${{ steps.setup-python.outputs.cache-hit != 'true' }} + + - name: Run Playwright Tests + run: | + cd src/frontend + npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + + - name: Upload blob report to GitHub Actions Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: blob-report-${{ matrix.shardIndex }} + path: src/frontend/blob-report + retention-days: 1 + + merge-reports: + needs: setup-and-test + runs-on: ubuntu-latest + if: always() + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: | + npx playwright merge-reports --reporter html ./all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@v4 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 diff --git a/.gitignore b/.gitignore index a2ff9a883..fb5586bc5 100644 --- a/.gitignore +++ b/.gitignore @@ -262,3 +262,5 @@ src/backend/base/langflow/frontend/ .docker scratchpad* chroma*/* +stuff/* +src/frontend/playwright-report/index.html diff --git a/Makefile b/Makefile index cb8991f56..bad35eef3 100644 --- a/Makefile +++ b/Makefile @@ -47,9 +47,9 @@ run_frontend: tests_frontend: ifeq ($(UI), true) - cd src/frontend && ./run-tests.sh --ui + cd src/frontend && npx playwright test --ui --project=chromium else - cd src/frontend && ./run-tests.sh + cd src/frontend && npx playwright test --project=chromium endif run_cli: diff --git a/docs/docs/guides/inputs-and-outputs.mdx b/docs/docs/guides/inputs-and-outputs.mdx index 9e514437e..8a9ce10ed 100644 --- a/docs/docs/guides/inputs-and-outputs.mdx +++ b/docs/docs/guides/inputs-and-outputs.mdx @@ -7,17 +7,19 @@ dynamically change the Interaction Panel and can be renamed to make it easier to Langflow 1.0 introduces new categories of components called Inputs and Outputs. They are used to make it easier to understand and interact with your flows. -Let's take a look at the what they are and how they work. +Let's start with what they have in common: + +- Components in these categories connect to components that have Text or Record inputs or outputs. Some can connect to both but you have to pick what type of data you want to output or input. +- They can be renamed to help you identify them more easily in the Interaction Panel and while using the API. +- They dynamically change the Interaction Panel to make it easier to understand and interact with your flows. + +Native Langflow Components were created to be powerful tools that work around Langflow's features. They are designed to be easy to use and understand, and to help you build your flows faster. + +Let's dive into Inputs and Outputs. ## Inputs -Some Input components output Text, others Record, and others both (you pick). They can be used to input data into any field that accepts Text or Record data. - -{/* Show pictures of Chat Input into Prompt and Chat Input into File Path in a file loader component */} - -As with all components, they can be renamed to help you identify them more easily in the Interaction Panel and while using the API. - -{/* Show picture of renaming a Chat Input component and the Interaction Panel */} +Inputs are components that are used to define where data comes into your flow. They can be used to receive data from the user, from a database, or from any other source that can be converted to Text or Record. The difference between Chat Input and other Input components is the format of the output, the number of configurable fields, and the way they are displayed in the Interaction Panel. @@ -27,6 +29,8 @@ You can find out more about it and the other Inputs [here](../components/inputs) ## Outputs -Some Output components output Text, others Record, and others both (you pick), just like the Inputs. They can be used to output data from any field that outputs Text or Record data. +Outputs are components that are used to define where data comes out of your flow. They can be used to send data to the user, to the Interaction Panel, or to define how the data will be displayed in the Interaction Panel. -{/* Show pictures of Prompt into Chat Output and File Path in a file loader component into Chat Output */} +The Chat Output works similarly to the Chat Input but does not have a field that allows for written input. It is used as an Output definition and can be used to send data to the user. + +You can find out more about it and the other Outputs [here](../components/outputs). \ No newline at end of file diff --git a/src/frontend/.github/workflows/playwright.yml b/src/frontend/.github/workflows/playwright.yml deleted file mode 100644 index 90b6b700d..000000000 --- a/src/frontend/.github/workflows/playwright.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Playwright Tests -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] -jobs: - test: - timeout-minutes: 60 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 18 - - name: Install dependencies - run: npm ci - - name: Install Playwright Browsers - run: npx playwright install --with-deps - - name: Run Playwright tests - run: npx playwright test - - uses: actions/upload-artifact@v3 - if: always() - with: - name: playwright-report - path: playwright-report/ - retention-days: 30 diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 2d61fd033..10ad18073 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -5770,9 +5770,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -7079,9 +7079,9 @@ } }, "node_modules/katex": { - "version": "0.16.9", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz", - "integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==", + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" diff --git a/src/frontend/playwright-report/index.html b/src/frontend/playwright-report/index.html deleted file mode 100644 index 131efdcae..000000000 --- a/src/frontend/playwright-report/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Document - - - - - diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index 30e7216c0..59f30c4ba 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -12,7 +12,7 @@ import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ testDir: "./tests", /* Run tests in files in parallel */ - fullyParallel: false, + fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ @@ -20,18 +20,22 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 2 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: [ - ["html", { open: "never", outputFolder: "playwright-report/test-results" }], - ], + timeout: 120 * 1000, + // reporter: [ + // ["html", { open: "never", outputFolder: "playwright-report/test-results" }], + // ], + reporter: process.env.CI ? "blob" : "html", /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: "http://127.0.0.1:3000", + baseURL: "http://localhost:3000/", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", }, + globalTeardown: require.resolve("./tests/globalTeardown.ts"), + /* Configure projects for major browsers */ projects: [ { @@ -48,39 +52,28 @@ export default defineConfig({ // name: "webkit", // use: { ...devices["Desktop Safari"] }, // }, - - /* Test against mobile viewports. */ - // { - // name: 'Mobile Chrome', - // use: { ...devices['Pixel 5'] }, - // }, - // { - // name: 'Mobile Safari', - // use: { ...devices['iPhone 12'] }, - // }, - - /* Test against branded browsers. */ - // { - // name: 'Microsoft Edge', - // use: { ...devices['Desktop Edge'], channel: 'msedge' }, - // }, - // { - // name: 'Google Chrome', - // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - // }, ], - /* Run your local dev server before starting the tests */ - // webServer: [ - // { - // command: "npm run backend", - // reuseExistingServer: !process.env.CI, - // timeout: 120 * 1000, - // }, - // { - // command: "npm run start", - // url: "http://127.0.0.1:3000", - // reuseExistingServer: !process.env.CI, - // }, - // ], + webServer: [ + { + command: + "poetry run uvicorn --factory langflow.main:create_app --host 127.0.0.1 --port 7860", + port: 7860, + env: { + LANGFLOW_DATABASE_URL: "sqlite:///./temp", + LANGFLOW_AUTO_LOGIN: "true", + }, + stdout: "ignore", + + reuseExistingServer: !process.env.CI, + timeout: 120 * 1000, + }, + { + command: "npm start", + port: 3000, + env: { + VITE_PROXY_TARGET: "http://127.0.0.1:7860", + }, + }, + ], }); diff --git a/src/frontend/run-tests.sh b/src/frontend/run-tests.sh index bb4535f5b..f04a09662 100755 --- a/src/frontend/run-tests.sh +++ b/src/frontend/run-tests.sh @@ -3,6 +3,17 @@ # Default value for the --ui flag ui=false +# Absolute path to the project root directory +PROJECT_ROOT="../../" + +# Check if necessary commands are available +for cmd in npx poetry fuser; do + if ! command -v $cmd &> /dev/null; then + echo "Error: Required command '$cmd' is not installed. Aborting." + exit 1 + fi +done + # Parse command-line arguments while [[ $# -gt 0 ]]; do key="$1" @@ -23,54 +34,85 @@ done terminate_process_by_port() { port="$1" echo "Terminating process on port: $port" - fuser -k -n tcp "$port" # Forcefully terminate processes using the specified port - echo "Process terminated." + if ! fuser -k -n tcp "$port"; then + echo "Failed to terminate process on port $port. Please check manually." + else + echo "Process terminated." + fi } delete_temp() { - cd ../../ - echo "Deleting temp database" - rm temp - echo "Temp database deleted." + if cd "$PROJECT_ROOT"; then + echo "Deleting temp database" + rm -f temp && echo "Temp database deleted." || echo "Failed to delete temp database." + else + echo "Failed to navigate to project root for cleanup." + fi } - # Trap signals to ensure cleanup on script termination trap 'terminate_process_by_port 7860; terminate_process_by_port 3000; delete_temp' EXIT -# install playwright if there is not installed yet -npx playwright install +# Ensure the script is executed from the project root directory +if ! cd "$PROJECT_ROOT"; then + echo "Error: Failed to navigate to project root directory. Aborting." + exit 1 +fi -# Navigate to the project root directory (where the Makefile is located) -cd ../../ +# Install playwright if not installed yet +if ! npx playwright install; then + echo "Error: Failed to install Playwright. Aborting." + exit 1 +fi -# Start the frontend using 'make frontend' in the background -make frontend & +# Start the frontend +make frontend > /dev/null 2>&1 & -# Give some time for the frontend to start (adjust sleep duration as needed) +# Adjust sleep duration as needed sleep 10 -#install backend -poetry install --extras deploy +# Install backend dependencies +if ! poetry install; then + echo "Error: Failed to install backend dependencies. Aborting." + exit 1 +fi -# Start the backend using 'make backend' in the background -LANGFLOW_DATABASE_URL=sqlite:///./temp LANGFLOW_AUTO_LOGIN=True poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser --env-file .env & - -# Give some time for the backend to start (adjust sleep duration as needed) +# Start the backend +LANGFLOW_DATABASE_URL=sqlite:///./temp LANGFLOW_AUTO_LOGIN=True poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser > /dev/null 2>&1 & +backend_pid=$! # Capture PID of the backend process +# Adjust sleep duration as needed sleep 25 # Navigate to the test directory -cd src/frontend - -# Run Playwright tests with or without UI based on the --ui flag -if [ "$ui" = true ]; then - PLAYWRIGHT_HTML_REPORT=playwright-report/e2e npx playwright test tests/end-to-end --ui --project=chromium -else - PLAYWRIGHT_HTML_REPORT=playwright-report/e2e npx playwright test tests/end-to-end --project=chromium +if ! cd src/frontend; then + echo "Error: Failed to navigate to test directory. Aborting." + kill $backend_pid # Terminate the backend process if navigation fails + echo "Backend process terminated." + exit 1 fi -npx playwright show-report +# Check if backend is running +if ! lsof -i :7860; then + echo "Error: Backend is not running. Aborting." + exit 1 +fi -# After the tests are finished, you can add cleanup or teardown logic here if needed +# Run Playwright tests +if [ "$ui" = true ]; then + TEST_COMMAND="npx playwright test tests/end-to-end --ui --project=chromium" +else + TEST_COMMAND="npx playwright test tests/end-to-end --project=chromium" +fi -# The trap will automatically terminate processes by port on script exit +if ! PLAYWRIGHT_HTML_REPORT=playwright-report/e2e $TEST_COMMAND; then + echo "Error: Playwright tests failed. Aborting." + exit 1 +fi + +if [ "$ui" = true ]; then + echo "Opening Playwright report..." + npx playwright show-report +fi + + +trap 'terminate_process_by_port 7860; terminate_process_by_port 3000; delete_temp; kill $backend_pid 2>/dev/null' EXIT \ No newline at end of file diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index 9847fd1e6..9d43cfdab 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -50,7 +50,7 @@ export default function FlowToolbar({ flow }: ChatType): JSX.Element {