feat(Variables): Introduce unresolvedVariablesNotificationMode#8710
Conversation
Codecov Report
@@ Coverage Diff @@
## master #8710 +/- ##
==========================================
+ Coverage 87.43% 87.52% +0.08%
==========================================
Files 256 259 +3
Lines 9631 9635 +4
==========================================
+ Hits 8421 8433 +12
+ Misses 1210 1202 -8
Continue to review full report at Codecov.
|
| frameworkVersion: '2' | ||
| enableLocalInstallationFallback: false # If set to 'true', guarantees that it's a locally (for service, in its node_modules) installed framework which processes the command | ||
| useDotenv: false # If set to 'true', environment variables will be automatically loaded from .env files | ||
| throwOnUnresolvedVariableReferences: false # If set to 'true', references to variables that cannot be resolved will result in an error being thrown |
There was a problem hiding this comment.
I think I would prefer sticking to unresolvedVariablesNotificationMode as enum as that gives us a bit more flexibility in the future if needed (if there would be a request to introduce another mode, or e.g. turning warnings/errors completely)
| expect(logWarningSpy.args[0][0]).to.contain('file'); | ||
| }); | ||
| }); | ||
| describe('#assertFound()', () => { |
There was a problem hiding this comment.
I think it would be better to try to use runServerless-based tests to test out the newly introduced funtionality here. We try to migrate all tests to runServerless, here you can see an example on how that might look like: https://github.com/G-Rath/serverless/blob/master/test/unit/lib/classes/Variables.test.js#L2745-L2783
There was a problem hiding this comment.
Sure, I'll give it a try - however, if I understand things correctly that'll result in a lot of fixtures (and possible high slowdown since those tests are expensive?) since we error on the first unresolved variable.
So if we want to have the same test coverage as before we'd need to have a test/fixture for each possible value of varType, for each possible mode supported by unresolvedVariablesNotificationMode.
A possible way around this could be keep the _describeVariableType method and unit test that, and use runServerless tests for the rest (which'd mean only needing 2 or 3 tests)
There was a problem hiding this comment.
Sure, I'll give it a try - however, if I understand things correctly that'll result in a lot of fixtures
We should reuse existing fixture (variables), which we can simply extend for every case
(and possible high slowdown since those tests are expensive?)
They're somewhat expensive, and it's good to minimize runServerless runs when possible, but all error cases are test ed individually, and in this case we need to do different runServerless run per fixture.
Test best if are added at the bottom of tests files, where we already have some runServerless based tests added
There was a problem hiding this comment.
So I've been trying to write a single test for now, but no matter what I do unresolvedVariablesNotificationMode doesn't seem to be making it into the config - is there anything I might have missed?
There was a problem hiding this comment.
@G-Rath can you commit the code, that you feel that should work and doesn't work for you?
There was a problem hiding this comment.
Technically we're not meant to test print out in this variables.test.js
But when adding new property ideally it should be onfirmed that it works as intended in all areas, otherwise submission is not really complete (and we avoid introducing incomplete/WIP merges to master)
There was a problem hiding this comment.
Technically we're not meant to test print out in this variables.test.js
I think the bug is elsewhere, as it looks like variables have already been resolved by the time print is being called (e.g. custom.myVariable is undefined and the warning has been printed) - tbh it could be the test runner is just truncating the output.
There was a problem hiding this comment.
Seems that the property is available on service (I'm guessing because I'm assigning it in Service.js) - does that sound like a valid way to access it, or should I continue to try and get it via serverless.config?
There was a problem hiding this comment.
Seems that the property is available on
service
On service instance? Or on service config property (which is accessible at service.service) ?
There was a problem hiding this comment.
Yes, on the this.service instance.
I've got things working now, and so have written tests + cleaned up my commit - should be ready for re-review :)
| return null; | ||
| } | ||
|
|
||
| assertFound(variableString, valueToPopulate) { |
There was a problem hiding this comment.
Why do we need two methods? Can't we integrate this handling in existing warnIfNotFound (which we can rename into e.g. handleUnresolved)
There was a problem hiding this comment.
I wasn't sure if the current method was being used by any plugins, and so wanted to keep the breaking change as small as possible.
Happy to do it as one method if you're fine with that - I went with assertFound for the name as that follows the name for methods in the assert module and so indicates that the method is an assertion guard.
(handleUnresolved makes more sense as a name if unresolvedVariablesNotificationMode is an enum)
There was a problem hiding this comment.
I wasn't sure if the current method was being used by any plugins
I think it's very unlikely, also it's considered as private part, so plugins should really not do that
There was a problem hiding this comment.
Awesome, I'll merge them into a single method then 🎉
Do you want me to do any form of underscore naming to highlight their private? I've noticed that's done in a couple of other places in the framework :)
There was a problem hiding this comment.
Do you want me to do any form of underscore naming to highlight their private? I've noticed that's done in a couple of other places in the framework :)
I believe it's only done in places where we want to distinct private API from public. Here it's not the case (whole class is private)
| const out = await runServerless({ | ||
| fixture: 'variables', | ||
| cliArgs: ['print'], | ||
| configExt: { | ||
| unresolvedVariablesNotificationMode: 'warn', | ||
| custom: { | ||
| myVariable1: '${env:missingEnvVar}', | ||
| myVariable2: '${opt:missingOpt}', | ||
| myVariable3: '${self:missingAttribute}', | ||
| myVariable4: '${file(./missingFile)}', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| ({ serverless } = out); |
There was a problem hiding this comment.
Why not:
const { serverless: { stdout } } = await runServerless(...);There was a problem hiding this comment.
Because serverless is declared here as a let, meaning this'll be a shadowing that eslint errors on.
There was a problem hiding this comment.
But in this case you do not access serverless but just stdout (and it's only that which I define in snippet)
There was a problem hiding this comment.
It's used on the line straight after this one - but I guess actually I could do:
const { serverless: { triggeredDeprecations }, stdoutData } = await runServerless(...);
There was a problem hiding this comment.
I've actually didn't notice need to access serverless.triggeredDeprecations, so sorry for misleading suggestion
Anyway it was flawed that runServerless tests share same context as other tests, it should not be the case. I've fixed that in master, and now there's no serverless shadowing, please rebase.
|
I just would like to thank you all for that feature! ❤️ |
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #8710 +/- ##
==========================================
+ Coverage 87.44% 87.52% +0.07%
==========================================
Files 256 259 +3
Lines 9631 9635 +4
==========================================
+ Hits 8422 8433 +11
+ Misses 1209 1202 -7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
I've followed the implementation suggested in the original issue, with some minor modification due to the issues age that I think meant the implementation got a little out of date.
In particular, I've changed the option to be a boolean rather than an enum as I think that's less ambiguous and everything on the issue imo points to this not being a mode like
configValidationMode. It's also an easy enough change to switch it back to an enum if that is desired.Because
warnIfNotFoundisn't marked as private I took the safe approach of not modifying it's behaviour aside from having it print the deprecation, or renaming it - this way if it's used by any plugins etc it shouldn't be breaking.Test-wise I've just copied the existing tests for
warnIfNotFoundand refactored them to checkto.throw¬.to.throw. I've duplicated the tests for checking the behaviour ofthrowOnUnresolvedVariableReferenceswhen it'sfalserather than try to be clever by somehow doing anexpect(warnIfNotFound).to.have.been.called()on the test subject.Overall I've gone for boring and simple rather than fancy and completely DRY.
Closes: #3367