-
-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add hotspot vouchers #554
Add hotspot vouchers #554
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR
Please add tests, please add to the gateway class, recommended is to also setup the pre-commit hook with setup.sh and you will catch a lot of small things
Here is a PR adding a new ApiHandler based class to the controller, adds api requests and tests, that should help you to get going Don't hesitate to ask questions if you get stuck |
Skimmed it through, will review during the weekend |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice! Just one small thing to improve from review and you need to fix the failing validation
Co-authored-by: Robert Svensson <Kane610@users.noreply.github.com>
@Kane610 , thank you very much. The suggested change has been implemented. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nearly there! Good job!
Some small areas of test coverage should be improved, I think there is no coverage of deletion path for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With these changes the tests should pass and coverage be 100%
You know if you setup the environment you only have to write pytest to run the tests locally ;)
diff --git a/tests/test_vouchers.py b/tests/test_vouchers.py
index 644ead6..ee81ba9 100644
--- a/tests/test_vouchers.py
+++ b/tests/test_vouchers.py
@@ -41,9 +41,9 @@ async def test_voucher_create(mock_aioresponse, unifi_controller, unifi_called_w
"quota": 0,
"expire_number": 3600,
"expire_unit": 1,
- "usage_quota": 1000,
- "rate_max_up": 5000,
- "rate_max_down": 2000,
+ "bytes": 1000,
+ "up": 5000,
+ "down": 2000,
"note": "Unit Testing",
},
)
@@ -108,7 +108,7 @@ async def test_vouchers(mock_aioresponse, unifi_controller, unifi_called_with):
voucher = vouchers["61facea3873fdb075ce28d71"]
assert voucher.id == "61facea3873fdb075ce28d71"
assert voucher.site_id == "5a32aa4ee4b0412345678910"
- assert voucher.note is None
+ assert voucher.note == ""
assert voucher.code == "44703"
assert voucher.quota == 1
assert voucher.duration == timedelta(minutes=480)
@@ -138,9 +138,12 @@ async def test_vouchers(mock_aioresponse, unifi_controller, unifi_called_with):
json={
"cmd": "create-voucher",
"n": 1,
- "quota": 0,
- "expire_number": 3600,
+ "quota": 1,
+ "expire_number": 480,
"expire_unit": 1,
+ "bytes": 1000,
+ "up": 2000,
+ "down": 5000,
},
)
@@ -150,6 +153,6 @@ async def test_vouchers(mock_aioresponse, unifi_controller, unifi_called_with):
"/api/s/default/cmd/hotspot",
json={
"cmd": "delete-voucher",
- "_id": "657e370a4543a555901865c7",
+ "_id": "61facea3873fdb075ce28d71",
},
)
D'oh, now I see the mistakes too. 😪 I have eliminated them. I prefer not to write how I develop... Spoiler: Not with a local runtime environment. 🤐 |
You should change to do it locally |
woohoo 100% coverage.
Oh yeah, I didn't realize how deep I was falling down the rabbit hole last year. I just wanted to write a little integration. Now there are three and we're in this PR here. |
I want ro go through it one last time. Jut I don't have time today and busy a few days so it would have to be on Monday |
So last commit |
Last attempt. Merge it or close this PR. It is difficult for me to document self-explanatory code in more detail. |
Maybe I'm using bad wording to express myself here and I apologize if that's the case. This should be read as me trying to motivate my issue with the current description in pydoc, what I have an understanding of what I'm missing in it based on your explanation and why this is important for me in the long term. Look here. The comment says "Code in known format 00000-00000". If the code where to be self explanatory it would not do anything but making sure that there is a hyphen in the middle. Now the code does something else as well, which is not obvious to me either what that means. It should be obvious why these two paths exist. You had to play around with it yourself to figure out the five character limit. I'm more or less asking you to rephrasing this "I experimented a bit and received vouchers with 5, 8 and regular 10 characters. When entering the code on the hotspot page, the hyphen must be placed after the fifth digit.". I don't think this is an unreasonable request worth getting defensive over. I've previously accepted PRs with code that when I needed to change things had to spend a lot of time to understand to when refactoring things. If functionality is not clear then it will come back as a personal cost on me as I'm the one sitting on long term maintenance of the code base. That's why I want to make sure to make new mistakes and learn from old. I hope I've explained myself enough and you have an understanding behind my motivations with this request. /R |
In the Hotspot Manager UI, the regular 10-digit code is displayed with the hyphen "in the middle". However, the unofficial API delivers it without this hyphen. Now it would be simple to deliver the code in the model as it comes from the API. However, the captive portal expects the hyphen to be entered. So I build in the code the hyphen "in the middle" - f"{c[:5]}-{c[5:]}". Through some nasty manipulation, I managed to get back a five and an eight-digit code. Putting a hyphen in there seems to be wrong. But maybe not. I don't know. Maybe it's just an edge case. There was no rocket science in the position of the hyphen. That's why I've now simplified the code. If it cracks at some point, we'll work on it then. |
Test fails FAILED tests/test_vouchers.py::test_vouchers[voucher_payload0] - AssertionError: assert '44703-' == '44703'
Will the output from unifi be with or without hyphen? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, to merge once test pass, two questions for completeness
expire_number=int( | ||
voucher.duration.total_seconds() / 60 # Get minutes. | ||
), | ||
expire_unit=1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the default value is 1 for expire unit would this be ok, or is there a specific reason this is 1
expire_unit=1, | |
expire_unit=voucher.expire_unit, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exire_unit is not an attribute of Voucher. 1 = minute, because expire_number came from voucher.duration in Seconds / 60 = Minutes
The attributes for vouchers of the return values of the API are called differently than those for creating.
For example, when creating, you pass the number of vouchers to be created. But these are then created as separate vouchers.
And when creating, you specify the expiry time and in which unit you specify the expiry time. In the return, you always get the duration time in seconds. However, you cannot create a voucher in seconds ....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, yes indeed, thanks, as it has the default value assigned this can just be removed.
expire_unit=1, |
"""Create voucher on controller.""" | ||
return await self.controller.request( | ||
VoucherCreateRequest.create( | ||
number=1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Number is a required item to create an instance of Voucher, is there a reason 1 is hardcoded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Number is not an attribute of Voucher. Number is the number of vouchers to be create in one request
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I would just add the default value to the create request and remove this instead.
number=1, |
Right now the test expects "44703-" |
expire_number=int( | ||
voucher.duration.total_seconds() / 60 # Get minutes. | ||
), | ||
expire_unit=1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, yes indeed, thanks, as it has the default value assigned this can just be removed.
expire_unit=1, |
"""Create voucher on controller.""" | ||
return await self.controller.request( | ||
VoucherCreateRequest.create( | ||
number=1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I would just add the default value to the create request and remove this instead.
number=1, |
Suggested changes in #554 |
No description provided.