2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 04:55:44 +00:00

Merge branch 'master' of https://github.com/inventree/InvenTree into matmair/issue6281

This commit is contained in:
Matthias Mair
2024-04-12 00:04:58 +02:00
32 changed files with 94 additions and 33 deletions

View File

@ -27,7 +27,7 @@ jobs:
) )
steps: steps:
- name: Backport Action - name: Backport Action
uses: sqren/backport-github-action@f7073a2287aefc1fa12685eb25a712ab5620445c # pin@v9.2.2 uses: sqren/backport-github-action@f54e19901f2a57f8b82360f2490d47ee82ec82c6 # pin@v9.2.2
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
auto_backport_label_prefix: backport-to- auto_backport_label_prefix: backport-to-

View File

@ -48,6 +48,7 @@ jobs:
- 'src/backend/requirements.txt' - 'src/backend/requirements.txt'
- 'src/backend/requirements-dev.txt' - 'src/backend/requirements-dev.txt'
migrations: migrations:
- '**/test_migrations.py'
- '**/migrations/**' - '**/migrations/**'
- '.github/workflows**' - '.github/workflows**'
- 'src/backend/requirements.txt' - 'src/backend/requirements.txt'
@ -220,7 +221,8 @@ jobs:
name: Tests - inventree-python name: Tests - inventree-python
runs-on: ubuntu-20.04 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: env:
wrapper_name: inventree-python wrapper_name: inventree-python
@ -261,7 +263,8 @@ jobs:
name: Tests - DB [SQLite] + Coverage name: Tests - DB [SQLite] + Coverage
runs-on: ubuntu-20.04 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 continue-on-error: true # continue if a step fails so that coverage gets pushed
env: env:
@ -292,11 +295,13 @@ jobs:
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: backend flag-name: backend
file: coverage.xml
git-commit: ${{ github.sha }} git-commit: ${{ github.sha }}
git-branch: ${{ github.ref }} git-branch: ${{ github.ref }}
parallel: true parallel: true
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1 uses: codecov/codecov-action@v4.3.0
if: always()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree slug: inventree/InvenTree
@ -305,7 +310,8 @@ jobs:
postgres: postgres:
name: Tests - DB [PostgreSQL] name: Tests - DB [PostgreSQL]
runs-on: ubuntu-20.04 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: env:
INVENTREE_DB_ENGINE: django.db.backends.postgresql INVENTREE_DB_ENGINE: django.db.backends.postgresql
@ -349,7 +355,8 @@ jobs:
name: Tests - DB [MySQL] name: Tests - DB [MySQL]
runs-on: ubuntu-20.04 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: env:
# Database backend configuration # Database backend configuration
@ -433,7 +440,8 @@ jobs:
git-commit: ${{ github.sha }} git-commit: ${{ github.sha }}
git-branch: ${{ github.ref }} git-branch: ${{ github.ref }}
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1 uses: codecov/codecov-action@v4.3.0
if: always()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree slug: inventree/InvenTree
@ -523,7 +531,14 @@ jobs:
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: cd src/frontend && npx playwright install --with-deps run: cd src/frontend && npx playwright install --with-deps
- name: Run Playwright tests - name: Run Playwright tests
id: tests
run: cd src/frontend && npx nyc playwright test 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 - name: Report coverage
if: always() if: always()
run: cd src/frontend && npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --exclude-after-remap false 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 }} git-branch: ${{ github.ref }}
parallel: true parallel: true
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1 uses: codecov/codecov-action@v4.3.0
if: always()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
slug: inventree/InvenTree slug: inventree/InvenTree

View File

@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - 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: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@ -1,3 +1,3 @@
# Dummy requirements file to trigger the package pipeline # 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
# #

View File

@ -285,6 +285,29 @@ QUERYCOUNT = {
'RESPONSE_HEADER': 'X-Django-Query-Count', '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 = CONFIG.get(
'authentication_backends', 'authentication_backends',
[ [

View File

@ -434,7 +434,11 @@ classic_frontendpatterns = [
urlpatterns = [] urlpatterns = []
if settings.INVENTREE_ADMIN_ENABLED: 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 += [ urlpatterns += [
path(f'{admin_url}/error_log/', include('error_report.urls')), path(f'{admin_url}/error_log/', include('error_report.urls')),
path(f'{admin_url}/', admin.site.urls, name='inventree-admin'), path(f'{admin_url}/', admin.site.urls, name='inventree-admin'),

View File

@ -258,6 +258,13 @@ class UserSettingsList(SettingsList):
common.models.InvenTreeUserSetting.build_default_values(user=request.user) common.models.InvenTreeUserSetting.build_default_values(user=request.user)
return super().list(request, *args, **kwargs) 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): def filter_queryset(self, queryset):
"""Only list settings which apply to the current user.""" """Only list settings which apply to the current user."""
try: try:

View File

@ -64,6 +64,7 @@ class TestSerialNumberMigration(MigratorTestCase):
big_ref_item.serial, big_ref_item.serial,
'9999999999999999999999999999999999999999999999999999999999999', '9999999999999999999999999999999999999999999999999999999999999',
) )
self.assertEqual(big_ref_item.serial_int, 0x7FFFFFFF) self.assertEqual(big_ref_item.serial_int, 0x7FFFFFFF)

View File

@ -2,6 +2,7 @@
-c requirements.txt -c requirements.txt
coverage[toml] # Unit test coverage coverage[toml] # Unit test coverage
coveralls==2.1.2 # Coveralls linking (for tracking coverage) # PINNED 2022-06-28 - Old version needed for correct upload 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-querycount # Display number of URL queries for requests
django-slowtests # Show which unit tests are running slowly django-slowtests # Show which unit tests are running slowly
django-test-migrations # Unit testing for database migrations django-test-migrations # Unit testing for database migrations

View File

@ -24,7 +24,10 @@ cryptography==42.0.5
distlib==0.3.8 distlib==0.3.8
# via virtualenv # via virtualenv
django==4.2.11 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-querycount==0.8.3
django-slowtests==1.1.1 django-slowtests==1.1.1
django-test-migrations==1.3.0 django-test-migrations==1.3.0

View File

@ -268,7 +268,7 @@ pyyaml==6.0.1
# tablib # tablib
qrcode[pil]==7.4.2 qrcode[pil]==7.4.2
# via django-allauth # via django-allauth
rapidfuzz==3.6.2 rapidfuzz==3.8.1
redis==5.0.3 redis==5.0.3
# via django-redis # via django-redis
referencing==0.34.0 referencing==0.34.0

View File

@ -6,7 +6,7 @@ export default defineConfig({
forbidOnly: !!process.env.CI, forbidOnly: !!process.env.CI,
retries: process.env.CI ? 1 : 0, retries: process.env.CI ? 1 : 0,
workers: process.env.CI ? 2 : undefined, 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 */ /* Configure projects for major browsers */
projects: [ projects: [

View File

@ -23,9 +23,9 @@ import { getDetailUrl } from '../../functions/urls';
import { base_url } from '../../main'; import { base_url } from '../../main';
import { apiUrl } from '../../states/ApiState'; import { apiUrl } from '../../states/ApiState';
import { useGlobalSettingsState } from '../../states/SettingsState'; import { useGlobalSettingsState } from '../../states/SettingsState';
import { YesNoButton } from '../buttons/YesNoButton';
import { ProgressBar } from '../items/ProgressBar'; import { ProgressBar } from '../items/ProgressBar';
import { StylishText } from '../items/StylishText'; import { StylishText } from '../items/StylishText';
import { YesNoButton } from '../items/YesNoButton';
import { getModelInfo } from '../render/ModelType'; import { getModelInfo } from '../render/ModelType';
import { StatusRenderer } from '../render/StatusRenderer'; import { StatusRenderer } from '../render/StatusRenderer';

View File

@ -6,7 +6,7 @@ import { IconCheck } from '@tabler/icons-react';
import { useServerApiState } from '../../states/ApiState'; import { useServerApiState } from '../../states/ApiState';
import { useLocalState } from '../../states/LocalState'; import { useLocalState } from '../../states/LocalState';
import { HostList } from '../../states/states'; import { HostList } from '../../states/states';
import { EditButton } from '../items/EditButton'; import { EditButton } from '../buttons/EditButton';
import { HostOptionsForm } from './HostOptionsForm'; import { HostOptionsForm } from './HostOptionsForm';
export function InstanceOptions({ export function InstanceOptions({

View File

@ -2,8 +2,8 @@ import { Trans } from '@lingui/macro';
import { Code, Flex, Group, Text } from '@mantine/core'; import { Code, Flex, Group, Text } from '@mantine/core';
import { Link, To } from 'react-router-dom'; import { Link, To } from 'react-router-dom';
import { YesNoButton } from '../buttons/YesNoButton';
import { DetailDrawerLink } from '../nav/DetailDrawer'; import { DetailDrawerLink } from '../nav/DetailDrawer';
import { YesNoButton } from './YesNoButton';
export function InfoItem({ export function InfoItem({
name, name,

View File

@ -19,7 +19,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { apiUrl, useServerApiState } from '../../states/ApiState'; import { apiUrl, useServerApiState } from '../../states/ApiState';
import { useLocalState } from '../../states/LocalState'; import { useLocalState } from '../../states/LocalState';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { CopyButton } from '../items/CopyButton'; import { CopyButton } from '../buttons/CopyButton';
type AboutLookupRef = { type AboutLookupRef = {
ref: string; ref: string;

View File

@ -20,7 +20,7 @@ export function LicenceView(entries: Readonly<any[]>) {
return ( return (
<Stack spacing="xs"> <Stack spacing="xs">
<Divider /> <Divider />
{entries?.length > 0 && ( {entries?.length > 0 ? (
<Accordion variant="contained" defaultValue="-"> <Accordion variant="contained" defaultValue="-">
{entries?.map((entry: any, index: number) => ( {entries?.map((entry: any, index: number) => (
<Accordion.Item key={entry.name} value={`entry-${index}`}> <Accordion.Item key={entry.name} value={`entry-${index}`}>
@ -38,6 +38,10 @@ export function LicenceView(entries: Readonly<any[]>) {
</Accordion.Item> </Accordion.Item>
))} ))}
</Accordion> </Accordion>
) : (
<Text>
<Trans>No Information provided - this is likely a server issue</Trans>
</Text>
)} )}
</Stack> </Stack>
); );
@ -53,6 +57,8 @@ export function LicenseModal() {
.catch(() => {}) .catch(() => {})
}); });
const rspdata = !data ? [] : Object.keys(data ?? {});
return ( return (
<Stack spacing="xs"> <Stack spacing="xs">
<Divider /> <Divider />
@ -69,16 +75,16 @@ export function LicenseModal() {
</Text> </Text>
</Alert> </Alert>
) : ( ) : (
<Tabs defaultValue={Object.keys(data)[0] ?? ''}> <Tabs defaultValue={rspdata[0] ?? ''}>
<Tabs.List> <Tabs.List>
{Object.keys(data ?? {}).map((key) => ( {rspdata.map((key) => (
<Tabs.Tab key={key} value={key}> <Tabs.Tab key={key} value={key}>
<Trans>{key} Packages</Trans> <Trans>{key} Packages</Trans>
</Tabs.Tab> </Tabs.Tab>
))} ))}
</Tabs.List> </Tabs.List>
{Object.keys(data ?? {}).map((key) => ( {rspdata.map((key) => (
<Tabs.Panel key={key} value={key}> <Tabs.Panel key={key} value={key}>
{LicenceView(data[key] ?? [])} {LicenceView(data[key] ?? [])}
</Tabs.Panel> </Tabs.Panel>

View File

@ -10,7 +10,7 @@ import { navTabs as mainNavTabs } from '../../defaults/links';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { InvenTreeStyle } from '../../globalStyle'; import { InvenTreeStyle } from '../../globalStyle';
import { apiUrl } from '../../states/ApiState'; import { apiUrl } from '../../states/ApiState';
import { ScanButton } from '../items/ScanButton'; import { ScanButton } from '../buttons/ScanButton';
import { MainMenu } from './MainMenu'; import { MainMenu } from './MainMenu';
import { NavHoverMenu } from './NavHoverMenu'; import { NavHoverMenu } from './NavHoverMenu';
import { NavigationDrawer } from './NavigationDrawer'; import { NavigationDrawer } from './NavigationDrawer';

View File

@ -4,7 +4,7 @@ import { useForm } from '@mantine/form';
import { useToggle } from '@mantine/hooks'; import { useToggle } from '@mantine/hooks';
import { api } from '../../../../App'; import { api } from '../../../../App';
import { EditButton } from '../../../../components/items/EditButton'; import { EditButton } from '../../../../components/buttons/EditButton';
import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints';
import { apiUrl } from '../../../../states/ApiState'; import { apiUrl } from '../../../../states/ApiState';
import { useUserState } from '../../../../states/UserState'; import { useUserState } from '../../../../states/UserState';

View File

@ -4,9 +4,9 @@
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Anchor } from '@mantine/core'; import { Anchor } from '@mantine/core';
import { YesNoButton } from '../components/buttons/YesNoButton';
import { Thumbnail } from '../components/images/Thumbnail'; import { Thumbnail } from '../components/images/Thumbnail';
import { ProgressBar } from '../components/items/ProgressBar'; import { ProgressBar } from '../components/items/ProgressBar';
import { YesNoButton } from '../components/items/YesNoButton';
import { TableStatusRenderer } from '../components/render/StatusRenderer'; import { TableStatusRenderer } from '../components/render/StatusRenderer';
import { RenderOwner } from '../components/render/User'; import { RenderOwner } from '../components/render/User';
import { formatCurrency, renderDate } from '../defaults/formatters'; import { formatCurrency, renderDate } from '../defaults/formatters';

View File

@ -8,8 +8,8 @@ import {
import { ReactNode, useCallback, useMemo } from 'react'; import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { YesNoButton } from '../../components/buttons/YesNoButton';
import { Thumbnail } from '../../components/images/Thumbnail'; import { Thumbnail } from '../../components/images/Thumbnail';
import { YesNoButton } from '../../components/items/YesNoButton';
import { formatPriceRange } from '../../defaults/formatters'; import { formatPriceRange } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';

View File

@ -2,8 +2,8 @@ import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { AddItemButton } from '../../components/buttons/AddItemButton'; import { AddItemButton } from '../../components/buttons/AddItemButton';
import { YesNoButton } from '../../components/buttons/YesNoButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles'; import { UserRoles } from '../../enums/Roles';
import { import {

View File

@ -23,6 +23,7 @@ import { useNavigate } from 'react-router-dom';
import { api } from '../../App'; import { api } from '../../App';
import { AddItemButton } from '../../components/buttons/AddItemButton'; import { AddItemButton } from '../../components/buttons/AddItemButton';
import { YesNoButton } from '../../components/buttons/YesNoButton';
import { import {
ActionDropdown, ActionDropdown,
DeleteItemAction, DeleteItemAction,
@ -30,7 +31,6 @@ import {
} from '../../components/items/ActionDropdown'; } from '../../components/items/ActionDropdown';
import { InfoItem } from '../../components/items/InfoItem'; import { InfoItem } from '../../components/items/InfoItem';
import { UnavailableIndicator } from '../../components/items/UnavailableIndicator'; import { UnavailableIndicator } from '../../components/items/UnavailableIndicator';
import { YesNoButton } from '../../components/items/YesNoButton';
import { import {
DetailDrawer, DetailDrawer,
DetailDrawerLink DetailDrawerLink

View File

@ -6,8 +6,8 @@ import { useQuery } from '@tanstack/react-query';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { api } from '../../App'; import { api } from '../../App';
import { YesNoButton } from '../../components/buttons/YesNoButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles'; import { UserRoles } from '../../enums/Roles';

View File

@ -3,7 +3,7 @@ import { useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { AddItemButton } from '../../components/buttons/AddItemButton'; import { AddItemButton } from '../../components/buttons/AddItemButton';
import { YesNoButton } from '../../components/items/YesNoButton'; import { YesNoButton } from '../../components/buttons/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles'; import { UserRoles } from '../../enums/Roles';

View File

@ -3,8 +3,8 @@ import { Text } from '@mantine/core';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { AddItemButton } from '../../components/buttons/AddItemButton'; import { AddItemButton } from '../../components/buttons/AddItemButton';
import { YesNoButton } from '../../components/buttons/YesNoButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles'; import { UserRoles } from '../../enums/Roles';
import { import {

View File

@ -12,9 +12,9 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { api } from '../../App'; import { api } from '../../App';
import { AddItemButton } from '../../components/buttons/AddItemButton'; import { AddItemButton } from '../../components/buttons/AddItemButton';
import { PassFailButton } from '../../components/buttons/YesNoButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { AttachmentLink } from '../../components/items/AttachmentLink'; import { AttachmentLink } from '../../components/items/AttachmentLink';
import { PassFailButton } from '../../components/items/YesNoButton';
import { RenderUser } from '../../components/render/User'; import { RenderUser } from '../../components/render/User';
import { renderDate } from '../../defaults/formatters'; import { renderDate } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';

View File

@ -870,7 +870,7 @@ def test(
if coverage: if coverage:
# Run tests within coverage environment, and generate report # Run tests within coverage environment, and generate report
c.run(f'coverage run {managePyPath()} {cmd}') c.run(f'coverage run {managePyPath()} {cmd}')
c.run('coverage html -i') c.run('coverage xml -i')
else: else:
# Run simple test runner, without coverage # Run simple test runner, without coverage
manage(c, cmd, pty=pty) manage(c, cmd, pty=pty)