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

FR: Local development server #34

Closed
buu700 opened this issue Jun 3, 2017 · 7 comments
Closed

FR: Local development server #34

buu700 opened this issue Jun 3, 2017 · 7 comments

Comments

@buu700
Copy link

buu700 commented Jun 3, 2017

Not sure if this should be merged into #6 or treated separately, but I have a few related feature requests:

  • Better integration with urish/firebase-server. It technically mostly works, but having to use 127.0.1 as the address (or edit /etc/hosts) seems like an unnecessary hack.

  • Greater involvement from the Firebase team in firebase-server development (to at least get it feature compatible with the production Firebase environment) or a first-party replacement.

  • Support for locally testing Firebase Storage. At the very least, an equivalent to FirebaseOptions .databaseURL for Storage that would allow me to pass in http://my-gcloud-dev_appserver/_ah/gcs would be very useful.

@jshcrowthe
Copy link
Contributor

@buu700 is your use case here (related to the urish/firebase-server) primarily for testing? If so I'd love to hear @katowulf's take on how we can isolate the firebase integration so it is easily testable.

To your storage question: If I'm understanding you correctly you asking to pass a custom bucket URL to storage. Is that correct? If so, you can do that already. Check out the following blog post: https://firebase.googleblog.com/2017/03/multiplying-power-firebase-storage.html

You can specify a storage bucket by calling the storage method of an app with a url.

i.e.

const app = firebase.initializeApp({ ... });
app.storage('<CUSTOM BUCKET URL>'); 

Just calling firebase.storage() will return the default bucket, in order to pass a bucket URL to the firebase namespace you can do the following:

firebase.app().storage('<CUSTOM BUCKET URL>');

That said, for local development, being able to leverage a local firebase-server would be great! I think that if there are notable deficiencies in that repo feel free to reach out for specific help.

@buu700
Copy link
Author

buu700 commented Jun 6, 2017

Thanks! Yep, this is for testing in a local development environment. firebase-server is meeting most of our needs for Realtime Database (aside from onDisconnect support, and security rules would be nice to have), but I'll test out that solution for passing in the local dev_appserver storage bucket.

@buu700
Copy link
Author

buu700 commented Jun 9, 2017

Okay, just went ahead and tried your workaround @jshcrowthe. It looks like app.storage() expects a gs:// URL, so passing in http://my-gcloud-dev_appserver/_ah/gcs (specifically, http://localhost:42000/_ah/gcs) doesn't work.

@jshcrowthe
Copy link
Contributor

@buu700 Oh, you were meaning a local server. Yeah currently server mocks for testing are something that we don't have. I would look into abstracting the firebase layer in your application so that you can provide the abstraction with fake data and can treat firebase as a black box.

Say for example I'm testing the value of a reference:

const functionIWantToTest = (data) => {
  firebase.database().ref('some/ref/path').once('value')
    .then(data => {
      // Perform transforms on the data (this is the part to be tested)
    });
};

By directly calling firebase.database().ref('some/ref/path').once('value') in this function, you are forced to either mock the network interaction or stub the namespace function itself. Both of these assume some sort of basic reimplementation of the firebase space (the network protocol, or stub function).

i.e.

describe('Test Harness', () => {
  let server; // Some sort of Firebase Server mock
  before(() => {
    // This does not actually exist
    server.match('some request')
      .respondWith('...')
  });
  after(() => {
    server.close();
  });
  it('Should transform data properly', () => {});
});

Or, if you mock the function itself:

import sinon from 'sinon';

describe('Test Harness', () => {
  it('Should transform data properly', () => {
    const stub = sinon.stub(firebase.database().ref('some/ref/path'), 'once');
    stub.withArgs('value').returns(new Promise(resolve => {
      resolve({ ... }) // My test data
    }));
  });
});

NOTE: I haven't actually tested this, please treat as pseudo-code

Instead by abstracting the firebase interaction into a function of its own, you have a higher degree of control over what is getting tested when (your code vs. a firebase change):

export const getFirebaseData = () => firebase.database().ref('some/ref/path').once('value');

export const functionIWantToTest = (data) => {
  getFirebaseData()
    .then(data => {
      // Perform transforms on the data (this is the part to be tested)
    });
};

Then in your test harness you need only stub the firebase data function

import sinon from 'sinon';
import * as testFile from 'testFile';

describe('Test Harness', () => {
  it('Should transform data properly', () => {
    const stub = sinon.stub(testFile, 'getFirebaseData');
    stub.returns(new Promise(resolve => {
      resolve({ ... }) // My test data
    }));
  });
});

By doing this you can test your code, treat firebase as a blackbox, but still remove the need to go to the network.

@buu700
Copy link
Author

buu700 commented Jun 11, 2017

Well, I meant for manual testing in a local environment, not just automated tests. We already have an Angular service that abstracts away Firebase and a mock implementation of the service, but for manual local testing to work we'd need another non-mock implementation that doesn't depend on Firebase (which we may want to write at some point anyway, but haven't so far).

@jshcrowthe
Copy link
Contributor

Ah gotcha.

Yeah, we currently don't have a local implementation of the Firebase Server. I would be curious to know what the deficiencies are in urish/firebase-server, but I don't know that this repo is the right place to have that discussion.

I will add a bullet to #6 to investigate this.

@buu700
Copy link
Author

buu700 commented Jun 12, 2017

Thanks, sounds good.

I would be curious to know what the deficiencies are in urish/firebase-server, but I don't know that this repo is the right place to have that discussion.

  • Storage support was the main concern from my original report.

  • This is more a deficiency in this SDK, not firebase-server itself: enforcing that the Realtime Database server address have exactly two periods makes local testing with firebase-server (where the address would ideally be localhost or a local IP) needlessly cumbersome.

  • Realtime Database works well enough for my purposes — onDisconnect, security rules, and Cloud Functions would all be nice to have, but I understand that you have to draw the line somewhere in protecting Firebase's secret sauce.

@firebase firebase locked and limited conversation to collaborators Oct 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants