<commit_before>![header](images/firemock-header.jpg)
# Firebase API {#top}

Up to now we've talk about the process of generating data for our mock database but just having a pile of data isn't that great. You'll want to **use** that data and how you'll want to use it is typically going to be using the existing Firebase API surface. Well fine sir/madame, that's exactly what we're providing.

## API Overview

Here's a pictorial diagram of the interfaces that Firebase exposes:

![api](images/firebase-api.jpg)

## Querying Firebase {#querying}

If you know how to query Firebase, then you largely know how to query the **firemock** API. Here's a simple example (we're putting this into a test where we're using the _mocha_ test runner and _chai_ grammer):

```js
it('test something about appointments', done => {
  // ... setup data ...
  m.ref('/appointments')
    .once('value')
    .then(snap => {
      expect(snap.val()).is.an('object');
      expect(snap.key).is.equal('appointments');
      expect(snap.numChildren()).is.equal(25);
      done();
    });
});
```

Let's walk through the example:

- the `[mock].ref()` call gives the Firebase "reference" API surface
- we use the `once` event to asynchronously query the database for the path "/appointments" (a promise is returned)
- `snap.val()` returns a JS hash of appointments keyed by push-id
- `snap.key` is not very interesting in this case but represents the query's root node
- `snap.numChildren()` just gives us the number of children that this DB path has; from our prior examples 25 is the number we'd expect

Cool but basic. What if we wanted to test for appointments scheduled in the next week?

### Filtering a Query

```js
import * as moment from 'moment';
it('appointments in the next week should exist', done => {
  // ... setup data ...
  m.ref('/appointments')
    .startAt(moment().toISOString(), 'when')
    .endAt(moment().add(7, 'days').toISOString(), 'when')
    .once('value')
    .then(snap => {
      expect(snap.val()).is.an('object');
      expect(snap.key).is.a('string');
      expect(snap.numChildren()).is.equal(x);
      done();
    });
});
```

So now you start to see that filters like startAt, endAt, and equalTo are usable in exactly the same way you use them when going back to the Firebase DB.

## Writing to the Database {#writing}

When we started talking about _schemas_ and _generation_, this was in essence a bulk way of writing data to the database. While this is typically done for initializing "state" into a desireable starting point it is not useful for testing Firebase code as this is not represented in Firebase's API. 

For those of you Firebase ace's the API endpoints we are concerned about when writing to the database include operations such as: `set()`, `update()`, `push()`, and `remove()`. A simple example of this might fall along these lines:

```js
const m = new Mock();

before(async () => {
  m.addSchema('customer', (h) => () => {
    first: h.faker.name.firstName(),
    last: h.faker.name.firstName(),
    email: h.chance.email(),
    address: h.chance.address()
  });
  m.queueSchema('customer', 10);
  m.generate();
});

it('pushing a new customer works', async () => {
  await m.ref('customers').push({
    first: 'John',
    last: 'Smith',
    email: '<EMAIL>'
  });
  const customers = await m.ref('customers').once('value');
  expect(customers.numChildren).to.equal(11);
}
```

This test isn't the best but hopefully it illustrates the use of the write-based `push` API used to push a new customer record into the mock database.

## Realtime Events {#realtime}

In the _querying_ section above we saw a traditional interaction between code and database ... the code queried for something in the database with the `once()` method and got back a result as a one time data snapshot. That's the way most databases work but as we know Firebase is different.

Rather than relying on `once()` to do our bidding in the traditional request-response style we instead state our _interest_ in data paths and let Firebase tell us when they've changed. You know the drill. Here's an example of how this might appear in a test:

```js
const m = new Mock();

before(async () => {
  m.addSchema('customer', (h) => () => {
    first: h.faker.name.firstName(),
    last: h.faker.name.firstName(),
    email: h.chance.email(),
    address: h.chance.address()
  });
  m.queueSchema('customer', 10);
  m.generate();
});

it('pushing a new customer works', (done) => {
  const onChildAdded = (snap) => {
    expect(customers.numChildren).to.equal(11);
    done();
  };
  m.ref('customers').on('child_added', onChildAdded);
}
```

## Other Features {#other}

### Firebase IDs

Rather than putting in some random push-id string we use the very useful `firebase-key` library to create _time appropriate_ id's which very closely resemble the ID you'd get with the Firebase DB.

### Network Delay

By default the Firebase events return with a delay of 5ms but this number can be set by adjusting the `delay()` method:

````js
import Mock from 'firemock';
const m = new Mock();
m.delay(200);
````

From this point forward all requests will have a 200ms delay. You can also configure with a tuple which indicates the min/max delays. For example the following config will result in random delays between 10 and 100ms:<commit_msg>real-time example update<commit_after>![header](images/firemock-header.jpg)
# Firebase API {#top}

Up to now we've talk about the process of generating data for our mock database but just having a pile of data isn't that great. You'll want to **use** that data and how you'll want to use it is typically going to be using the existing Firebase API surface. Well fine sir/madame, that's exactly what we're providing.

## API Overview

Here's a pictorial diagram of the interfaces that Firebase exposes:

![api](images/firebase-api.jpg)

## Querying Firebase {#querying}

If you know how to query Firebase, then you largely know how to query the **firemock** API. Here's a simple example (we're putting this into a test where we're using the _mocha_ test runner and _chai_ grammer):

```js
it('test something about appointments', done => {
  // ... setup data ...
  m.ref('/appointments')
    .once('value')
    .then(snap => {
      expect(snap.val()).is.an('object');
      expect(snap.key).is.equal('appointments');
      expect(snap.numChildren()).is.equal(25);
      done();
    });
});
```

Let's walk through the example:

- the `[mock].ref()` call gives the Firebase "reference" API surface
- we use the `once` event to asynchronously query the database for the path "/appointments" (a promise is returned)
- `snap.val()` returns a JS hash of appointments keyed by push-id
- `snap.key` is not very interesting in this case but represents the query's root node
- `snap.numChildren()` just gives us the number of children that this DB path has; from our prior examples 25 is the number we'd expect

Cool but basic. What if we wanted to test for appointments scheduled in the next week?

### Filtering a Query

```js
import * as moment from 'moment';
it('appointments in the next week should exist', done => {
  // ... setup data ...
  m.ref('/appointments')
    .startAt(moment().toISOString(), 'when')
    .endAt(moment().add(7, 'days').toISOString(), 'when')
    .once('value')
    .then(snap => {
      expect(snap.val()).is.an('object');
      expect(snap.key).is.a('string');
      expect(snap.numChildren()).is.equal(x);
      done();
    });
});
```

So now you start to see that filters like startAt, endAt, and equalTo are usable in exactly the same way you use them when going back to the Firebase DB.

## Writing to the Database {#writing}

When we started talking about _schemas_ and _generation_, this was in essence a bulk way of writing data to the database. While this is typically done for initializing "state" into a desireable starting point it is not useful for testing Firebase code as this is not represented in Firebase's API. 

For those of you Firebase ace's the API endpoints we are concerned about when writing to the database include operations such as: `set()`, `update()`, `push()`, and `remove()`. A simple example of this might fall along these lines:

```js
const m = new Mock();

before(async () => {
  m.addSchema('customer', (h) => () => {
    first: h.faker.name.firstName(),
    last: h.faker.name.firstName(),
    email: h.chance.email(),
    address: h.chance.address()
  });
  m.queueSchema('customer', 10);
  m.generate();
});

it('pushing a new customer works', async () => {
  await m.ref('customers').push({
    first: 'John',
    last: 'Smith',
    email: '<EMAIL>'
  });
  const customers = await m.ref('customers').once('value');
  expect(customers.numChildren).to.equal(11);
}
```

This test isn't the best but hopefully it illustrates the use of the write-based `push` API used to push a new customer record into the mock database.

## Realtime Events {#realtime}

In the _querying_ section above we saw a traditional interaction between code and database ... the code queried for something in the database with the `once()` method and got back a result as a one time data snapshot. That's the way most databases work but as we know Firebase is different.

Rather than relying on `once()` to do our bidding in the traditional request-response style we instead state our _interest_ in data paths and let Firebase tell us when they've changed. You know the drill. Here's an example of how this might appear in a test:

```js
const m = new Mock();

before(async () => {
  m.addSchema('customer', (h) => () => {
    first: h.faker.name.firstName(),
    last: h.faker.name.firstName(),
  });
  m.queueSchema('customer', 10);
  m.generate();
});

it('pushing a new customer works', (done) => {
  const onChildAdded = (snap) => {
    expect(customers.numChildren).to.equal(11);
    done();
  };
  m.ref('customers').on('child_added', onChildAdded);
  m.ref('customers').push({ first: 'John', last: 'Smith' });
}
```

## Other Features {#other}

### Firebase IDs

Rather than putting in some random push-id string we use the very useful `firebase-key` library to create _time appropriate_ id's which very closely resemble the ID you'd get with the Firebase DB.

### Network Delay

By default the Firebase events return with a delay of 5ms but this number can be set by adjusting the `delay()` method:

````js
import Mock from 'firemock';
const m = new Mock();
m.delay(200);
````

From this point forward all requests will have a 200ms delay. You can also configure with a tuple which indicates the min/max delays. For example the following config will result in random delays between 10 and 100ms:
{'fraction_non_alphanumeric': 0.12140515222482436, 'fraction_numerical': 0.00468384074941452, 'mean_word_length': 3.9243542435424352, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1911458', 'n_tokens_mistral': 3176, 'n_tokens_neox': 2998, 'n_words': 1362}