O Cloud Firestore e o Realtime Database dependem de linguagens de regras avançadas e concisas criadas especificamente para monitorar a segurança das informações e o controle de acesso. No entanto, como as regras se tornam mais longas e complexas, talvez você precise de ajuda para depurar erros no comportamento delas.
Os emuladores do Firebase incluem a capacidade de gerar relatórios de cobertura de regras para que você veja exatamente o que cada subexpressão avaliou ao reproduzir um erro. Os relatórios também fornecem informações sobre a frequência com que cada caso de teste usou uma regra, como as técnicas tradicionais de cobertura de linha.
Gerar um relatório
Depois de executar um conjunto de testes, é possível acessar relatórios de cobertura que mostram como cada uma das suas regras de segurança foi avaliada.
Para acessar os relatórios, consulte um endpoint exposto no emulador enquanto ele está em execução. Para uma versão otimizada para navegadores, use o seguinte URL:
http://localhost:8080/emulator/v1/projects/<database_name> :ruleCoverage.html
http://localhost:9000/.inspect/coverage?ns=<database_name>
Isso divide suas regras em expressões e subexpressões em que é possível passar o mouse para encontrar mais informações, incluindo o número de execuções e os valores retornados. Para a versão em JSON bruta desses dados, inclua o seguinte URL em sua consulta:
http://localhost:8080/emulator/v1/projects/<database_name> :ruleCoverage
http://localhost:9000/.inspect/coverage.json?ns=<database_name>
Regras de exemplo de depuração
Para gerar facilmente um relatório de teste, use os guias de início rápido do emulador disponíveis no GitHub para Cloud Firestore e Realtime Database. Nesses guias, você encontra instruções de instalação e inicialização adequadas dos emuladores, além de testes de amostra a partir de um conjunto de regras de exemplo.
Considere um exemplo de app que usa Cloud Firestore e conta quantas vezes os usuários clicam em um botão. O aplicativo emprega as seguintes regras:
service cloud.firestore { match /databases/{database}/documents { match /counters/{counter} { allow read; allow write: if request.resource.data.value == resource.data.value +1; } } }
Para depurar os erros nas regras mostradas acima, use o exemplo de teste JavaScript a seguir:
const counter0 = db.collection("counters").doc("0");
await firebase.assertSucceeds(counter0.set({value: 0}));
O emulador gera um relatório disponível no URL indicado acima:
http://localhost:8080/emulator/v1/projects/<database_name> :ruleCoverage.html
O relatório mostra os seguintes erros indefinidos e valores nulos:
O problema com este exemplo específico lida é que as regras não diferenciam entre a criação e a atualização do documento. Assim, a gravação não será permitida se o documento não existir, e o documento não será criado porque não existe. Ao diferenciar a gravação ("write") em duas operações mais específicas, criação e atualização ("create" e "update", respectivamente), o problema é resolvido.
service cloud.firestore { match /databases/{database}/documents { match /counters/{counter} { allow read; allow create: if request.resource.data.value == 0; allow update: if request.resource.data.value == resource.data.value +1; } } }
O relatório gerado mostra com que frequência cada regra foi usada e o que foi retornado.