Skip to content

Commit

Permalink
Merge branch 'inventree:master' into style-chg
Browse files Browse the repository at this point in the history
  • Loading branch information
matmair authored Dec 16, 2024
2 parents a2c2c12 + 3041d90 commit a57dfd2
Show file tree
Hide file tree
Showing 179 changed files with 89,305 additions and 86,400 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/postCreateCommand.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ invoke update -s
invoke dev.setup-dev

# Install required frontend packages
invoke dev.frontend-install
invoke int.frontend-install

# remove existing gitconfig created by "Avoiding Dubious Ownership" step
# so that it gets copied from host to the container to have your global
Expand Down
1 change: 1 addition & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ changelog:
exclude:
labels:
- translation
- translations
- documentation
categories:
- title: Breaking Changes
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ jobs:
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # [email protected]
- name: Set up Docker Buildx
if: github.event_name != 'pull_request'
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # pin@v3.7.1
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # pin@v3.8.0
- name: Set up cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # [email protected]
Expand Down Expand Up @@ -166,7 +166,7 @@ jobs:
- name: Push Docker Images
id: push-docker
if: github.event_name != 'pull_request'
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # pin@v6.9.0
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # pin@v6.10.0
with:
context: .
file: ./contrib/container/Dockerfile
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/qc_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ jobs:
- name: Coverage Tests
run: invoke dev.test --coverage
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # pin@v5.0.7
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # pin@v5.1.1
if: always()
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down Expand Up @@ -440,7 +440,7 @@ jobs:
- name: Run Tests
run: invoke dev.test --migrations --report --coverage
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # pin@v5.0.7
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # pin@v5.1.1
if: always()
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down Expand Up @@ -545,7 +545,7 @@ jobs:
if: always()
run: cd src/frontend && npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --exclude-after-remap false
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # pin@v5.0.7
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # pin@v5.1.1
if: always()
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: Build frontend
run: cd src/frontend && npm run compile && npm run build
- name: Create SBOM for frontend
uses: anchore/sbom-action@55dc4ee22412511ee8c3142cbea40418e6cec693 # pin@v0
uses: anchore/sbom-action@df80a981bc6edbc4e220a492d3cbe9f5547a6e75 # pin@v0
with:
artifact-name: frontend-build.spdx
path: src/frontend
Expand All @@ -63,7 +63,7 @@ jobs:
zip -r ../frontend-build.zip * .vite
- name: Attest Build Provenance
id: attest
uses: actions/attest-build-provenance@ef244123eb79f2f7a7e75d99086184180e6d0018 # pin@v1
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # pin@v1
with:
subject-path: "${{ github.workspace }}/src/backend/InvenTree/web/static/frontend-build.zip"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9
with:
sarif_file: results.sarif
2 changes: 1 addition & 1 deletion .github/workflows/translations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
git reset --hard
git reset HEAD~
- name: crowdin action
uses: crowdin/github-action@a9ffb7d5ac46eca1bb1f06656bf888b39462f161 # pin@v2
uses: crowdin/github-action@8dfaf9c206381653e3767e3cb5ea5f08b45f02bf # pin@v2
with:
upload_sources: true
upload_translations: false
Expand Down
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@
![CI](https://github.com/inventree/inventree/actions/workflows/qc_checks.yaml/badge.svg)
[![Documentation Status](https://readthedocs.org/projects/inventree/badge/?version=latest)](https://inventree.readthedocs.io/en/latest/?badge=latest)
![Docker Build](https://github.com/inventree/inventree/actions/workflows/docker.yaml/badge.svg)
[![Netlify Status](https://api.netlify.com/api/v1/badges/9bbb2101-0a4d-41e7-ad56-b63fb6053094/deploy-status)](https://app.netlify.com/sites/inventree/deploys)

[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7179/badge)](https://bestpractices.coreinfrastructure.org/projects/7179)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/inventree/InvenTree/badge)](https://securityscorecards.dev/viewer/?uri=github.com/inventree/InvenTree)
[![Netlify Status](https://api.netlify.com/api/v1/badges/9bbb2101-0a4d-41e7-ad56-b63fb6053094/deploy-status)](https://app.netlify.com/sites/inventree/deploys)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=inventree_InvenTree&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=inventree_InvenTree)

[![codecov](https://codecov.io/gh/inventree/InvenTree/graph/badge.svg?token=9DZRGUUV7B)](https://codecov.io/gh/inventree/InvenTree)
[![Crowdin](https://badges.crowdin.net/inventree/localized.svg)](https://crowdin.com/project/inventree)
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/inventree/inventree)
[![Docker Pulls](https://img.shields.io/docker/pulls/inventree/inventree)](https://hub.docker.com/r/inventree/inventree)

![GitHub Org's stars](https://img.shields.io/github/stars/inventree?style=social)
[![GitHub Org's stars](https://img.shields.io/github/stars/inventree?style=social)](https://github.com/inventree/InvenTree/)
[![Twitter Follow](https://img.shields.io/twitter/follow/inventreedb?style=social)](https://twitter.com/inventreedb)
[![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/inventree?style=social)](https://www.reddit.com/r/InvenTree/)

[![Mastdon](https://img.shields.io/badge/dynamic/json?label=Mastodon&query=followers_count&url=https%3A%2F%2Fchaos.social%2Fapi%2Fv1%2Faccounts%2Flookup%3Facct=InvenTree&logo=mastodon&style=social)](https://chaos.social/@InvenTree)

<h4>
<a href="https://demo.inventree.org/">View Demo</a>
Expand Down Expand Up @@ -163,10 +164,7 @@ If you use InvenTree and find it to be useful, please consider [sponsoring the p
<!-- Acknowledgments -->
## :gem: Acknowledgements

We would like to acknowledge a few special projects:
- [PartKeepr](https://github.com/partkeepr/PartKeepr) as a valuable predecessor and inspiration
- [Readme Template](https://github.com/Louis3797/awesome-readme-template) for the template of this page

We want to acknowledge [PartKeepr](https://github.com/partkeepr/PartKeepr) as a valuable predecessor and inspiration.
Find a full list of used third-party libraries in [our documentation](https://docs.inventree.org/en/latest/credits/).

## :heart: Support
Expand Down
50 changes: 25 additions & 25 deletions contrib/container/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ asgiref==3.8.1 \
--hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \
--hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590
# via django
django==4.2.16 \
--hash=sha256:1ddc333a16fc139fd253035a1606bb24261951bbc3a6ca256717fa06cc41a898 \
--hash=sha256:6f1616c2786c408ce86ab7e10f792b8f15742f7b7b7460243929cb371e7f1dad
django==4.2.17 \
--hash=sha256:3a93350214ba25f178d4045c0786c61573e7dbfa3c509b3551374f1e11ba8de0 \
--hash=sha256:6b56d834cc94c8b21a8f4e775064896be3b4a4ca387f2612d4406a5927cd2fdc
# via
# -r contrib/container/requirements.in
# django-auth-ldap
Expand Down Expand Up @@ -199,35 +199,35 @@ setuptools==75.6.0 \
--hash=sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6 \
--hash=sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d
# via -r contrib/container/requirements.in
sqlparse==0.5.2 \
--hash=sha256:9e37b35e16d1cc652a2545f0997c1deb23ea28fa1f3eefe609eee3063c3b105f \
--hash=sha256:e99bc85c78160918c3e1d9230834ab8d80fc06c59d03f8db2618f65f65dda55e
sqlparse==0.5.3 \
--hash=sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272 \
--hash=sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca
# via django
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
# via
# psycopg
# psycopg-pool
uv==0.5.4 \
--hash=sha256:05b45c7eefb178dcdab0d49cd642fb7487377d00727102a8d6d306cc034c0d83 \
--hash=sha256:2118bb99cbc9787cb5e5cc4a507201e25a3fe88a9f389e8ffb84f242d96038c2 \
--hash=sha256:30ce031e36c54d4ba791d743d992d0a4fd8d70480db781d30a2f6f5125f39194 \
--hash=sha256:4432215deb8d5c1ccab17ee51cb80f5de1a20865ee02df47532f87442a3d6a58 \
--hash=sha256:493aedc3c758bbaede83ecc8d5f7e6a9279ebec151c7f756aa9ea898c73f8ddb \
--hash=sha256:69079e900bd26b0f65069ac6fa684c74662ed87121c076f2b1cbcf042539034c \
--hash=sha256:8d7a4a3df943a7c16cd032ccbaab8ed21ff64f4cb090b3a0a15a8b7502ccd876 \
--hash=sha256:928ed95fefe4e1338d0a7ad2f6b635de59e2ec92adaed4a267f7501a3b252263 \
--hash=sha256:a79a0885df364b897da44aae308e6ed9cca3a189d455cf1c205bd6f7b03daafa \
--hash=sha256:ca72e6a4c3c6b8b5605867e16a7f767f5c99b7f526de6bbb903c60eb44fd1e01 \
--hash=sha256:cd7a5a3a36f975a7678f27849a2d49bafe7272143d938e9b6f3bf28392a3ba00 \
--hash=sha256:dd2df2ba823e6684230ab4c581f2320be38d7f46de11ce21d2dbba631470d7b6 \
--hash=sha256:df3cb58b7da91f4fc647d09c3e96006cd6c7bd424a81ce2308a58593c6887c39 \
--hash=sha256:ed5659cde099f39995f4cb793fd939d2260b4a26e4e29412c91e7537f53d8d25 \
--hash=sha256:f07e5e0df40a09154007da41b76932671333f9fecb0735c698b19da25aa08927 \
--hash=sha256:f40c6c6c3a1b398b56d3a8b28f7b455ac1ce4cbb1469f8d35d3bbc804d83daa4 \
--hash=sha256:f511faf719b797ef0f14688f1abe20b3fd126209cf58512354d1813249745119 \
--hash=sha256:f806af0ee451a81099c449c4cff0e813056fdf7dd264f3d3a8fd321b17ff9efc
uv==0.5.7 \
--hash=sha256:071b57c934bdee8d7502a70e9ea0739a10e9b2d1d0c67e923a09e7a23d9a181b \
--hash=sha256:13961a8116515eb288c4f91849fba11ebda0dfeec44cc356e388b3b03b2dbbe1 \
--hash=sha256:1c5b89c64fb627f52f1e9c9bbc4dcc7bae29c4c5ab8eff46da3c966bbd4caed2 \
--hash=sha256:27c630780e1856a70fbeb267e1ed6835268a1b50963ab9a984fafa4184389def \
--hash=sha256:46b03a9a78438219fb3060c096773284e2f22417a9c1f8fdd602f0650b3355c2 \
--hash=sha256:4d22a5046a6246af85c92257d110ed8fbcd98b16824e4efa9d825d001222b2cb \
--hash=sha256:737a06b15c4e6b8ab7dd0a577ba766380bda4c18ba4ecfcfff37d336f1b03a00 \
--hash=sha256:747c011da9f631354a1c89b62b19b8572e040d3fe01c6fb8d650facc7a09fdbb \
--hash=sha256:76b514c79136e779cccf90cce5d60f317a0d42074e9f4c059f198ef435f2f6ab \
--hash=sha256:78c3c040e52c09a410b9788656d6e760d557f223058537081cb03a3e25ce89de \
--hash=sha256:a141b40444c4184efba9fdc10abb3c1cff32154c7f8b0ad46ddc180d65a82d90 \
--hash=sha256:a45648db157d2aaff859fe71ec738efea09b972b8864feb2fd61ef856a15b24f \
--hash=sha256:a4fc62749bda8e7ae62212b1d85cdf6c7bad41918b3c8ac5a6d730dd093d793d \
--hash=sha256:b79e32438390add793bebc41b0729054e375be30bc53f124ee212d9c97affc39 \
--hash=sha256:ba25eb99891b95b5200d5e369b788d443fae370b097e7268a71e9ba753f2af3f \
--hash=sha256:c1e7b5bcc8b380e333e948c01f6f4c6203067b5de60a05f8ed786332af7a9132 \
--hash=sha256:d0600d2b2fbd9a9446bfbb7f03d88bc3d0293b949ce40e326429dd4fe246c926 \
--hash=sha256:fb4a3ccbe13072b98919413ac8378dd3e2b5480352f75c349a4f71f423801485
# via -r contrib/container/requirements.in
wheel==0.45.1 \
--hash=sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729 \
Expand Down
2 changes: 1 addition & 1 deletion contrib/dev_reqs/requirements.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Packages needed for CI/packages
requests==2.32.3
pyyaml==6.0.2
jc==1.25.3
jc==1.25.4
6 changes: 3 additions & 3 deletions contrib/dev_reqs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ idna==3.10 \
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
# via requests
jc==1.25.3 \
--hash=sha256:ea17a8578497f2da92f73924d9d403f4563ba59422fbceff7bb4a16cdf84a54f \
--hash=sha256:fa3140ceda6cba1210d1362f363cd79a0514741e8a1dd6167db2b2e2d5f24f7b
jc==1.25.4 \
--hash=sha256:1e4f45d2e5b72cf9d300b0d9df0578c0d3b553843e3ad37a525d93bb0e94aca1 \
--hash=sha256:a32eaf029c56b582dadae48895f20784d0f84f2fa28a8e2b32f377a8bffa8b39
# via -r contrib/dev_reqs/requirements.in
pygments==2.18.0 \
--hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \
Expand Down
174 changes: 174 additions & 0 deletions docs/docs/extend/plugins/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
Title: Unit Tests
---

## Unit Tests
For complicated plugins it makes sense to add unit tests the code to ensure
that plugins work correctly and are compatible with future versions too.
You can run these tests as part of your ci against the current stable and
latest tag to get notified when something breaks before it gets released as
part of stable. InvenTree offers a framework for testing. Please refer
to [Unit Tests](../../develop/contributing.md) for more information.

### Prerequisites
For plugin testing the following environment variables must be set to True:

| Name | Function | Value |
| --- | --- | --- |
| INVENTREE_PLUGINS_ENABLED | Enables the use of 3rd party plugins | True |
| INVENTREE_PLUGIN_TESTING | Enables enables all plugins no matter of their active state in the db or built-in flag | True |
| INVENTREE_PLUGIN_TESTING_SETUP | Enables the url mixin | True |

### Test program

A file called test_plugin_name.py should be added to the plugin directory. It can have the
following structure:

```
# Basic unit tests for the plugin
from InvenTree.unit_test import InvenTreeTestCase
class TestMyPlugin(InvenTreeTestCase):
def test_my_function(self):
do some work here...
```

The test can be executed using invoke:

```
invoke dev.test -r module.file.class
```

Plugins are usually installed outside of the InventTree directory, e.g. in .local/lib/...
I that case module must be omitted.

```
invoke dev.test -r plugin_directory.test_plugin_name.TestMyPlugin
```

### do some work here... A simple Example
A simple example is shown here. Assume the plugin has a function that converts a price string
that comes from a supplier API to a float value. The price might have the form "1.456,34 €".
It can be different based on country and local settings.
The function in the plugin will convert it to a float 1456.34. It is in the class MySupplier
and has the following structure:

```
class MySupplier():
def reformat_price(self, string_price):
...
return float_price
```

This function needs to be tested. The test can look like this:

```
from .myplugin import MySupplier
def test_reformat_price(self):
self.assertEqual(MySupplier.reformat_price(self, '1.456,34 €'), 1456.34)
self.assertEqual(MySupplier.reformat_price(self, '1,45645 €'), 1.45645)
self.assertEqual(MySupplier.reformat_price(self, '1,56 $'), 1.56)
self.assertEqual(MySupplier.reformat_price(self, ''), 0)
self.assertEqual(MySupplier.reformat_price(self, 'Mumpitz'), 0)
```

The function assertEqual flags an error in case the two arguments are not equal. In equal case
no error is flagged and the test passes. The test function tests five different
input variations. More might be added based on the requirements.

### Involve the database
Now we test a function that uses InvenTree database objects. The function checks if a part
should be updated with latest data from a supplier. Parts that are not purchasable or inactive
should not be updated. The function in the plugin has the following form:

```
class MySupplier():
def should_be_updated(self, my_part):
...
return True/False
```

To test this function, parts are needed in the database. The test framework creates
a dummy database for each run which is empty. Parts for testing need to be added.
This is done in the test function which looks like:

```
from part.models import Part, PartCategory
def test_should_be_updated(self):
test_cat = PartCategory.objects.create(name='test_cat')
active_part = Part.objects.create(
name='Part1',
IPN='IPN1',
category=test_cat,
active=True,
purchaseable=True,
component=True,
virtual=False)
inactive_part = Part.objects.create(
name='Part2',
IPN='IPN2',
category=test_cat,
active=False,
purchaseable=True,
component=True,
virtual=False)
non_purchasable_part = Part.objects.create(
name='Part3',
IPN='IPN3',
category=test_cat,
active=True,
purchaseable=False,
component=True,
virtual=False)
self.assertEqual(MySupplier.should_be_updated(self, active_part, True, 'Active part')
self.assertEqual(MySupplier.should_be_updated(self, inactive_part, False, 'Inactive part')
self.assertEqual(MySupplier.should_be_updated(self, non_purchasable_part, False, 'Non purchasable part')
```

A category and three parts are created. One part is active, one is inactive and one is not
purchasable. The function should_be_updated is tested with all
three parts. The first test should return True, the others False. A message was added to the assert
function for better clarity of test results.

The dummy database is completely separate from the one that you might use for development
and it is deleted after the test. There is no danger for your development database.

In case everything is OK, the result looks like:

```
----------------------------------------------------------------------
Ran 1 tests in 0.809s
OK
Destroying test database for alias 'default'...
```

In case of a problem you will see something like:

```
======================================================================
FAIL: test_should_be_updated (inventree_supplier_sync.test_supplier_sync.TestSyncPlugin)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/michael/.local/lib/python3.10/site-packages/inventree_supplier_sync/test_supplier_sync.py", line 73, in test_should_be_updated
self.assertEqual(SupplierSyncPlugin.should_be_updated(self, non_purchasable_part,), False, 'Non purchasable part')
AssertionError: True != False : Non purchasable part
----------------------------------------------------------------------
Ran 3 tests in 0.679s
FAILED (failures=1)
Destroying test database for alias 'default'...
```

In the AssertionError the message appears that was added to the assertEqual function.
Loading

0 comments on commit a57dfd2

Please sign in to comment.