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
Fake and real window fixtures for tests #5425
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.
Don't have time for a thorough review, but this looks amazing!
|
||
beforeEach(() => { | ||
return new Promise(function(resolve, reject) { | ||
const iframe = document.createElement('iframe'); |
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.
Can this use iframe.js
? I suppose you did this on purpose?
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.
I did this on purpose here to separate "pure" window from window with AMP setup. And also I changed some defaults, such as runtimeOff
that I believe are more valid for our tests. And for migration purposes I kept createIframePromise
w/o changes to be able to migrate over time.
import * as cust from '../../src/custom-element'; | ||
import * as sinon from 'sinon'; | ||
|
||
import * as describes from '../../testing/describes'; |
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.
should we make it a global instead?
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.
Done
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.
I also made sandbox
global. Just sandbox
for now to see how it plays out. We may do this for other vars as well.
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.
It looks cool!
That definitely would help to further isolate tests.
In the past, one thing I couldn't find a nice solution is how to simulate a postMessage in the test. You know since we created this iframe, the postMessage should be from the iframe window, not the doc window.
* clock: (!FakeClock|undefined), | ||
* })} fn | ||
*/ | ||
export function sandboxed(name, spec, fn) { |
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.
ha, shall we just make this the default? any use case a sandbox can be unwanted?
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.
I was thinking about that. But for migration I decided to do sandboxed
instead. You still need to do top-level describe
and we'll adopt sandboxed
instead until all tests are migrated. After that, we can push it into all tests by default.
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.
How about just making it a part of the realWinSpec then?
I just don't like that we need to repeat such a hiarachy in every test:
describes.sandboxed(()=>{
describes.readWindow()=>
export function realWin(name, spec, fn) { | ||
return describe(name, function() { | ||
|
||
const test = Object.create(null); |
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.
nitpick: how about call it env
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.
Done
}); | ||
|
||
afterEach(() => { | ||
sandbox.restore(); | ||
}); | ||
|
||
describe('registerExtension', () => { | ||
describes.fakeWin('registerExtension', {}, test => { |
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.
just curious why the tests have to be done in a fake window?
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.
Well. This simply recognizes that we do it a lot. A number of things are just too hard to mock out on a life window object.
delete test.win; | ||
}); | ||
|
||
describe(SUB, function() { |
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.
Is the SUB reserved for future expansion to tests under more env?
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.
No, but I have to call describe
here to get tests-own beforeEach and afterEach called and if I call describe
, it must have a name, even if it's just a space.
|
||
|
||
/** | ||
* A test with a fake window. |
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.
should it be real win?
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.
Done
|
||
/** | ||
* @param {function()} handler | ||
* @param {number=} timeout |
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.
missing the var_args on the sig
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.
Done
All! PTAL, all comments addressed. @lannka, I don't have a story on |
*/ | ||
static intercept(target) { | ||
target.eventListeners = new EventListeners(); | ||
target.addEventListener = function(type, handler, captureOrOpts) { |
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.
do these listeners exist in the full scope of the test run?
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.
Only between beforeEach
and afterEach
.
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.
awesome
export function sandboxed(name, spec, fn) { | ||
return describe(name, function() { | ||
|
||
const env = Object.create(null); |
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.
@dvoytenko should we also freeze or seal the env object?
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.
We can't. This object is shared between all tests runs :( That's why I'm so careful with delete
s and probably will be even more so.
LGTM deferring for a 2nd LGTM |
2670eb6
to
b3e3bbb
Compare
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 one comment.
* clock: (!FakeClock|undefined), | ||
* })} fn | ||
*/ | ||
export function sandboxed(name, spec, fn) { |
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.
How about just making it a part of the realWinSpec then?
I just don't like that we need to repeat such a hiarachy in every test:
describes.sandboxed(()=>{
describes.readWindow()=>
@lannka Hmm. This nesting is optional. But let me try to remove it altogether... |
@lannka I refactored things a bit. Now all describes create a sandbox (or reuse an existing one). This definitely looks better. PTAL. |
} | ||
}); | ||
|
||
describe(SUB, function() { |
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.
We do we have another describe
block?
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.
So that the callback we call (fn
) can call its own beforeEach
and afterEach
and we observe the nested behavior.
|
||
describe('registerExtension', () => { | ||
describes.sandboxed('Extensions', {}, () => { |
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.
I guess this is not needed anymore after you refactoring?
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.
Not super needed, no. But I still like the grouping feature since it combines two distinct group of tests inside. The simpler cases will not need it.
…mp_reddit_extension * 'master' of https://github.com/ampproject/amphtml: (65 commits) Send vars from carousel to amp-analytics (ampproject#5388) Rolling back pan-x on scrollable carousel. (ampproject#5490) Add context.library.name to Segment (ampproject#5467) Rollback pan-x on carousel as it does not work on android. (ampproject#5473) cron job from @erwinmombay to update size.txt (ampproject#5468) Added example of usage of carousel arrows (ampproject#5397) ALP for A4A (ampproject#5430) Add Affiliate-B support for amp-ad (ampproject#5223) First cut of changes for New Type Inference (ampproject#5438) Lightbox 2.0: Use object-fit:cover for thumbnails Upgrade Closure Compiler to v20160911 (Sep 11, 2016) (ampproject#5457) Fake and real window fixtures for tests (ampproject#5425) Backgrounded Variable added to Timer Trigger (ampproject#5240) make `touch-action: pan-x` on `amp-carousel` (ampproject#5391) Fix PR check on new branches (ampproject#5455) Do not rely on ampExtendedElements being created (ampproject#5454) Turn type checking for 3p code back on. (ampproject#5452) Update ads/README.md with gulp lint tip (ampproject#5444) Migrate document-submit to doc scope (ampproject#5437) Link to Building an AMP Extension document. (ampproject#5451) ...
* Fake and real window fixtures for tests * review fixes * whitelist test vars * flush vsync * add storage API * linter * Always define sandbox and make fixtures reusable
* Fake and real window fixtures for tests * review fixes * whitelist test vars * flush vsync * add storage API * linter * Always define sandbox and make fixtures reusable
No description provided.