Skip to content
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

Merged
merged 7 commits into from Oct 7, 2016

Conversation

dvoytenko
Copy link
Contributor

No description provided.

Copy link
Member

@cramforce cramforce left a 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');
Copy link
Member

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?

Copy link
Contributor Author

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';
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor Author

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.

Copy link
Contributor

@lannka lannka left a 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) {
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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);
Copy link
Contributor

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

Copy link
Contributor Author

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 => {
Copy link
Contributor

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?

Copy link
Contributor Author

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() {
Copy link
Contributor

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?

Copy link
Contributor Author

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.
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@dvoytenko
Copy link
Contributor Author

All! PTAL, all comments addressed.

@lannka, I don't have a story on postMessage yet. But I'm hoping, once this is in, we will all fill in the gaps.

*/
static intercept(target) {
target.eventListeners = new EventListeners();
target.addEventListener = function(type, handler, captureOrOpts) {
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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);
Copy link
Member

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?

Copy link
Contributor Author

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 deletes and probably will be even more so.

@erwinmombay
Copy link
Member

LGTM deferring for a 2nd LGTM

Copy link
Contributor

@lannka lannka left a 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) {
Copy link
Contributor

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 lannka added LGTM and removed NEEDS REVIEW labels Oct 6, 2016
@dvoytenko
Copy link
Contributor Author

@lannka Hmm. This nesting is optional. But let me try to remove it altogether...

@dvoytenko
Copy link
Contributor Author

@lannka I refactored things a bit. Now all describes create a sandbox (or reuse an existing one). This definitely looks better. PTAL.

@dvoytenko dvoytenko merged commit d5c8afb into ampproject:master Oct 7, 2016
@dvoytenko dvoytenko deleted the amptest1-fakewin branch October 7, 2016 01:19
}
});

describe(SUB, function() {
Copy link
Contributor

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?

Copy link
Contributor Author

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', {}, () => {
Copy link
Contributor

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?

Copy link
Contributor Author

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.

samiamorwas pushed a commit to samiamorwas/amphtml that referenced this pull request Oct 10, 2016
…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)
  ...
dreamofabear pushed a commit to dreamofabear/amphtml that referenced this pull request Oct 12, 2016
* 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
mkhatib pushed a commit to mkhatib/amphtml that referenced this pull request Oct 14, 2016
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants