diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 9afc5b840f..67ed6f6da8 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -27,7 +27,7 @@ jobs: ) steps: - name: Backport Action - uses: sqren/backport-github-action@f7073a2287aefc1fa12685eb25a712ab5620445c # pin@v9.2.2 + uses: sqren/backport-github-action@f54e19901f2a57f8b82360f2490d47ee82ec82c6 # pin@v9.2.2 with: github_token: ${{ secrets.GITHUB_TOKEN }} auto_backport_label_prefix: backport-to- diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index ca8ef33b49..c55f1dde86 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -48,6 +48,7 @@ jobs: - 'src/backend/requirements.txt' - 'src/backend/requirements-dev.txt' migrations: + - '**/test_migrations.py' - '**/migrations/**' - '.github/workflows**' - 'src/backend/requirements.txt' @@ -220,7 +221,8 @@ jobs: name: Tests - inventree-python runs-on: ubuntu-20.04 - needs: pre-commit + needs: [ 'pre-commit', 'paths-filter' ] + if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' env: wrapper_name: inventree-python @@ -261,7 +263,8 @@ jobs: name: Tests - DB [SQLite] + Coverage runs-on: ubuntu-20.04 - needs: [ 'pre-commit' ] + needs: [ 'pre-commit', 'paths-filter' ] + if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' continue-on-error: true # continue if a step fails so that coverage gets pushed env: @@ -292,11 +295,13 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} flag-name: backend + file: coverage.xml git-commit: ${{ github.sha }} git-branch: ${{ github.ref }} parallel: true - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4.0.1 + uses: codecov/codecov-action@v4.3.0 + if: always() with: token: ${{ secrets.CODECOV_TOKEN }} slug: inventree/InvenTree @@ -305,7 +310,8 @@ jobs: postgres: name: Tests - DB [PostgreSQL] runs-on: ubuntu-20.04 - needs: [ 'pre-commit' ] + needs: [ 'pre-commit', 'paths-filter' ] + if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' env: INVENTREE_DB_ENGINE: django.db.backends.postgresql @@ -349,7 +355,8 @@ jobs: name: Tests - DB [MySQL] runs-on: ubuntu-20.04 - needs: [ 'pre-commit' ] + needs: [ 'pre-commit', 'paths-filter' ] + if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.force == 'true' env: # Database backend configuration @@ -433,7 +440,8 @@ jobs: git-commit: ${{ github.sha }} git-branch: ${{ github.ref }} - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4.0.1 + uses: codecov/codecov-action@v4.3.0 + if: always() with: token: ${{ secrets.CODECOV_TOKEN }} slug: inventree/InvenTree @@ -523,7 +531,14 @@ jobs: - name: Install Playwright Browsers run: cd src/frontend && npx playwright install --with-deps - name: Run Playwright tests + id: tests run: cd src/frontend && npx nyc playwright test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() && steps.tests.outcome == 'failure' }} + with: + name: playwright-report + path: src/frontend/playwright-report/ + retention-days: 14 - name: Report coverage if: always() run: cd src/frontend && npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --exclude-after-remap false @@ -537,7 +552,8 @@ jobs: git-branch: ${{ github.ref }} parallel: true - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4.0.1 + uses: codecov/codecov-action@v4.3.0 + if: always() with: token: ${{ secrets.CODECOV_TOKEN }} slug: inventree/InvenTree diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 8d69fcf44a..e3633a6f27 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 with: sarif_file: results.sarif diff --git a/requirements.txt b/requirements.txt index 63e33d7163..3e374ea6fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ # Dummy requirements file to trigger the package pipeline -# The new requirements file is located in src/backend/requirements.txt +# The backend requirements file is located in src/backend/requirements.txt # diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index 6f744d5f13..9a5ec52514 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -285,6 +285,29 @@ QUERYCOUNT = { 'RESPONSE_HEADER': 'X-Django-Query-Count', } +ADMIN_SHELL_ENABLE = False +ADMIN_SHELL_IMPORT_DJANGO = False +ADMIN_SHELL_IMPORT_MODELS = False + +# In DEBUG mode, add support for django-admin-shell +# Ref: https://github.com/djk2/django-admin-shell +if ( + DEBUG + and INVENTREE_ADMIN_ENABLED + and get_boolean_setting('INVENTREE_DEBUG_SHELL', 'debug_shell', False) +): # noqa + try: + import django_admin_shell + + INSTALLED_APPS.append('django_admin_shell') + ADMIN_SHELL_ENABLE = True + + logger.warning('Admin shell is enabled') + except ModuleNotFoundError: + logger.warning( + 'django-admin-shell is not installed - Admin shell is not enabled' + ) + AUTHENTICATION_BACKENDS = CONFIG.get( 'authentication_backends', [ diff --git a/src/backend/InvenTree/InvenTree/urls.py b/src/backend/InvenTree/InvenTree/urls.py index 83c54d14cb..d9f4c51a71 100644 --- a/src/backend/InvenTree/InvenTree/urls.py +++ b/src/backend/InvenTree/InvenTree/urls.py @@ -434,7 +434,11 @@ classic_frontendpatterns = [ urlpatterns = [] if settings.INVENTREE_ADMIN_ENABLED: - admin_url = (settings.INVENTREE_ADMIN_URL,) + admin_url = settings.INVENTREE_ADMIN_URL + + if settings.ADMIN_SHELL_ENABLE: # noqa + urlpatterns += [path(f'{admin_url}/shell/', include('django_admin_shell.urls'))] + urlpatterns += [ path(f'{admin_url}/error_log/', include('error_report.urls')), path(f'{admin_url}/', admin.site.urls, name='inventree-admin'), diff --git a/src/backend/InvenTree/common/api.py b/src/backend/InvenTree/common/api.py index f3e5066bde..50f6361e0b 100644 --- a/src/backend/InvenTree/common/api.py +++ b/src/backend/InvenTree/common/api.py @@ -258,6 +258,13 @@ class UserSettingsList(SettingsList): common.models.InvenTreeUserSetting.build_default_values(user=request.user) return super().list(request, *args, **kwargs) + def get_queryset(self): + """Return prefetched queryset.""" + queryset = super().get_queryset() + queryset = queryset.prefetch_related('user') + + return queryset + def filter_queryset(self, queryset): """Only list settings which apply to the current user.""" try: diff --git a/src/backend/InvenTree/stock/test_migrations.py b/src/backend/InvenTree/stock/test_migrations.py index 1d2eb0f0b2..c052325f17 100644 --- a/src/backend/InvenTree/stock/test_migrations.py +++ b/src/backend/InvenTree/stock/test_migrations.py @@ -64,6 +64,7 @@ class TestSerialNumberMigration(MigratorTestCase): big_ref_item.serial, '9999999999999999999999999999999999999999999999999999999999999', ) + self.assertEqual(big_ref_item.serial_int, 0x7FFFFFFF) diff --git a/src/backend/requirements-dev.in b/src/backend/requirements-dev.in index ab3c583153..b345e119ba 100644 --- a/src/backend/requirements-dev.in +++ b/src/backend/requirements-dev.in @@ -2,6 +2,7 @@ -c requirements.txt coverage[toml] # Unit test coverage coveralls==2.1.2 # Coveralls linking (for tracking coverage) # PINNED 2022-06-28 - Old version needed for correct upload +django-admin-shell # Remote shell access django-querycount # Display number of URL queries for requests django-slowtests # Show which unit tests are running slowly django-test-migrations # Unit testing for database migrations diff --git a/src/backend/requirements-dev.txt b/src/backend/requirements-dev.txt index 770b65b283..693c8bc1d4 100644 --- a/src/backend/requirements-dev.txt +++ b/src/backend/requirements-dev.txt @@ -24,7 +24,10 @@ cryptography==42.0.5 distlib==0.3.8 # via virtualenv django==4.2.11 - # via django-slowtests + # via + # django-admin-shell + # django-slowtests +django-admin-shell==2.0.1 django-querycount==0.8.3 django-slowtests==1.1.1 django-test-migrations==1.3.0 diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index dec20bd674..b83a2ce622 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -268,7 +268,7 @@ pyyaml==6.0.1 # tablib qrcode[pil]==7.4.2 # via django-allauth -rapidfuzz==3.6.2 +rapidfuzz==3.8.1 redis==5.0.3 # via django-redis referencing==0.34.0 diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index ded3e1028b..d40ec5cf42 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, retries: process.env.CI ? 1 : 0, workers: process.env.CI ? 2 : undefined, - reporter: process.env.CI ? 'github' : 'list', + reporter: process.env.CI ? [['html', { open: 'never' }], ['github']] : 'list', /* Configure projects for major browsers */ projects: [ diff --git a/src/frontend/src/components/items/CopyButton.tsx b/src/frontend/src/components/buttons/CopyButton.tsx similarity index 100% rename from src/frontend/src/components/items/CopyButton.tsx rename to src/frontend/src/components/buttons/CopyButton.tsx diff --git a/src/frontend/src/components/items/EditButton.tsx b/src/frontend/src/components/buttons/EditButton.tsx similarity index 100% rename from src/frontend/src/components/items/EditButton.tsx rename to src/frontend/src/components/buttons/EditButton.tsx diff --git a/src/frontend/src/components/items/ScanButton.tsx b/src/frontend/src/components/buttons/ScanButton.tsx similarity index 100% rename from src/frontend/src/components/items/ScanButton.tsx rename to src/frontend/src/components/buttons/ScanButton.tsx diff --git a/src/frontend/src/components/items/YesNoButton.tsx b/src/frontend/src/components/buttons/YesNoButton.tsx similarity index 100% rename from src/frontend/src/components/items/YesNoButton.tsx rename to src/frontend/src/components/buttons/YesNoButton.tsx diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx index d82615212d..e0c8a6cc44 100644 --- a/src/frontend/src/components/details/Details.tsx +++ b/src/frontend/src/components/details/Details.tsx @@ -23,9 +23,9 @@ import { getDetailUrl } from '../../functions/urls'; import { base_url } from '../../main'; import { apiUrl } from '../../states/ApiState'; import { useGlobalSettingsState } from '../../states/SettingsState'; +import { YesNoButton } from '../buttons/YesNoButton'; import { ProgressBar } from '../items/ProgressBar'; import { StylishText } from '../items/StylishText'; -import { YesNoButton } from '../items/YesNoButton'; import { getModelInfo } from '../render/ModelType'; import { StatusRenderer } from '../render/StatusRenderer'; diff --git a/src/frontend/src/components/forms/InstanceOptions.tsx b/src/frontend/src/components/forms/InstanceOptions.tsx index 9dc1c1115f..4074cee3cf 100644 --- a/src/frontend/src/components/forms/InstanceOptions.tsx +++ b/src/frontend/src/components/forms/InstanceOptions.tsx @@ -6,7 +6,7 @@ import { IconCheck } from '@tabler/icons-react'; import { useServerApiState } from '../../states/ApiState'; import { useLocalState } from '../../states/LocalState'; import { HostList } from '../../states/states'; -import { EditButton } from '../items/EditButton'; +import { EditButton } from '../buttons/EditButton'; import { HostOptionsForm } from './HostOptionsForm'; export function InstanceOptions({ diff --git a/src/frontend/src/components/items/InfoItem.tsx b/src/frontend/src/components/items/InfoItem.tsx index dbfdae25ec..ad12e5d855 100644 --- a/src/frontend/src/components/items/InfoItem.tsx +++ b/src/frontend/src/components/items/InfoItem.tsx @@ -2,8 +2,8 @@ import { Trans } from '@lingui/macro'; import { Code, Flex, Group, Text } from '@mantine/core'; import { Link, To } from 'react-router-dom'; +import { YesNoButton } from '../buttons/YesNoButton'; import { DetailDrawerLink } from '../nav/DetailDrawer'; -import { YesNoButton } from './YesNoButton'; export function InfoItem({ name, diff --git a/src/frontend/src/components/modals/AboutInvenTreeModal.tsx b/src/frontend/src/components/modals/AboutInvenTreeModal.tsx index 19e7d5011c..4c4bd53c14 100644 --- a/src/frontend/src/components/modals/AboutInvenTreeModal.tsx +++ b/src/frontend/src/components/modals/AboutInvenTreeModal.tsx @@ -19,7 +19,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { apiUrl, useServerApiState } from '../../states/ApiState'; import { useLocalState } from '../../states/LocalState'; import { useUserState } from '../../states/UserState'; -import { CopyButton } from '../items/CopyButton'; +import { CopyButton } from '../buttons/CopyButton'; type AboutLookupRef = { ref: string; diff --git a/src/frontend/src/components/modals/LicenseModal.tsx b/src/frontend/src/components/modals/LicenseModal.tsx index 05c8d4a79c..a790e765b5 100644 --- a/src/frontend/src/components/modals/LicenseModal.tsx +++ b/src/frontend/src/components/modals/LicenseModal.tsx @@ -20,7 +20,7 @@ export function LicenceView(entries: Readonly) { return ( - {entries?.length > 0 && ( + {entries?.length > 0 ? ( {entries?.map((entry: any, index: number) => ( @@ -38,6 +38,10 @@ export function LicenceView(entries: Readonly) { ))} + ) : ( + + No Information provided - this is likely a server issue + )} ); @@ -53,6 +57,8 @@ export function LicenseModal() { .catch(() => {}) }); + const rspdata = !data ? [] : Object.keys(data ?? {}); + return ( @@ -69,16 +75,16 @@ export function LicenseModal() { ) : ( - + - {Object.keys(data ?? {}).map((key) => ( + {rspdata.map((key) => ( {key} Packages ))} - {Object.keys(data ?? {}).map((key) => ( + {rspdata.map((key) => ( {LicenceView(data[key] ?? [])} diff --git a/src/frontend/src/components/nav/Header.tsx b/src/frontend/src/components/nav/Header.tsx index b4f139cfb8..755db08a8d 100644 --- a/src/frontend/src/components/nav/Header.tsx +++ b/src/frontend/src/components/nav/Header.tsx @@ -10,7 +10,7 @@ import { navTabs as mainNavTabs } from '../../defaults/links'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { InvenTreeStyle } from '../../globalStyle'; import { apiUrl } from '../../states/ApiState'; -import { ScanButton } from '../items/ScanButton'; +import { ScanButton } from '../buttons/ScanButton'; import { MainMenu } from './MainMenu'; import { NavHoverMenu } from './NavHoverMenu'; import { NavigationDrawer } from './NavigationDrawer'; diff --git a/src/frontend/src/pages/Index/Settings/AccountSettings/AccountDetailPanel.tsx b/src/frontend/src/pages/Index/Settings/AccountSettings/AccountDetailPanel.tsx index 576e34a75d..f5b89678b9 100644 --- a/src/frontend/src/pages/Index/Settings/AccountSettings/AccountDetailPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AccountSettings/AccountDetailPanel.tsx @@ -4,7 +4,7 @@ import { useForm } from '@mantine/form'; import { useToggle } from '@mantine/hooks'; import { api } from '../../../../App'; -import { EditButton } from '../../../../components/items/EditButton'; +import { EditButton } from '../../../../components/buttons/EditButton'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { apiUrl } from '../../../../states/ApiState'; import { useUserState } from '../../../../states/UserState'; diff --git a/src/frontend/src/tables/ColumnRenderers.tsx b/src/frontend/src/tables/ColumnRenderers.tsx index acd89d48c4..a7f266e8da 100644 --- a/src/frontend/src/tables/ColumnRenderers.tsx +++ b/src/frontend/src/tables/ColumnRenderers.tsx @@ -4,9 +4,9 @@ import { t } from '@lingui/macro'; import { Anchor } from '@mantine/core'; +import { YesNoButton } from '../components/buttons/YesNoButton'; import { Thumbnail } from '../components/images/Thumbnail'; import { ProgressBar } from '../components/items/ProgressBar'; -import { YesNoButton } from '../components/items/YesNoButton'; import { TableStatusRenderer } from '../components/render/StatusRenderer'; import { RenderOwner } from '../components/render/User'; import { formatCurrency, renderDate } from '../defaults/formatters'; diff --git a/src/frontend/src/tables/bom/BomTable.tsx b/src/frontend/src/tables/bom/BomTable.tsx index 5c4e602526..b2101897dc 100644 --- a/src/frontend/src/tables/bom/BomTable.tsx +++ b/src/frontend/src/tables/bom/BomTable.tsx @@ -8,8 +8,8 @@ import { import { ReactNode, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; +import { YesNoButton } from '../../components/buttons/YesNoButton'; import { Thumbnail } from '../../components/images/Thumbnail'; -import { YesNoButton } from '../../components/items/YesNoButton'; import { formatPriceRange } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; diff --git a/src/frontend/src/tables/company/AddressTable.tsx b/src/frontend/src/tables/company/AddressTable.tsx index 96af3c7d9f..bef8d0cef9 100644 --- a/src/frontend/src/tables/company/AddressTable.tsx +++ b/src/frontend/src/tables/company/AddressTable.tsx @@ -2,8 +2,8 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { YesNoButton } from '../../components/buttons/YesNoButton'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; -import { YesNoButton } from '../../components/items/YesNoButton'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { UserRoles } from '../../enums/Roles'; import { diff --git a/src/frontend/src/tables/machine/MachineListTable.tsx b/src/frontend/src/tables/machine/MachineListTable.tsx index 28c703f304..d46772f4b2 100644 --- a/src/frontend/src/tables/machine/MachineListTable.tsx +++ b/src/frontend/src/tables/machine/MachineListTable.tsx @@ -23,6 +23,7 @@ import { useNavigate } from 'react-router-dom'; import { api } from '../../App'; import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { YesNoButton } from '../../components/buttons/YesNoButton'; import { ActionDropdown, DeleteItemAction, @@ -30,7 +31,6 @@ import { } from '../../components/items/ActionDropdown'; import { InfoItem } from '../../components/items/InfoItem'; import { UnavailableIndicator } from '../../components/items/UnavailableIndicator'; -import { YesNoButton } from '../../components/items/YesNoButton'; import { DetailDrawer, DetailDrawerLink diff --git a/src/frontend/src/tables/part/ParametricPartTable.tsx b/src/frontend/src/tables/part/ParametricPartTable.tsx index c842efde04..ee2baa620f 100644 --- a/src/frontend/src/tables/part/ParametricPartTable.tsx +++ b/src/frontend/src/tables/part/ParametricPartTable.tsx @@ -6,8 +6,8 @@ import { useQuery } from '@tanstack/react-query'; import { useCallback, useMemo, useState } from 'react'; import { api } from '../../App'; +import { YesNoButton } from '../../components/buttons/YesNoButton'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; -import { YesNoButton } from '../../components/items/YesNoButton'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; diff --git a/src/frontend/src/tables/part/PartCategoryTable.tsx b/src/frontend/src/tables/part/PartCategoryTable.tsx index 46cbe72b2f..8f78438b18 100644 --- a/src/frontend/src/tables/part/PartCategoryTable.tsx +++ b/src/frontend/src/tables/part/PartCategoryTable.tsx @@ -3,7 +3,7 @@ import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { AddItemButton } from '../../components/buttons/AddItemButton'; -import { YesNoButton } from '../../components/items/YesNoButton'; +import { YesNoButton } from '../../components/buttons/YesNoButton'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; diff --git a/src/frontend/src/tables/part/PartParameterTable.tsx b/src/frontend/src/tables/part/PartParameterTable.tsx index a598cf885a..80e37fbb20 100644 --- a/src/frontend/src/tables/part/PartParameterTable.tsx +++ b/src/frontend/src/tables/part/PartParameterTable.tsx @@ -3,8 +3,8 @@ import { Text } from '@mantine/core'; import { useCallback, useMemo, useState } from 'react'; import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { YesNoButton } from '../../components/buttons/YesNoButton'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; -import { YesNoButton } from '../../components/items/YesNoButton'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { UserRoles } from '../../enums/Roles'; import { diff --git a/src/frontend/src/tables/stock/StockItemTestResultTable.tsx b/src/frontend/src/tables/stock/StockItemTestResultTable.tsx index dba02931cf..8014e1a33b 100644 --- a/src/frontend/src/tables/stock/StockItemTestResultTable.tsx +++ b/src/frontend/src/tables/stock/StockItemTestResultTable.tsx @@ -12,9 +12,9 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { api } from '../../App'; import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { PassFailButton } from '../../components/buttons/YesNoButton'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; import { AttachmentLink } from '../../components/items/AttachmentLink'; -import { PassFailButton } from '../../components/items/YesNoButton'; import { RenderUser } from '../../components/render/User'; import { renderDate } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; diff --git a/tasks.py b/tasks.py index 4113511ea9..37052e2014 100644 --- a/tasks.py +++ b/tasks.py @@ -870,7 +870,7 @@ def test( if coverage: # Run tests within coverage environment, and generate report c.run(f'coverage run {managePyPath()} {cmd}') - c.run('coverage html -i') + c.run('coverage xml -i') else: # Run simple test runner, without coverage manage(c, cmd, pty=pty)