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
Load one ad a time. #9808
Load one ad a time. #9808
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,16 +58,17 @@ export function getAmpAdRenderOutsideViewport(element) { | |
/** | ||
* Increments loading ads count for throttling. | ||
* @param {!Window} win | ||
* @param {!Promise=} opt_loadingPromise | ||
*/ | ||
export function incrementLoadingAds(win) { | ||
export function incrementLoadingAds(win, opt_loadingPromise) { | ||
if (win[LOADING_ADS_WIN_ID_] === undefined) { | ||
win[LOADING_ADS_WIN_ID_] = 0; | ||
} | ||
win[LOADING_ADS_WIN_ID_]++; | ||
timerFor(win).delay(() => { | ||
// Unfortunately we don't really have a good way to measure how long it | ||
// takes to load an ad, so we'll just pretend it takes 1 second for | ||
// now. | ||
win[LOADING_ADS_WIN_ID_]--; | ||
}, 1000); | ||
timerFor(win) | ||
.timeoutPromise(1000, opt_loadingPromise || new Promise(() => {})) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. timeoutPromise() only require the timeout value to be defined. would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
.catch(() => {}) | ||
.then(() => { | ||
win[LOADING_ADS_WIN_ID_]--; | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ import { | |
} from '../concurrent-load'; | ||
import {createElementWithAttributes} from '../../../../src/dom'; | ||
import {installTimerService} from '../../../../src/service/timer-impl'; | ||
import {macroTask} from '../../../../testing/yield'; | ||
import * as lolex from 'lolex'; | ||
|
||
describes.realWin('concurrent-load', {}, env => { | ||
|
@@ -75,13 +76,27 @@ describes.realWin('concurrent-load', {}, env => { | |
installTimerService(win); | ||
}); | ||
|
||
it('should throttle ad loading one per second', () => { | ||
it('should throttle ad loading one per second', function* () { | ||
expect(is3pThrottled(win)).to.be.false; | ||
incrementLoadingAds(win); | ||
expect(is3pThrottled(win)).to.be.true; | ||
clock.tick(999); | ||
yield macroTask(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could return the promise from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test then becomes: clock.tick(999);
expect(is3pThrottled(win)).to.be.true;
clock.tick(1);
yield promise;
expect(is3pThrottled(win)).to.be.false; the first check is meaningless here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's unfair to only yield on the 2nd tick. (and you can't yield on the first, which will run into a deadlock :-)) this is not testing the right thing: clock.tick(1000);
expect(is3pThrottled(win)).to.be.true;
clock.tick(1);
yield promise;
expect(is3pThrottled(win)).to.be.false; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now, the macroTask isn't testing anything. You've frozen time in test's window. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree we should yield before doing each check. Here we try to test that loading ads count will decrease by 1 after 1 sec, and only after 1 sec.
we can't tell if the promise is resolved only after 1sec. It is possible that the promise has already resolved after 999ms, but macroTasks not executed, loading ad count hasn't decresed by 1 when test code ran. This is probably right to do:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@jridgewell here we want to yield an event loop so that if the timer has triggered the promise resolver, we wait till the resolution finish. @zhouyx your suggestion is also treating the 2 ticks differently, which I don't like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd agree with @zhouyx here, if you want to test specifically that it only resolves after 1s. I'm still against relying on macrotasks for promise changes to complete, though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we want to treat the 2 ticks differently? isn't it cheating? are we doing a test to just get it passed? we have to do 2 checks with all other conditions the same, if we really want to test the 1000ms triggering logic. the test is translated to:
|
||
expect(is3pThrottled(win)).to.be.true; | ||
clock.tick(1); | ||
yield macroTask(); | ||
expect(is3pThrottled(win)).to.be.false; | ||
}); | ||
|
||
it('should throttle ad one a time', function* () { | ||
expect(is3pThrottled(win)).to.be.false; | ||
let resolver; | ||
incrementLoadingAds(win, new Promise(res => { | ||
resolver = res; | ||
})); | ||
expect(is3pThrottled(win)).to.be.true; | ||
resolver(); | ||
yield macroTask(); | ||
expect(is3pThrottled(win)).to.be.false; | ||
}); | ||
}); | ||
|
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.
Instead of creating a never resolving promise, can't you just pass
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.
done