Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@getcircuit/firestore-test
Advanced tools
<!-- @import "[TOC]" {cmd="toc" depthFrom=2 depthTo=6 orderedList=false} -->
@getcircuit/firestore-test
This package is comprised of a set of utilities to help you write tests for your Firestore code. It mainly provides two significant features:
jest
test environment.The CLI is a simple wrapper around the firebase
CLI, but with the project
set to test
and pointing to this package's firebase.json
configuration file.
# Start the emulator indefinitely
firestore-test emulator:start
# Start the emulator and run a command
firestore-test emulator:exec "<command>"
Example:
# Start the emulator and run jest
firestore-test emulator:exec "jest"
export {
testFirestore,
getUniqueTestRootRef,
waitForSnapshotListenersInSync,
uuid,
waitLoadedAccessor,
spySignal,
} from '@getcircuit/firestore-test'
testFirestore
is a function that returns a Firestore
instance that is connected to the emulator.
getUniqueTestRootRef
is a function that returns a DocumentReference
that is unique to the current test. This is useful when you want to seed data that is specific to the current test without having to seed a whole team.
import { getUniqueTestRootRef } from '@getcircuit/firestore-test'
const ref = getUniqueTestRootRef() // DocumentReference to /test-suite/{randomId}
waitForSnapshotListenersInSync()
is a function that returns a promise that resolves when all active snapshot listeners are in sync with the remote firestore. This is useful when you want to guarantee that a test is waiting for a firestore document to be updated.
uuid()
is a function that returns a pseudo-random string. This is useful when you want to generate a random id.
waitLoadedAccessor(signal)
is a function that returns a promise that resolves when the given LoadableAccessor
is loaded. This is useful when you want to guarantee that a test is waiting for an LoadableAccessor
to be loaded.
spySignal(signal)
is a function that returns a jest.Mock
that is spying on the given LoadableAccessor
. This is useful when you want to verify that a signal has been called after any of its dependencies were updated.
export {
seedDepots,
seedMembers,
seedPatches,
seedPlan,
seedPlanDrivers,
seedRoute,
seedStops,
seedTeam,
seedUsers,
} from '@getcircuit/firestore-test'
Each seeding utility accepts a DeepPartial
version of the data being seeded. Properties that are not explicitly set will fallback to what has been defined inside the src/firebase/data-factories
directory.
Each seeded model may or may not receive an id
property. If no id
is provided, a random one will be generated.
await seedStops({
collection,
stops: [
{ id: 'stop-1', name: 'Stop 1' }, // Stop 1 will have a known id
{ name: 'Stop 2' }, // Stop 2 will have a random id
],
})
While there are individual methods to seed users, members, depots, etc, you don't need to use them directly. For example, to seed a team with members and their users, you can use _only_ the seedTeam
method:
import { seedTeam } from '@getcircuit/firestore-test'
const teamSelectors = await seedTeam({
members: [
{ id: 'john', name: 'John Doe' },
{ id: 'jane', name: 'Jane Doe' },
],
})
This will automatically create the users for the specified members, and link their DocumentReferences
accordingly.
We can then select these references with the help of the teamSelectors
object:
teamSelectors.membersRef() // => CollectionReference<Member>
teamSelectors.memberRef('john') // => DocumentReference<Member>
teamSelectors.userRef('john') // => DocumentReference<User>
Since each test is expected to seed its own data, the user
collection is shared between all tests. Creating an user via their member is done by using the same id given to the member. So if two different tests created a member with id john
, both tests would try to write data to the same firestore document.
To prevent this, the seedTeam
function prefixes the user id with the id of the team.
const teamSelectors = await seedTeam({
id: 'team-1',
members: [
{ id: 'john', name: 'John Doe' },
{ id: 'jane', name: 'Jane Doe' },
],
})
teamSelectors.userRef('john').id // => 'team-1-john'
In case one wants to verify the id of a user, the teamSelectors
object provides a userId
method that will return the prefixed id:
teamSelectors.userId('john') // => 'team-1-john'
This is one of the reasons the returned selectors are particularly useful, as this prefixing logic is encapsulated inside them.
As we saw, some of the seeding methods allow you to seed various firestore models at once. While this can speed up writing tests, it can also lead to some confusion when it comes to cross-references.
For example, imagine that we want to seed a team with one member that is assigned to a depot. At the moment of calling seedTeam
, nothing exists, so there's no way to link the member-to-be to the depot-to-be.
const teamSelectors = await seedTeam({
depots: [{ id: 'depot-1' }],
members: [
{
id: 'john',
name: 'John Doe',
depot: ???, // How to link the member to the depot?
},
],
})
There are two ways to solve this:
This is the most concise way, as it allows you to, instead of providing the seeding arguments directly, pass a function that will be called with the selectors. This function should return the data that will be used to seed the model.
const teamSelectors = await seedTeam((teamSelectors) => ({
depots: [{ id: 'depot-1' }],
members: [
{
id: 'john',
name: 'John Doe',
depot: teamSelectors.depotRef('depot-1'),
},
],
}))
This is the most verbose way, but it allows you to have full control over the references. However, you will need to manually link the references and deal with the "user id" conflict mentioned on the About seeding users via members
section.
const teamSelectors = await seedTeam({
depots: [{ id: 'depot-1' }],
})
const userSelectors = await seedUsers({
teamRef: teamSelectors.teamRef,
users: [
{
id: 'john',
name: 'John Doe',
},
],
mapId: (id) => teamSelectors.userId(id),
})
const memberSelectors = await seedMembers({
teamRef: teamSelectors.teamRef,
members: [
{
id: 'john',
name: 'John Doe',
depot: teamSelectors.depotRef('depot-1'),
},
],
})
Each test that connects to the firestore emulator is expected to be self-contained. This means that each test should seed its own data. Cleaning up is not necessary.
import { seedTeam, seedRoute } from '@getcircuit/firestore-test'
test('route is created', async () => {
// Seeds a team with one member
const { teamRef, memberRef, userRef } = await seedTeam({
members: [{ id: 'chris' }],
})
// Seeds a route with linking it to the driver user and member documents
const { routeRef } = await seedRoute(teamRef, {
route: {
driver: userRef('chris'),
member: memberRef('chris'),
},
})
expect('...').toEqual('...')
})
@getcircuit/firestore-test
provides a JestConfig file to serve as a base for your project's jest
setup.
It can be imported from the @getcircuit/firestore-test/jest-config
entry-point.
// myProject/jest.config.js
const shared = require('@getcircuit/firestore-test/jest-config')
module.exports = {
...shared,
// your custom config
}
In case your Firestore-related test doesn't need a whole team, you can use the getUniqueTestRootRef
method to get a unique document ref pointing to test-suite/{randomId}
. This is useful to avoid having to create a unique collection in each test to prevent conflicts.
import { getUniqueTestRootRef } from '@getcircuit/firestore-test'
test('test 1', async () => {
const rootRef = getUniqueTestRootRef()
const patches = rootRef.collection('patches')
// do stuff with this patches collection
})
test('test 2', async () => {
const rootRef = getUniqueTestRootRef() // this is different from the previous test
const patches = rootRef.collection('patches') // the collections in both tests have the same name, but live in different paths
// do stuff with this patches collection
})
FAQs
<!-- @import "[TOC]" {cmd="toc" depthFrom=2 depthTo=4 orderedList=false} -->
The npm package @getcircuit/firestore-test receives a total of 0 weekly downloads. As such, @getcircuit/firestore-test popularity was classified as not popular.
We found that @getcircuit/firestore-test demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 19 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.