Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Feature request: FakeAsync should have a flush function #735

Closed
juliemr opened this issue Apr 12, 2017 · 7 comments
Closed

Feature request: FakeAsync should have a flush function #735

juliemr opened this issue Apr 12, 2017 · 7 comments
Assignees

Comments

@juliemr
Copy link
Member

juliemr commented Apr 12, 2017

This function would simulate moving time forward until the queue of pending macrotasks is cleared.
With multiple setTimeouts, it would move to the furthest in the future.
It would clear chained setTimeouts.
Intervals would not affect it.

For example (using end-user syntax based on Angular's helpers):

fakeAsync(() => {
  let x = y = z = 0;
  setTimeout(() => { x++; }, 100);
  setTimeout(() => { y++; }, 7000);
  setInterval(() => { z++; }, 100);

  flush();

  expect(x).toEqual(1);
  expect(y).toEqual(1);
  expect(z).toEqual(7);
});

fakeAsync(() => {
  let x = y = z = 0;
  setTimeout(() => {
    x++;
    setTimeout(() => {
      y++;
    }, 100);
  }, 200);
  setInterval(() => { z++; }, 100);

  flush();

  expect(x).toEqual(1);
  expect(y).toEqual(1);
  expect(z).toEqual(3);
});

fakeAsync(() => {
  let z = 0;
  setInterval(() => { z++; }, 100);
  
  flush();

  expect(z).toEqual(0);
});
@juliemr juliemr self-assigned this Apr 12, 2017
@juliemr
Copy link
Member Author

juliemr commented Apr 12, 2017

cc @mhevery does this design look good?

@juliemr
Copy link
Member Author

juliemr commented Apr 12, 2017

Return value could be the length of time moved.

@heathkit
Copy link

heathkit commented Apr 17, 2017

I think I'd prefer if it moved to the next timeout. Something like advanceClockToNextTimeout()? Though I guess that's just a preference, I could see either way.

@juliemr
Copy link
Member Author

juliemr commented Apr 19, 2017

I think I prefer flushing all of them. Here's how I see it: if you're testing some behavior you don't control, you just want to move time forward until stuff is done. If you only advanced to the next timeout, you'd need to do that X times, where X is a guessing game.

If you control the behavior, you're in a position to use tick(TIME) to move forward to just the next timeout.

We could, potentially, also add a next method to do what you're describing?

@heathkit
Copy link

Yeah, makes sense. I was thinking for behavior you don't control, you might want to assert something after each event or that timeouts occur in some particular order. I think you're right, though, in those situations it'd probably just make more sense to use tick().

What about polling behavior where there's always a timeout being scheduled? Would we be able to detect that and give a helpful error message? Maybe something like be flush(MAX_TIME), where there's a reasonable default and flush is guaranteed to return when the clock hits the limit?

juliemr added a commit to juliemr/zone.js that referenced this issue Apr 24, 2017
The `flush` method advances time until all non-periodic timers
are cleared from the queue. It has a configurable limit (default 20)
of tasks that will be run before it gives up and throws an error,
in order to avoid infinite loops when polling timeouts are present.

Closes angular#735
@juliemr
Copy link
Member Author

juliemr commented Apr 24, 2017

In my PR, I add flush(MAX_TASK_INVOCATIONS) with a default of 20 and you get a decent error message if it's exceeded. Does this look good?

juliemr added a commit to juliemr/zone.js that referenced this issue Apr 24, 2017
The `flush` method advances time until all non-periodic timers
are cleared from the queue. It has a configurable limit (default 20)
of tasks that will be run before it gives up and throws an error,
in order to avoid infinite loops when polling timeouts are present.

Closes angular#735
juliemr added a commit to juliemr/zone.js that referenced this issue Apr 25, 2017
The `flush` method advances time until all non-periodic timers
are cleared from the queue. It has a configurable limit (default 20)
of tasks that will be run before it gives up and throws an error,
in order to avoid infinite loops when polling timeouts are present.

Closes angular#735
@heathkit
Copy link

LGTM.

It feels a little more natural to me to do it by max elapsed time. I'm thinking of page-level tests as being kind of black box, so you'd say "I don't know what tasks this thing is going to start, but I do know it shouldn't take longer than 500ms" or something. But limiting it based on the number of tasks also seems reasonable, and as long as there's a good error message it's all good.

mhevery pushed a commit that referenced this issue Apr 26, 2017
The `flush` method advances time until all non-periodic timers
are cleared from the queue. It has a configurable limit (default 20)
of tasks that will be run before it gives up and throws an error,
in order to avoid infinite loops when polling timeouts are present.

Closes #735
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants